diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknCharMap.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknCharMap.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,8166 @@ +/* +* Copyright (c) 2002-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: Special character table. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "AknPanic.h" +#include "avkon.hrh" +#include "AknUtils.h" +#include +#include +#include +#include "aknCharMap.h" +#include "aknappui.h" +#include "aknconsts.h" +#include "AknDef.h" +#include +#include +#include +#include "aknSctDialog.h" // CAknCharmapDialog +#include +#include +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + +#include +// For the TEikScrollBarModelType +#include + +#include +#include +#include +#include + +#include // KCRUidAvkon, KAknRecentSctData +#include // CRepository +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PictograhGrouping.h" +#include "AknSettingCache.h" +#include "aknsctfocushandler.h" + +#include "AknSmileyModel.h" + +_LIT(KResFileName, "z:\\resource\\avkon.r"); + +const TInt KAknSctCBaButtonDirections = 3; // bottom, right and left + +const TUint KThaiSCTCombiningSymbolAdd = 0xE900; + +enum + { + EAknCharMapButton1DownInGrid = 0x00000001, + EAknCharMapHasBeenScrolledByDrag = 0x00000002, + EAknCharMapCharsAllocated = 0x00000004, // flag that iChars points to HBufC + EAknCharMapPressedDown = 0x00000008 // flag for press down effect + }; + + +const TUint KHistoryEmptyChar = CEditableText::ETabCharacter; +const TUint KHistoryEmptyCharForDisplay = CEditableText::ESpace; + +const TInt KAknSctRadioOn = 1; +const TInt KAknSctRadioOff = 0; +const TInt KAreaIdRecent = 0; +const TInt KAreaIdMain = 1; +const TInt KAreaIdTail = 2; + + +// ---------------------------------------------------------------------------- +// TEmotionUtils definition +// ---------------------------------------------------------------------------- +// + +const TUint KEmotionCharBase = 0xf880; + +class TEmotionUtils + { +public: + static TBool IsEmotionChar(TChar aChar); + static TChar EmotionChar(TInt aId); + static TInt EmotionId(TChar aChar); + static TChar EmotionSwitchToSmileyChar(); + static TChar EmotionSwitchToSctChar(); + }; + +TBool TEmotionUtils::IsEmotionChar(TChar aChar) + { + return (aChar >= KEmotionCharBase); + } + +TChar TEmotionUtils::EmotionChar(TInt aId) + { + return (KEmotionCharBase + aId); + } + +TInt TEmotionUtils::EmotionId(TChar aChar) + { + return (TInt)(aChar - KEmotionCharBase); + } + +TChar TEmotionUtils::EmotionSwitchToSmileyChar() + { + return KEmotionCharBase + CSmileyModel::EIconSwitchToSmiley; + } + +TChar TEmotionUtils::EmotionSwitchToSctChar() + { + return KEmotionCharBase + CSmileyModel::EIconSwitchToSct; + } + + +// ---------------------------------------------------------------------------- +// CAknCharMapHistory definition +// ---------------------------------------------------------------------------- +// +/** + * Recent data management when a Special characters or a Pictograph characters + * @lib avkon.lib + * @since 2.8 + * + */ +class CAknCharMapHistory : public CBase + { + public: // Constructors and destructor + /** + * Two-phased constructor. + */ + static CAknCharMapHistory* NewL(); + + /** + * Destructor. + */ + ~CAknCharMapHistory(); + + public: // enum + enum THistoryType + { + EHistoryTypeNull = -1, + EHistoryTypeFull = 0, + EHistoryTypeHalf, + EHistoryTypePicto, + EHistoryTypePicto2, + EHistoryTypeMax + }; + + enum THistoryFilter + { + EHistoryFilterMixed = 0, // text and emotion + EHistoryFilterTextOnly, + EHistoryFilterEmotionOnly, + EHistoryFilterMax + }; + + enum THistorySize + { + KHistoryBufferSize = 15 + }; + + public: // New functions + /** + * Load recent characters from file. + * @since 2.8 + */ + TInt LoadL(); + /** + * Reset recent data arrary. + * @since 2.8 + */ + void ResetArray(); + /** + * Store recent data to file. + * @since 2.8 + */ + TInt SaveL(); + /** + * Get recent data. + * @since 2.8 + * @param aHistoryType The kind of charctor map, refer to THistoryType + */ + const TDesC& RecentString(THistoryType aHistoryType, THistoryFilter aHistoryFilter=EHistoryFilterMixed); + /** + * Insert a character which select on SCT/Picto. + * @since 2.8 + * @param aHistoryType The kind of charctor map, refer to THistoryType + * @param aChar Insert a character + */ + void InsertChar(THistoryType aHistoryType, const TChar aChar); + + private: + /** + * C++ default constructor. + * @since 2.8 + */ + CAknCharMapHistory(); + + /** + * By default Symbian 2nd phase constructor is private. + * @since 2.8 + */ + void ConstructL(); + + private: + /** + * Insert a character to a HBufC. + * @param aHistoryBuf ahistory buffer + * @param aChar Insert a character + */ + void InsertCharToHistoryBuf(TDes& aHistoryBuf, const TChar aChar); + + private: // Data + // Recent characters + TBuf iMixedHistoryArray[EHistoryTypeMax]; + TBuf iTextHistoryArray[EHistoryTypeMax]; + TBuf iEmotionHistory; + + enum TBufferCount + { + KHistoryBufferCount = (EHistoryTypeMax+EHistoryTypeMax+1) + }; + }; + + +// ---------------------------------------------------------------------------- +// Navi button class definition +// ---------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAknSctNaviButton) : public CBase + { + public: + static CAknSctNaviButton* NewL( + const CCoeControl& aParent, + TInt aButtonId, + TResourceReader& reader); + ~CAknSctNaviButton(); + + private: + CAknSctNaviButton(TInt aButtonId); + void ConstructL( + const CCoeControl& aParent, + TResourceReader& reader); + + public: + void SetFocused(TBool aState); + void SetEnabled(TBool aState); + TBool IsFocused(); + TBool IsEnabled(); + + public: + CAknButton* iButtonControl; + TInt iButtonId; + TBool iPressed; + TBool iRepeat; + }; + +// ---------------------------------------------------------------------------- +// Table Navi class definition +// ---------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAknSctTableNavi) : public CAknControl, public MAknSctFocusHandler + { + public: + CAknSctTableNavi(CAknCharMap* aCharMap, CAknCharMapExtension* aExtension); + ~CAknSctTableNavi(); + + public: // from CCoeControl + TInt CountComponentControls() const; + CCoeControl* ComponentControl( TInt aIndex ) const; + virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode); + void ConstructFromResourceL(TResourceReader& aReader); + virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent); + virtual TSize MinimumSize(); + virtual void SizeChanged(); + + public: // from MAknSctFocusHandler + virtual CCoeControl* FocusedControl(); + virtual TBool EnterControl(TInt aX, TInt aY); + virtual void MoveFocus(TInt aX, TInt aY); + virtual TBool ExitWithKey(TInt aKeycode); + virtual TBool LeaveControl(); + + public: + TInt TableCount(); + void TableExitL(); + static TInt DoTableExit(TAny* aThis); + void UpdateNextTableButtonL(); + + private: + TInt ButtonPosition(TInt aButtonIndex) const; + TInt SetStatusChanged(); + void NextTableL(); + + private: // data + TInt iButtonIndex; + RPointerArray iButtonArray; + CAknCharMap* iCharMap; + CAknCharMapExtension* iExtension; + CIdle *iIdle; + + TInt iPressedButtonIndex; + }; + +// ---------------------------------------------------------------------------- +// Navigator class definition +// ---------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAknSctPageNavi) : public CAknControl, public MAknSctFocusHandler, public MCoeControlObserver + { + public: + CAknSctPageNavi( CAknCharMap* aCharMap, CAknCharMapExtension* aExtension); + ~CAknSctPageNavi(); + + public: // new methods + void UpdatePageTitleL() const; + + public: // from CCoeControl + TInt CountComponentControls() const; + CCoeControl* ComponentControl( TInt aIndex ) const; + virtual TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode); + void ConstructFromResourceL(TResourceReader& aReader); + virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent); + virtual TSize MinimumSize(); + virtual void SizeChanged(); + virtual void Draw(const TRect& aRect) const; + + public: // from MCoeControlObserver + void HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType); // for button repeat + + public: // from MAknSctFocusHandler + virtual CCoeControl* FocusedControl(); + virtual TBool EnterControl(TInt aX, TInt aY); + virtual void MoveFocus(TInt aX, TInt aY); + virtual TBool ExitWithKey(TInt aKeycode); + virtual TBool LeaveControl(); + + private: + TBool IsNextButton() const; + + private: // data + TInt iButtonIndex; + RPointerArray iButtonArray; + CAknCharMap* iCharMap; + CAknCharMapExtension* iExtension; + CEikLabel* iTitle; + }; + +// ---------------------------------------------------------------------------- +// Category button class defintion +// ---------------------------------------------------------------------------- +// +class CAknSctCategoryButton : public CBase + { + public: + static CAknSctCategoryButton* NewL( + const CCoeControl& aParent, + TResourceReader& reader, + TInt aCategoryButtonId, + TInt aSctCaseId); + ~CAknSctCategoryButton(); + private: + CAknSctCategoryButton( + TInt aCategoryButtonId, + TInt aSctCaseId); + void ConstructL( + const CCoeControl& aParent, + TResourceReader& reader); + + public: + void SetFocused(TBool aState); + + public: + CAknButton* iButtonControl; // own + TInt iButtonId; + TInt iSctCaseId; + TBool iValid; + }; + +// ---------------------------------------------------------------------------- +// Radio button class defintion +// ---------------------------------------------------------------------------- +// +class CAknSctRadioButton : public CAknControl, public MAknSctFocusHandler + { + public: + enum TAknSctRadioButtonFlags + { + EAknSctRadioButtonResize = 0x1, + EAknSctRadioButtonEnd + }; + public: + CAknSctRadioButton(); + CAknSctRadioButton(CAknCharMap* aCharMap, + CAknCharMapExtension* aExtension); + ~CAknSctRadioButton(); + public: // from MAknSctFocusHandler + virtual CCoeControl* FocusedControl(); + virtual TBool EnterControl(TInt aX, TInt aY); + virtual void MoveFocus(TInt aX, TInt aY); + virtual TBool ExitWithKey(TInt aKeycode); + virtual TBool LeaveControl(); + + public: // from CCoeControl + TInt CountComponentControls() const; + CCoeControl* ComponentControl( TInt aIndex ) const; + virtual TKeyResponse OfferKeyEventL( + const TKeyEvent& aKeyEvent, TEventCode); + void ConstructFromResourceL(TResourceReader& aReader); + + /** + * This function handles pointer events directed at the charmapdialog. + * @param aPointerEvent The pointer event directed at the charmapdialog. + */ + virtual void HandlePointerEventL(const TPointerEvent& aPointerEvent); + + virtual TSize MinimumSize(); + virtual void SizeChanged(); + virtual void Draw(const TRect& aRect) const; + + public: // New function + // The number of Buttons + inline TInt Count() const; + + void SetCurrentCategory(TInt aCategory); + void SetValidSctCase(TInt aSctCase); + void RemoveInvalidButton(); + + private: // data + RPointerArray iButtonArray; + MCoeControlObserver* iObserver; + TInt iFlags; + CAknCharMapExtension* iExtension; + CAknCharMap* iCharMap; + TInt iButtonIndex; + TInt iEntryIndex; + }; +// end of CAknSctRadioButton class definition + +// ---------------------------------------------------------------------------- +// Extension class defintion +// ---------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAknCharMapExtension) : + public CBase, + public MObjectProvider, + public MAknSctFocusHandler, + public MSmileyIconObserver + { + public: + CAknCharMapExtension(); + ~CAknCharMapExtension(); + + public: // new methods + void SetCharMapControl(CAknCharMap* aCtrl); + MAknSctFocusHandler* FocusHandler(); + + public: // from MAknSctFocusHandler + virtual CCoeControl* FocusedControl(); + virtual TBool EnterControl(TInt aX, TInt aY); + virtual void MoveFocus(TInt aX, TInt aY); + virtual TBool ExitWithKey(TInt aKeycode); + virtual TBool LeaveControl(); + + protected: + TTypeUid::Ptr MopSupplyObject(TTypeUid aId); + MObjectProvider* MopNext(); + + private: // from MSmileyIconObserver + virtual void ThumbnailLoaded(CSmileyIcon* aSmileyIcon); + virtual void AnimationChanged(CSmileyIcon* aSmileyIcon); + + public: + TBool IsEmotionEnabled() const; + TBool IsShowingEmotion() const; + TBool NeedEmotionSwitchIcon() const; + HBufC* ReadEmotionHBufCL(); + void LoadEmotionTumbnails(const TDesC& aSctChars); + void SetEmotionSize(const TSize& aSize); + + CSmileyIcon* EmotionIcon(TChar aEmotionChar); + TBool DrawEmotion(CWindowGc& aGc, const TRect& aRect, TChar aEmotionChar); + void HandleFocusStatusChanged(TChar aChar, TBool aIsFocused); + + public: // data + MCoeControlObserver *iObserver; + HBufC* iCharsQwerty; + HBufC* iTitleBuf; + + TUint iFlags; + TInt iMaxVisibleRows; + CAknsFrameBackgroundControlContext* iBgContext; + MObjectProvider* iCharMap; + TBool iMenuSct; // Is SCT used in editing menu + TBool iKeyOkEvent; // ETrue is set after pressing OK Key + + // FeatureManager + TBool iPictographsBuffer; // ETrue means Picto is valid. + TBool iPictographsBufferGrouping; // ETrue means Picto grouping is valid. + TBool iJapaneseSctUi; // Title and Softkey for Japanese varinat + TBool iHasCategoryButtonUi; // Has Category button UI + CAknSctRadioButton* iRadioButton; + TInt iCurrentCategory; // defined enum TAknSCTCategoryButton on avkon.hrh + + // QHD layout. + CAknCharMap* iCharMapProxy; + MAknSctFocusHandler* iFocusHandler; + CAknSctTableNavi* iTableNavi; + CAknSctPageNavi* iPageNavi; + HBufC* iEntryBuf; + CEikLabel* iCategoryTitle; + CEikLabel* iCategoryEntry; + TBool iSelectAllowed; + + // Whether or not kinetic scrolling is enabled in the device. + // Focus scrolling is disabled if kinetic scrolling is used. + TBool iKineticScrolling; + // Indicates whether menu sct is highlighted or not. + TBool iMenuSctHighlighted; + + public: // for Emotion + HBufC* iCharsSmiley; + CSmileyModel iSmileyModel; + TChar iLastFocusedSmileyChar; + TBool iIsShowingEmotion; + TBool iIsEnableEmotion; + + public: // Single click + /** + * Is single click mode enabled + */ + TBool iSingleClickEnabled; + + /** + * Is highlight visible + */ + TBool iHighlightVisible; + }; + +// ---------------------------------------------------------------------------- +// Navi button class implementation +// ---------------------------------------------------------------------------- +// +CAknSctNaviButton* CAknSctNaviButton::NewL(const CCoeControl& aParent, TInt aButtonId, TResourceReader& aReader) + { + CAknSctNaviButton* self = new( ELeave ) CAknSctNaviButton(aButtonId); + CleanupStack::PushL( self ); + self->ConstructL(aParent, aReader); + CleanupStack::Pop(); + return self; + } + +CAknSctNaviButton::CAknSctNaviButton(TInt aButtonId) : iButtonId(aButtonId) + { + } + +void CAknSctNaviButton::ConstructL(const CCoeControl& aParent, TResourceReader& aReader) + { + iButtonControl = CAknButton::NewL(aReader); + iButtonControl->SetContainerWindowL(aParent); + } + +CAknSctNaviButton::~CAknSctNaviButton() + { + delete iButtonControl; + } + +void CAknSctNaviButton::SetFocused(TBool aState) + { + iButtonControl->SetFocus(aState); + iButtonControl->DrawNow(); + } + +void CAknSctNaviButton::SetEnabled(TBool aState) + { + iButtonControl->MakeVisible(aState); + } + +TBool CAknSctNaviButton::IsFocused() + { + return iButtonControl->IsFocused(); + } + +TBool CAknSctNaviButton::IsEnabled() + { + return iButtonControl->IsVisible(); + } + +// ---------------------------------------------------------------------------- +// Table navi class implementation +// ---------------------------------------------------------------------------- +// +CAknSctTableNavi::CAknSctTableNavi(CAknCharMap* aCharMap, CAknCharMapExtension* aExtension) : +iCharMap(aCharMap), iExtension(aExtension) + { + } + +CAknSctTableNavi::~CAknSctTableNavi() + { + if (iButtonArray.Count()) + { + iButtonArray.ResetAndDestroy(); + } + iButtonArray.Close(); + delete iIdle; + } + +TInt CAknSctTableNavi::CountComponentControls() const + { + return iButtonArray.Count(); + } + +CCoeControl* CAknSctTableNavi::ComponentControl( TInt aIndex ) const + { + CCoeControl* rtn; + if (aIndex < iButtonArray.Count()) + { + rtn = iButtonArray[aIndex]->iButtonControl; + } + else + { + rtn = NULL; + } + return rtn; + } + +TKeyResponse CAknSctTableNavi::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aModifiers) + { + CAknSctNaviButton* buttonObj = iButtonArray[iButtonIndex]; + buttonObj->iButtonControl->OfferKeyEventL(aKeyEvent,aModifiers); + TKeyResponse response = EKeyWasNotConsumed; + TUint code=aKeyEvent.iCode; + switch (code) + { + case EKeyEnter: + case EKeyOK: + { + switch (buttonObj->iButtonId) + { + case EAknSctTableNaviExit: + { + iExtension->iKeyOkEvent = ETrue; + TableExitL(); + response = EKeyWasConsumed; + } + break; + // add all supported table types here. + case EAknSctTableNaviSpecialChar: + case EAknSctTableNaviEmotion: + { + NextTableL(); + response = EKeyWasConsumed; + } + break; + default: + break; + } + } + break; + case EKeyLeftArrow: + case '4': + { + MoveFocus(-1,0); + response = EKeyWasConsumed; + } + break; + case EKeyRightArrow: + case '6': + { + MoveFocus(1,0); + response = EKeyWasConsumed; + } + break; + case EKeyUpArrow: + case '2': + { + response = EKeyWasConsumed; + if ((iButtonIndex==0) && !Layout_Meta_Data::IsLandscapeOrientation()) + { + // Left page button. + if (iExtension->iPageNavi && iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + } + } + else + { + // Last radio button. + if ((iButtonIndex==0) && iExtension->iRadioButton) + { + if (iExtension->iRadioButton->EnterControl(0,iExtension->iRadioButton->Count()-1)) + { + LeaveControl(); + } + break; + } + + // Grid bottom row. + TInt xPos = ButtonPosition(iButtonIndex); + if (iCharMap->ColMax(0) > iCharMap->ColMax(xPos)) + { + xPos = iCharMap->RowMax(iCharMap->ColMax(0)); + } + + if (iExtension->EnterControl(xPos,iCharMap->ColMax(xPos))) + { + LeaveControl(); + break; + } + } + } + break; + + case EKeyDownArrow: + case '8': + { + response = EKeyWasConsumed; + + // First radio button. + if ((iButtonIndex==0) && iExtension->iRadioButton) + { + if (iExtension->iRadioButton->EnterControl(0,0)) + { + LeaveControl(); + } + break; + } + + // Grid top row. + TInt xPos = ButtonPosition(iButtonIndex); + if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos))) + { + LeaveControl(); + break; + } + } + break; + + default: + break; + } + return response; + } + +void CAknSctTableNavi::TableExitL() + { + delete iIdle; + iIdle = 0; + iIdle = CIdle::NewL(CActive::EPriorityIdle); + iIdle->Start(TCallBack(DoTableExit, this)); + } + +TInt CAknSctTableNavi::DoTableExit(TAny* aThis) + { + return ((CAknSctTableNavi*)aThis)->SetStatusChanged(); + } + +TInt CAknSctTableNavi::ButtonPosition(TInt aButtonIndex) const + { + // buttons behind the 1th are behavior as one button + return (aButtonIndex==0) ? 0 : 1; + } + +TInt CAknSctTableNavi::SetStatusChanged() + { + TRAPD(err, iCharMap->SetStatusChanged(EAknCharSelectedTableExitButton)); + return err; + } + +void CAknSctTableNavi::NextTableL() + { + iCharMap->SetStatusChanged(EAknCharSelectedNextTableButton); + } + +void CAknSctTableNavi::ConstructFromResourceL(TResourceReader& aReader) + { + // Table navi buttons. + TInt counts = aReader.ReadInt16(); + for (TInt i = 0; i < counts; i++) + { + TInt buttonId = aReader.ReadInt16(); + TInt resId = aReader.ReadInt32(); + TResourceReader buttonReader; + iCoeEnv->CreateResourceReaderLC(buttonReader, resId); + CAknSctNaviButton* buttonObj = CAknSctNaviButton::NewL(*this, buttonId, buttonReader); + iButtonArray.Append(buttonObj); + CleanupStack::PopAndDestroy(); // buttonReader + } + } + +void CAknSctTableNavi::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition)) + { + if (aPointerEvent.iType == TPointerEvent::EButton1Down) + { + iPressedButtonIndex = -1; + + for (TInt index = 0; index < iButtonArray.Count(); index++) + { + CAknSctNaviButton* buttonObj = iButtonArray[index]; + if(buttonObj->IsEnabled()) + { + TRect buttonRect = buttonObj->iButtonControl->Rect(); + if (buttonRect.Contains(aPointerEvent.iPosition)) + { + iPressedButtonIndex = index; + } + } + } + } + else if (aPointerEvent.iType == TPointerEvent::EButton1Up) + { + if(iPressedButtonIndex >= 0) + { + CAknSctNaviButton* buttonObj = iButtonArray[iPressedButtonIndex]; + if(buttonObj->IsEnabled()) + { + iButtonIndex = iPressedButtonIndex; + + TRect buttonRect = buttonObj->iButtonControl->Rect(); + if (buttonRect.Contains(aPointerEvent.iPosition)) + { + switch (buttonObj->iButtonId) + { + case EAknSctTableNaviExit: + { + iExtension->iKeyOkEvent = ETrue; + TableExitL(); + } + return; + + case EAknSctTableNaviSpecialChar: + case EAknSctTableNaviEmotion: + { + NextTableL(); + } + return; + + default: + break; + } + } + } + } + } + } + + CCoeControl::HandlePointerEventL(aPointerEvent); + } + +TSize CAknSctTableNavi::MinimumSize() + { + return Rect().Size(); + } + +void CAknSctTableNavi::SizeChanged() + { + if (iButtonArray.Count()>0) + { + + TInt ctrlVariety = 2; + TInt cellVariety = 1; + if(!iCharMap->IsJapaneseSctUi()) + { + ctrlVariety = (iCharMap->TableCount()>1) ? 0 : 1; + cellVariety = 0; + } + + TAknLayoutRect cellLayRect, buttonLayRect; + TRect buttonRect; + + // Table exit. + cellLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::cell_graphic2_control_pane(ctrlVariety,0)); + buttonLayRect.LayoutRect(cellLayRect.Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp05(cellVariety)); + buttonRect = buttonLayRect.Rect(); + + TAknLayoutRect iconLayRect; + iconLayRect.LayoutRect(buttonRect, AknLayoutScalable_Avkon::cell_graphic2_control_pane_g1(cellVariety)); + TSize iconSize = iconLayRect.Rect().Size(); + + CAknSctNaviButton* buttonObj = iButtonArray[0]; + buttonObj->iButtonControl->SetRect(buttonRect); + buttonObj->iButtonControl->SetHighlightRect(buttonRect); + buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved); + buttonObj->iButtonControl->SetIconSize(iconSize); + buttonObj->SetEnabled(ETrue); + + // Table change. + if (iCharMap->TableCount() > 1) + { + cellLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::cell_graphic2_control_pane(ctrlVariety,1)); + buttonLayRect.LayoutRect(cellLayRect.Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp05(cellVariety)); + buttonRect = buttonLayRect.Rect(); + + for (TInt i(1); iiButtonControl->SetRect(buttonRect); + buttonObj->iButtonControl->SetHighlightRect(buttonRect); + buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved); + buttonObj->iButtonControl->SetIconSize(iconSize); + buttonObj->SetEnabled(ETrue); + } + } + + TRAP_IGNORE(UpdateNextTableButtonL()); + } + } + + +void CAknSctTableNavi::UpdateNextTableButtonL() + { + + TBool isFocused = EFalse; + + // table switch buttons stay in one place. + for(TInt index(1); indexIsEnabled()) + { + isFocused = buttonObj->IsFocused(); + } + } + + // fresh focused button + for (TInt index(1); indexTableCount() > 1) + { + switch (iCharMap->NextTableCase()) + { + case EAknCharMapTableSpecialChar: + { + TBool isShown = EFalse; + if(iExtension->IsShowingEmotion()) + { + isShown = (buttonObj->iButtonId==EAknSctTableNaviSpecialChar); + } + else + { + isShown = (buttonObj->iButtonId==EAknSctTableNaviEmotion); + } + buttonObj->SetEnabled(isShown); + buttonObj->SetFocused(isShown && isFocused); + if(isShown && isFocused) + { + iButtonIndex = index; + } + } + break; + + default: + buttonObj->SetEnabled(EFalse); + break; + } + } + else + { + buttonObj->SetEnabled(EFalse); + } + } + } + +CCoeControl* CAknSctTableNavi::FocusedControl() + { + return this; + } + +TBool CAknSctTableNavi::EnterControl(TInt aX, TInt /*aY*/) + { + if (IsVisible()) + { + if ((aX >= 0) && (aX < iButtonArray.Count())) + { + TInt index = aX; + if (AknLayoutUtils::LayoutMirrored()) // reverse. + { + index = (iButtonArray.Count() - 1) - aX; + } + + index = ButtonPosition(index); + + for(; indexIsEnabled()) + { + iButtonIndex = index; + iExtension->iFocusHandler = this; + buttonObj->SetFocused(ETrue); + return ETrue; + } + } + } + } + return EFalse; + } + +void CAknSctTableNavi::MoveFocus(TInt aX, TInt /*aY*/) + { + TInt delta = aX; + if (AknLayoutUtils::LayoutMirrored()) // reverse. + { + delta = -aX; + } + + TInt buttonIndex = iButtonIndex + delta; + + // loop until find next position + for (TInt i = 0; i < iButtonArray.Count(); i++) + { + + if (buttonIndex > iButtonArray.Count() - 1) // goto Next control + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // First radio button. + if (iExtension->iRadioButton) + { + if (iExtension->iRadioButton->EnterControl(0,0)) + { + LeaveControl(); + } + break; + } + // Grid start. + if (iExtension->EnterControl(0,iCharMap->ColMin(0))) + { + LeaveControl(); + } + } + else + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + } + } + break; + } + + else if (buttonIndex < 0) // goto Prev control + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Right page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + } + } + else + { + // Grid end. + TInt posY = iCharMap->ColMax(0); + if (iExtension->EnterControl(iCharMap->RowMax(posY),posY)) + { + LeaveControl(); + } + } + break; + } + + if (iButtonArray[buttonIndex]->IsEnabled()) // goto next button in This control + { + CAknSctNaviButton* buttonObj; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(EFalse); + iButtonIndex = buttonIndex; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(ETrue); + break; + } + + buttonIndex += (delta < 0) ? -1 : 1; // get next position + } + } + +TBool CAknSctTableNavi::LeaveControl() + { + for (TInt i = 0; i < iButtonArray.Count(); i++ ) + { + iButtonArray[i]->SetFocused(EFalse); + } + return ETrue; + } + +TBool CAknSctTableNavi::ExitWithKey(TInt /*aKeycode*/) + { + if (iButtonArray[iButtonIndex]->iButtonId != EAknSctTableNaviExit) + { + return EFalse; + } + else + { + return ETrue; + } + } + +// ---------------------------------------------------------------------------- +// Page Navi class implementation +// ---------------------------------------------------------------------------- +// +CAknSctPageNavi::CAknSctPageNavi( + CAknCharMap* aCharMap, + CAknCharMapExtension* aExtension) + :iCharMap(aCharMap), + iExtension(aExtension) + { + } + +CAknSctPageNavi::~CAknSctPageNavi() + { + if (iButtonArray.Count()) + { + iButtonArray.ResetAndDestroy(); + } + iButtonArray.Close(); + delete iTitle; + } + +TInt CAknSctPageNavi::CountComponentControls() const + { + TInt num= 0; + if (iTitle) + { + num++; + } + if (iButtonArray.Count() > 0) + { + num += iButtonArray.Count(); + } + return num; + } + +CCoeControl* CAknSctPageNavi::ComponentControl( TInt aIndex ) const + { + if (iTitle) + { + if ( aIndex == 0 ) + { + return iTitle; + } + aIndex--; + } + if (iButtonArray.Count() > 0) + { + return iButtonArray[ aIndex ]->iButtonControl; + } + return NULL; + } + +TKeyResponse CAknSctPageNavi::OfferKeyEventL( + const TKeyEvent& aKeyEvent, + TEventCode aModifiers) + { + CAknSctNaviButton* buttonObj = iButtonArray[iButtonIndex]; + buttonObj->iButtonControl->OfferKeyEventL(aKeyEvent,aModifiers); + TKeyResponse response = EKeyWasNotConsumed; + TUint code=aKeyEvent.iCode; + switch (code) + { + case EKeyEnter: + case EKeyOK: + { + switch (buttonObj->iButtonId) + { + case EAknSctPageNaviPrevPage: + { + iCharMap->PrevPageL(); + } + break; + case EAknSctPageNaviNextPage: + { + iCharMap->NextPageL(); + } + break; + default: + return EKeyWasConsumed; + } + buttonObj->SetFocused(ETrue); + response = EKeyWasConsumed; + UpdatePageTitleL(); + } + break; + case EKeyLeftArrow: + case '4': + { + MoveFocus(-1,0); + response = EKeyWasConsumed; + } + break; + case EKeyRightArrow: + case '6': + { + MoveFocus(1,0); + response = EKeyWasConsumed; + } + break; + case EKeyUpArrow: + case '2': + { + response = EKeyWasConsumed; + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + if (iExtension->iRadioButton && !IsNextButton()) + { + // Last radio button. + if (iExtension->iRadioButton->EnterControl( + 0,iExtension->iRadioButton->Count()-1)) + { + LeaveControl(); + } + break; + } + } + TInt xPos; + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + xPos = IsNextButton() ? iCharMap->MaxCols() - 1 : 0; + } + else + { + if (IsNextButton()) + { + xPos = iCharMap->MaxCols() - 1; + } + else + { + xPos = !iExtension->iRadioButton ? + iCharMap->TableCount() : iCharMap->MaxCols()-2; + } + } + if (iCharMap->ColMax(0) > iCharMap->ColMax(xPos)) + { + xPos = iCharMap->RowMax(iCharMap->ColMax(0)); + } + // Grid bottom row. + if (iExtension->EnterControl(xPos,iCharMap->ColMax(xPos))) + { + LeaveControl(); + break; + } + } + break; + case EKeyDownArrow: + case '8': + { + response = EKeyWasConsumed; + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + if (!IsNextButton()) + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + else + { + // Grid top row. + TInt xPos = iCharMap->MaxCols() - 1; + if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos))) + { + LeaveControl(); + break; + } + } + } + else + { + TInt xPos; + if (IsNextButton()) + { + xPos = iCharMap->MaxCols() - 1; + } + else + { + xPos = !iExtension->iRadioButton ? + iCharMap->TableCount() : iCharMap->MaxCols() - 2; + } + // Grid top row. + if (iExtension->EnterControl(xPos,iCharMap->ColMin(xPos))) + { + LeaveControl(); + break; + } + } + } + break; + default: + break; + } + return response; + } + +TBool CAknSctPageNavi::IsNextButton() const + { + if (iButtonIndex < iButtonArray.Count() && iButtonArray[iButtonIndex]) + { + return iButtonArray[iButtonIndex]->iButtonId == EAknSctPageNaviNextPage; + } + return EFalse; + } + +void CAknSctPageNavi::ConstructFromResourceL(TResourceReader& aReader) + { + TInt counts = aReader.ReadInt16(); + for (TInt i = 0; i < counts; i++) + { + TInt buttonId = aReader.ReadInt16(); + TInt resId = aReader.ReadInt32(); + TResourceReader oneButtonReader; + iCoeEnv->CreateResourceReaderLC(oneButtonReader, resId); + CAknSctNaviButton* buttonObj = + CAknSctNaviButton::NewL(*this, buttonId, oneButtonReader); + buttonObj->iButtonControl->SetObserver(this); // for handling control events. + iButtonArray.Append(buttonObj); + CleanupStack::PopAndDestroy(); // oneButtonReader + } + iTitle = new (ELeave) CEikLabel; + } + +void CAknSctPageNavi::HandleControlEventL( + CCoeControl* aControl, + TCoeEvent aEventType) + { + if (aEventType == EEventStateChanged && AknLayoutUtils::PenEnabled()) // action on key repeat + { + for (TInt index=0; index < iButtonArray.Count(); index++) + { + CAknSctNaviButton* buttonObj = iButtonArray[index]; + TRect buttonRect = buttonObj->iButtonControl->Rect(); + if (buttonObj->iButtonControl == aControl) + { + if (buttonObj->IsEnabled() && buttonObj->iPressed) + { + iButtonIndex = index; + switch (buttonObj->iButtonId) + { + case EAknSctPageNaviPrevPage: + { + buttonObj->iRepeat = ETrue; // Set button repeat. + iCharMap->PrevPageL(); + UpdatePageTitleL(); + } + break; + case EAknSctPageNaviNextPage: + { + buttonObj->iRepeat = ETrue; // Set button repeat. + iCharMap->NextPageL(); + UpdatePageTitleL(); + } + break; + default: + break; + } + } + } + } + } + } + +void CAknSctPageNavi::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + if (AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition)) + { + if (aPointerEvent.iType == TPointerEvent::EButton1Down) + { + for (TInt index=0; index < iButtonArray.Count(); index++) + { + CAknSctNaviButton* buttonObj = iButtonArray[index]; + buttonObj->iPressed = EFalse; + buttonObj->iRepeat = EFalse; + TRect buttonRect = buttonObj->iButtonControl->Rect(); + if (buttonRect.Contains(aPointerEvent.iPosition)) + { + if (buttonObj->IsEnabled()) + { + buttonObj->iButtonControl->SetButtonFlags(KAknButtonKeyRepeat); + buttonObj->iPressed = ETrue; // Set button pressed. + } + } + } + } + else if (aPointerEvent.iType == TPointerEvent::EButton1Up) // action on button release. + { + for (TInt index=0; index < iButtonArray.Count(); index++) + { + CAknSctNaviButton* buttonObj = iButtonArray[index]; + TRect buttonRect = buttonObj->iButtonControl->Rect(); + if (buttonRect.Contains(aPointerEvent.iPosition)) + { + if (buttonObj->IsEnabled()) + { + if (buttonObj->iPressed && !buttonObj->iRepeat) + { + iButtonIndex = index; + switch (buttonObj->iButtonId) + { + case EAknSctPageNaviPrevPage: + { + iCharMap->PrevPageL(); + UpdatePageTitleL(); + } + break; + case EAknSctPageNaviNextPage: + { + iCharMap->NextPageL(); + UpdatePageTitleL(); + } + break; + default: + break; + } + } + } + } + buttonObj->iPressed = EFalse; // Button released. + buttonObj->iRepeat = EFalse; + } + } + } + CCoeControl::HandlePointerEventL(aPointerEvent); + } + +TSize CAknSctPageNavi::MinimumSize() + { + return Rect().Size(); + } + +void CAknSctPageNavi::SizeChanged() + { + + TAknLayoutRect pageButtonLayRect; + TInt pageVariate = !iCharMap->IsJapaneseSctUi() ? ((iCharMap->TableCount() > 1) ? 0 : 1) : 2; + + CAknSctNaviButton* buttonObj; + TRect rect; + + buttonObj = iButtonArray[0]; + buttonObj->iButtonControl->SetButtonFlags(0); + if (!AknLayoutUtils::LayoutMirrored()) + { + buttonObj->iButtonId = EAknSctPageNaviPrevPage; + pageButtonLayRect.LayoutRect(Rect(),AknLayoutScalable_Avkon::bg_button_pane_cp10(pageVariate)); + } + else + { + buttonObj->iButtonId = EAknSctPageNaviNextPage; + pageButtonLayRect.LayoutRect(Rect(),AknLayoutScalable_Avkon::bg_button_pane_cp11(pageVariate)); + } + rect = pageButtonLayRect.Rect(); + buttonObj->iButtonControl->SetRect(rect); + buttonObj->iButtonControl->SetHighlightRect(rect); + TAknLayoutRect pageButtonIconLayRect; + pageButtonIconLayRect.LayoutRect(pageButtonLayRect.Rect(), AknLayoutScalable_Avkon::graphic2_pages_pane_g1(pageVariate)); + buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved); + TSize iconSize = pageButtonIconLayRect.Rect().Size(); + buttonObj->iButtonControl->SetIconSize(iconSize); + + buttonObj = iButtonArray[1]; + buttonObj->iButtonControl->SetButtonFlags(0); + if (!AknLayoutUtils::LayoutMirrored()) + { + buttonObj->iButtonId = EAknSctPageNaviNextPage; + pageButtonLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp11(pageVariate)); + } + else + { + buttonObj->iButtonId = EAknSctPageNaviPrevPage; + pageButtonLayRect.LayoutRect(Rect(), AknLayoutScalable_Avkon::bg_button_pane_cp10(pageVariate)); + } + rect = pageButtonLayRect.Rect(); + buttonObj->iButtonControl->SetRect(rect); + buttonObj->iButtonControl->SetHighlightRect(rect); + buttonObj->iButtonControl->SetIconScaleMode(EAspectRatioPreserved); + buttonObj->iButtonControl->SetIconSize(iconSize); + + // Page text. + TRect parentRect = Rect(); + AknLayoutUtils::LayoutLabel(iTitle, parentRect, AknLayoutScalable_Avkon::graphic2_pages_pane_t1(pageVariate).LayoutLine()); + + // Page text color + TAknLayoutText textLayout; + textLayout.LayoutText(parentRect, AknLayoutScalable_Avkon::graphic2_pages_pane_t1(pageVariate)); + TRect textRect = textLayout.TextRect(); + TRgb color = textLayout.Color(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if (skin) + { + (void)AknsUtils::GetCachedColor(skin, color, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6); + } + TRAP_IGNORE(AknLayoutUtils::OverrideControlColorL(*iTitle, EColorLabelText, color)); + TRAP_IGNORE(UpdatePageTitleL()); + } + +void CAknSctPageNavi::Draw(const TRect& /*aRect*/) const + { + TRAP_IGNORE(UpdatePageTitleL()); + } + +void CAknSctPageNavi::UpdatePageTitleL() const + { + CArrayFix* numbers = new(ELeave)CArrayFixFlat(2); + CleanupStack::PushL(numbers); + numbers->AppendL(iCharMap->CurrentPage()); + numbers->AppendL(iCharMap->PageCount()); + HBufC* page = + StringLoader::LoadL( + R_AVKON_SPECIAL_CHARACTERS_PAGE_INDICATOR, *numbers, iEikonEnv); + CleanupStack::PopAndDestroy(); // numbers + iTitle->SetTextL(page->Des()); + iTitle->SetBrushStyle(CGraphicsContext::ENullBrush); + delete page; + } + +CCoeControl* CAknSctPageNavi::FocusedControl() + { + return this; + } + +TBool CAknSctPageNavi::EnterControl(TInt aX, TInt /*aY*/) + { + if (IsVisible()) + { + if ((aX >= 0) && (aX < iButtonArray.Count())) + { + CAknSctNaviButton* buttonObj; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(EFalse); + TInt index = aX; + if (AknLayoutUtils::LayoutMirrored()) // reverse. + { + index = iButtonArray.Count() - 1 - aX; + } + buttonObj = iButtonArray[index]; + if (buttonObj->IsEnabled()) + { + iButtonIndex = index; + iExtension->iFocusHandler = this; + buttonObj->SetFocused(ETrue); + return ETrue; + } + } + } + return EFalse; + } + +void CAknSctPageNavi::MoveFocus(TInt aX, TInt /*aY*/) + { + TInt delta = aX; + TInt buttonIndex = iButtonIndex + delta; + for (TInt i = 0; i < iButtonArray.Count(); i++) + { + if (buttonIndex > iButtonArray.Count() - 1) // Next control. + { + if (!AknLayoutUtils::LayoutMirrored()) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + else + { + // First radio button. + if (iExtension->iRadioButton && + iExtension->iRadioButton->EnterControl(0,0)) + { + LeaveControl(); + break; + } + // Grid start. + TInt yPos = iCharMap->ColMin(0); + if (iExtension->EnterControl(iCharMap->RowMin(yPos),yPos)) + { + LeaveControl(); + break; + } + } + } + else + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Grid end. + TInt yPos = iCharMap->ColMax(0); + if (iExtension->EnterControl(iCharMap->RowMax(yPos),yPos)) + { + LeaveControl(); + break; + } + } + else + { + // Last table button. + TInt xPos = iCharMap->TableCount() - 1; + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(xPos,0)) + { + LeaveControl(); + break; + } + } + } + break; + } + else if (buttonIndex < 0) // Prev control + { + if (!AknLayoutUtils::LayoutMirrored()) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Grid end. + TInt yPos = iCharMap->ColMax(0); + if (iExtension->EnterControl(iCharMap->RowMax(yPos),yPos)) + { + LeaveControl(); + break; + } + } + else + { + // Last table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(iCharMap->TableCount()-1,0)) + { + LeaveControl(); + break; + } + } + } + else + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + else + { + // Grid start. + TInt yPos = iCharMap->ColMin(0); + if (iExtension->EnterControl(iCharMap->RowMin(yPos),yPos)) + { + LeaveControl(); + break; + } + } + } + } + + if (iButtonArray[buttonIndex]->IsEnabled()) // This control + { + CAknSctNaviButton* buttonObj; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(EFalse); + iButtonIndex = buttonIndex; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(ETrue); + break; + } + buttonIndex += (delta < 0) ? -1 : 1; + } + } + +TBool CAknSctPageNavi::LeaveControl() + { + for (TInt i = 0; i < iButtonArray.Count(); i++ ) + { + iButtonArray[i]->SetFocused(EFalse); + } + return ETrue; + } + +TBool CAknSctPageNavi::ExitWithKey(TInt /*aKeycode*/) + { + return EFalse; + } + +// ---------------------------------------------------------------------------- +// Category button class implementation +// ---------------------------------------------------------------------------- +// +CAknSctCategoryButton* CAknSctCategoryButton::NewL( + const CCoeControl& aParent, + TResourceReader& reader, + TInt aCategoryButtonId, + TInt aSctCaseId) + { + CAknSctCategoryButton* self = + new( ELeave ) CAknSctCategoryButton(aCategoryButtonId, aSctCaseId); + + CleanupStack::PushL( self ); + self->ConstructL(aParent, reader); + CleanupStack::Pop(); + + return self; + } + +CAknSctCategoryButton::CAknSctCategoryButton( + TInt aCategoryButtonId, + TInt aSctCaseId) + : iButtonId(aCategoryButtonId) + , iSctCaseId(aSctCaseId) + { + } + +void CAknSctCategoryButton::ConstructL( + const CCoeControl& aParent, + TResourceReader& aReader) + { + iButtonControl = CAknButton::NewL(aReader); + iButtonControl->SetContainerWindowL(aParent); + } + +CAknSctCategoryButton::~CAknSctCategoryButton() + { + delete iButtonControl; + } + +void CAknSctCategoryButton::SetFocused(TBool aState) + { + iButtonControl->SetFocus(aState); + iButtonControl->DrawNow(); + } + + +// ---------------------------------------------------------------------------- +// Radio button class implementation +// ---------------------------------------------------------------------------- +// +CAknSctRadioButton::CAknSctRadioButton() + { + } + +CAknSctRadioButton::CAknSctRadioButton( + CAknCharMap* aCharMap, + CAknCharMapExtension* aExtension) + :iExtension(aExtension), + iCharMap(aCharMap) + { + } + +CAknSctRadioButton::~CAknSctRadioButton() + { + iButtonArray.ResetAndDestroy(); + iButtonArray.Close(); + } + +TInt CAknSctRadioButton::CountComponentControls() const + { + return iButtonArray.Count(); + } + +CCoeControl* CAknSctRadioButton::ComponentControl( TInt aIndex ) const + { + if (aIndex < iButtonArray.Count()) + { + return iButtonArray[aIndex]->iButtonControl; + } + return NULL; + } + +TKeyResponse CAknSctRadioButton::OfferKeyEventL( + const TKeyEvent& aKeyEvent, + TEventCode /*aModifiers*/) + { + TKeyResponse responce = EKeyWasNotConsumed; + TUint code=aKeyEvent.iCode; + switch (code) + { + case EKeyEnter: + case EKeyOK: + { + if (AknLayoutUtils::PenEnabled()) + { + // Grid. + TInt yPos = iCharMap->ColMin(0); + TInt xPos = iCharMap->RowMin(yPos); + if (iExtension->EnterControl(xPos,yPos)) + { + CAknButton* buttonCtrlObj; + TInt currentIndex; + TInt newIndex; + for (TInt index=0; index < iButtonArray.Count(); index++) + { + buttonCtrlObj = iButtonArray[index]->iButtonControl; + currentIndex = buttonCtrlObj->StateIndex(); + if (index == iButtonIndex) + { + newIndex = KAknSctRadioOn; + } + else + { + newIndex = KAknSctRadioOff; + } + if (currentIndex != newIndex) + { + buttonCtrlObj->SetCurrentState(newIndex, ETrue); + if (newIndex == KAknSctRadioOn) + { + iExtension->iCurrentCategory = + iButtonArray[index]->iButtonId; + iCharMap->SetStatusChanged(EAknCharChangedCategory); + } + } + } + LeaveControl(); + } + } + responce = EKeyWasConsumed; + } + break; + case EKeyLeftArrow: + case '4': + { + responce = EKeyWasConsumed; + if (AknLayoutUtils::PenEnabled()) + { + TInt yPos = iButtonIndex - 1; + if (iCharMap->RowMax(yPos) < 0) + { + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + if (iExtension->iRadioButton) + { + // Right page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + break; + } + } + } + // Next button up. + MoveFocus(0,-1); + break; + } + else + { + //Previous row end. + TInt xPos = iCharMap->RowMax(yPos); + if (iExtension->EnterControl(xPos,yPos)) + { + LeaveControl(); + break; + } + } + break; + } + // Move by grid. + iCharMap->TakeFocus(); + TInt xPos = iCharMap->CursorPos().iX; + TInt yPos = iCharMap->CursorPos().iY; + if (xPos == 0) + { + iCharMap->MoveFocus(-1,0); + } + iCharMap->ShowFocus(); + } + break; + case EKeyRightArrow: + case '6': + { + responce = EKeyWasConsumed; + if (AknLayoutUtils::PenEnabled()) + { + TInt yPos = iButtonIndex; + if (iCharMap->RowMax(yPos) < 0) + { + // Next button down. + MoveFocus(0,1); + break; + } + else + { + // 1st cell in the row. + if (iExtension->EnterControl(0,yPos)) + { + LeaveControl(); + break; + } + } + break; + } + // Move by grid. + iCharMap->TakeFocus(); + TInt xPos = iCharMap->CursorPos().iX; + TInt yPos = iCharMap->CursorPos().iY; + if (xPos == iCharMap->RowMax(yPos)) + { + iCharMap->MoveFocus(1,0); + } + iCharMap->ShowFocus(); + } + break; + case EKeyDownArrow: + case '8': + { + MoveFocus(0, 1); + responce = EKeyWasConsumed; + } + break; + case EKeyUpArrow: + case '2': + { + MoveFocus(0,-1); + responce = EKeyWasConsumed; + } + break; + default: + break; + } + return responce; + } + +void CAknSctRadioButton::ConstructFromResourceL(TResourceReader& aReader) + { + TInt counts = aReader.ReadInt16(); + TResourceReader reader; + TInt categorybutton_id; + TInt sctcase_id; + TInt resId; + CAknSctCategoryButton* buttonObj; + TBool allowCreation; + + for (TInt index=0; index < counts; index++) + { + allowCreation = EFalse; + // button id + categorybutton_id = aReader.ReadInt16(); + sctcase_id = aReader.ReadInt16(); + switch (categorybutton_id) + { + case EAknSCTCategoryButtonHalfCase: + case EAknSCTCategoryButtonFullCase: + allowCreation = ETrue; + break; + case EAknSCTCategoryButtonPicto: + if (iExtension->iPictographsBuffer) + { + allowCreation = ETrue; + } + break; + case EAknSCTCategoryButtonPicto1: + case EAknSCTCategoryButtonPicto2: + if (iExtension->iPictographsBuffer && + iExtension->iPictographsBufferGrouping) + { + allowCreation = ETrue; + } + break; + default: + break; + } + + if (allowCreation) + { + // read the button resource + resId = aReader.ReadInt32(); + iCoeEnv->CreateResourceReaderLC( reader, resId ); + // create Category button object + buttonObj = CAknSctCategoryButton::NewL( + *this, reader, categorybutton_id, sctcase_id); + // Append button + iButtonArray.Append(buttonObj); + CleanupStack::PopAndDestroy(); // reader + } + else + { + // Skip data + resId = aReader.ReadInt32(); + } + } + + } + +void CAknSctRadioButton::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + TRect rect(Rect()); + if (AknLayoutUtils::PenEnabled() && rect.Contains(aPointerEvent.iPosition)) + { + if (aPointerEvent.iType == TPointerEvent::EButton1Down) + { + CAknButton* buttonCtrlObj; + TRect rectButton; + TInt currentIndex; + TInt newIndex; + for (TInt index=0; index < iButtonArray.Count(); index++) + { + buttonCtrlObj = iButtonArray[index]->iButtonControl; + rectButton = buttonCtrlObj->Rect(); + currentIndex = buttonCtrlObj->StateIndex(); + + if (rectButton.Contains(aPointerEvent.iPosition)) + { + newIndex = KAknSctRadioOn; + } + else + { + newIndex = KAknSctRadioOff; + } + if (currentIndex != newIndex) + { + buttonCtrlObj->SetCurrentState(newIndex, ETrue); + if (newIndex == KAknSctRadioOn) + { + if (AknLayoutUtils::PenEnabled()) + { + iButtonIndex = index; + } + iExtension->iCurrentCategory = + iButtonArray[index]->iButtonId; + iCharMap->SetStatusChanged(EAknCharChangedCategory); + } + } + } + } + else if (aPointerEvent.iType == TPointerEvent::EDrag) + { + } + else if (aPointerEvent.iType == TPointerEvent::EButton1Up) + { + } + } + else + { + CCoeControl::HandlePointerEventL(aPointerEvent); + } + } + +TSize CAknSctRadioButton::MinimumSize() + { + TAknLayoutRect oneButtonLayRect; + if (!AknLayoutUtils::PenEnabled()) + { + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + // Main pane without softkeys + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Calc the variety + TInt maxVariety = charMapDialogVariety.LastVariety(); + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVariety)); + + // Calculate the size relatively + TRect relativeDialog(TPoint(0,0),popupGridLayRect.Rect().Size()); + + // Get the layout of the actual character grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(relativeDialog, + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + TAknLayoutRect categoryButtonLayRect; + categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_sct_catagory_button_pane()); + + oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(), + AknLayoutScalable_Avkon::cell_sct_catagory_button_pane()); + } + else + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + TAknLayoutRect oneButtonLayRect; + TAknLayoutRect categoryButtonLayRect; + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_control_pane(4)); + + categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_catg_pane(0)); + } + else + { + oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_control_pane(5)); + + categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_catg_pane(1)); + + } + } + + TSize size(oneButtonLayRect.Rect().Width(), + oneButtonLayRect.Rect().Height() * iButtonArray.Count()); + return size; + } + +void CAknSctRadioButton::SizeChanged() + { + TRect base; + if (!AknLayoutUtils::PenEnabled()) + { + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + // Main pane without softkeys + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Calc the variety + TInt maxVariety = charMapDialogVariety.LastVariety(); + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVariety)); + + // Calculate the size relatively + TRect relativeDialog(TPoint(0,0), popupGridLayRect.Rect().Size()); + + // Get the layout of the actual character grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(relativeDialog, + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + TAknLayoutRect categoryButtonLayRect; + categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_sct_catagory_button_pane()); + + TAknLayoutRect oneButtonLayRect; + oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(), + AknLayoutScalable_Avkon::cell_sct_catagory_button_pane()); + + base = oneButtonLayRect.Rect(); + } + else + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + TAknLayoutRect oneButtonLayRect; + TAknLayoutRect categoryButtonLayRect; + if ( !Layout_Meta_Data::IsLandscapeOrientation() ) + { + oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_control_pane(4)); + + categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_catg_pane(0)); + } + else + { + oneButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_control_pane(5)); + + categoryButtonLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic2_catg_pane(1)); + + } + base.iTl = categoryButtonLayRect.Rect().iTl; + base.SetSize(oneButtonLayRect.Rect().Size()); + } + + if (iButtonArray.Count() > 0) + { + CAknButton* buttonCtrlObj; + + TMargins8 margins; + margins.iTop = 1; + margins.iBottom = 0; + margins.iLeft = 0; + margins.iRight = 0; + + // Change the size of buttons + for (TInt index=0; index < iButtonArray.Count(); index++) + { + buttonCtrlObj = iButtonArray[index]->iButtonControl; + if (buttonCtrlObj) + { + if (AknLayoutUtils::PenEnabled()) + { + buttonCtrlObj->SetHighlightRect(base); + } + buttonCtrlObj->SetRect( base ); + buttonCtrlObj->SetIconSize( base.Size() ); + buttonCtrlObj->SetMargins( margins ); + buttonCtrlObj->SetIconScaleMode(EAspectRatioPreserved); + base.Move(TPoint(0, base.Size().iHeight)); + } + } + } + } + +void CAknSctRadioButton::Draw(const TRect& /*aRect*/) const + { + // no draw + } + +/** + * Returns ETrue if the aFlag bitfield in iFlags is set, EFalse if it + * is clear + */ +inline TInt CAknSctRadioButton::Count() const + { + return iButtonArray.Count(); + } + +void CAknSctRadioButton::SetCurrentCategory(TInt aCategory) + { + CAknSctCategoryButton* buttonObj; + TInt status; + + for (TInt index=0; index < iButtonArray.Count(); index++) + { + buttonObj = iButtonArray[index]; + status = (buttonObj->iButtonId == aCategory)? + KAknSctRadioOn : KAknSctRadioOff; + buttonObj->iButtonControl->SetCurrentState(status, ETrue); + } + } + +void CAknSctRadioButton::SetValidSctCase(TInt aSctCase) + { + CAknSctCategoryButton* buttonObj; + + for (TInt index=0; index < iButtonArray.Count(); index++) + { + buttonObj = iButtonArray[index]; + if (buttonObj->iSctCaseId == aSctCase) + { + buttonObj->iValid = ETrue; + break; + } + // Here is the special case for Half-width/Lower/Upper + else if (buttonObj->iSctCaseId == EAknSCTHalfCase + && (aSctCase == EAknSCTLowerCase + || aSctCase == EAknSCTUpperCase) + ) + { + buttonObj->iValid = ETrue; + break; + } + } + } + +void CAknSctRadioButton::RemoveInvalidButton() + { + CAknSctCategoryButton* buttonObj; + + for (TInt index=iButtonArray.Count()-1; index >= 0; index--) + { + buttonObj = iButtonArray[index]; + if (!buttonObj->iValid) + { + if (buttonObj->iSctCaseId == EAknSCTHalfCase) + { + if (iButtonArray.Count() > 1) + { + delete buttonObj; + iButtonArray.Remove(index); + } + } + else + { + delete buttonObj; + iButtonArray.Remove(index); + } + } + } + } + +CCoeControl* CAknSctRadioButton::FocusedControl() + { + return this; + } + +TBool CAknSctRadioButton::EnterControl(TInt /*aX*/, TInt aY) + { + if (IsVisible()) + { + if ((aY >= 0) && (aY < Count())) + { + if (iExtension->iHasCategoryButtonUi) + { + iEntryIndex = aY; + iExtension->iFocusHandler = this; + if (AknLayoutUtils::PenEnabled()) + { + iButtonIndex = aY; + CAknSctCategoryButton* buttonObj = + iButtonArray[iButtonIndex]; + buttonObj->SetFocused(ETrue); + } + return ETrue; + } + } + } + return EFalse; + } + +void CAknSctRadioButton::MoveFocus(TInt /*aX*/, TInt aY) + { + CAknSctCategoryButton* buttonObj; + CAknButton* buttonCtrlObj; + TInt buttonIndex = iButtonIndex + aY; + if (buttonIndex > iButtonArray.Count() - 1) + { + if (!AknLayoutUtils::PenEnabled()) + { + // First radio button. + buttonIndex = 0; + } + else + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + return; + } + } + else + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + return; + } + } + } + } + else if (buttonIndex < 0) + { + if (!AknLayoutUtils::PenEnabled()) + { + // Last radio button. + buttonIndex = iButtonArray.Count() - 1; + } + else + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + return; + } + } + } + + if (!AknLayoutUtils::PenEnabled()) + { + buttonObj = iButtonArray[iButtonIndex]; + buttonCtrlObj = buttonObj->iButtonControl; + buttonCtrlObj->SetCurrentState(KAknSctRadioOff, ETrue); + iButtonIndex = buttonIndex; + buttonObj = iButtonArray[iButtonIndex]; + buttonCtrlObj = buttonObj->iButtonControl; + buttonCtrlObj->SetCurrentState(KAknSctRadioOn, ETrue); + iExtension->iCurrentCategory = + iButtonArray[buttonIndex]->iButtonId; + iCharMap->SetStatusChanged(EAknCharChangedCategory); + } + else + { + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(EFalse); + iButtonIndex = buttonIndex; + buttonObj = iButtonArray[iButtonIndex]; + buttonObj->SetFocused(ETrue); + } + } + +TBool CAknSctRadioButton::LeaveControl() + { + for (TInt i = 0; i < iButtonArray.Count(); i++ ) + { + iButtonArray[i]->SetFocused(EFalse); + } + return ETrue; + } + +TBool CAknSctRadioButton::ExitWithKey(TInt /*aKeycode*/) + { + return EFalse; + } + +// ---------------------------------------------------------------------------- +// Extension class implementation +// ---------------------------------------------------------------------------- +// +CAknCharMapExtension::CAknCharMapExtension() : iSmileyModel(this) +,iSingleClickEnabled( iAvkonAppUi->IsSingleClickCompatible() ) + { + iObserver = NULL; + iPictographsBuffer = FeatureManager::FeatureSupported(KFeatureIdJapanesePicto); + iPictographsBufferGrouping = FeatureManager::FeatureSupported(KFeatureIdJapanesePictographsGrouping); + iKineticScrolling = CAknPhysics::FeatureEnabled(); + + TRAP_IGNORE(iSmileyModel.LoadResourceL()); + } + +TTypeUid::Ptr CAknCharMapExtension::MopSupplyObject(TTypeUid aId) + { + return MAknsControlContext::SupplyMopObject(aId, iBgContext ); + } + +MObjectProvider* CAknCharMapExtension::MopNext() + { + return iCharMap; + } + +CAknCharMapExtension::~CAknCharMapExtension() + { + delete iCharsSmiley; + delete iCharsQwerty; + delete iBgContext; + + delete iRadioButton; + delete iTitleBuf; + + delete iPageNavi; + delete iTableNavi; + delete iCategoryTitle; + delete iCategoryEntry; + delete iEntryBuf; + } + +void CAknCharMapExtension::SetCharMapControl(CAknCharMap* aCtrl) + { + iCharMapProxy = aCtrl; + } + +MAknSctFocusHandler* CAknCharMapExtension::FocusHandler() + { + return iFocusHandler; + } + +CCoeControl* CAknCharMapExtension::FocusedControl() + { + return iCharMapProxy; + } + +TBool CAknCharMapExtension::EnterControl(TInt aX, TInt aY) + { + if(iCharMapProxy->EnterControl(aX, aY)) + { + iFocusHandler = this; + iCharMapProxy->HandleFocusStatusChanged(); + return ETrue; + } + else + { + return EFalse; + } + } + +void CAknCharMapExtension::MoveFocus(TInt aX, TInt aY) + { + iCharMapProxy->TakeFocus(); + TRAP_IGNORE(iCharMapProxy->MoveFocus(aX, aY)); + } + +TBool CAknCharMapExtension::LeaveControl() + { + return iCharMapProxy->LeaveControl(); + } + +TBool CAknCharMapExtension::ExitWithKey(TInt /*aKeycode*/) + { + return ETrue; + } + +void CAknCharMapExtension::ThumbnailLoaded(CSmileyIcon* /*aSmileyIcon*/) + { + iCharMapProxy->DrawDeferred(); + } + +void CAknCharMapExtension::AnimationChanged(CSmileyIcon* /*aSmileyIcon*/) + { + iCharMapProxy->DrawCursor(); + } + +TBool CAknCharMapExtension::IsEmotionEnabled() const + { + return iIsEnableEmotion; + } + +TBool CAknCharMapExtension::IsShowingEmotion() const + { + return iIsShowingEmotion; + } + +TBool CAknCharMapExtension::NeedEmotionSwitchIcon() const + { + // Emotion switch char + TBool needEmotionSwitchIcon = (!AknLayoutUtils::PenEnabled() && IsEmotionEnabled() && !iMenuSct); + return needEmotionSwitchIcon; + } + +HBufC* CAknCharMapExtension::ReadEmotionHBufCL() + { + TInt smileyCount = iSmileyModel.Count(); + HBufC* charsSmiley = HBufC::NewL(smileyCount); + TPtr charsSmileyPtr(charsSmiley->Des()); + for(TInt id(CSmileyModel::EIconSmiley); idReadyToDraw()) + { + TRect iconRect(TPoint(),icon->Size()); + TInt xoffset = (aRect.Width() - iconRect.Width()) / 2; + TInt yoffset = (aRect.Height() - iconRect.Height()) / 2; + + aGc.BitBltMasked(aRect.iTl+TPoint(xoffset,yoffset), icon->Image(), iconRect, icon->Mask(), FALSE); + return ETrue; + } + else + { + return EFalse; + } + } + +const TInt KEmotionAnimationRepeatCount = 30; // 30 times +const TInt KEmotionAnimationDelay = 150*1000; // 0.15s + +void CAknCharMapExtension::HandleFocusStatusChanged(TChar aChar, TBool aIsFocused) + { + CSmileyIcon* lastIcon = EmotionIcon(iLastFocusedSmileyChar); + if(lastIcon) + { + lastIcon->StopAnimation(); + } + + CSmileyIcon* focusedIcon = EmotionIcon(aChar); + if(focusedIcon) + { + if(aIsFocused) + { + if(iHighlightVisible) + { + TRAP_IGNORE(focusedIcon->PlayAnimationL(KEmotionAnimationRepeatCount, KEmotionAnimationDelay)); + } + } + else + { + focusedIcon->StopAnimation(); + } + } + + iLastFocusedSmileyChar = aChar; + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CAknCharMapHistory* CAknCharMapHistory::NewL() + { + CAknCharMapHistory* self = new (ELeave) CAknCharMapHistory; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CAknCharMapHistory::ConstructL() + { + LoadL(); + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::CAknCharMapHistory +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAknCharMapHistory::CAknCharMapHistory() + { + } + +// Destructor +CAknCharMapHistory::~CAknCharMapHistory() + { + ResetArray(); + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::LoadL() +// Load recent characters from file +// ----------------------------------------------------------------------------- +// +TInt CAknCharMapHistory::LoadL() + { + // get the value of recently characters + const TInt length = KHistoryBufferSize * KHistoryBufferCount; + TBuf buf; + + CRepository* repository = CRepository::NewLC(KCRUidAvkon); + TInt err = repository->Get(KAknRecentSctData, buf); // Get KAknRecentSctData value + if (err == KErrNone) + { + if (buf.Length() != length) // buffer is not wanted + { + buf.Fill(KHistoryEmptyChar, length); // set default characters (default=tab character) + err = repository->Set(KAknRecentSctData, buf); // Create KAknRecentSctData key + } + } + CleanupStack::PopAndDestroy(repository); // repository + + // reset arrary + ResetArray(); + + // set recently characters to array + TInt parsePos = 0; + for (TInt i=0; i buf; + + for (TInt i=0; iSet(KAknRecentSctData, buf); + CleanupStack::PopAndDestroy(repository); // repository + + return err; + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::RecentString() +// Get recent data +// ----------------------------------------------------------------------------- +// +const TDesC& CAknCharMapHistory::RecentString(THistoryType aHistoryType, THistoryFilter aHistoryFilter) + { + __ASSERT_ALWAYS((EHistoryTypeFull<=aHistoryType && aHistoryType charBuf; + charBuf.Append(aChar); + aHistoryBuf.Insert(0, charBuf); + } + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknCharMap::LengthOfRecentChar() +// Get the length of the recent charactors. +// ----------------------------------------------------------------------------- +// +TInt CAknCharMap::LengthOfRecentChar() + { + TInt len(0); + if ( iChars != NULL ) + { + for ( TInt index=0; index < iMaxColumns; index++ ) + { + if ( (*iChars)[index] != KHistoryEmptyChar ) + { + len++; + } + else + { + break; + } + } + } + return len; + } + + +EXPORT_C CAknCharMap::CAknCharMap() : iMaxColumns(-1) + { + // Must be created here to get the member variables available + TRAPD(err, iExtension = new (ELeave) CAknCharMapExtension); + iExtension->iCharMap = this; + + if(err) + return; + + iExtension->iFlags = 0x00; + + // if feature language is Japanese + CAknEnv* env = CAknEnv::Static(); + if (env) + { + if (env->IsFeatureLanguage(KFeatureIdJapanese)) + { + iExtension->iJapaneseSctUi = ETrue; + iExtension->iHasCategoryButtonUi = ETrue; + } + } + iExtension->iFocusHandler = iExtension; + iExtension->SetCharMapControl(this); + + if ( iExtension->iSingleClickEnabled ) + { + iExtension->iHighlightVisible = EFalse; + } + + DoLayout(); + + AKNTASHOOK_ADD( this, "CAknCharMap" ); + } + +EXPORT_C CAknCharMap::~CAknCharMap() + { + AKNTASHOOK_REMOVE(); + + delete iCharsBufferFull; + delete iCharsBufferHalf; + delete iCharsBufferLower; + delete iCharsBufferUpper; + delete iCharsBufferNumeric; + delete iPictographsBuffer; + delete iPictographsBuffer2; + + delete iSBFrame; + delete iPictoInterface; + + + delete iTitleDefault; + delete iTitleFull; + delete iTitleHalf; + delete iTitlePicto; + delete iTitlePicto2; + + // menu sct replaces the iChars with on HBufC + if (iExtension->iFlags & EAknCharMapCharsAllocated) // iChars contains HBufC + { // so delete it + delete iChars; + } + + + delete iExtension; + delete iCharMapHistory; + + iSpecialCharCases.Close(); + iSpecialCharPages.Close(); + iPictographCases.Close(); + iPictographPages.Close(); + MTouchFeedback* feedback = MTouchFeedback::Instance(); + feedback->RemoveFeedbackForControl( this ); + } + +void CAknCharMap::DoLayout() + { + TAknTextLineLayout specialCharItemLayout; + if (AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct) + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + specialCharItemLayout = + AknLayoutScalable_Avkon::cell_graphic2_pane_t1(1); + } + else if (IsJapaneseSctUi()) + { + specialCharItemLayout = + AknLayoutScalable_Avkon::cell_graphic2_pane_t1(2); + } + else + { + specialCharItemLayout = + AknLayoutScalable_Avkon::cell_graphic2_pane_t1(0); + } + } + else + { + specialCharItemLayout = + AknLayoutScalable_Avkon::cell_graphic_popup_pane_t2(); + } + iFont = AknLayoutUtils::FontFromId ( specialCharItemLayout.FontId() ); + if (iPictoInterface) + { + __ASSERT_ALWAYS(iFont, Panic(EAknPanicNullPointer)); + iCurrentPictographHeight = EHeight16; + iPictoInterface->Interface()->SelectPictographHeightForFont(*iFont,iCurrentPictographHeight); + } + iIsMirrored = AknLayoutUtils::LayoutMirrored(); + iDrawnBefore = EFalse; + CountMaxColumnsAndCellSizes(); + SizeChanged(); + + // load Emotion icon resource, but not load images + TSize iconSize(iGridItemWidth,iGridItemHeight); + iconSize.iWidth = iconSize.iWidth * 2 / 3; + iconSize.iHeight = iconSize.iHeight * 2 / 3; + Extension()->SetEmotionSize(iconSize); + } + + +EXPORT_C void CAknCharMap::ConstructFromResourceL(TResourceReader& aReader) + { + CEikDialog* dlg; + MopGetObject(dlg); + CEikDialogExtension* dlgExtension = dlg ? dlg->Extension():NULL; + if (dlgExtension) + { + if (CAknEnv::Static()->TransparencyEnabled()) + { + // CAknCharMapDialog doesn't have extension + dlgExtension->iPublicFlags.Set( + CEikDialogExtension::EClipChildControlRect); + } + + if (AknLayoutUtils::PenEnabled()) // for full screen touch ui. + { + dlgExtension->iPublicFlags.Set( + CEikDialogExtension::EUseVirtualInput); + } + else + { + dlgExtension->iPublicFlags.Clear( + CEikDialogExtension::EUseVirtualInput); + } + } + + // Special character set. + ReadCharSetFromResourceL(aReader); + + // Pictograph character set. + TBool offscreen = EFalse; + if ( iExtension->iPictographsBuffer ) + { + CreatePictoCharL(); + offscreen = ETrue; + } + + SetCharacterCaseL(EAknSCTLowerCase); + + // Recent character set. + if (!iCharMapHistory) + { + iCharMapHistory = CAknCharMapHistory::NewL(); + AppendRecentCharL(); + } + + // Touch support. + if (AknLayoutUtils::PenEnabled()) + { + if ( DrawableWindow() ) + { + EnableDragEvents(); + SetGloballyCapturing(ETrue); + SetPointerCapture(ETrue); + } + } + + // Alternate components. + if (AknLayoutUtils::PenEnabled()) + { + if (iExtension->iHasCategoryButtonUi) + { + EnableCategoryInputFieldL(); + EnableCategoryButtonsL(); + } + EnableNavigationButtonsL(); + } + else + { + if (iExtension->iHasCategoryButtonUi) + { + EnableCategoryButtonsL(); + } + } + + // Offscreen background. + if (offscreen) + { + CreateOffscreenBackgroundL(); + } + + iExtension->iBgContext = + CAknsFrameBackgroundControlContext::NewL(KAknsIIDQsnFrPopup, TRect(0,0,1,1), TRect(0,0,1,1), EFalse); + } + + +EXPORT_C TInt CAknCharMap::HeightInRows() + { + return (iShowCasesRef->Count()>1 ? iMaxColumns+1 : iRows); + } + +EXPORT_C void CAknCharMap::SetEmotionModeL(TAknCharMapEmotionMode aEmotionMode) + { + TBool isCurrentEnable = iExtension->iIsEnableEmotion; + + switch(aEmotionMode) + { + case EAknCharMapEmotionUse: + iExtension->iIsShowingEmotion = EFalse; + iExtension->iIsEnableEmotion = ETrue; + break; + + case EAknCharMapEmotionFirst: + iExtension->iIsShowingEmotion = ETrue; + iExtension->iIsEnableEmotion = ETrue; + break; + + default: + iExtension->iIsShowingEmotion = EFalse; + iExtension->iIsEnableEmotion = EFalse; + break; + } + + if(isCurrentEnable!=iExtension->iIsEnableEmotion && iExtension->NeedEmotionSwitchIcon()) + { + DisableRecentCharsRow(); + AppendRecentCharL(); + SetCharacterCaseL(iSpecialCharCase); + } + } + +EXPORT_C void CAknCharMap::SetCharacterCaseL(TInt aCharCase) + { + __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidResourceData)); + + // PictoMode + if(aCharCase & EAknCharMapPictoNoUse) + { + SetPictoMode(EAknCharMapPictoNoUse); + } + else if(aCharCase & EAknCharMapPictoFirst) + { + SetPictoMode(EAknCharMapPictoFirst); + } + + // EmotionMode + if(aCharCase & EAknCharMapEmotionNoUse) + { + SetEmotionModeL(EAknCharMapEmotionNoUse); + } + else if(aCharCase & EAknCharMapEmotionUse) + { + SetEmotionModeL(EAknCharMapEmotionUse); + } + else if(aCharCase & EAknCharMapEmotionFirst) + { + SetEmotionModeL(EAknCharMapEmotionFirst); + } + + // do set character case + iSpecialCharCase = aCharCase & KCharMapCaseMask; + + if (iChaMapTableCase != EAknCharMapTableSpecialChar) + { + if (iCaseIndex == 1) + { + iChars = iPictographsBuffer2; + } + else + { + iChars = iPictographsBuffer; + } + iShowCasesRef = &iPictographCases; + iShowPagesRef = &iPictographPages; + } + else + { + iShowCasesRef = &iSpecialCharCases; + iShowPagesRef = &iSpecialCharPages; + + // default + iSpecialCharCase = EAknSCTLowerCase; + iChars = iCharsBufferLower; + + if(iExtension->iCharsSmiley && iExtension->IsShowingEmotion()) + { + iChars = iExtension->iCharsSmiley; + } + else if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase) + { + iChars = iCharsBufferUpper; + } + else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric) + { + iChars = iCharsBufferNumeric; + } + else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase) + { + iChars = iCharsBufferFull; + } + else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase) + { + iChars = iCharsBufferHalf; + } + else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty) + { + iChars = iExtension->iCharsQwerty; + } + } + + // calculate page count for all pages + iSpecialCharPages.Reset(); // reset the current page count for different charsets + TRAP_IGNORE( + { + iSpecialCharPages.AppendL( PageCountFromChars(*iChars) ); + for (TInt i(1); i < iSpecialCharCases.Count(); ++i) + { + HBufC* chars = CharsFromCase(iSpecialCharCases[i]); + if (chars) + { + iSpecialCharPages.AppendL( PageCountFromChars(*chars) ); + } + } + } ); + + __ASSERT_ALWAYS( iChars && iChars->Length()>0, Panic(EAknPanicInvalidResourceData)); + + iRows = ((iChars->Length() - 1) / iMaxColumns ) + 1 ; + iFirstVisibleRow = 0; + iAnimated = EFalse; + iCursorPos = TPoint(0, 0); + + if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar && !Extension()->iMenuSct) ) + { + iCursorPos = TPoint(0, 1); + } + + iExtension->iCurrentCategory = Category(); + if (iExtension->iRadioButton) + { + iExtension->iRadioButton->SetCurrentCategory(iExtension->iCurrentCategory); + } + + // Create and set the scb visible even though there is nothing to scroll + delete iSBFrame; + iSBFrame=NULL; + + if ( !AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct ) // No scrollbars in use. + { + iSBFrame=new(ELeave) CEikScrollBarFrame(this, NULL, ETrue); + iSBFrame->CreateDoubleSpanScrollBarsL(EFalse, EFalse, ETrue, EFalse); // non-window owning scrollbar + iSBFrame->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto); + iSBFrame->VerticalScrollBar()->SetMopParent(iExtension); + UpdateScrollIndicatorL(); + } + + iExtension->LoadEmotionTumbnails(*iChars); + + CAknSctPageNavi* pageNavi = Extension()->iPageNavi; + if(pageNavi) + { + pageNavi->MakeVisible(PageCount()>1); + } + + HandleFocusStatusChanged(); + + } + +EXPORT_C void CAknCharMap::SetBuffer(TDes& aSpecialChars) + { + iFetcherCharsBuffer = &aSpecialChars; + } + +void CAknCharMap::ReadCharSetFromResourceL(TResourceReader& aReader) + { + __ASSERT_DEBUG(iExtension, Panic(EAknPanicInvalidResourceData)); + + iChars = NULL; + + delete iCharsBufferHalf; + iCharsBufferHalf = NULL; + delete iCharsBufferFull; + iCharsBufferFull = NULL; + delete iCharsBufferLower; + iCharsBufferLower = NULL; + delete iCharsBufferUpper; + iCharsBufferUpper = NULL; + delete iCharsBufferNumeric; + iCharsBufferNumeric = NULL; + delete iExtension->iCharsQwerty; + iExtension->iCharsQwerty = NULL; + delete iExtension->iCharsSmiley; + iExtension->iCharsSmiley = NULL; + + TInt component_count=aReader.ReadInt16(); + for (TInt ii=0;iiiCharsQwerty = aReader.ReadHBufCL(); + break; + default: + break; + } + } + + iExtension->iCharsSmiley = iExtension->ReadEmotionHBufCL(); + + // EFalse is set to iSetRecentSct variable when setting special + // characters from resouce. + iSetRecentSct = EFalse; + } + + +void CAknCharMap::ReadAndAddCharSetFromResourceL(TResourceReader& aReader) + { + ReadCharSetFromResourceL( aReader ); + + // Add recent used characters + if ( iCharMapHistory ) + { + delete iCharMapHistory; + iCharMapHistory = NULL; + } + iCharMapHistory = CAknCharMapHistory::NewL(); + AppendRecentCharL(); + } + +EXPORT_C TSize CAknCharMap::MinimumSize() + { + TRect rect; + if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct) + { + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = charMapDialogVariety.LastVariety(); + + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; + TInt varietyOffset = maxVariety + 1; + + if(Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; + } + + if(location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if(location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; + } + + TInt varietyNumber = varietyOffset - iRows; + + if(varietyNumber < 0) + { + varietyNumber = 0; + } + else if(iRows<=0) + { + varietyNumber -= 1; + } + + varietyNumber += maxVarietyOffset; + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect( mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + rect = gridWithScrollLayRect.Rect(); + } + else + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + rect = popupGridLayRect.Rect(); + } + + return rect.Size(); + } + + +// This method is needed to set correct initial value to scroll indicator. +EXPORT_C void CAknCharMap::ActivateL() + { + CCoeControl::ActivateL(); + if (iRows > iExtension->iMaxVisibleRows) + { + UpdateScrollIndicatorL(); + } + } + + +EXPORT_C TKeyResponse CAknCharMap::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aModifiers) + { + // Other key events. + if (iExtension->iFocusHandler->FocusedControl() != this) + { + return iExtension->iFocusHandler->FocusedControl()->OfferKeyEventL(aKeyEvent, aModifiers); + } + + // Grid key events. + if( ((*iChars)[0] == KHistoryEmptyChar) && + ((*iChars)[iChars->Length()-1] == KHistoryEmptyChar)) + { + return EKeyWasConsumed; + } + + TUint code=aKeyEvent.iCode; + + // First key event enables the highlight + if ( iExtension->iSingleClickEnabled && !iExtension->iHighlightVisible ) + { + if ( code == EKeyUpArrow || code == EKeyDownArrow || + code == EKeyLeftArrow || code == EKeyRightArrow || + code == EKeyEnter ) + { + iExtension->iHighlightVisible = ETrue; + iCursorPos = TPoint( 0, 0 ); + DrawCursor(); + HandleFocusStatusChanged(); + return EKeyWasConsumed; + } + } + + switch (code) + { + case EKeyLeftArrow: + case '4': + { + if (iExtension->iRadioButton && (iCursorPos.iX == 0)) // Radio button. + { + if (iExtension->iRadioButton->EnterControl(iCursorPos.iX,iCursorPos.iY)) + { + LeaveControl(); + break; + } + } + + if (AknLayoutUtils::PenEnabled()) + { + if (!iIsMirrored) + { + if ((iCursorPos.iX == 0) && (iCursorPos.iY == ColMin(0))) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Last table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(TableCount() - 1,0)) + { + LeaveControl(); + break; + } + } + else + { + // Right page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + break; + } + } + } + } + else + { + if (((iCursorPos.iY == ColMax(0)) && (iCursorPos.iX == RowMax(ColMax(0))))) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + else + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + } + } + } + MoveFocus(-1,0); + break; + } + case EKeyRightArrow: + case '6': + { + if (iExtension->iRadioButton && + (iCursorPos.iX == RowMax(iCursorPos.iY)) && + (iCursorPos.iY <= (iExtension->iRadioButton->Count() - 2))) + { + // Radio button. + if (iExtension->iRadioButton->EnterControl(iCursorPos.iX,iCursorPos.iY+1)) + { + LeaveControl(); + break; + } + } + if (AknLayoutUtils::PenEnabled()) + { + if (!iIsMirrored) + { + if ((iCursorPos.iY == ColMax(0)) && + (iCursorPos.iX == RowMax(ColMax(0)))) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + else + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + } + } + else + { + if ((iCursorPos.iY == ColMin(0)) && + (iCursorPos.iX == 0)) + { + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + // First table button. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + + } + else + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + break; + } + } + } + } + } + MoveFocus(1,0); + break; + } + case EKeyUpArrow: + case '2': + { + if (AknLayoutUtils::PenEnabled()) + { + if (iCursorPos.iY == ColMin(iCursorPos.iX)) + { + if (!iExtension->iRadioButton && iCursorPos.iX < TableCount()) + { + // Table button up. + if ( iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(iCursorPos.iX,0)) + { + LeaveControl(); + break; + } + } + else + { + if (iCursorPos.iX == MaxCols() - 1) + { + // Right page button. + if ( iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + break; + } + } + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + if ((!iExtension->iRadioButton && + (iCursorPos.iX == TableCount())) || + ((iExtension->iRadioButton) && + (iCursorPos.iX == MaxCols()-2))) + { + // Left page button. + if ( iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + } + // Grid bottom row. + if (ColMax(0) > ColMax(iCursorPos.iX)) + { + EnterControl(RowMax(ColMax(0)), ColMax(0)); + break; + } + EnterControl(iCursorPos.iX, ColMax( iCursorPos.iX)); + break; + } + } + } + MoveFocus(0,-1); + break; + } + case EKeyDownArrow: + case '8': + { + if (AknLayoutUtils::PenEnabled()) + { + if (iCursorPos.iY == ColMax(iCursorPos.iX)) + { + if (iCursorPos.iX > RowMax(ColMax(0))) + { + // Grid last item. + EnterControl(RowMax(ColMax(0)), ColMax(0)); + break; + } + if ((iCursorPos.iX == MaxCols() - 1) || + (!Layout_Meta_Data::IsLandscapeOrientation() && + iExtension->iRadioButton && + (iCursorPos.iX == MaxCols() - 2))) + { + // Right page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(1,0)) + { + LeaveControl(); + break; + } + } + if ((Layout_Meta_Data::IsLandscapeOrientation() && + !iExtension->iRadioButton && + (iCursorPos.iX == TableCount())) || + (!Layout_Meta_Data::IsLandscapeOrientation() && + (iCursorPos.iX == 0)) || + (Layout_Meta_Data::IsLandscapeOrientation() && + iExtension->iRadioButton && + (iCursorPos.iX == MaxCols() - 2))) + { + // Left page button. + if (iExtension->iPageNavi && + iExtension->iPageNavi->EnterControl(0,0)) + { + LeaveControl(); + break; + } + } + if (!iExtension->iRadioButton && + iCursorPos.iX < TableCount()) + { + // Table button down. + if (iExtension->iTableNavi && + iExtension->iTableNavi->EnterControl(iCursorPos.iX,0)) + { + LeaveControl(); + break; + } + } + // Grid top row. + EnterControl(iCursorPos.iX, ColMin(iCursorPos.iX)); + break; + } + } + MoveFocus(0,1); + break; + } + case '5': + case EKeySpace: + { + AppendFocusSctToDestinationBufferL(); + } + break; + case EKeyEnter: + case EKeyOK: + if(!Extension()->iKeyOkEvent) + { + if(AppendFocusSctToDestinationBufferL()) + { + Extension()->iKeyOkEvent = ETrue; + } + else + { + return EKeyWasNotConsumed; + } + } + break; + default: + return EKeyWasNotConsumed; + + } + return EKeyWasConsumed; + } + +EXPORT_C TCoeInputCapabilities CAknCharMap::InputCapabilities() const + { + return TCoeInputCapabilities(TCoeInputCapabilities::EAllText); + } + +/** +* Control position of this control is registered for skin library when necessary +* in CEikDialogPage::SetDataPosition, so we do not do that in this method. +*/ +EXPORT_C void CAknCharMap::SizeChanged() + { + + if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct) + { + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = charMapDialogVariety.LastVariety(); + + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; + TInt varietyOffset = maxVariety + 1; + if(Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; + } + if(location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if(location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; + } + + TInt varietyNumber = varietyOffset - iRows; + if(varietyNumber < 0) + { + varietyNumber = 0; + } + else if(iRows<=0) + { + varietyNumber -= 1; + } + varietyNumber += maxVarietyOffset; + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + TRect relativePopup(TPoint(0,0), popupGridLayRect.Rect().Size()); + + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(relativePopup, AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + TAknLayoutRect gridLayRect; + if (iExtension->iHasCategoryButtonUi) + { + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), AknLayoutScalable_Avkon::grid_graphic_popup_pane(2)); + } + else + { + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), AknLayoutScalable_Avkon::grid_graphic_popup_pane(0)); + } + + // Grid. + TRect contentRect = Extension()->iMenuSct ? Rect() : gridLayRect.Rect(); + if ( Extension()->iMenuSct ) + { + contentRect.iBr.iY -= (contentRect.Height() - Rect().Height()); + } + iOffset.iY = contentRect.iTl.iY + 1; + iGridTopLeft.iY = contentRect.iTl.iY; + if ( iIsMirrored ) + { + iOffset.iX = contentRect.iBr.iX - iGridItemWidth + 1; + iGridTopLeft.iX = contentRect.iBr.iX - iGridItemWidth; + } + else + { + iOffset.iX = contentRect.iTl.iX + 1; + iGridTopLeft.iX = contentRect.iTl.iX; + } + + // Category buttons. + if (iExtension && iExtension->iHasCategoryButtonUi) + { + if (iExtension->iRadioButton) + { + TAknLayoutRect categoryButtonLayRect; + categoryButtonLayRect.LayoutRect(gridWithScrollLayRect.Rect(),AknLayoutScalable_Avkon::grid_sct_catagory_button_pane()); + + TAknLayoutRect oneButtonLayRect; + oneButtonLayRect.LayoutRect(categoryButtonLayRect.Rect(),AknLayoutScalable_Avkon::cell_sct_catagory_button_pane()); + + TSize size(oneButtonLayRect.Rect().Width(), oneButtonLayRect.Rect().Height()*iExtension->iRadioButton->Count()); + TRect rectRadio(categoryButtonLayRect.Rect().iTl, size); + iExtension->iRadioButton->SetRect(rectRadio); + } + } + + + // Background context. + if(iExtension && iExtension->iBgContext) + { + TInt varietyNumber = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; + TAknLayoutRect innerRect; + innerRect.LayoutRect(relativePopup, AknLayoutScalable_Avkon::bg_popup_window_pane_g1(varietyNumber)); + iExtension->iBgContext->SetFrameRects( relativePopup, innerRect.Rect() ); + } + + TRAP_IGNORE( UpdateScrollIndicatorL() ); + } + else + { + + TInt variety; + if (!IsJapaneseSctUi()) + { + variety = Layout_Meta_Data::IsLandscapeOrientation() ? 3 : 1; + if(TableCount() > 1) variety--; + } + else + { + variety = Layout_Meta_Data::IsLandscapeOrientation() ? 5 : 4; + } + + // Popup. + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + TRect popupGridRect = popupGridLayRect.Rect(); + + // Grid. + TAknLayoutRect gridLayRect; + gridLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_pane(variety)); + TRect gridRect = gridLayRect.Rect(); + + iOffset.iY = gridRect.iTl.iY + 1; + iGridTopLeft.iY = gridRect.iTl.iY; + if ( iIsMirrored ) + { + iOffset.iX = gridRect.iBr.iX - iGridItemWidth + 1; + iGridTopLeft.iX = gridRect.iBr.iX - iGridItemWidth; + } + else + { + iOffset.iX = gridRect.iTl.iX + 1; + iGridTopLeft.iX = gridRect.iTl.iX; + } + + // Category + if (iExtension->iHasCategoryButtonUi && iExtension->iRadioButton) // Radio buttons. + { + TAknLayoutRect oneButtonLayRect; + TAknLayoutRect categoryButtonLayRect; + TInt oneButtonLayVariety, categoryButtonLayVariety; + + if (Layout_Meta_Data::IsLandscapeOrientation()) + { + oneButtonLayVariety = 5; + categoryButtonLayVariety = 1; + } + else + { + oneButtonLayVariety = 4; + categoryButtonLayVariety = 0; + } + + oneButtonLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_control_pane(oneButtonLayVariety)); + categoryButtonLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_catg_pane(categoryButtonLayVariety)); + + TSize size(oneButtonLayRect.Rect().Width(), + oneButtonLayRect.Rect().Height() * iExtension->iRadioButton->Count()); + TRect rectRadio(categoryButtonLayRect.Rect().iTl, size); + iExtension->iRadioButton->SetRect(rectRadio); + } + + // Table navigation. + if (iExtension->iTableNavi) + { + TAknLayoutRect tableNaviLayRect; + tableNaviLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::grid_graphic2_control_pane(variety)); + iExtension->iTableNavi->SetRect(tableNaviLayRect.Rect()); + } + + // Page navigation. + if (iExtension->iPageNavi) + { + if (PageCount() > 1) + { + iExtension->iPageNavi->MakeVisible(ETrue); + + TAknLayoutRect pageNaviLayRect; + pageNaviLayRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::graphic2_pages_pane(variety)); + iExtension->iPageNavi->SetRect(pageNaviLayRect.Rect()); + } + else + { + iExtension->iPageNavi->MakeVisible(EFalse); + } + } + + // Background context. + if(iExtension->iBgContext) + { + TAknLayoutRect innerRect; + innerRect.LayoutRect(popupGridRect, AknLayoutScalable_Avkon::bg_popup_window_pane_cp21(variety)); + + TRect relativePopupRect(TPoint(0,0), popupGridRect.Size()); + iExtension->iBgContext->SetFrameRects(relativePopupRect,innerRect.Rect()); + } + + } + } + +EXPORT_C void CAknCharMap::HandleResourceChange(TInt aType) + { + TRAP_IGNORE(DoHandleResourceChangeL(aType)); + CCoeControl::HandleResourceChange(aType); + } + +void CAknCharMap::DoHandleResourceChangeL(TInt aType) + { + if (aType == KEikDynamicLayoutVariantSwitch) + { + TInt cursorIndexBeforeSwitch = (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns + iCursorPos.iX; + TInt recentLengthBeforeSwitch = iMaxColumns; + TBool recentWasSetBeforeSwitch = iSetRecentSct; + + // Disabled because the buffer content may change due to diffent layout. + if (recentWasSetBeforeSwitch) DisableRecentCharsRow(); + + // Calculate the new magnitudes (iMaxColumns, etc.). + DoLayout(); + + // Append right amount of recent characters due to different layout. + if (recentWasSetBeforeSwitch) AppendRecentCharL(); + + // Sets the character case because the buffer content may have changed. + SetCharacterCaseL(iSpecialCharCase); + + // status after layout switch. + TInt recentLengthAfterSwitch = iMaxColumns; // recentLength has changed after switch + TInt cursorIndexAfterSwitch; + if(cursorIndexBeforeSwitch < recentLengthBeforeSwitch) + { + cursorIndexAfterSwitch = cursorIndexBeforeSwitch; + } + else + { + cursorIndexAfterSwitch = cursorIndexBeforeSwitch - recentLengthBeforeSwitch + recentLengthAfterSwitch; + } + + // the new first row is the top row on the page where the new focus is. + TInt pageVolume = iMaxColumns * iExtension->iMaxVisibleRows; + iFirstVisibleRow = (cursorIndexAfterSwitch / pageVolume * pageVolume) / iMaxColumns; + + // the cursor positions are relative to current page + TInt cursorIndexAfterSwitchInPage = cursorIndexAfterSwitch - (iMaxColumns * iFirstVisibleRow); + iCursorPos.iX = cursorIndexAfterSwitchInPage % iMaxColumns; + iCursorPos.iY = cursorIndexAfterSwitchInPage / iMaxColumns; + + iOldCursorPos = iCursorPos; + + // for full screen touch UI. + CEikDialog* dlg; + MopGetObject(dlg); + CEikDialogExtension* dlgExtension = dlg ? dlg->Extension() : NULL; + if (dlgExtension) + { + if (AknLayoutUtils::PenEnabled()) + { + dlgExtension->iPublicFlags.Set(CEikDialogExtension::EUseVirtualInput); + } + else + { + dlgExtension->iPublicFlags.Clear(CEikDialogExtension::EUseVirtualInput); + } + } + + // Sets alternate UI controls. + if (iExtension->iHasCategoryButtonUi) + { + if (AknLayoutUtils::PenEnabled()) + { + EnableCategoryInputFieldL(); + EnableNavigationButtonsL(); + } + else + { + DisableCategoryInputFieldL(); + DisableNavigationButtonsL(); + } + EnableCategoryButtonsL(); + } + else + { + DisableCategoryInputFieldL(); + DisableCategoryButtonsL(); + if (AknLayoutUtils::PenEnabled()) + { + EnableNavigationButtonsL(); + } + else + { + DisableNavigationButtonsL(); + } + } + + // and finally updates the page counts (from setcasetable) + iSpecialCharPages.Reset(); // reset the current page count for different charsets + iSpecialCharPages.AppendL( PageCountFromChars(*iChars) ); + for (TInt i(1); i < iSpecialCharCases.Count(); ++i) + { + HBufC* chars = CharsFromCase(iSpecialCharCases[i]); + if (chars) iSpecialCharPages.AppendL( PageCountFromChars(*chars) ); + } + + if (iExtension->iPictographsBuffer && iPictoInterface) + { + __ASSERT_ALWAYS(iPictoInterface->Interface(), Panic(EAknPanicNullPointer)); + iPictographPages.Reset(); + iPictographCases.Reset(); + iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer) ); + iPictographCases.AppendL(EAknCharMapTablePicto); + if (iExtension->iPictographsBufferGrouping) + { + iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer2) ); + iPictographCases.AppendL( EAknCharMapTablePicto2 ); + } + } + + UpdateScrollIndicatorL(); + RefreshNaviPageL(); + + // create the background again as the background size has changed + // !resize an option but the cost only differs with the creation of the graphic objects! + CreateOffscreenBackgroundL(); + iOffscreenBgDrawn = EFalse; + } + + else if ( aType == KAknsMessageSkinChange ) + { + iOffscreenBgDrawn = EFalse; + } + else if ( aType == KAknMessageFocusLost && iExtension->iHighlightVisible ) + { + iExtension->iHighlightVisible = EFalse; + DrawCursor(); + } + } + +void CAknCharMap::EnableNavigationButtonsL() + { + if ( iExtension ) + { + if ( !iExtension->iTableNavi ) + { + iExtension->iTableNavi = new(ELeave) CAknSctTableNavi(this, iExtension); + iExtension->iTableNavi->SetContainerWindowL(*this); + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_TABLE_NAVI_CONTROL); + iExtension->iTableNavi->ConstructFromResourceL(reader); + iExtension->iTableNavi->SetNonFocusing(); + iExtension->iTableNavi->SetMopParent(iExtension); + CleanupStack::PopAndDestroy(); // reader + } + + iExtension->iTableNavi->MakeVisible(ETrue); + + if ( !iExtension->iPageNavi ) + { + iExtension->iPageNavi = new(ELeave) CAknSctPageNavi(this, iExtension); + iExtension->iPageNavi->SetContainerWindowL(*this); + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_PAGE_NAVI_CONTROL); + iExtension->iPageNavi->ConstructFromResourceL(reader); + iExtension->iPageNavi->SetNonFocusing(); + iExtension->iPageNavi->SetMopParent(iExtension); + CleanupStack::PopAndDestroy(); // reader + } + + iExtension->iPageNavi->MakeVisible(ETrue); + } + } + +void CAknCharMap::DisableNavigationButtonsL() + { + if ( iExtension && iExtension->iTableNavi ) + { + iExtension->iTableNavi->MakeVisible( EFalse ); + } + if ( iExtension && iExtension->iPageNavi ) + { + iExtension->iPageNavi->MakeVisible( EFalse ); + } + } + +void CAknCharMap::EnableCategoryButtonsL() + { + if (!iExtension->iRadioButton) + { + iExtension->iRadioButton = new(ELeave) CAknSctRadioButton(this, iExtension); + iExtension->iRadioButton->SetContainerWindowL(*this); + TResourceReader reader; + iCoeEnv->CreateResourceReaderLC(reader, R_AVKON_SCT_CATEGORY_BUTTON_CONTROL); + iExtension->iRadioButton->ConstructFromResourceL(reader); + iExtension->iRadioButton->SetNonFocusing(); + iExtension->iRadioButton->SetMopParent(iExtension); + CleanupStack::PopAndDestroy(); // reader + } + iExtension->iRadioButton->MakeVisible(ETrue); + } + +void CAknCharMap::DisableCategoryButtonsL() + { + if (iExtension && iExtension->iRadioButton) + { + iExtension->iRadioButton->MakeVisible(EFalse); + } + } + +void CAknCharMap::EnableCategoryInputFieldL() + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + // Enable title field. + if (!iExtension->iCategoryTitle) + { + iExtension->iCategoryTitle = new(ELeave) CEikLabel; + iExtension->iCategoryTitle->SetContainerWindowL(*this); + iExtension->iCategoryTitle->SetTextL(KNullDesC()); + } + Extension()->iCategoryTitle->SetBrushStyle(CGraphicsContext::ENullBrush); + TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; + AknLayoutUtils::LayoutLabel(iExtension->iCategoryTitle, popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window_t1(variety)); + TAknLayoutText titleLayRect; + titleLayRect.LayoutText(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window_t1(variety).LayoutLine()); + TRgb color = titleLayRect.Color(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if( skin ) + { + (void)AknsUtils::GetCachedColor(skin, color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6); + } + TRAP_IGNORE(AknLayoutUtils::OverrideControlColorL(*(iExtension->iCategoryTitle), + EColorLabelText, color)); + if (iExtension->iPictographsBuffer && iPictoInterface) + { + iExtension->iCategoryTitle->EnablePictographsL(*iPictoInterface); + } + iExtension->iCategoryTitle->MakeVisible(ETrue); + + + // Enable entry field. + if (!iExtension->iCategoryEntry) + { + iExtension->iCategoryEntry = new(ELeave) CEikLabel; + iExtension->iCategoryEntry->SetContainerWindowL(*this); + iExtension->iCategoryEntry->SetTextL(KNullDesC()); + } + Extension()->iCategoryEntry->SetBrushStyle(CGraphicsContext::ENullBrush); + AknLayoutUtils::LayoutLabel(iExtension->iCategoryEntry, popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety)); + TAknLayoutText entryLayRect; + entryLayRect.LayoutText(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety).LayoutLine()); + color = entryLayRect.Color(); + if( skin ) + { + (void)AknsUtils::GetCachedColor(skin, color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6); + } + TRAP_IGNORE( AknLayoutUtils::OverrideControlColorL(*(iExtension->iCategoryEntry), + EColorLabelText, color)); + if (iExtension->iPictographsBuffer && iPictoInterface) + { + iExtension->iCategoryEntry->EnablePictographsL(*iPictoInterface); + } + iExtension->iCategoryEntry->MakeVisible(ETrue); + + UpdateInputFieldL(); + } + +void CAknCharMap::DisableCategoryInputFieldL() + { + if (iExtension->iCategoryTitle) + { + iExtension->iCategoryTitle->MakeVisible(EFalse); + } + + if (iExtension->iCategoryEntry) + { + iExtension->iCategoryEntry->MakeVisible(EFalse); + } + } + + +void CAknCharMap::Draw(const TRect& /*aRect*/) const + { + TInt cursorPos = 0; + + CWindowGc& gc=SystemGc(); + gc.UseFont(iFont); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( this ); + + TRect rect = Rect(); + + if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct) + { + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = charMapDialogVariety.LastVariety(); + + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; + TInt varietyOffset = maxVariety + 1; + + if(Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; + } + + if(location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if(location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows; + + if(varietyNumber < 0) + { + varietyNumber = 0; + } + else if(iRows<=0) + { + varietyNumber -= 1; + } + varietyNumber += maxVarietyOffset; + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + // Background height. + TInt backgroundHeightOffset = + popupGridLayRect.Rect().Height() - rect.iBr.iY; + + rect.iBr.iY += backgroundHeightOffset; + } + else + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + // Background height. + TInt backgroundHeightOffset = + popupGridLayRect.Rect().Height() - rect.iBr.iY; + + rect.iBr.iY += backgroundHeightOffset * 2; + } + + // Grid (main). + if ( !Extension()->iMenuSct ) + { + // 1) Draw the background + + // Check if we got an offscreen bitmap allocated for skin background and + // there is bitmap background in the current skin. + if( CAknEnv::Static()->TransparencyEnabled() ) + { + TRegionFix<10> clipReg; + clipReg.AddRect(rect); + if ( iFirstVisibleRow == 0 && iSetRecentSct ) + { + TPoint pos = iGridTopLeft; + TInt endX = pos.iX + iGridItemWidth * iMaxColumns + 1; + TInt endY = pos.iY + iGridItemHeight; + // eliminate the overlap area between menu sct and the first menu item. + if ( Extension()->iMenuSct ) + { + endY--; + } + clipReg.SubRect( TRect( pos, TPoint( endX, endY ) ) ); + } + // Take scroll bar out of clip region + if (iSBFrame) + { + clipReg.SubRect(iSBFrame->GetScrollBarHandle( + CEikScrollBar::EVertical)->Rect()); + } + gc.SetClippingRegion(clipReg); + } + AknsDrawUtils::Background( skin, cc, this, gc, rect,KAknsDrawParamNoClearUnderImage); + if( CAknEnv::Static()->TransparencyEnabled() ) + { + gc.CancelClippingRegion(); + } + + gc.SetPenStyle(CGraphicsContext::ESolidPen); + gc.SetBrushStyle(CGraphicsContext::ENullBrush); + gc.SetPenSize(TSize(1,1)); + + // 2) Draw the grid + DrawGrid(gc); + } + + // Grid (recent). + if (iFirstVisibleRow==0 && iSetRecentSct) + { + DrawRecentCharFrame(gc); + } + + // Cell items. + TInt charIndex = iFirstVisibleRow * iMaxColumns; + cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + TInt numberOfChars = NumberOfVisibleChars(); + TBool highlighted = EFalse; + for (TInt j = 0; j < numberOfChars; j++) + { + + // emotions in next line are all ready to draw + if((j%iMaxColumns) == 0) + { + if(!EmotionsAreAllReadyToDraw(charIndex, iMaxColumns)) break; + } + + // grid is focused and cursor pos is same with the current index. + if ( iExtension->iMenuSct ) + { + highlighted = iExtension->iMenuSctHighlighted && + (iExtension->iFocusHandler->FocusedControl()==this) && + (j==cursorPos); + } + else + { + highlighted = ((iExtension->iFocusHandler->FocusedControl()==this) && (j==cursorPos)); + } + DrawItem(gc, CursorRect(j, charIndex), charIndex, highlighted, EFalse); + charIndex++; + } + iDrawnBefore = ETrue; + gc.DiscardFont(); + } + +//-------------------------------------------------------------- +// Return how many chars to be drawn +//-------------------------------------------------------------- +// +TInt CAknCharMap::NumberOfVisibleChars() const + { + TInt numberOfCharsToBeDrawn = iChars->Length(); + numberOfCharsToBeDrawn -= (iFirstVisibleRow * iMaxColumns); + if ( numberOfCharsToBeDrawn > (iExtension->iMaxVisibleRows * iMaxColumns)) + { + numberOfCharsToBeDrawn = iExtension->iMaxVisibleRows * iMaxColumns; + } + __ASSERT_DEBUG( numberOfCharsToBeDrawn >= 1, Panic(EAknPanicOutOfRange)); + + if(Extension()->iMenuSct) + { + return Min(iExtension->iMaxVisibleRows * iMaxColumns, iChars->Length()); + } + return numberOfCharsToBeDrawn; + } + +/** +* +* Local method to return the RTL mirrored character for the (LTR) input character +* +* The method has buffers ready to accept surrogate pairs when they become supported in the +* descriptor methods. +* +* The return buffer is padded with extra characters that in theory may arise in bidirectional +* conversion, but since only one character is input, no leading "zero width joiner" will be +* at index 0. Hence, the resulting character at 0 is returned, with no check for the zero width +* joiner. +*/ +TChar MirrorChar(TChar a) + { + TBuf<2> buf; // ready for when surrogate pairs need handling + buf.Append(a); + TBidirectionalState::TRunInfo ri; + TBidiLogicalToVisual bl2v(buf, ETrue, &ri, 1); // Only 1 run info element passed + bl2v.Reorder(); + TBuf<2+TBidiLogicalToVisual::KMinCharAvailable> result; + bl2v.GetVisualLine(result, 0, buf.Length(), 0xFFFF); + // Always use index 0 as this situation can not result in a zero-width joiner at index 0 + return result[0]; // This return is not surrogate pair-ready + } + +//------------------------------------------------------------------------- +// Set the pen, color, brush, etc. before drawing the frame of a special char +// item. +// Note: The frame is inside the cell. +//------------------------------------------------------------------------- +// +void CAknCharMap::SetItemFrameStyle( CWindowGc& aGc) const + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( this ); + TRgb colorFrame = AKN_LAF_COLOR(215); + AknsUtils::GetCachedColor( skin, colorFrame, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 ); + aGc.SetPenColor(colorFrame); + aGc.SetPenSize(TSize(1,1)); + } + +//-------------------------------------------------------------- +// Draw the rect edge lines which are inside the cell and around +// the char. +//-------------------------------------------------------------- +// +void CAknCharMap::DrawItemFrame( CWindowGc& aGc, + const TRect& aItemRect, TInt aCharIndex, + TBool aHighlighted, + TBool /*aDrawBackground*/ ) const + { + SetItemFrameStyle(aGc); + + if(IsRecentChar(aCharIndex)) + { + // recent char hasn't inner frames. + return; + } + if( aHighlighted ) + { + aGc.DrawRect( aItemRect ); + } + } + +//-------------------------------------------------------------- +// brush the background rect inside the cell. +//-------------------------------------------------------------- +// +void CAknCharMap::DrawItemShade( CWindowGc& aGc, + const TRect& aItemRect, TInt /*aCharIndex*/, + TBool aHighlighted, + TBool aDrawBackground ) const + { + + TRect innerRect = aItemRect; + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( this ); + + if( aHighlighted ) + { + TRgb color = AKN_LAF_COLOR(210); + + if( !( iExtension->iFlags & EAknCharMapPressedDown ) + || iExtension->iSingleClickEnabled ) + { + AknsUtils::GetCachedColor( skin, + color, + KAknsIIDQsnHighlightColors, + EAknsCIQsnHighlightColorsCG1 ); + } + + else + { + AknsUtils::GetCachedColor( skin, color, KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG2 ); + } + aGc.SetBrushColor(color); + aGc.Clear( innerRect ); + } + else if( aDrawBackground ) + { + if ( iExtension->iBgContext ) + { + cc = iExtension->iBgContext; + } + AknsDrawUtils::Background( skin, cc, this, aGc, innerRect ); + } + } + +void CAknCharMap::DrawItem( + CWindowGc& aGc, + const TRect& aSctPosition, + TInt aCharIndex, + TBool aHighlighted, + TBool aDrawBackground ) const + { + if (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface) + { + DrawPicto(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground); + return; + } + + if ( iExtension->iSingleClickEnabled && + !iExtension->iHighlightVisible ) + { + aHighlighted = EFalse; + } + + DrawItemShade(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground); + + DrawItemFrame(aGc, aSctPosition, aCharIndex, aHighlighted, aDrawBackground); + + TAknTextLineLayout specialCharItemLayout; + if (AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct) + { + if ( Layout_Meta_Data::IsLandscapeOrientation() ) + { + specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(1); + } + else if (IsJapaneseSctUi()) + { + specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(2); + } + else + { + specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic2_pane_t1(0); + } + } + else + { + specialCharItemLayout = AknLayoutScalable_Avkon::cell_graphic_popup_pane_t2(); + } + + TRect textRect = aSctPosition; + if( IsRecentChar(aCharIndex) ) + { + textRect.Move(0, -1); //because height of recent char frame decreased 1. + if( Extension()->iMenuSct ) + { + textRect.Move(0, -1); //because menu sct will also shrink 1. + } + } + TAknLayoutText textLayout; + textLayout.LayoutText(textRect, specialCharItemLayout); + + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( this ); + + TRgb color; + TBuf<1> symbol; + TChar character = '\t'; + character = (*iChars)[ aCharIndex ]; + + // Is Mirrored language (Arabic or Hebrew) used as input language + TBool mirroredLanguage( + AknTextUtils::CurrentScriptDirectionality() == TBidiText::ERightToLeft); + + // Obtain mirrored forms + if ( mirroredLanguage ) + { + TChar oldCharacter( character ); + character = MirrorChar( oldCharacter ); + } + // Note: the character is now mirrored. The following visual substitution may need to be + // aware of this: + + _LIT(KChar,"%c"); + + // Special cases if needed to use PUA symbols on screen + if ( (character == CEditableText::EParagraphDelimiter) || (character == 0x000A) ) // Line feed + { + if ( mirroredLanguage ) + { + symbol.Format(KChar, KPuaCodeMirroredLineFeedSymbol); // Symbol for mirrored line feed + } + else + { + symbol.Format(KChar, KPuaCodeLineFeedSymbol); // Symbol for line feed + } + } + else if ( character == CEditableText::ESpace ) // Space + { + symbol.Format(KChar, KPuaCodeSpaceSymbol); // Symbol for space + } + else if ( character == 0x3000 ) // Full width Space + { + symbol.Format(KChar, KPuaCodeFullWidthSpaceSymbol); // Symbol for space + } + else if ( character == 0x200E ) // RLM + { + symbol.Format(KChar, KPuaCodeRightToLeftSymbol); // Symbol for RLM + } + else if ( character == 0x200F ) // LRM + { + symbol.Format(KChar, KPuaCodeLeftToRightSymbol); // Symbol for LRM + } + else if ( ( character == 0x0E31 || + 0x0E33 <= character && character <= 0x0E3A) || + (0x0E47 <= character && character <= 0x0E4E) ) // Thai SCT-cases + { + symbol.Format(KChar, TUint(character)+KThaiSCTCombiningSymbolAdd); + } + else if ( character == KHistoryEmptyChar ) + { + symbol.Format(KChar, KHistoryEmptyCharForDisplay); + } + else // Defaul case - show symbol as it is + { + symbol.Format(KChar, static_cast(character)); + } + + if ( aHighlighted ) + { + AknsUtils::GetCachedColor( skin, color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG24 ); + } + else + { + AknsUtils::GetCachedColor( skin, color, + KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG19 ); + } + + if(TEmotionUtils::IsEmotionChar(symbol[0])) + { + iExtension->DrawEmotion(aGc, textLayout.TextRect(), symbol[0]); + } + else + { + textLayout.DrawText( aGc, symbol, EFalse, color ); + } + + } + + +//------------------------------------------------------- +// Set the color, pen, style for drawing recent char map +// frame +//------------------------------------------------------- +// +void CAknCharMap::SetRecentCharFrameStyle( CWindowGc& aGc) const + { + TRgb colorRecentLine = AKN_LAF_COLOR(215); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + AknsUtils::GetCachedColor( skin, colorRecentLine, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 ); + aGc.SetPenColor(colorRecentLine); + aGc.SetPenSize(TSize(2,2)); + } + +//------------------------------------------------------- +// Draw the outter thick frame for the all recent chars. +//------------------------------------------------------- +// +void CAknCharMap::DrawRecentCharFrame( CWindowGc& aGc) const + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = iExtension->iBgContext; + if ( !cc ) + { + cc = AknsDrawUtils::ControlContext( this ); + } + + TPoint pos = iGridTopLeft; + TInt endX = pos.iX + iGridItemWidth * iMaxColumns + 1; + TInt endY = pos.iY + iGridItemHeight; + TRect drawRect(TPoint(pos.iX, pos.iY), TPoint(endX, endY)); + // eliminate the overlap area between menu sct and the first menu item. + if ( Extension()->iMenuSct ) + { + drawRect = Rect(); + endY--; + } + + AknsDrawUtils::Background( skin, cc, this, aGc, drawRect ); + + SetRecentCharFrameStyle(aGc); + if(iIsMirrored) + { + pos.iX = iGridTopLeft.iX - ((iMaxColumns - 1) * iGridItemWidth); + endX = iGridTopLeft.iX + iGridItemWidth + 1; + } + + aGc.DrawRect( TRect(TPoint(pos.iX-1, pos.iY-1), TPoint(endX, endY))); + + MTouchFeedback* feedback = MTouchFeedback::Instance(); + CFeedbackSpec* spec = CFeedbackSpec::New(); + + if ( spec && feedback ) + { + CAknCharMap* mutableThis = MUTABLE_CAST( CAknCharMap* ,this ); + TInt recentChars = mutableThis->LengthOfRecentChar(); + TRect rect; + spec->AddFeedback( ETouchEventStylusDown, + ETouchFeedbackList ); + rect.SetRect( pos, TPoint( pos.iX + recentChars * iGridItemWidth, pos.iY + iGridItemHeight )); + if ( iIsMirrored ) + { + TInt emptyRecentSlots = iMaxColumns - recentChars; + rect.Move( emptyRecentSlots * iGridItemWidth, 0 ); + } + feedback->SetFeedbackArea( this, KAreaIdRecent, rect, spec ); + + delete spec; + } + } + +//------------------------------------------------------- +// Set the pen, color, brush, etc. to draw the char map +// grid +//------------------------------------------------------- +// +void CAknCharMap::SetGridStyle( CWindowGc& aGc) const + { + TRgb colorLine = AKN_LAF_COLOR(219); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + AknsUtils::GetCachedColor( skin, colorLine, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG5 ); + aGc.SetPenColor(colorLine); + aGc.SetPenSize(TSize(1,1)); + } + +//------------------------------------------------------- +// draw the char map grid +// Note: only draw the grid, do not draw the recent char +// map frame. +//------------------------------------------------------- +// +void CAknCharMap::DrawGrid( CWindowGc& aGc) const + { + SetGridStyle(aGc); + + // + // a better method: (0~MaxChars) do:[:each| each drawRect.] + // + const TSize gridItemRectSize( iGridItemWidth + 1, iGridItemHeight + 1); + TInt numberOfCells = NumberOfVisibleChars(); + TPoint pos = iGridTopLeft; + TInt ii=0; + if (iFirstVisibleRow == 0 && iSetRecentSct) + { + pos.iY += iGridItemHeight; //skip the recent char area + ii=iMaxColumns; + } + else + { + // remove area for recent characters because they does not exist in this view + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->RemoveFeedbackArea( this, KAreaIdRecent ); + } + } + for(; ii < numberOfCells; ++ii) + { + aGc.DrawRect(TRect( pos, gridItemRectSize )); + + if ( iIsMirrored ) + { + pos.iX -= iGridItemWidth; + } + else + { + pos.iX += iGridItemWidth; + } + + if( (ii+1) % iMaxColumns == 0 ) + { + pos.iX = iGridTopLeft.iX; //reset for each row. + pos.iY += iGridItemHeight; + } + } + MTouchFeedback* feedback = MTouchFeedback::Instance(); + CFeedbackSpec* spec = CFeedbackSpec::New(); + + if ( feedback && spec ) + { + TInt orphans = NumberOfVisibleChars() % iMaxColumns; + TInt rows = NumberOfVisibleChars() / iMaxColumns; + CAknCharMap* mutableThis = MUTABLE_CAST( CAknCharMap* ,this ); + TInt recentChars = mutableThis->LengthOfRecentChar(); + TRect rectMain; + TPoint nextTopLeft = iGridTopLeft; + + if ( CurrentPage() == 1 ) + { + nextTopLeft.iY += iGridItemHeight; + if ( rows > 0 ) + rows--; + } + + rectMain.SetRect( nextTopLeft, TPoint(nextTopLeft.iX + iMaxColumns * iGridItemWidth, nextTopLeft.iY + rows * iGridItemHeight) ); + if ( iIsMirrored ) + { + rectMain.Move( ( 1 - iMaxColumns ) * iGridItemWidth, 0 ); + } + + spec->AddFeedback( ETouchEventStylusDown, + ETouchFeedbackList ); + if ( rows ) + { + feedback->SetFeedbackArea( this, KAreaIdMain, rectMain, spec ); + } + else + { + feedback->RemoveFeedbackArea( this, KAreaIdMain ); + } + + nextTopLeft.iY = rectMain.iBr.iY; + + if ( orphans ) + { + TRect rectOrphans; + rectOrphans.SetRect( TPoint( iGridTopLeft.iX, pos.iY), TPoint( iGridTopLeft.iX + orphans * iGridItemWidth, pos.iY + iGridItemHeight) ); + if ( iIsMirrored ) + { + rectOrphans.Move( ( 1 - orphans ) * iGridItemWidth, 0 ); + } + + feedback->SetFeedbackArea( this, KAreaIdTail, rectOrphans, spec ); + } + else + { + // remove feedback area for tail area because all rows of grid has maximum number of characters + feedback->RemoveFeedbackArea( this, KAreaIdTail ); + } + + delete spec; + } + } + +// Optimizes drawing. Only cursor is drawn. +void CAknCharMap::DrawCursor() const + { + // Whole SCT has to be drawn at least once. + // If the user presses arrow key before SCT has been drawn, + // only cursor position is drawn without this check. + if ( !iDrawnBefore ) + { + DrawNow(); + } + else + { + CWindowGc& gc = SystemGc(); + // Only redraw old and new cursor position cells + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + ActivateGc(); + gc.UseFont(iFont); + } + + TInt cursorPos = 0; + if ( iOldCursorPos != iCursorPos ) + { + // Redraw only if old pos different from current pos + cursorPos = iOldCursorPos.iX + iOldCursorPos.iY * iMaxColumns; + DrawCell( cursorPos, EFalse ); + } + + cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( cursorPos, (iExtension->iFocusHandler->FocusedControl()==this) ); + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::DrawCell +// ----------------------------------------------------------------------------- +// +void CAknCharMap::DrawCell( + TInt aCursorPos, + TBool aHighLighted ) const + { + // calculate character index + TInt charIndex = aCursorPos + iFirstVisibleRow * iMaxColumns; + if(charIndex >= iChars->Length()) + { + return; + } + + // If we are only redrawing for animations, no need to draw non-animated items. + if (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface) + { + if ( iAnimated && + !iPictoInterface->Interface()->IsAnimated((*iChars)[charIndex],iCurrentPictographHeight) ) + { + return; + } + } + + TRect rect = CursorRect( aCursorPos, charIndex ); + + if( CAknEnv::Static()->TransparencyEnabled() ) + { + + const TBool backedUp = IsBackedUp(); + if ( !backedUp ) + { + Window().Invalidate( rect ); + Window().BeginRedraw( rect ); + } + + ActivateGc(); + CWindowGc& gc = SystemGc(); + gc.UseFont(iFont); + + DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue ); + + gc.DiscardFont(); + DeactivateGc(); + + if ( !backedUp ) + { + Window().EndRedraw(); + } + } + else + { + if ( !Extension()->iMenuSct ) + { + Window().Invalidate( rect ); + Window().BeginRedraw( rect ); + DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue ); + Window().EndRedraw(); + } + else + { + DrawItem( SystemGc(), rect, charIndex, aHighLighted, ETrue ); + } + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::CursorRect +// ----------------------------------------------------------------------------- +// +TRect CAknCharMap::CursorRect( TInt aCursorPos, TInt aCharIndex) const + { + TPoint pos = iOffset; + + if (iIsMirrored) + { + pos.iX -= (aCursorPos % iMaxColumns) * iGridItemWidth; + } + else // Not mirrored + { + pos.iX += (aCursorPos % iMaxColumns) * iGridItemWidth; + } + + pos.iY += (aCursorPos / iMaxColumns) * iGridItemHeight; + TRect res = TRect( pos, TSize( iGridItemWidth - 2, iGridItemHeight - 2 ) ); + if(IsRecentChar(aCharIndex)) + { + res.iBr.iY --; //because the width of recent char frame is 2 but not 1. + } + // Eliminate the overlap between menu sct and the first menu option' item + if ( Extension()->iMenuSct ) + { + res.iBr.iY --; + } + return res; + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::MoveCursorL +// ----------------------------------------------------------------------------- +// +void CAknCharMap::MoveCursorL(TInt aDeltaX, TInt aDeltaY) + { + __ASSERT_DEBUG( + (aDeltaX <= 1) && (aDeltaX >= -1) && + (aDeltaY <= 1) && (aDeltaY >= -1) && + ((aDeltaX * aDeltaY) == 0), Panic(EAknPanicOutOfRange)); + + if (iIsMirrored) + aDeltaX = -aDeltaX; + + iOldCursorPos = iCursorPos; + TInt oldFirstVisibleRow = iFirstVisibleRow; + + TInt globalYPos = iCursorPos.iY + iFirstVisibleRow; + TInt lastColumnOnLastRow(0); + if ( Extension()->iMenuSct ) + { + lastColumnOnLastRow = LengthOfRecentChar() - 1; + } + else + { + lastColumnOnLastRow = (iChars->Length() - 1) % iMaxColumns; + } + + TInt checktable(-1); + TInt skipchar = aDeltaX != 0 ? 1: 0; + TBool caseChange(EFalse); + + // First line is NULL when Cursor was second line + if ( (iCursorPos.iY+iFirstVisibleRow == 1) && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar) ) + ) + { + caseChange = ETrue; + // Cursor was on the second line + if (aDeltaY < 0) + { + globalYPos--; + } + // Cursor was on the second line and first position + if (aDeltaX < 0 && iCursorPos.iX == 0) + { + globalYPos--; + //iCursorPos.iY = 0; + iCursorPos.iX = 0; + } + } + else + { + TInt delta = aDeltaX != 0 ? aDeltaX: aDeltaY; + TInt next = aDeltaX != 0 ? aDeltaX: 0; + TInt charIndex = iCursorPos.iX + + (iCursorPos.iY + aDeltaY + iFirstVisibleRow) * iMaxColumns; //the x index includes the current row + + for(TInt i(0); i <= iMaxColumns; ++i) + { + if (aDeltaY < 0 && charIndex < 0) + { + charIndex = 0; + caseChange = ETrue; // prev case + } + if (aDeltaY > 0 && iChars->Length() <= charIndex) // index 0 length 1 etc. + { + // set Position(iCursorPos.iX, 0) + charIndex = iChars->Length() - 1;//iCursorPos.iX; + i = charIndex; + caseChange = ETrue; // next case + } + if (aDeltaX < 0 && charIndex <= 0) + { + charIndex = iChars->Length() - 1; + caseChange = ETrue; // prev case + } + if (aDeltaX > 0 && iChars->Length() - 1 <= charIndex) + { + charIndex = 0; + caseChange = ETrue; // next case + } + if (caseChange && iShowCasesRef->Count() > 1) + { + // change case + break; + } + if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[charIndex+next])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[charIndex+next]!=KHistoryEmptyChar) ) + { + break; + } + charIndex += delta; + skipchar++; + } + } + + if (aDeltaX < 0) + { + // Cursor was moved to left. + if (iCursorPos.iX > skipchar - 1) + { + iCursorPos.iX -= skipchar; + } + else + { + if (skipchar > iMaxColumns) + { + globalYPos--; + iCursorPos.iX = iMaxColumns; + } + // Go to previous line + globalYPos--; + if (globalYPos < 0) + { + // Cursor was on the first line - go to last line. + globalYPos = iRows - 1; + // x - position to the last item on the last row. + iCursorPos.iX = lastColumnOnLastRow; + checktable = iMaxColumns; + } + else + { + // x - position to last column. + iCursorPos.iX = iMaxColumns - skipchar; + } + } + } + + if (aDeltaX > 0) + { + // Cursor was moved to right. + if (globalYPos < iRows - 1) + { + // Not in the last row. + if (iCursorPos.iX < iMaxColumns - skipchar) + { + // If not on the last columns, move cursor to next column. + iCursorPos.iX += skipchar; + } + else + { + // Cursor was on last column, + // move to first column of the next line. + iCursorPos.iX = 0; + globalYPos++; + } + } + else + { + // Currently on the last row. + if ( iCursorPos.iX < lastColumnOnLastRow ) + { + // If there are more items on this row, move cursor to next item. + iCursorPos.iX++; + } + else + { + // No more item on the current row. + // Move to first item on the first row. + iCursorPos.iX = 0; + checktable = 0; + globalYPos = 0; + } + } + } + + if (aDeltaY < 0) + { + iCursorPos.iX -= skipchar; + if (iCursorPos.iX < 0) + { + iCursorPos.iX += (iMaxColumns - 1); + globalYPos--; + } + // Cursor was moved to up. + if (globalYPos > 0) + { + // Cursor was not on the first line - move it to previous row. + globalYPos--; + } + else + { + checktable = iCursorPos.iX; + // Move cursot to last to row. + globalYPos = iRows - 1; + if (iCursorPos.iX > lastColumnOnLastRow) + { + // No items in the current column on the last row - + // move cursor to last item on the row. + iCursorPos.iX = lastColumnOnLastRow; + } + } + } + + if (aDeltaY > 0) + { + iCursorPos.iX = (iCursorPos.iX + skipchar) % iMaxColumns; + globalYPos += (iCursorPos.iX + skipchar) / iMaxColumns; + // Cursor was moved to down. + if (globalYPos < iRows - 1) + { + // Cursor is not on the last row. Move cursor to next row. + globalYPos++; + if (globalYPos == iRows - 1 && iCursorPos.iX > lastColumnOnLastRow) + { + // No items in the current column on the last row - + // move cursor to last item on the row. + iCursorPos.iX = lastColumnOnLastRow; + } + } + else + { + // Cursor was at the last row - move it to the first row. + globalYPos = 0; + checktable = iCursorPos.iX; + } + } + iCursorPos.iY = globalYPos - iFirstVisibleRow; + + if (globalYPos < iFirstVisibleRow) + { + // Cursor was moved from the top row. + if (globalYPos <= 0) + { + iFirstVisibleRow = 0; + iCursorPos = TPoint(iCursorPos.iX, 0); + } + else + { + // If cursor was moved up out of the visible area - show it again. + iFirstVisibleRow -= iExtension->iMaxVisibleRows; + iCursorPos = TPoint(iCursorPos.iX, iExtension->iMaxVisibleRows - 1); + } + } + + if (globalYPos > iFirstVisibleRow + iExtension->iMaxVisibleRows - 1) + { + if (globalYPos == iRows - 1) + { + // When cursor has moved from the top line, + // it is adjusted to a page boundary. + iFirstVisibleRow = VisibleRows(); + iCursorPos = TPoint( + iCursorPos.iX, + (iRows - 1) % iExtension->iMaxVisibleRows + ); + } + else + { + // If cursor was moved down out of the visible area - show it again. + iFirstVisibleRow += iExtension->iMaxVisibleRows; + iCursorPos = TPoint(iCursorPos.iX, 0); + } + } + + TInt increment(1); + if (aDeltaY < 0 || aDeltaX < 0) + { + increment = -1; + } + if (checktable >= 0 && SwitchAnotherTableL(increment) > 0) + { + TInt lastColumnOnLastRow = ((iChars->Length() - 1) % iMaxColumns); + TPoint pt(checktable, 0); + if (aDeltaY < 0 || aDeltaX < 0) + { + iFirstVisibleRow = + ((*iShowPagesRef)[iCaseIndex] - 1) * iExtension->iMaxVisibleRows; + pt.iX = Min(pt.iX, lastColumnOnLastRow); + pt.iY = iRows - 1; + if (iRows > iExtension->iMaxVisibleRows) + { + pt.iY -= (((iRows-1) / iExtension->iMaxVisibleRows) * iExtension->iMaxVisibleRows); + } + + } + else if (iRows == 1) + { + pt.iX = Min(pt.iX, lastColumnOnLastRow); + } + else if (caseChange) + { + // When first line is NULL, cursor is moved to the second line + TInt index = pt.iX + (pt.iY + iFirstVisibleRow) * iMaxColumns; + for (; index >= 0 ; index--) + { + if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[index])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[index] != KHistoryEmptyChar) ) + { + break; + } + } + if (index < 0) + { + pt.iY = 1; + } + else + { + pt.iX = index; + } + } + + HandleFocusStatusChanged(); + + iCursorPos = pt; + UpdateScrollIndicatorL(); + DrawNow(); + } + else + { + if (caseChange) + { + TPoint pt(iCursorPos); + // When first line is NULL, cursor is moved to the second line + TInt index = pt.iX + (pt.iY + iFirstVisibleRow) * iMaxColumns; + for (; index >= 0 ; index--) + { + if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && iPictoInterface->Interface()->IsPictograph((*iChars)[index])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[index]!=KHistoryEmptyChar) ) + { + break; + } + } + if (index < 0) + { + pt.iY = 1; + } + else + { + pt.iX = (index % iMaxColumns); + } + iCursorPos = pt; + } + + if ((iRows > iExtension->iMaxVisibleRows) && + (iOldCursorPos.iY + oldFirstVisibleRow != iCursorPos.iY + iFirstVisibleRow)) + { + UpdateScrollIndicatorL(); + } + + HandleFocusStatusChanged(); + + if (oldFirstVisibleRow == iFirstVisibleRow) + { + // Draw only cursor if the view to the content was not scrolled. + DrawCursor(); + } + else + { + DrawNow(); + } + } + } + +void CAknCharMap::UpdateScrollIndicatorL() + { + if ( !iSBFrame ) + { + return; + } + TEikScrollBarModel hSbarModel; + TEikScrollBarModel vSbarModel; + + TEikScrollBarFrameLayout layout; + + // Main pane without softkeys + TRect mainPaneRect; + if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EPopupParent, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + // Dialog layout, check variety first + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = charMapDialogVariety.LastVariety(); + + // Check the CBA, if the orientation is not landscape + // there is not so much varieties + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; // the offset for the certain cba location variety + TInt varietyOffset = maxVariety + 1; + + // landscape variety number must be calculated offset == number of varieties + // same applies to the variety number for the biggest sized layout for the variety + if(Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1)/KAknSctCBaButtonDirections; // the offset for one variety + } + + // for right and left cba buttons the max variety is not zero + // the varities are ordered by the location of the cba and the descending order + // e.g the biggest sized layout first, the smallest last + if(location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if(location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; // 2* + } + + TInt varietyNumber = varietyOffset - iRows; + + // if more lines than possible to show, use the default + // (the biggest grid) variety + if(varietyNumber < 0) + varietyNumber = 0; + // if zero rows, use the minimum + else if(iRows<=0) + varietyNumber -= 1; + + //add the varietyoffset + varietyNumber += maxVarietyOffset; + + // Layout the dialog size + TAknLayoutRect dialogLayRect; + dialogLayRect.LayoutRect( mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(varietyNumber)); + + TRect dialogRect = dialogLayRect.Rect(); + + // Get the layout of the actual character grid with scrollbar + TAknLayoutRect gridWithScrollLayRect; + + gridWithScrollLayRect.LayoutRect(TRect(TPoint(0,0),TSize(dialogRect.Size())), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + // Calculate the relative rect for the grid + TRect parent = gridWithScrollLayRect.Rect(); + + TAknWindowComponentLayout scrollbarLayout; + if (iExtension->iHasCategoryButtonUi) + { + scrollbarLayout = AknLayoutScalable_Avkon::scroll_pane_cp5(1); + } + else + { + scrollbarLayout = AknLayoutScalable_Avkon::scroll_pane_cp5(0); + } + + vSbarModel.iScrollSpan = PageCount() * iExtension->iMaxVisibleRows; + vSbarModel.iThumbSpan = iExtension->iMaxVisibleRows; + + if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan) + { + // For EDoubleSpan type scrollbar + vSbarModel.iThumbPosition = (CurrentPage()-1) * iExtension->iMaxVisibleRows; + TAknDoubleSpanScrollBarModel hDsSbarModel(hSbarModel); + TAknDoubleSpanScrollBarModel vDsSbarModel(vSbarModel); + + iSBFrame->Tile(&vDsSbarModel); + AknLayoutUtils::LayoutVerticalScrollBar(iSBFrame, parent, + scrollbarLayout); + iSBFrame->SetVFocusPosToThumbPos(vDsSbarModel.FocusPosition()); + } + else + { + // For EArrowHead type scrollbar + vSbarModel.iThumbPosition = iCursorPos.iY + iFirstVisibleRow; + iSBFrame->TileL(&hSbarModel,&vSbarModel,parent,parent,layout); + iSBFrame->SetVFocusPosToThumbPos(vSbarModel.iThumbPosition); + } + } + +void CAknCharMap::Reserved_1() + { + } + +void CAknCharMap::Reserved_2() + { + } + +const TDesC* CAknCharMap::LowerCaseCharacters() const + { + return iCharsBufferLower; + } + +const TDesC* CAknCharMap::UpperCaseCharacters() const + { + return iCharsBufferUpper; + } + +const TDesC* CAknCharMap::NumericCharacters() const + { + return iCharsBufferNumeric; + } + +void CAknCharMap::CopyCharactersL( const CAknCharMap& aCharMap ) + { + const TDesC* chars = aCharMap.LowerCaseCharacters(); + if ( chars ) + { + delete iCharsBufferLower; + iCharsBufferLower = NULL; + if (Extension()->iMenuSct) + { + iCharsBufferLower = chars->Mid(iMaxColumns).AllocL(); + } + else + { + iCharsBufferLower = chars->AllocL(); + } + } + + chars = aCharMap.UpperCaseCharacters(); + if ( chars ) + { + delete iCharsBufferUpper; + iCharsBufferUpper = NULL; + if (Extension()->iMenuSct) + { + iCharsBufferUpper = chars->Mid(iMaxColumns).AllocL(); + } + else + { + iCharsBufferUpper = chars->AllocL(); + } + } + + chars = aCharMap.NumericCharacters(); + if ( chars ) + { + delete iCharsBufferNumeric; + iCharsBufferNumeric = NULL; + if (Extension()->iMenuSct) + { + iCharsBufferNumeric = chars->Mid(iMaxColumns).AllocL(); + } + else + { + iCharsBufferNumeric = chars->AllocL(); + } + } + + chars = NULL; + if (aCharMap.iExtension) + { + chars = aCharMap.iExtension->iCharsQwerty; + } + if ( chars ) + { + delete iExtension->iCharsQwerty; + iExtension->iCharsQwerty = NULL; + if (Extension()->iMenuSct) + { + iExtension->iCharsQwerty = chars->Mid(iMaxColumns).AllocL(); + } + else + { + iExtension->iCharsQwerty = chars->AllocL(); + } + } + } + +void CAknCharMap::DrawPictographArea() + { + if (iChaMapTableCase != EAknCharMapTableSpecialChar) + { + CWindowGc& gc = SystemGc(); + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + ActivateGc(); + gc.UseFont( iFont ); + } + + // Calculate the number of items. + TInt numberOfCharsToBeDrawn = iChars->Length(); + numberOfCharsToBeDrawn -= (iFirstVisibleRow * iMaxColumns); + if ( numberOfCharsToBeDrawn > (iExtension->iMaxVisibleRows * iMaxColumns)) + { + numberOfCharsToBeDrawn = iExtension->iMaxVisibleRows * iMaxColumns; + } + __ASSERT_DEBUG( numberOfCharsToBeDrawn >= 1, Panic(EAknPanicOutOfRange)); + + // Draw all items. Implementation takes care that only animated + // items are actually redrawn. + + iAnimated = ETrue; + + TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + + for (TInt j = 0; j < numberOfCharsToBeDrawn; j++) + { + DrawCell( j, j == cursorPos ); + } + + iAnimated = EFalse; + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + } + } + +TInt CAknCharMap::PageCount() const + { + TInt page(0); + for (TInt i(0); i < iShowCasesRef->Count(); ++i) + { + page += (*iShowPagesRef)[i]; + } + + return page; + } + +TInt CAknCharMap::CurrentPage() const + { + TInt page(0); + for (TInt i(0); i < iCaseIndex; ++i) + { + page += (*iShowPagesRef)[i]; + } + + return ((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) + 1 + page; + } + + +TBool CAknCharMap::HasPictoInterface() const + { + return (iPictoInterface != NULL); + } + +TBool CAknCharMap::SwitchTablesL(TBool& aLayoutChanged) + { + aLayoutChanged = EFalse; + + TBool result(EFalse); + + if (iPictoInterface) + { + TInt oldVisibleRows = Min(iRows, iExtension->iMaxVisibleRows); + + iChaMapTableCase = (iChaMapTableCase!=EAknCharMapTableSpecialChar) ? EAknCharMapTableSpecialChar : EAknCharMapTablePicto; + iCaseIndex = 0; + + // In case picto, char case must be kept same as previous value. + TInt charcase = (iChaMapTableCase==EAknCharMapTableSpecialChar) ? iSpecialCharCases[iCaseIndex] : iSpecialCharCase; + SetCharacterCaseL(charcase); + + TInt visibleRows = Min(iRows, iExtension->iMaxVisibleRows); + + // Return also information whether the layout changed or not. + aLayoutChanged = (oldVisibleRows != visibleRows); + + if (!AknLayoutUtils::PenEnabled()) + { + UpdateScrollIndicatorL(); + } + else + { + UpdateInputFieldL(); + } + + if (aLayoutChanged) + { + // If the number of the visible row is changed, + // it is necessary to re-create the background. + CreateOffscreenBackgroundL(); + } + + result = ETrue; + } + else + { + result = SwitchSctAndEmotionL(); + } + + return result; + } + +void CAknCharMap::CreateOffscreenBackgroundL() + { + + } + +TInt CAknCharMap::NextPageL() + { + HandleFocusStatusChanged(EFalse); + + TInt page(0); + iFirstVisibleRow = + (((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) + 1) + * iExtension->iMaxVisibleRows; + if (iFirstVisibleRow > VisibleRows()) + { + iFirstVisibleRow = 0; + + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + + page = SwitchAnotherTableL(1); + } + else + { + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + + } + UpdateHeadingPane( ETrue ); + UpdateScrollIndicatorL(); + HandleFocusStatusChanged(); + DrawNow(); + + return page; + } + +TInt CAknCharMap::PrevPageL() + { + HandleFocusStatusChanged(EFalse); + + TInt page(0); + TInt firstVisibleRow = + (((iCursorPos.iY + iFirstVisibleRow) / iExtension->iMaxVisibleRows) - 1) * + iExtension->iMaxVisibleRows; + if (firstVisibleRow < 0) + { + SwitchAnotherTableL(-1); + iFirstVisibleRow = ((*iShowPagesRef)[iCaseIndex] - 1 ) * iExtension->iMaxVisibleRows; + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + } + else + { + iFirstVisibleRow = firstVisibleRow; + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + } + UpdateHeadingPane( ETrue ); + UpdateScrollIndicatorL(); + HandleFocusStatusChanged(); + DrawNow(); + + return page; + } + +HBufC* CAknCharMap::AppendTextL(HBufC* aChars, HBufC* aText) + { + if (!aChars) + { + return aText; + } + + aChars = aChars->ReAllocL(aChars->Length() + aText->Length()); + aChars->Des().Append(aText->Des()); + delete aText; + + return aChars; + } + +void CAknCharMap::DrawPicto( + CWindowGc& aGc, + const TRect& aSctPosition, + TInt aCharIndex, + TBool aHighlighted, + TBool aDrawBackground ) const + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + + if (aHighlighted) + { + //aGc.SetPenColor(AKN_LAF_COLOR(215)); + TRgb color = AKN_LAF_COLOR(215); + AknsUtils::GetCachedColor( skin, color, + KAknsIIDQsnLineColors, EAknsCIQsnLineColorsCG7 ); + aGc.SetPenColor(color); + if (!IsRecentChar(aCharIndex)) + { + aGc.DrawRect( aSctPosition ); + } + + // Shrink by one pixel in all directions. + TRect innerRect = aSctPosition; + if (!IsRecentChar(aCharIndex)) + { + innerRect.Shrink(1,1); + } + + + color = AKN_LAF_COLOR(210); + AknsUtils::GetCachedColor(skin,color, + KAknsIIDQsnHighlightColors,EAknsCIQsnHighlightColorsCG1); + aGc.SetBrushColor(color); + aGc.Clear( innerRect ); + } + + // Draw the background of the item if requested + else if ( aDrawBackground ) + { + aGc.SetBrushStyle(CGraphicsContext::ESolidBrush); + aGc.SetBrushColor(AKN_LAF_COLOR(0)); + + TRect innerRect = aSctPosition; + if (IsRecentChar(aCharIndex)) + { + innerRect.Shrink(1,1); + } + aGc.Clear( innerRect ); + } + if (iPictoInterface->Interface()->IsPictograph((*iChars)[aCharIndex])) + { + if (iExtension->iPictographsBufferGrouping) + { + TAknPictographDrawingMode drawingMode = + aHighlighted?EDrawingModeWhite:EDrawingModeNormal; + iPictoInterface->Interface()->SetPictographDrawingMode(drawingMode); + } + iPictoInterface->Interface()->DrawPictograph( + aGc, + aSctPosition, + (*iChars)[aCharIndex], + iCurrentPictographHeight ); + } + } + +void CAknCharMap::DrawOffscreenBackgroundIfRequired() const + { + + } + +EXPORT_C CCoeControl* CAknCharMap::ComponentControl(TInt aIndex) const + { + if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan) + { + if ( aIndex == 0 ) + { + return iSBFrame->VerticalScrollBar(); + } + aIndex--; + } + + if (iExtension->iRadioButton) + { + if ( aIndex == 0 ) + { + return iExtension->iRadioButton; + } + aIndex--; + } + + if (iExtension->iCategoryTitle) + { + if ( aIndex == 0 ) + { + return iExtension->iCategoryTitle; + } + aIndex--; + } + if (iExtension->iCategoryEntry) + { + if ( aIndex == 0 ) + { + return iExtension->iCategoryEntry; + } + aIndex--; + } + + if (iExtension->iTableNavi) + { + if ( aIndex == 0 ) + { + return iExtension->iTableNavi; + } + aIndex--; + } + if (iExtension->iPageNavi) + { + if ( aIndex == 0 ) + { + return iExtension->iPageNavi; + } + aIndex--; + } + + return NULL; + } + +EXPORT_C TInt CAknCharMap::CountComponentControls() const + { + TInt num = 0; + if (iSBFrame && iSBFrame->TypeOfVScrollBar() == CEikScrollBarFrame::EDoubleSpan) + { + num++; + } + if (iExtension->iRadioButton) + { + num++; + } + if (iExtension->iCategoryTitle) + { + num++; + } + if (iExtension->iCategoryEntry) + { + num++; + } + if (iExtension->iTableNavi) + { + num++; + } + if (iExtension->iPageNavi) + { + num++; + } + return num; + } + +void CAknCharMap::SetPictoMode(TAknCharMapPictoMode aMode) + { + if (aMode == EAknCharMapPictoNoUse) + { + delete iPictoInterface; + iPictoInterface = NULL; + } + else if (aMode == EAknCharMapPictoFirst) + { + iChaMapTableCase = EAknCharMapTablePicto; + } + } + +void CAknCharMap::SetCaseTableL(const RArray & aCase) + { + + // set current case characters to display on SCT + HBufC* currentcasechars = iCharsBufferLower; + if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase) + currentcasechars = iCharsBufferUpper; + else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric) + currentcasechars = iCharsBufferNumeric; + else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase) + currentcasechars = iCharsBufferFull; + else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase) + currentcasechars = iCharsBufferHalf; + else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty) + currentcasechars = iExtension->iCharsQwerty; + + iSpecialCharPages.AppendL( PageCountFromChars(*currentcasechars) ); + + iSpecialCharCases.AppendL( iSpecialCharCase ); + if (iExtension->iRadioButton) + { + // Set the sct case mode to valid + iExtension->iRadioButton->SetValidSctCase(iSpecialCharCase); + } + + if (aCase.Count() > 0) + { + for (TInt i(0); i < aCase.Count(); ++i) + { + HBufC* chars = CharsFromCase(aCase[i]); + if (chars) + { + iSpecialCharCases.AppendL( aCase[i] ); + iSpecialCharPages.AppendL( PageCountFromChars(*chars) ); + if (iExtension->iRadioButton) + { + // Set the sct case mode to valid + iExtension->iRadioButton->SetValidSctCase(aCase[i]); + } + } + } + } + + if (iExtension->iPictographsBuffer && iPictoInterface) + { + __ASSERT_ALWAYS( + iPictoInterface->Interface(), Panic(EAknPanicNullPointer)); + + iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer) ); + iPictographCases.AppendL(EAknCharMapTablePicto); + if (iExtension->iPictographsBufferGrouping) + { + iPictographPages.AppendL( PageCountFromChars(*iPictographsBuffer2) ); + iPictographCases.AppendL(EAknCharMapTablePicto2); + if (iExtension->iRadioButton) + { + // Set the sct case mode to valid + iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph1); + iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph2); + } + } + else + { + if (iExtension->iRadioButton) + { + // Set the sct case mode to valid + iExtension->iRadioButton->SetValidSctCase(EAknSCTPictograph); + } + } + } + + if (iExtension->iRadioButton) + { + // Remove invalid category buttons + iExtension->iRadioButton->RemoveInvalidButton(); + __ASSERT_DEBUG( iExtension->iRadioButton->Count() > 0, + Panic(EAknPanicInvalidValue)); + } + } + +void CAknCharMap::SetTitleL(TPtrC aTitle) + { + iTitleDefault = HBufC::NewL(aTitle.Length()); + iTitleDefault->Des().Copy(aTitle); + + HBufC* title; + if (iExtension->iPictographsBufferGrouping) + { + title = StringLoader::LoadLC( + R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH1, iCoeEnv); + iTitlePicto = HBufC::NewL(title->Length()); + iTitlePicto->Des().Copy(*title); + CleanupStack::PopAndDestroy(title); // title + + title = StringLoader::LoadLC( + R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH2, iCoeEnv); + iTitlePicto2 = HBufC::NewL(title->Length()); + iTitlePicto2->Des().Copy(*title); + CleanupStack::PopAndDestroy(title); // title + } + else + { + title = StringLoader::LoadLC( + R_AVKON_SPECIAL_CHARACTERS_PICTOGRAPH, iCoeEnv); + iTitlePicto = HBufC::NewL(title->Length()); + iTitlePicto->Des().Copy(*title); + CleanupStack::PopAndDestroy(title); // title + // Picto2 isn't used. + iTitlePicto2 = NULL; + } + + title = StringLoader::LoadLC( + R_AVKON_SPECIAL_CHARACTERS_HALF_SYMBOL, iCoeEnv); + iTitleHalf = HBufC::NewL(title->Length()); + iTitleHalf->Des().Copy(*title); + CleanupStack::PopAndDestroy(); // title + + title = StringLoader::LoadLC( + R_AVKON_SPECIAL_CHARACTERS_FULL_SYMBOL, iCoeEnv); + iTitleFull = HBufC::NewL(title->Length()); + iTitleFull->Des().Copy(*title); + CleanupStack::PopAndDestroy(); // title + } + +const TDesC* CAknCharMap::Title() const + { + HBufC* title = iTitleDefault; + if (iChaMapTableCase == EAknCharMapTableSpecialChar) + { + if (iSpecialCharCase == EAknSCTHalfCase) + { + title = iTitleHalf; + } + if (iSpecialCharCase == EAknSCTFullCase) + { + title = iTitleFull; + } + } + else + { + if (iCaseIndex == 1) + { + title = iTitlePicto2; + } + else + { + title = iTitlePicto; + } + } + return title; + } + +TInt CAknCharMap::SwitchAnotherTableL(TInt aIncrement) + { + TInt page(0); + if (iShowCasesRef->Count() > 1) + { + iCaseIndex += aIncrement; + if (iShowCasesRef->Count() - 1 < iCaseIndex) + { + iCaseIndex = 0; + } + if (iCaseIndex < 0) + { + iCaseIndex = iShowCasesRef->Count() - 1; + } + SetCharacterCaseL((*iShowCasesRef)[iCaseIndex]); + page = PageCount(); + } + return page; + } + +void CAknCharMap::CountMaxColumnsAndCellSizes() + { + TRect mainPaneRect; + if (!AknLayoutUtils::PenEnabled() || Extension()->iMenuSct) + { + if(!AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect)) + { + mainPaneRect = iAvkonAppUi->ClientRect(); + } + + TAknLayoutScalableParameterLimits charMapDialogVariety = + AknLayoutScalable_Avkon::popup_grid_graphic_window_ParamLimits(); + + TInt maxVariety = charMapDialogVariety.LastVariety(); + + AknLayoutUtils::TAknCbaLocation location = AknLayoutUtils::CbaLocation(); + TInt maxVarietyOffset = 0; + TInt varietyOffset = maxVariety + 1; + if(Layout_Meta_Data::IsLandscapeOrientation()) + { + varietyOffset = (maxVariety + 1) / KAknSctCBaButtonDirections; + } + + if(location == AknLayoutUtils::EAknCbaLocationRight) + { + maxVarietyOffset = varietyOffset; + } + else if(location == AknLayoutUtils::EAknCbaLocationLeft) + { + maxVarietyOffset = varietyOffset + varietyOffset; + } + + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(mainPaneRect, + AknLayoutScalable_Avkon::popup_grid_graphic_window(maxVarietyOffset)); + + TAknLayoutRect gridWithScrollLayRect; + gridWithScrollLayRect.LayoutRect(popupGridLayRect.Rect(), + AknLayoutScalable_Avkon::listscroll_popup_graphic_pane()); + + + TAknLayoutRect gridLayRect; + if (iExtension->iHasCategoryButtonUi) + { + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic_popup_pane(2)); + } + else + { + gridLayRect.LayoutRect(gridWithScrollLayRect.Rect(), + AknLayoutScalable_Avkon::grid_graphic_popup_pane(0)); + } + + TRect gridRect = Extension()->iMenuSct ? Rect(): gridLayRect.Rect(); + + TAknLayoutRect firstCellLayRect; + firstCellLayRect.LayoutRect(gridRect, + AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,0,0)); + + TRect firstCellRect; + if ( Extension()->iMenuSct ) + { + firstCellRect = TRect( TPoint(0, 0), + TSize( firstCellLayRect.Rect().Width(), Rect().Height() ) ); + } + else + { + firstCellRect = firstCellLayRect.Rect(); + } + + TAknLayoutRect rightCellLayRect; + rightCellLayRect.LayoutRect(gridRect, + AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,1,0)); + + TInt firstVisibleIndex = iFirstVisibleRow * iMaxColumns; + // Max columns. + iMaxColumns = gridRect.Width() / firstCellRect.Width(); + iFirstVisibleRow = firstVisibleIndex / iMaxColumns; + + // Max visible rows. + iExtension->iMaxVisibleRows = gridRect.Height() / firstCellRect.Height(); + + // Cell width. + iGridItemWidth = + rightCellLayRect.Rect().iTl.iX - firstCellLayRect.Rect().iTl.iX; + if (iGridItemWidth < 0) + { + iGridItemWidth = -iGridItemWidth; + } + + // Cell height. + if ( Extension()->iMenuSct ) + { + iGridItemHeight = firstCellRect.Height(); + } + else + { + TAknLayoutRect downCellLayRect; + downCellLayRect.LayoutRect(gridRect, + AknLayoutScalable_Avkon::cell_graphic_popup_pane_cp2(0,0,1)); + iGridItemHeight = + downCellLayRect.Rect().iTl.iY - firstCellLayRect.Rect().iTl.iY; + } + } + else + { + TAknLayoutRect popupGridLayRect; + popupGridLayRect.LayoutRect(iAvkonAppUi->ApplicationRect(), + AknLayoutScalable_Avkon::popup_grid_graphic2_window(0)); + + TRect popupGridRect = popupGridLayRect.Rect(); + + TInt gridVariety; + if (!IsJapaneseSctUi()) + { + if(!Layout_Meta_Data::IsLandscapeOrientation()) + { + gridVariety = (TableCount() > 1) ? 0 : 1; + } + else + { + gridVariety = (TableCount() > 1) ? 2 : 3; + } + } + else + { + gridVariety = !Layout_Meta_Data::IsLandscapeOrientation() ? 4 : 5; + } + + TAknLayoutRect gridLayRect; + gridLayRect.LayoutRect(popupGridRect, + AknLayoutScalable_Avkon::grid_graphic2_pane(gridVariety)); + + TRect gridRect = gridLayRect.Rect(); + + TAknLayoutRect firstCellLayRect; + firstCellLayRect.LayoutRect(popupGridRect, + AknLayoutScalable_Avkon::aid_size_cell_graphic2(gridVariety,0,0)); + + TRect firstCellRect = firstCellLayRect.Rect(); + TInt firstVisibleIndex = iFirstVisibleRow * iMaxColumns; + + // Max columns. + iMaxColumns = gridRect.Width() / firstCellRect.Width(); + iFirstVisibleRow = firstVisibleIndex / iMaxColumns; + + // Max visible rows. + iExtension->iMaxVisibleRows = gridRect.Height() / firstCellRect.Height(); + + // Cell width. + iGridItemWidth = firstCellRect.Width(); + + // Cell height. + iGridItemHeight = firstCellRect.Height(); + } + } + +HBufC* CAknCharMap::CharsFromCase(TInt aCharCase) const + { + __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidValue)); + + HBufC* chars = NULL; + switch (aCharCase) + { + case EAknSCTLowerCase: + chars = iCharsBufferLower; + break; + case EAknSCTUpperCase: + chars = iCharsBufferUpper; + break; + case EAknSCTNumeric: + chars = iCharsBufferNumeric; + break; + case EAknSCTFullCase: + chars = iCharsBufferFull; + break; + case EAknSCTHalfCase: + chars = iCharsBufferHalf; + break; + case EAknSCTQwerty: + chars = iExtension->iCharsQwerty; + break; + default: + break; + } + return chars; + } + +TInt CAknCharMap::PageCountFromChars(TDesC& aChars) const + { + TInt page(aChars.Length() / (iExtension->iMaxVisibleRows * iMaxColumns)); + if ((page * (iExtension->iMaxVisibleRows * iMaxColumns)) != aChars.Length()) + { + page++; + } + return page; + } + +TInt CAknCharMap::VisibleRows() const + { + TInt count((*iShowPagesRef)[iCaseIndex] - 1); + return count * iExtension->iMaxVisibleRows; + } + +void CAknCharMap::CreatePictoCharL() + { + if (!iExtension->iPictographsBuffer) + { + return; + } + + delete iPictographsBuffer; + iPictographsBuffer = NULL; + delete iPictographsBuffer2; + iPictographsBuffer2 = NULL; + delete iPictoInterface; + iPictoInterface = NULL; + + iPictoInterface = CAknPictographInterface::NewL(*this, *this); + if (iPictoInterface) + { + __ASSERT_ALWAYS(iFont, Panic(EAknPanicNullPointer)); + iCurrentPictographHeight = EHeight16; + iPictoInterface->Interface()->SelectPictographHeightForFont(*iFont,iCurrentPictographHeight); + } + + // set pictograph characters + if (iExtension->iPictographsBufferGrouping) + { + for (TInt index=0; index < 2; index++) + { + PictograhGrouping::TAknPictographGroupType type = + ( index == 0 )? PictograhGrouping::TAknPictographGroup1 + : PictograhGrouping::TAknPictographGroup2; + // get pictograph characters + HBufC* temp = PictograhGrouping::AllocStringLC(type); + HBufC* buf = HBufC::NewL(temp->Length()); + TPtr ptr(buf->Des()); + ptr.Append(*temp); + CleanupStack::PopAndDestroy(temp); // temp + + if ( index == 0 ) + { + iPictographsBuffer = buf; + } + else + { + iPictographsBuffer2 = buf; + } + } + } + else if ( iPictoInterface ) + { + // get pictograph characters + HBufC* temp = + iPictoInterface->Interface()->SupportedPictographCodesL(); + CleanupStack::PushL(temp); + + iPictographsBuffer = HBufC::NewL(temp->Length()); + TPtr ptr = iPictographsBuffer->Des(); + ptr.Append(*temp); + CleanupStack::PopAndDestroy(temp); // temp + + // picto2 is not used. + iPictographsBuffer2 = NULL; + } + + // EFalse is set to iSetRecentPic variable when setting special + // characters from resouce. + iSetRecentPic = EFalse; + } + +//-------------------------------------------------------------------------- +// void CAknCharMap::HandlePointerEventL() +// The function works in two different ways. First (1), if the pointer is set +// down or dragged the "focus" shall either move to it or follow the pointer. +// Second (2) when the pointer is lifted the char below the pointer is set in +// to the array in which all the special characters are placed by the normal +// (rocker) method. +//-------------------------------------------------------------------------- +EXPORT_C void CAknCharMap::HandlePointerEventL(const TPointerEvent& aPointerEvent) + { + if ( AknLayoutUtils::PenEnabled() && Rect().Contains(aPointerEvent.iPosition)) + { + if (iExtension->iFocusHandler->FocusedControl() != this)// Tapping will move focus to grid. + { + iExtension->iFocusHandler->LeaveControl(); + iExtension->iFocusHandler = iExtension; + } + + TInt newGridX; // For the whole + TInt newGridY; // For the whole grid. + TInt yInPixels = aPointerEvent.iPosition.iY - iGridTopLeft.iY; + newGridY = yInPixels / iGridItemHeight; + + newGridX = -1; + + if ( iIsMirrored ) + { + TInt topRight = iGridTopLeft.iX - ( iMaxColumns - 1 ) * iGridItemWidth; + TInt topLeft = iGridTopLeft.iX + iGridItemWidth; + if ( ( aPointerEvent.iPosition.iX > topRight ) && + ( aPointerEvent.iPosition.iX < topLeft ) ) + { + newGridX = ( topLeft - aPointerEvent.iPosition.iX ) / iGridItemWidth; + } + } + else if ((aPointerEvent.iPosition.iX - iGridTopLeft.iX) > 0) + { + newGridX = (aPointerEvent.iPosition.iX - iGridTopLeft.iX) / iGridItemWidth; + } + + // The pointer has been set down or dragged into the area of the grid. (it might be in + // the "white space" at the end of the grid) + if ((yInPixels >= 0 && yInPixels < iGridItemHeight * iExtension->iMaxVisibleRows) && + // When the pointer is in rows except the recent character row + ((((newGridY + iFirstVisibleRow) != 0) && newGridX < iMaxColumns && newGridX >= 0) || + // When the pointer is in the recent character row + ( (newGridY + iFirstVisibleRow == 0) && (newGridX< LengthOfRecentChar()))) ) + { + // For any action to be taken, the pointer event must either be a Button1Down or a drag event + // which has originated from a Button1Down in to the grid. + if (iExtension->iFlags&EAknCharMapHasBeenScrolledByDrag || + aPointerEvent.iType == TPointerEvent::EButton1Down || + iExtension->iFlags&EAknCharMapButton1DownInGrid) + { + if (aPointerEvent.iType == TPointerEvent::EButton1Down) + { + iExtension->iSelectAllowed = ETrue; // enable selection. + } + iExtension->iFlags |= EAknCharMapButton1DownInGrid; + TUint globalY = newGridY + iFirstVisibleRow; + if (iChars->Length() > globalY * iMaxColumns + newGridX) + { + if (aPointerEvent.iType == TPointerEvent::EButton1Down || + aPointerEvent.iType == TPointerEvent::EDrag) + { + if (iCursorPos.iX+(iCursorPos.iY+iFirstVisibleRow)*iMaxColumns < iChars->Length()) + { + iOldCursorPos = iCursorPos; + } + else + { + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + } + + iCursorPos.iY = newGridY; + iCursorPos.iX = newGridX; + + if( iExtension->iSingleClickEnabled && + iExtension->iHighlightVisible && + aPointerEvent.iType == TPointerEvent::EDrag ) + { + TInt focusPos = iCursorPos.iX + ( iFirstVisibleRow + + iCursorPos.iY ) * iMaxColumns; + TInt oldFocusPos = iOldCursorPos.iX + ( + iFirstVisibleRow + + iOldCursorPos.iY ) * iMaxColumns; + if ( focusPos != oldFocusPos ) + { + iExtension->iHighlightVisible = EFalse; + iExtension->iSelectAllowed = EFalse; + } + } + + if ( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + iExtension->iFlags |= EAknCharMapPressedDown; + } + else if ( iOldCursorPos != iCursorPos ) + { + iExtension->iFlags &= (~EAknCharMapPressedDown); + } + + // down event on an item, play feedback + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback && + aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + feedback->InstantFeedback( this, ETouchFeedbackList ); + } + if ( aPointerEvent.iType == TPointerEvent::EDrag && + iCursorPos != iOldCursorPos ) + { + // Disable selection. + iExtension->iSelectAllowed = EFalse; + + if ( iExtension->iKineticScrolling ) + { + // Don't allow changing the item by dragging. + iCursorPos = iOldCursorPos; + } + } + + if( aPointerEvent.iType == TPointerEvent::EButton1Down ) + { + if( iExtension->iSingleClickEnabled ) + { + iExtension->iHighlightVisible = ETrue; + } + + HandleFocusStatusChanged(); + } + + DrawCursor(); + } + else if (aPointerEvent.iType == TPointerEvent::EButton1Up) + { + // Observe that selection has been changed, so char map dialog can get + // selected char, add it to text and close. + if (iExtension->iObserver && + iExtension->iFlags & EAknCharMapPressedDown) + { + iStatusChanged = + iExtension->iSelectAllowed ? + EAknCharSelectedSpecialCharacter : EAknCharNoSelection; + // up event hit the same item that was selected by down event, + // play feedback + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->InstantFeedback( this, + ETouchFeedbackList, + ETouchFeedbackVibra, + TPointerEvent() ); + } + + iExtension->iObserver->HandleControlEventL( + this, MCoeControlObserver::EEventStateChanged); + } + } + } + // The user tapped on a cell which does not have item. Remove highlight + else if ( iExtension->iSingleClickEnabled ) + { + iExtension->iHighlightVisible = EFalse; + DrawCursor(); + } + } + } + else if ( iExtension->iSingleClickEnabled ) + { + iExtension->iHighlightVisible = EFalse; + DrawCursor(); + } + + CCoeControl::HandlePointerEventL(aPointerEvent); + + // if Stylus is lifted we clear all flags. + if (aPointerEvent.iType == TPointerEvent::EButton1Up) + { + iExtension->iFlags &= (~EAknCharMapButton1DownInGrid); + iExtension->iFlags &= (~EAknCharMapHasBeenScrolledByDrag); + iExtension->iFlags &= (~EAknCharMapPressedDown); + if ( !iSBFrame ) + { + return; + } + CEikScrollBar* vScrollBar = iSBFrame->VerticalScrollBar(); + if(vScrollBar) + { + vScrollBar->HandlePointerEventL(aPointerEvent); + } + } + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::SetObserver +// Sets the observer. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknCharMap::SetObserver( MCoeControlObserver* aObserver ) + { + if (iExtension) + { + iExtension->iObserver = aObserver; + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::HandleScrollEventL +// Handles the different scroll events so that the map reacts accordingly. +// ----------------------------------------------------------------------------- +// +void CAknCharMap::HandleScrollEventL( + CEikScrollBar* aScrollBar, + TEikScrollEvent aEventType) + { + TBool update = EFalse; + + switch (aEventType) + { + case EEikScrollUp: + case EEikScrollPageUp: + { + // nothing done if we are already on the first page. + if (iFirstVisibleRow != 0) + { + iFirstVisibleRow -= iExtension->iMaxVisibleRows; + update = ETrue; + } + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + + UpdateHeadingPane( ETrue ); + UpdateScrollIndicatorL(); + } + break; + case EEikScrollDown: + case EEikScrollPageDown: + { + // nothing done if we are already on the last page. + if (iFirstVisibleRow != (PageCount() -1 ) * iExtension->iMaxVisibleRows) + { + iFirstVisibleRow += iExtension->iMaxVisibleRows; + update = ETrue; + } + iCursorPos = TPoint(0, 0); + UpdateHeadingPane( ETrue ); + UpdateScrollIndicatorL(); + } + break; + case EEikScrollThumbDragVert: + { + TInt thumbPosition; + TInt halfPage = iExtension->iMaxVisibleRows/2; + // Ask which type of scrollbar is shown + CAknAppUi* appUi = iAvkonAppUi; + TBool isDoubleSpan = + CEikScrollBarFrame::EDoubleSpan == iSBFrame->TypeOfVScrollBar(); + if (isDoubleSpan) + { + thumbPosition = + static_cast + (aScrollBar->Model())->FocusPosition(); + } + else + { + thumbPosition = aScrollBar->Model()->iThumbPosition; + } + + // If the slider is in the range of less then a half page from a possible correct thumb position. + // thus 0 <= iFirstVisibleRow - thumbPosition < halfPage. Or in the other direction: + // 0 <= thumbPosition - iFirstVisibleRow < halfPage + if (!((0 <= iFirstVisibleRow - thumbPosition && + iFirstVisibleRow - thumbPosition < halfPage )|| + (0 <= thumbPosition - iFirstVisibleRow && + thumbPosition - iFirstVisibleRow < halfPage))) + { + TReal toRound = thumbPosition/(TReal)iExtension->iMaxVisibleRows; + if (toRound * 2 > (TInt)toRound * 2 + 1) + { + toRound++; + } + iFirstVisibleRow = (TInt)toRound * iExtension->iMaxVisibleRows; + if(iFirstVisibleRow == 0 && + ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[0])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0]==KHistoryEmptyChar)) ) + { + iCursorPos = TPoint(0, 1); + } + else + { + iCursorPos = TPoint(0, 0); + } + UpdateHeadingPane( EFalse ); + update = ETrue; + } + } + break; + case EEikScrollThumbReleaseVert: + { + UpdateScrollIndicatorL(); + } + break; + case EEikScrollLeft: // flow through + case EEikScrollRight: // flow through + case EEikScrollPageLeft: // flow through + case EEikScrollPageRight: // flow through + case EEikScrollThumbDragHoriz: // flow through + case EEikScrollThumbReleaseHoriz: // flow through + // do nothing + break; + default: + // do nothing + break; + } + // If we have move up to the first page we check the first low is empty or not and + // set iCursorPos respective + if (iFirstVisibleRow == 0 and iCursorPos.iY == 0) + { + if ( (iChaMapTableCase!=EAknCharMapTableSpecialChar && !iPictoInterface->Interface()->IsPictograph((*iChars)[iCursorPos.iX])) || + (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[iCursorPos.iX]==KHistoryEmptyChar && !Extension()->iMenuSct) ) + { + iCursorPos = TPoint(iCursorPos.iX, 1); + } + } +// If we have moved down to the last page we check that the cursor is in a place where it can be +// drawn. + if (iFirstVisibleRow == (iRows/iExtension->iMaxVisibleRows) * iExtension->iMaxVisibleRows) + { + // the old cursor is set to a "safe" position where it at least can be. + iOldCursorPos.iX = 0; + iOldCursorPos.iY = 0; + // if the last page has only one line which isn't filled complitely. + if (iChars->Length()%iMaxColumns - 1 < iCursorPos.iX && iRows%iExtension->iMaxVisibleRows == 1) + { + iCursorPos.iX = iChars->Length()%iMaxColumns - 1; + } + // If the cursor is in a position where it would go unto a spot with out + // a character when scrolled. + if (iCursorPos.iY + iFirstVisibleRow >= iRows) + { + if (iChars->Length()%iMaxColumns > iCursorPos.iX) + { + iCursorPos.iY = iRows - 1 - iFirstVisibleRow; + } + else + { + iCursorPos.iY = iRows - 2 - iFirstVisibleRow; + } + } + // If the cursor is actually on the last row, but is still in the + // area where there is now chars. (the rest of the last row) + if (iChars->Length() <= (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns + iCursorPos.iX && + iCursorPos.iY + iFirstVisibleRow + 1 == iRows) + { + iCursorPos.iY--; + } + // if the corrections did not help and the cursor is in the area + // where there is a valid row, but no chars anymore + } + + // to avoid flicker we draw only if there really was something new to draw. + if (update) + { + if (iExtension->iObserver) + { + iExtension->iObserver->HandleControlEventL(this, MCoeControlObserver::EEventRequestFocus); + } + + HandleFocusStatusChanged(); + DrawDeferred(); + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::AppendRecentCharL() +// Append the recent data to SCT/Picto data +// ----------------------------------------------------------------------------- +// +void CAknCharMap::AppendRecentCharL() + { + __ASSERT_ALWAYS( iCharMapHistory, Panic(EAknPanicInvalidValue)); + __ASSERT_DEBUG( iExtension, Panic(EAknPanicInvalidValue)); + + if(iSetRecentSct) return; + + for (TInt index=0; index < 8; index++ ) + { + + CAknCharMapHistory::THistoryType historyType = CAknCharMapHistory::EHistoryTypeNull; + HBufC** charsBuf = NULL; + + switch (index) + { + case 0: + historyType = CAknCharMapHistory::EHistoryTypeFull; + charsBuf = &iCharsBufferFull; + break; + case 1: + historyType = CAknCharMapHistory::EHistoryTypeHalf; + charsBuf = &iCharsBufferHalf; + break; + case 2: + historyType = CAknCharMapHistory::EHistoryTypeHalf; + charsBuf = &iCharsBufferLower; + break; + case 3: + historyType = CAknCharMapHistory::EHistoryTypeHalf; + charsBuf = &iCharsBufferUpper; + break; + case 4: + historyType = CAknCharMapHistory::EHistoryTypeHalf; + charsBuf = &iCharsBufferNumeric; + break; + case 5: + historyType = CAknCharMapHistory::EHistoryTypePicto; + charsBuf = &iPictographsBuffer; + break; + case 6: + historyType = CAknCharMapHistory::EHistoryTypePicto2; + charsBuf = &iPictographsBuffer2; + break; + case 7: + historyType = CAknCharMapHistory::EHistoryTypeHalf; + charsBuf = &iExtension->iCharsQwerty; + break; + default: + break; + } + + TPtrC textHistory = iCharMapHistory->RecentString(historyType, CAknCharMapHistory::EHistoryFilterTextOnly); + + *charsBuf = InsertSwitchCharAndHistoryToCharsBufL(*charsBuf, + TEmotionUtils::EmotionSwitchToSmileyChar(), + textHistory); + } + + // Emotion history + TPtrC emotionHistory = iCharMapHistory->RecentString(CAknCharMapHistory::EHistoryTypeFull, CAknCharMapHistory::EHistoryFilterEmotionOnly); + iExtension->iCharsSmiley = InsertSwitchCharAndHistoryToCharsBufL(iExtension->iCharsSmiley, + TEmotionUtils::EmotionSwitchToSctChar(), + emotionHistory); + + // ETrue are set to each variable when setting the recent used characters. + iSetRecentSct = ETrue; + iSetRecentPic = ETrue; + } + +HBufC* CAknCharMap::InsertSwitchCharAndHistoryToCharsBufL(HBufC* aCharsBuf, TChar aSwitchChar, const TDesC& aHistory) + { + if (aCharsBuf) + { + // Check whether recent charcters are included in base charcters. + TBuf insertBuffer; + for (TInt index=0; indexLocate(txt)!=KErrNotFound || TEmotionUtils::IsEmotionChar(txt) || txt==KHistoryEmptyChar) + { + insertBuffer.Append(txt); + } + } + + while(insertBuffer.Length() < iMaxColumns) // empty history stuff + { + insertBuffer.Append(KHistoryEmptyChar); + } + + insertBuffer.SetLength(iMaxColumns); // max length is one line + + // Emotion switch char + if(Extension()->NeedEmotionSwitchIcon()) + { + insertBuffer.Append(aSwitchChar); + } + + // insert to des buffer + TInt charsLength = insertBuffer.Length() + aCharsBuf->Length(); // history + Emotion swich char + text + aCharsBuf = aCharsBuf->ReAllocL(charsLength); + aCharsBuf->Des().Insert(0, insertBuffer); // history + } + + return aCharsBuf; + } + +// ----------------------------------------------------------------------------- +// CAknCharMapHistory::IsRecentChar() +// Check whether the character(of index) is recent data, or not +// The default value of first argument is 0. +// ----------------------------------------------------------------------------- +// +TBool CAknCharMap::IsRecentChar(TInt aIndex /*=0*/) const + { + TBool rtn = EFalse; + if (iCharMapHistory) + { + switch (iChaMapTableCase) + { + case EAknCharMapTableSpecialChar: + switch (iSpecialCharCase) + { + case EAknSCTHalfCase: + case EAknSCTLowerCase: + case EAknSCTUpperCase: + case EAknSCTNumeric: + case EAknSCTQwerty: + case EAknSCTFullCase: + if (aIndex CAknCharMapHistory::EHistoryTypeNull) + { + iCharMapHistory->InsertChar(historyType, aChar); + } + + // Save recent data + iCharMapHistory->SaveL(); + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::ConstructMenuSctRowL() +// Constructs the SCT for editing menu. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknCharMap::ConstructMenuSctRowL() + { + Extension()->iMenuSct = ETrue; + TResourceReader reader; + + TInt resourceId = R_AVKON_MENU_SCT_ROW_DEFAULT_CONTENTS; + if (FeatureManager::FeatureSupported(KFeatureIdChinese)) + { + resourceId = R_AVKON_MENU_SCT_ROW_DEFAULT_CONTENTS_CHINESE; + } + + CCoeEnv::Static()->CreateResourceReaderLC( reader, resourceId ); + ConstructFromResourceL( reader ); + CleanupStack::PopAndDestroy(); + } + + +EXPORT_C void CAknCharMap::ConstructMenuSctRowL(TInt aResourceId) + { + Extension()->iMenuSct = ETrue; + Extension()->iMenuSctHighlighted = ETrue; + TResourceReader reader; + CCoeEnv::Static()->CreateResourceReaderLC( reader, + aResourceId ); + ConstructFromResourceL( reader ); + CleanupStack::PopAndDestroy(); + } + + +// ----------------------------------------------------------------------------- +// CAknCharMap::ConstructMenuSctRowFromDialogL() +// Constructs the SCT for editing menu from the set resource. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknCharMap::ConstructMenuSctRowFromDialogL(TInt aResourceId) + { + Extension()->iMenuSct = ETrue; + Extension()->iMenuSctHighlighted = ETrue; + + CEikDialog* dialog = new(ELeave) CEikDialog(); + dialog->ReadResourceLC(aResourceId); + CAknCharMap* charmapControl = STATIC_CAST(CAknCharMap*, dialog->Control(EAknSCTQueryContentId)); + + // the code below emulates ConstructFromResourceL(), but gets value from charmapControl + CopyCharactersL(*charmapControl); // replaces ReadCharSetFromResourceL() + CleanupStack::PopAndDestroy(dialog); + TBuf<32> fileName(KResFileName); + TInt langcode= iAvkonEnv->SettingCache().InputLanguage(); + if (langcode < 10) + { + fileName.Append('0'); + } + fileName.AppendNum(langcode); + TResourceReader reader; + RFs& fs = iEikonEnv->FsSession(); + if ( BaflUtils::FileExists(fs, fileName) ) + { + RResourceFile resourceFile; + resourceFile.OpenL( fs, fileName ); + CleanupClosePushL( resourceFile ); // push + resourceFile.ConfirmSignatureL( 0 ); + if ( resourceFile.OwnsResourceId(aResourceId) ) + { + HBufC8* resource= + resourceFile.AllocReadLC(aResourceId); // push + reader.SetBuffer(resource); + TBuf<32> specialChars; + CAknCharMapDialog* langDialog = + new( ELeave ) CAknCharMapDialog( + EAknSCTLowerCase, specialChars ); + CleanupStack::PushL( langDialog ); // push + langDialog->CreateWindowL(); + langDialog->ConstructFromResourceL(reader); + CAknCharMap* langMap = STATIC_CAST( CAknCharMap*, + langDialog->Control( EAknSCTQueryContentId ) ); + CopyCharactersL( *langMap ); + CleanupStack::PopAndDestroy(2); // langDialog, resource + } + CleanupStack::PopAndDestroy(); // resourcefile + } + + if ( iExtension->iPictographsBuffer ) + { + CreatePictoCharL(); + } + + if (!iCharMapHistory) + { + iCharMapHistory = CAknCharMapHistory::NewL(); + iSetRecentSct = ETrue; + iSetRecentPic = ETrue; + } + + if ( iExtension->iPictographsBuffer ) + { + CreateOffscreenBackgroundL(); + } + + delete iExtension->iBgContext; + iExtension->iBgContext = NULL; + + if ( DrawableWindow() && AknLayoutUtils::PenEnabled() ) + { + EnableDragEvents(); + SetGloballyCapturing( ETrue ); + SetPointerCapture( ETrue ); + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::HighlightSctRow() +// Highlight the row of recent used character according to argument. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknCharMap::HighlightSctRow(TBool aHighlight) + { + // If the row is empty, nothing to do + if (LengthOfRecentChar() == 0) + { + return; + } + + HandleFocusStatusChanged(aHighlight); + + CWindowGc& gc = SystemGc(); + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + ActivateGc(); + gc.UseFont(iFont); + } + + TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( cursorPos, aHighlight ); + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + // Menu SCT is being used. + if ( Extension()->iMenuSct ) + { + Extension()->iMenuSctHighlighted = aHighlight; + } + } +// ----------------------------------------------------------------------------- +// CAknCharMap::SetMenuSctRect() +// Sets the rect for menu SCT. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknCharMap::SetMenuSctRect( const TRect& aRect ) + { + + if(Rect() == aRect) return; + + SetRect( aRect ); + + if ( !iIsMirrored ) + { + iGridTopLeft = aRect.iTl; + iOffset.iX = aRect.iTl.iX + 1; + iOffset.iY = aRect.iTl.iY + 1; + } + else + { + iGridTopLeft.iX = aRect.iBr.iX; + iGridTopLeft.iY = aRect.iTl.iY; + iOffset.iX = aRect.iTl.iX + 1; + iOffset.iY = aRect.iTl.iY + 1; + } + + + DoLayout(); + + if (iCharMapHistory) + { + CAknCharMapHistory::THistoryType charmap = CAknCharMapHistory::EHistoryTypeNull; + + switch (iSpecialCharCase) + { + case 0: // lower + charmap = CAknCharMapHistory::EHistoryTypeHalf; + break; + case 1: // upper + charmap = CAknCharMapHistory::EHistoryTypeHalf; + break; + case 2: // numeric + charmap = CAknCharMapHistory::EHistoryTypeHalf; + break; + case 3: // full + charmap = CAknCharMapHistory::EHistoryTypeFull; + break; + case 4: // half + charmap = CAknCharMapHistory::EHistoryTypeHalf; + break; + case 5: // qwerty + charmap = CAknCharMapHistory::EHistoryTypeHalf; + break; + case 6: // picto + charmap = CAknCharMapHistory::EHistoryTypePicto; + break; + case 7: // picto 2 + charmap = CAknCharMapHistory::EHistoryTypePicto2; + break; + default: + break; + } + + CAknCharMapHistory::THistoryFilter historyFilter; + if(iExtension->IsEmotionEnabled()) + { + historyFilter = CAknCharMapHistory::EHistoryFilterMixed; + } + else + { + historyFilter = CAknCharMapHistory::EHistoryFilterTextOnly; + } + + const TDesC& recentChars = iCharMapHistory->RecentString(charmap, historyFilter); + + // if iChars already contains HBufC, delete iChars and reset ichars + if (iExtension->iFlags & EAknCharMapCharsAllocated) + { + delete iChars; + iChars = NULL; + if (iChaMapTableCase != EAknCharMapTableSpecialChar) + { + if (iCaseIndex == 1) + { + iChars = iPictographsBuffer2; + } + else + { + iChars = iPictographsBuffer; + } + iShowCasesRef = &iPictographCases; + iShowPagesRef = &iPictographPages; + } + else + { + iShowCasesRef = &iSpecialCharCases; + iShowPagesRef = &iSpecialCharPages; + iChars = iCharsBufferLower; + if (iCharsBufferUpper && iSpecialCharCase==EAknSCTUpperCase) + iChars = iCharsBufferUpper; + else if (iCharsBufferNumeric && iSpecialCharCase==EAknSCTNumeric) + iChars = iCharsBufferNumeric; + else if (iCharsBufferFull && iSpecialCharCase==EAknSCTFullCase) + iChars = iCharsBufferFull; + else if (iCharsBufferHalf && iSpecialCharCase==EAknSCTHalfCase) + iChars = iCharsBufferHalf; + else if (iExtension->iCharsQwerty && iSpecialCharCase==EAknSCTQwerty) + iChars = iExtension->iCharsQwerty; + + if(iChars == iCharsBufferLower) + { + iSpecialCharCase = EAknSCTLowerCase; + } + } + // mark that iChars doesn't point to HBufC + iExtension->iFlags &= (~EAknCharMapCharsAllocated); + } + iRows = 1; + TPtrC realChars = iChars->Des(); // get only the SCT chars + + // Check whether recent charcters are included in base charcters. + HBufC* newrecent = HBufC::New(recentChars.Length()); + if( newrecent == NULL) + { + return; + } + + TPtr ptrrecent(newrecent->Des()); + ptrrecent.Copy(recentChars); + for (TInt index=0; index < ptrrecent.Length(); index++) + { + if (ptrrecent[index] != KHistoryEmptyChar) + { + if(TEmotionUtils::IsEmotionChar(ptrrecent[index])) + { + continue; + } + else + { + TInt err = realChars.Locate(ptrrecent[index]); + if (err == KErrNotFound) + { + ptrrecent.Delete(index,1); + ptrrecent.Append(KHistoryEmptyChar); + index--; + } + } + } + } + if (iExtension->iFlags & EAknCharMapCharsAllocated) // iChars already contains HBufC + { // so delete old instance + delete iChars; + iChars = NULL; + } + + iChars = newrecent; + iChars->Des().SetLength(iMaxColumns); + if (iChaMapTableCase==EAknCharMapTableSpecialChar && (*iChars)[0] == KHistoryEmptyChar) + { + iCursorPos = TPoint(0, 1); + } + if (iCursorPos.iX >= iMaxColumns) + { + iCursorPos = TPoint(0, 0); + } + iExtension->iFlags |= EAknCharMapCharsAllocated; // mark that iChars points to HBufC + } + + iExtension->LoadEmotionTumbnails(*iChars); + + HandleFocusStatusChanged(); + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::CharacterCase() +// Get current character case. +// ----------------------------------------------------------------------------- +// +TInt CAknCharMap::CharacterCase() + { + return iSpecialCharCase; + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::DisableRecentCharsRow() +// Hides the first row that shows recent characters. +// ----------------------------------------------------------------------------- +// +void CAknCharMap::DisableRecentCharsRow() + { + if(!iSetRecentSct) return; + + iSetRecentSct = EFalse; + iSetRecentPic = EFalse; + + TInt insertedLength = iMaxColumns; + + // Emotion switch char + if(Extension()->NeedEmotionSwitchIcon()) + { + insertedLength++; + } + + for (TInt index=0; index < 8; index++ ) + { + HBufC** base = NULL; + + switch (index) + { + case 0: + base = &iCharsBufferFull; + break; + case 1: + base = &iCharsBufferHalf; + break; + case 2: + base = &iCharsBufferLower; + break; + case 3: + base = &iCharsBufferUpper; + break; + case 4: + base = &iCharsBufferNumeric; + break; + case 5: + base = &iPictographsBuffer; + break; + case 6: + base = &iExtension->iCharsQwerty; + break; + case 7: + base = &iPictographsBuffer2; + break; + default: + break; + } + + if (*base) + { + // Remove recent characters from the beginning. + // Length of removed characters is iMaxColumns + (*base)->Des().Delete(0, insertedLength); + } + } + + // delete Emotion history + iExtension->iCharsSmiley->Des().Delete(0, insertedLength); + } + + +// ----------------------------------------------------------------------------- +// CAknCharMap::Extension +// Asserts that extension object has been created. +// ----------------------------------------------------------------------------- +// +CAknCharMapExtension* CAknCharMap::Extension() const + { + __ASSERT_ALWAYS( iExtension, Panic( EAknPanicNullPointer ) ); + return iExtension; + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::UpdateHeadingPane +// Updates page number and title in Heading Pane. +// ----------------------------------------------------------------------------- +// +void CAknCharMap::UpdateHeadingPane( TBool aUpdateTitle ) + { + if (iExtension->iObserver && + !AknLayoutUtils::PenEnabled() && !Extension()->iMenuSct) + { + CAknCharMapDialog* dialog = + static_cast(iExtension->iObserver ); + CAknPopupHeadingPane* headingPane = + static_cast< CAknPopupHeadingPane* > + (dialog-> Control( EAknSCTQueryHeadingId ) ); + + if ( headingPane ) + { + TRAP_IGNORE( + { + // Update heading pane's page number + headingPane->SetPageL( CurrentPage(), PageCount() ); + + // Update also title if requested + if ( aUpdateTitle) + { + const TDesC* title = (IsJapaneseSctUi())? + TitleWithSelectingSpecialChar() + :Title(); + if ( title ) + { + // + headingPane->SetTextL( *title ); + } + } + } ); + } + } + } + + + + +void CAknCharMap::SetStatusChanged(const TInt aStatusChanged) + { + iStatusChanged = aStatusChanged; + if (iExtension->iObserver) + { + TRAP_IGNORE( iExtension->iObserver->HandleControlEventL(this, MCoeControlObserver::EEventStateChanged) ); + } + } + +TInt CAknCharMap::StatusChanged() + { + return iStatusChanged; + } + +TInt CAknCharMap::CurrentCategory() + { + return iExtension->iCurrentCategory; + } + +TInt CAknCharMap::Category() + { + TInt category = EAknSCTCategoryButtonHalfCase; + if (iChaMapTableCase == EAknCharMapTableSpecialChar) + { + if (iSpecialCharCase == EAknSCTFullCase) + { + category = EAknSCTCategoryButtonFullCase; + } + } + else + { + if (iExtension->iPictographsBufferGrouping) + { + category = (iCaseIndex == 1) ? + EAknSCTCategoryButtonPicto2 : EAknSCTCategoryButtonPicto1; + } + else + { + category = EAknSCTCategoryButtonPicto; + } + } + return category; + } + +/** + * Change to new category + */ +TBool CAknCharMap::ChangeCategoryL(const TInt aCategory, TBool& aLayoutChanged) + { + TBool result(ETrue); + + aLayoutChanged = EFalse; + + TInt oldVisibleRows = iRows; + if (oldVisibleRows > iExtension->iMaxVisibleRows) + { + oldVisibleRows = iExtension->iMaxVisibleRows; + } + + switch (aCategory) + { + case EAknSCTCategoryButtonHalfCase: + iChaMapTableCase = EAknCharMapTableSpecialChar; + SetCharacterCaseL(EAknSCTHalfCase); + break; + case EAknSCTCategoryButtonFullCase: + iChaMapTableCase = EAknCharMapTableSpecialChar; + SetCharacterCaseL(EAknSCTFullCase); + break; + case EAknSCTCategoryButtonPicto: + iChaMapTableCase = EAknCharMapTablePicto; + iCaseIndex = 0; + SetCharacterCaseL(iSpecialCharCase); + break; + case EAknSCTCategoryButtonPicto1: + iChaMapTableCase = EAknCharMapTablePicto; + iCaseIndex = 0; + SetCharacterCaseL(iSpecialCharCase); + break; + case EAknSCTCategoryButtonPicto2: + iChaMapTableCase = EAknCharMapTablePicto; + iCaseIndex = 1; + SetCharacterCaseL(iSpecialCharCase); + break; + default: + Panic(EAknPanicOutOfRange); + break; + } + + TInt visibleRows = iRows; + if (visibleRows > iExtension->iMaxVisibleRows) + { + visibleRows = iExtension->iMaxVisibleRows; + } + + // Return also information whether the layout changed or not. + aLayoutChanged = ( oldVisibleRows != visibleRows ); + + UpdateScrollIndicatorL(); + + UpdateInputFieldL(); + + RefreshNaviPageL(); + + if (aLayoutChanged) + { + // If the number of the visible row is changed, + // it is necessary to re-create the background. + CreateOffscreenBackgroundL(); + } + return result; + } + + +TBool CAknCharMap::IsSupportCategoryButtonUi() const + { + return (iExtension)? iExtension->iHasCategoryButtonUi : EFalse; + } + +TBool CAknCharMap::IsJapaneseSctUi() const + { + return (iExtension)? iExtension->iJapaneseSctUi : EFalse; + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::TitleWithSelectingSpecialChar() +// Return the title string with the selecting special characters +// ----------------------------------------------------------------------------- +// + +const TDesC* CAknCharMap::TitleWithSelectingSpecialChar() + { + const TDesC* title = Title(); + TRAPD(err, CreateTitleWithSelectingSpecialCharL(title)); + if (err != KErrNone) + { + return title; + } + else + { + return Extension()->iTitleBuf; + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::ChangeFocusSct() +// Change the current focus either Grid or Category buttons +// If aFocusOn is EFalse, from Grid to Category buttons, +// If aFocusOn is ETrue, from Category buttons to Grid +// ----------------------------------------------------------------------------- +// +void CAknCharMap::ChangeFocusSct(TBool aFocusOn) + { + CWindowGc& gc = SystemGc(); + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + ActivateGc(); + gc.UseFont(iFont); + } + + TInt cursorPos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( cursorPos, aFocusOn ); + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + } + +// ----------------------------------------------------------------------------- +// CAknCharMap::CreateTitleWithSelectingSpecialCharL() +// Create the string mixing title and the selecting special characters, +// and Set it to Extension()->iTitleBuf. +// ----------------------------------------------------------------------------- +// +void CAknCharMap::CreateTitleWithSelectingSpecialCharL(const TDesC* aTitle) + { + const TDesC* title = aTitle; + if ( title ) + { + if (!AknLayoutUtils::PenEnabled()) + { + CAknCharMapDialog* dialog = + static_cast(iExtension->iObserver); + CAknPopupHeadingPane* headingPane = + static_cast( + dialog->Control(EAknSCTQueryHeadingId)); + if (Extension()->iTitleBuf) + { + delete Extension()->iTitleBuf; + Extension()->iTitleBuf =NULL; + } + Extension()->iTitleBuf = + HBufC::NewL(title->Length() + iFetcherCharsBuffer->Length()); + TPtr titlePtr(Extension()->iTitleBuf->Des()); + HBufC* tempBuf = iFetcherCharsBuffer->AllocLC(); + TPtr tempPtr(tempBuf->Des()); + + CCoeControl* titleCtrl = (CCoeControl*)headingPane->Prompt(); + TRect promptRect = titleCtrl->Rect(); + + TInt varietyIndex = (AknLayoutUtils::PenEnabled())? 3 : 1; + TAknTextComponentLayout textLayout = + AknLayoutScalable_Avkon::heading_pane_t1(varietyIndex); + + TRect parentRect; + TAknLayoutRect popupRect; + if(!AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EPopupParent, parentRect)) + { + parentRect = iAvkonAppUi->ClientRect(); + } + popupRect.LayoutRect(parentRect, + AknLayoutScalable_Avkon::popup_window_general(1)); + + TAknLayoutRect headingRect; + TAknWindowComponentLayout headingPaneLayout = + AknLayoutScalable_Avkon::heading_pane(0); + headingRect.LayoutRect(TRect(TPoint(0,0), + popupRect.Rect().Size()), headingPaneLayout); + parentRect = headingRect.Rect(); + + TAknLayoutText textRect; + textRect.LayoutText(parentRect, textLayout); + TInt controlWidth = textRect.TextRect().Width(); + + const CFont* promptFont = + AknLayoutUtils::FontFromId( textLayout.Font() ); + + TInt titleWidth = promptFont->TextWidthInPixels(*title); + TInt textWidth = promptFont->TextWidthInPixels(tempPtr); + FOREVER + { + if (titleWidth >= controlWidth) + { + titlePtr.Append(*title); + break; + } + if (controlWidth >= (titleWidth + textWidth)) + { + titlePtr.Append(*title); + titlePtr.Append(tempPtr); + break; + } + if (tempPtr.Length() > 1) + { + tempPtr.Delete(0,1); + tempPtr[0] = CEditableText::EEllipsis; + textWidth = promptFont->TextWidthInPixels(tempPtr); + } + else + { + titleWidth = controlWidth + 1; + } + } + CleanupStack::PopAndDestroy(tempBuf); + } + } + } + +void CAknCharMap::RefreshNaviPageL() + { + if (iExtension->iPageNavi) + { + iExtension->iPageNavi->UpdatePageTitleL(); + } + } + +TAknChaMapTableCase CAknCharMap::NextTableCase() const + { + return EAknCharMapTableSpecialChar; // Currently no other maps supported. + } + +MAknSctFocusHandler* CAknCharMap::FocusHandler() + { + return iExtension->iFocusHandler; + } + +CCoeControl* CAknCharMap::FocusedControl() + { + return this; + } + +TBool CAknCharMap::EnterControl(TInt aX, TInt aY) + { + if ((aY < 0) || (aY >= iExtension->iMaxVisibleRows)) + { + return EFalse; // Out of grid. + } + + if ((aX < 0) || (aX >= iMaxColumns)) + { + return EFalse; // Out of grid. + } + + TInt pos = 0; + + CWindowGc& gc = SystemGc(); + if(!CAknEnv::Static()->TransparencyEnabled()) + { + ActivateGc(); + gc.UseFont(iFont); + } + + // clear cell + pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( pos, EFalse ); + + iCursorPos = TPoint(aX, aY); // new pos. + + // highlight cell + pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( pos, ETrue ); + + UpdateHeadingPane( ETrue ); + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + + return ETrue; + } + +void CAknCharMap::MoveFocus(TInt aX, TInt aY) + { + TRAP_IGNORE(MoveCursorL(aX,aY)); + } + +TBool CAknCharMap::LeaveControl() + { + HandleFocusStatusChanged(EFalse); + + CWindowGc& gc = SystemGc(); + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + ActivateGc(); + gc.UseFont(iFont); + } + + TInt pos = iCursorPos.iX + iCursorPos.iY * iMaxColumns; + DrawCell( pos, EFalse ); + + if( !CAknEnv::Static()->TransparencyEnabled() ) + { + gc.DiscardFont(); + DeactivateGc(); + } + + return ETrue; + } + +TInt CAknCharMap::TableCount() const + { + // Numbers of tables excluding pictographs. + // there will be sct table and Emotion table(if enabled) + return Extension()->IsEmotionEnabled() ? 2 : 1; + } + +void CAknCharMap::UpdateInputFieldL() + { + if (!iExtension) + { + return; // Not ready for updates. + } + + TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; + + // Update title field. + const TDesC* title = Title(); + if (iExtension->iCategoryTitle && title) + { + iExtension->iCategoryTitle->SetTextL(*title); + Window().Invalidate(iExtension->iCategoryTitle->Rect()); + iExtension->iCategoryTitle->SetBrushStyle( + CGraphicsContext::ENullBrush); + } + + // Update entry field. + if (iExtension->iCategoryEntry && + iFetcherCharsBuffer && iFetcherCharsBuffer->Length()>0) + { + if (Extension()->iEntryBuf) + { + delete Extension()->iEntryBuf; + Extension()->iEntryBuf =NULL; + } + Extension()->iEntryBuf = + HBufC::NewL(iFetcherCharsBuffer->Length()); + TPtr entryPtr(Extension()->iEntryBuf->Des()); + + HBufC* tempBuf = iFetcherCharsBuffer->AllocLC(); + TPtr tempPtr(tempBuf->Des()); + + TInt variety = + Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; + const CFont* entryFont = AknLayoutUtils::FontFromId( + AknLayoutScalable_Avkon::popup_grid_graphic2_window_t2(variety).Font()); + TInt entryWidth = entryFont->TextWidthInPixels(tempPtr); + + TInt controlWidth = Extension()->iCategoryEntry->Size().iWidth; + + FOREVER + { + if (entryWidth < controlWidth) + { + entryPtr.Append(tempPtr); + break; + } + if (tempPtr.Length() > 1) + { + tempPtr.Delete(0,1); + tempPtr[0] = CEditableText::EEllipsis; + entryWidth = entryFont->TextWidthInPixels(tempPtr); + } + else + { + entryWidth = controlWidth + 1; + } + } + + Extension()->iCategoryEntry->SetTextL(tempPtr); + Window().Invalidate(iExtension->iCategoryEntry->Rect()); + Extension()->iCategoryEntry->SetBrushStyle( + CGraphicsContext::ENullBrush); + + CleanupStack::PopAndDestroy(tempBuf); + } + } + +TInt CAknCharMap::RowMin(TInt aRow) const + { + TInt index = KErrNotFound; + if ((aRow >= 0) && (aRow < iExtension->iMaxVisibleRows)) + { + TInt start = (iFirstVisibleRow + aRow) * iMaxColumns; + for (TInt i = 0; i < iMaxColumns; i++) + { + TInt pos = start + i; + if ((pos >= 0) && (pos < iChars->Length())) + { + if ((*iChars)[pos] != KHistoryEmptyChar) + { + index = i; // the first valid cell in the row. + break; + } + } + } + } + return index; + } + +TInt CAknCharMap::RowMax(TInt aRow) const + { + TInt index = KErrNotFound; + if ((aRow >= 0) && (aRow < iExtension->iMaxVisibleRows)) + { + TInt start = (iFirstVisibleRow + aRow) * iMaxColumns; + for (TInt i = iMaxColumns - 1; i >= 0; i--) + { + TInt pos = start + i; + if ((pos >= 0) && (pos < iChars->Length())) + { + if ((*iChars)[pos] != KHistoryEmptyChar) + { + index = i; // the last valid cell in the row. + break; + } + } + } + } + return index; + } + +TInt CAknCharMap::ColMin(TInt aCol) const + { + TInt index = KErrNotFound; + if ((aCol >= 0) && (aCol < iMaxColumns)) + { + TInt start = iFirstVisibleRow * iMaxColumns + aCol; + for (TInt i = 0; i < iExtension->iMaxVisibleRows; i++) + { + TInt pos = start + iMaxColumns * i; + if ((pos >= 0) && (pos < iChars->Length())) + { + if ((*iChars)[pos] != KHistoryEmptyChar) + { + index = i; // the first valid cell in the column. + break; + } + } + } + } + return index; + } + +TInt CAknCharMap::ColMax(TInt aCol) const + { + TInt index = KErrNotFound; + if ((aCol >= 0) && (aCol < iMaxColumns)) + { + TInt start = iFirstVisibleRow * iMaxColumns + aCol; + for (TInt i = iExtension->iMaxVisibleRows - 1; i >= 0; i--) + { + TInt pos = start + iMaxColumns * i; + if ((pos >= 0) && (pos < iChars->Length())) + { + if ((*iChars)[pos] != KHistoryEmptyChar) + { + index = i; // the last valid cell in the column. + break; + } + } + } + } + return index; + } + +TInt CAknCharMap::MaxCols() const + { + return iMaxColumns; + } + +TBool CAknCharMap::TakeFocus() + { + TInt success = EFalse; + if (iExtension->iFocusHandler->FocusedControl() != this) + { + iExtension->iFocusHandler->LeaveControl(); + iExtension->iFocusHandler = iExtension; + success = ETrue; + } + return success; + } + +void CAknCharMap::ShowFocus() + { + ChangeFocusSct(ETrue); + } + +TPoint CAknCharMap::CursorPos() + { + return iCursorPos; + } + + +// for emotion added + +void CAknCharMap::HandleFocusStatusChanged(TBool aIsFocused) + { + TInt focusPos = iCursorPos.iX + (iFirstVisibleRow + iCursorPos.iY) * iMaxColumns; + if(focusPos>=0 && focusPosLength()) + { + aIsFocused &= (iExtension->iFocusHandler->FocusedControl()==this); + iExtension->HandleFocusStatusChanged((*iChars)[focusPos], aIsFocused); + } + } + +TBool CAknCharMap::EmotionsAreAllReadyToDraw(TInt aIndex, TInt aCount) const + { + for(TInt i(0); iLength()) + { + TChar name = (*iChars)[aIndex++]; + CSmileyIcon* icon = iExtension->EmotionIcon(name); + if(icon && !icon->ReadyToDraw()) + { + return EFalse; + } + } + else + { + break; + } + } + + return ETrue; + } + +void CAknCharMap::GetFocusSctName(TChar& aChar, TDes& aName) const + { + TInt pos = iMaxColumns * (iFirstVisibleRow + iCursorPos.iY) + iCursorPos.iX; + + aChar = (*iChars)[pos]; + + aName.Zero(); + + if(TEmotionUtils::IsEmotionChar(aChar)) + { + CSmileyIcon* icon = iExtension->EmotionIcon(aChar); + if ( icon ) + { + aName.Append(icon->Name()); + } + } + else + { + aName.Append(aChar); + } + } + +TBool CAknCharMap::HaveBufferToAppendFocusSct() const + { + TChar sctChar; + TBuf<10> sctName; + GetFocusSctName(sctChar, sctName); + + return ( iFetcherCharsBuffer->Length() + sctName.Length() < iFetcherCharsBuffer->MaxLength() ); + } + +TBool CAknCharMap::AppendFocusSctToDestinationBufferL() + { + TBool appended = EFalse; + + TChar sctChar; + TBuf<10> sctName; + GetFocusSctName(sctChar, sctName); + + if(Extension()->NeedEmotionSwitchIcon() && + (sctChar==TEmotionUtils::EmotionSwitchToSctChar() || sctChar==TEmotionUtils::EmotionSwitchToSmileyChar())) + { + SwitchSctAndEmotionL(); + } + else if(iFetcherCharsBuffer->Length() + sctName.Length() < iFetcherCharsBuffer->MaxLength()) + { + iFetcherCharsBuffer->Append(sctName); + + if (iCharMapHistory) + { + SaveRecentDataL(sctChar); + } + + appended = ETrue; + } + else + { + return EFalse; // return here + } + + if (!Extension()->iMenuSct) + { + UpdateHeadingPane( ETrue ); + } + + if (iExtension->iCategoryEntry) + { + iExtension->iCategoryEntry->SetTextL(*iFetcherCharsBuffer); + UpdateInputFieldL(); + } + + return appended; + + } + +TBool CAknCharMap::SwitchSctAndEmotionL() + { + if(Extension()->IsEmotionEnabled()) + { + Extension()->iIsShowingEmotion = !Extension()->IsShowingEmotion(); + + SetCharacterCaseL(iSpecialCharCase); + + CAknSctTableNavi* tableNavi = Extension()->iTableNavi; + if(tableNavi) + { + tableNavi->UpdateNextTableButtonL(); + } + + DrawNow(); + + return ETrue; + } + else + { + return EFalse; + } + } + + +// End of File