javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swtdateeditor.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 09 Jun 2010 09:34:07 +0300
branchRCL_3
changeset 19 71c436fe3ce0
parent 18 9ac0a0a7da70
child 21 4376525cdefb
permissions -rw-r--r--
Revision: v2.1.28 Kit: 2010123

/*******************************************************************************
 * Copyright (c) 2005, 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Nokia Corporation - S60 implementation
 *******************************************************************************/


#include <eswtcore.rsg>
#include <AknLayoutFont.h>
#include <AknsControlContext.h>
#include <AknsDrawUtils.h>
#include <avkon.rsg>
#include <AknUtils.h>
#include <AknDef.h>
#ifdef RD_JAVA_S60_RELEASE_9_2
#include <AknPriv.hrh>
#endif
#include <swtlaffacade.h>
#if defined( RD_SCALABLE_UI_V2 )
#include <swtbuttonproxy.h>
#include <aknconsts.h>
#include <avkon.mbg>
#include <fepbase.h>
#endif // RD_SCALABLE_UI_V2
#include "swteditindicator.h"
#include "swtfont.h"
#include "swtdateeditor.h"


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


// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::NewL
// ---------------------------------------------------------------------------------------------
//
CSwtDateEditor* CSwtDateEditor::NewL(MSwtDisplay& aDisplay, TSwtPeer aPeer,
                                     MSwtComposite& aParent, TInt aStyle)
{
    CSwtDateEditor* self = new(ELeave) CSwtDateEditor(aDisplay, aPeer, aParent, aStyle);
    CleanupStack::PushL(self);
    self->ConstructL();
    self->InitControlBaseL();
    CleanupStack::Pop(self);
    return self;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::CSwtDateEditor
// ---------------------------------------------------------------------------------------------
//
CSwtDateEditor::CSwtDateEditor(MSwtDisplay& aDisplay,
                               TSwtPeer aPeer,
                               MSwtComposite& aParent,
                               TInt aStyle)
        : ASwtControlBase(aDisplay, aPeer, &aParent, aStyle)
        , iCurrentFieldLength(0)
        , iCurrentFieldDecimalPlacesCount(0)
        , iLastField(0)
{
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::~CSwtDateEditor
// ---------------------------------------------------------------------------------------------
//
CSwtDateEditor::~CSwtDateEditor()
{
    delete iEditor;
    delete iIndicator;
    if (iDefaultFont)
    {
        iDefaultFont->RemoveRef();
    }

#ifdef _lint
    iEditor      = NULL;
    iDefaultFont = NULL;
#endif
}


// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::ConstructL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::ConstructL()
{
    ASSERT(iParent);
    CCoeControl& coeParent = iParent->Control()->CoeControl();
    SetContainerWindowL(coeParent);
    CCoeControl::MakeVisible(coeParent.IsVisible());
    CCoeControl::SetDimmed(coeParent.IsDimmed());
    SetComponentsToInheritVisibility(ETrue);

    CSwtEditIndicatorRedictor* redirector = MopGetObject(redirector);
    if (redirector)
    {
        iIndicator = CSwtEditIndicator::NewL(CoeControl());
    }

    // Read the Java Epoc date in the resource file
    HBufC* minDateString = iEikonEnv->AllocReadResourceLC(R_SWT_DATEEDITOR_MIN_DATE);
    iEpocDateInMicroSec = TTime(minDateString->Des()).Int64();
    CleanupStack::PopAndDestroy(minDateString);

    SetBackground(this);   // Back will be drawn by ASwtControlBase::Draw
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::RetrieveDefaultFontL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::RetrieveDefaultFontL()
{
    if (iDefaultFont)
    {
        iDefaultFont->RemoveRef();
        iDefaultFont = NULL;
    }
    // Not same but similar to Text's font. Height most probably the same.
    const CFont* font = AknLayoutUtils::FontFromId(CSwtLafFacade::GetFontId(
                            CSwtLafFacade::EFont2MidpTimePaneT1Font));
    ASSERT(font);
    iDefaultFont = CSwtFont::NewL(iDisplay.Device(), *font);

    if (!iFont)
    {
        // to avoid the default font of CEikEdwin
        ProcessFontUpdate();
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::ProcessFontUpdate
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::ProcessFontUpdate()
{
    const MSwtFont* swtFont=GetFont();
    ASSERT(swtFont);
    const CFont& font = (swtFont->Font());
    iEditor->SetFont(&font);
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::PrepareForFocusChangeL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::PrepareForFocusChangeL()
{
    if (IsFocused())
    {
        iEditor->PrepareForFocusGainL();
    }
    else
    {
        iEditor->PrepareForFocusLossL();
        if (iIndicator)
        {
            iIndicator->SetState(EStateNone);
        }
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::CountComponentControls
// ---------------------------------------------------------------------------------------------
//
TInt CSwtDateEditor::CountComponentControls() const
{
    TInt count(0);
    if (iEditor)
    {
        count = 1;
        if (iIndicator)
        {
            count++;
        }
    }
    return count;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::ComponentControl
// ---------------------------------------------------------------------------------------------
//
CCoeControl* CSwtDateEditor::ComponentControl(TInt aIndex) const
{
    ASSERT(iEditor);
    if (aIndex == 0)
    {
        return iEditor;
    }
    return iIndicator->IndicatorContainer();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::FocusChanged
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::FocusChanged(TDrawNow aDrawNow)
{
    if (iEditor)
    {
        TRAP_IGNORE(PrepareForFocusChangeL());
        iEditor->SetFocus(IsFocused());
    }

    HandleFocusChanged(aDrawNow);
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::MakeVisible
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::MakeVisible(TBool aVisible)
{
    // Close VKB. Do it here instead of FocusChange to avoid split input flicker.
    if (iEditor->IsFocused() && !aVisible)
    {
        CCoeFep* fep = iDisplay.CoeEnv()->Fep();
        if (fep)
        {
            fep->HandleDestructionOfFocusedItem();
        }
    }
    CCoeControl::MakeVisible(aVisible);
    FocusabilityChanged();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetBackgroundL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetBackgroundL(const MSwtColor* aColor)
{
    ASwtControlBase::DoSetBackgroundL(aColor);
    TRgb color((aColor) ? aColor->RgbValue() : iEikonEnv->Color(EColorControlBackground));
    iEditor->OverrideColorL(EColorControlBackground, color);

    // While background color is set, the editor's control context must be null,
    // otherwise there will be ugly background drawing problems while typing.
    // It looks like there is no need to override FocusBackgroundPolicy,
    // SetUseOverrideColors causes the editor to ignore the skin back.
    // If a foreground color has been set, cannot go back to skin colors yet.
    if (!iFgColorIsCustom)
    {
        if (aColor)
        {
            iEditor->SetUseOverrideColors(ETrue);
        }
        else
        {
            iEditor->SetUseOverrideColors(EFalse);
        }
    }

    if (aColor)
    {
        iBgColorIsCustom = ETrue;
    }
    else
    {
        iBgColorIsCustom = EFalse;
    }

    Redraw();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetForegroundL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetForegroundL(const MSwtColor* aColor)
{
    ASwtControlBase::DoSetForegroundL(aColor);

    TRgb color((aColor) ? aColor->RgbValue() : iEikonEnv->Color(EColorControlText));
    iEditor->OverrideColorL(EColorControlText, color);

    // If a back color has been set, cannot go back to skin colors yet.
    if (!iBgColorIsCustom)
    {
        if (aColor)
        {
            iEditor->SetUseOverrideColors(ETrue);
        }
        else
        {
            iEditor->SetUseOverrideColors(EFalse);
        }
    }

    if (aColor)
    {
        iFgColorIsCustom = ETrue;
    }
    else
    {
        iFgColorIsCustom = EFalse;
    }

    Redraw();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::OfferKeyEventL
// ---------------------------------------------------------------------------------------------
//
TKeyResponse CSwtDateEditor::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
    TBool traversalDoIt = ETrue;

    if (iEditor)
    {
        switch (aKeyEvent.iCode)
        {
        case EKeyUpArrow:
            traversalDoIt = ETrue;
            break;
        case EKeyDownArrow:
            traversalDoIt = ETrue;
            break;
        case EKeyRightArrow:
            traversalDoIt = ((iEditor->CurrentField() == iEditor->NumFields()-1) &&
                             (GetShell().FindTraversalTargetL(ESwtTraverseArrowNext, *this)));
            break;
        case EKeyLeftArrow:
            traversalDoIt = (iEditor->CurrentField() == 0 &&
                             GetShell().FindTraversalTargetL(ESwtTraverseArrowNext, *this));
            break;
        default:
            traversalDoIt = ETrue;
        }
    }

    return ASwtControlBase::HandleKeyL(aKeyEvent, aType, traversalDoIt);
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::ProcessKeyEventL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::ProcessKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
{
    if (!iEditor)
    {
        return;
    }

    if (aType != EEventKey)
        return;

    TInt code = aKeyEvent.iCode;
    TBool amPmField = IsFieldAmPmField(iEditor->CurrentField());
    TBool offsetStyleField = IsFieldOffsetStyleField(iEditor->CurrentField());

    TBool isFieldNumeric = !amPmField && !offsetStyleField;
    TBool wasFieldChangedAlready = IsCurrentFieldChanged(isFieldNumeric);
    UpdateFieldCounters(isFieldNumeric, wasFieldChangedAlready);

    iEditor->OfferKeyEventL(aKeyEvent, aType);
    //MSK label update may be needed.
    if (AknLayoutUtils::MSKEnabled())
    {
        MSwtCommandArranger* commandArranger = iDisplay.CommandArranger();
        if (commandArranger)
        {
            commandArranger->UpdateMSKLabelL();
        }
    }
    // End MSK
    if (aKeyEvent.iCode == EKeyEnter)
    {
        iDisplay.PostDefaultSelectionEventL(iPeer);
    }

    TBool isModifyEventAllowed = IsModifyEventAllowed(code, wasFieldChangedAlready);

    if (isModifyEventAllowed || amPmField || offsetStyleField)
    {
        iDisplay.PostModifyEventL(iPeer);
    }
}


// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsFieldChanged
// ---------------------------------------------------------------------------------------------
//

TBool CSwtDateEditor::IsCurrentFieldChanged(TBool aIsFieldNumeric)
{
    TBool isFieldChangedAlready = ETrue;
    if (aIsFieldNumeric)
    {
        isFieldChangedAlready = CEikMfneField::EInverseVideo !=
                                iEditor->Field(iEditor->CurrentField())->HighlightType();
    }
    return isFieldChangedAlready;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsFieldChanged
// ---------------------------------------------------------------------------------------------
//

void CSwtDateEditor::UpdateFieldCounters(TBool aIsFieldNumeric, TBool aIsFieldChanged)
{
    if (aIsFieldNumeric)
    {
        if (!aIsFieldChanged)
        {
            TBuf<16> actualText;
            actualText.AppendNum(
                static_cast<CEikMfneNumber*>(iEditor->Field(iEditor->CurrentField()))->Value());
            iCurrentFieldDecimalPlacesCount = actualText.Length();
            iCurrentFieldLength = 0;
        }
    }
    else
    {
        iCurrentFieldLength = 0;
        iCurrentFieldDecimalPlacesCount = 0;
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsModifyEventAllowed
// ---------------------------------------------------------------------------------------------
//
TBool CSwtDateEditor::IsModifyEventAllowed(TInt aKeyCode, TBool aWasFieldChangedAlready)
{
    TInt fieldMinimumValue = 0;
    TInt fieldMaximumValue = 0;
    CEikMfneNumber* currentField = static_cast<CEikMfneNumber*>(iEditor->Field(iEditor->CurrentField()));
    currentField->GetMinimumAndMaximum(fieldMaximumValue, fieldMaximumValue);
    TBuf<16> minText;
    minText.AppendNum(fieldMinimumValue);
    TBuf<16> maxText;
    maxText.AppendNum(fieldMaximumValue);
    TInt maxDigits = Max(2, Max(minText.Length(), maxText.Length()));
    TBool isZeroChar = 0 == (aKeyCode - TText(currentField->DigitType()));
    TBool raiseEvent = ETrue;
    TBool isArrowKey = (aKeyCode == EKeyLeftArrow) || (aKeyCode == EKeyRightArrow);
    TChar ch = TChar(aKeyCode);

    if (iEditor->CurrentField() != iLastField || isArrowKey)
    {
        iCurrentFieldLength = 0;
        iCurrentFieldDecimalPlacesCount = 0;
        if (isArrowKey && !aWasFieldChangedAlready)
        {
            raiseEvent = EFalse;
        }
    }
    else if (EKeyBackspace == aKeyCode)
    {
        if (!aWasFieldChangedAlready)
        {
            iCurrentFieldLength = maxDigits;
        }

        iCurrentFieldLength--;
        iCurrentFieldDecimalPlacesCount--;
        if (iCurrentFieldDecimalPlacesCount < 1)
        {
            raiseEvent = EFalse;
        }
    }
    else if (ch.IsDigit())
    {
        iCurrentFieldLength++;
        if (iCurrentFieldLength >= maxDigits)
        {
            iCurrentFieldLength = 0;
            iCurrentFieldDecimalPlacesCount = 0;
        }
        else
        {
            raiseEvent = !isZeroChar || (iCurrentFieldDecimalPlacesCount > 0);
        }
        if (!aWasFieldChangedAlready)
        {
            iCurrentFieldDecimalPlacesCount = 0;
        }
        if (!isZeroChar || (iCurrentFieldDecimalPlacesCount > 0 && isZeroChar))
        {
            iCurrentFieldDecimalPlacesCount++;
        }
    }
    else
    {
        raiseEvent = false;
    }

    iLastField = iEditor->CurrentField();

    return raiseEvent;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsFieldAmPmField
// ---------------------------------------------------------------------------------------------
//
TBool CSwtDateEditor::IsFieldAmPmField(TInt fieldIndex) const
{
    // current field is am/pm field if it accepts something else than positive integers
    TBool amPmField = (iDateEditorStyle == MSwtDateEditor::ESwtTime ||
                       iDateEditorStyle == MSwtDateEditor::ESwtDateTime)  &&
                      (iEditor->Field(fieldIndex)->InputCapabilities().Capabilities() &
                       ~TCoeInputCapabilities::EWesternNumericIntegerPositive);
    return amPmField;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsFieldOffsetStyleField
// ---------------------------------------------------------------------------------------------
//
TBool CSwtDateEditor::IsFieldOffsetStyleField(TInt fieldIndex) const
{
    // current field is +/- field if it accepts something else than positive integers
    TBool offsetStyleField = (iDateEditorStyle == MSwtDateEditor::ESwtOffset)  &&
                             (iEditor->Field(fieldIndex)->InputCapabilities().Capabilities() &
                              ~TCoeInputCapabilities::EWesternNumericIntegerPositive);
    return offsetStyleField;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetDimmed
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetDimmed(TBool aDimmed)
{
    ASSERT(iEditor);

    // Close VKB. Do it here instead of FocusChange to avoid split input flicker.
    if (iEditor->IsFocused() && aDimmed)
    {
        CCoeFep* fep = iDisplay.CoeEnv()->Fep();
        if (fep)
        {
            fep->HandleDestructionOfFocusedItem();
        }
    }

    CCoeControl::SetDimmed(aDimmed);
    iEditor->SetDimmed(aDimmed);
    FocusabilityChanged();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::HandleResourceChange
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::HandleResourceChange(TInt aType)
{
    TRAP_IGNORE(SwtHandleResourceChangeL(aType));
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SwtHandleResourceChangeL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SwtHandleResourceChangeL(TInt aType)
{
    CAknControl::HandleResourceChange(aType);

    if (aType == KAknsMessageSkinChange
            || aType == KEikDynamicLayoutVariantSwitch)
    {
        if (!iFont)
        {
            RetrieveDefaultFontL();
        }
        else
        {
            ProcessFontUpdate();
        }
        SizeChanged();
    }
#ifdef RD_JAVA_S60_RELEASE_9_2
    else if (aType == KAknSplitInputEnabled)
    {
        const MSwtShell* activeShell = iDisplay.UiUtils().GetActiveShell();
        if (activeShell && activeShell->FocusControl() == this)
        {
            iDisplay.UiUtils().SetSplitInputEditor(this);
        }
    }
#endif
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SizeChanged
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SizeChanged()
{
    if (!iEditor)
    {
        return;
    }

    // Update component size
    // Place the Editor at the center of the SwtDateEditor
    TSize swtSize(BorderInnerRect().Size());
    TPoint swtPos(Position());

    if (iIndicator)
    {
        const TPoint indPos(swtPos.iX + GetBorderWidth(),
                            swtPos.iY + GetBorderWidth());
        iIndicator->IndicatorContainer()->SetPosition(indPos);

        const TSize indicatorSize(swtSize.iWidth, KSWTEditIndicatorHeight);
        iIndicator->IndicatorContainer()->SetSize(indicatorSize);
        swtSize.iHeight -= indicatorSize.iHeight;
        swtPos.iY += indicatorSize.iHeight;
    }

    // The native editor adds these margins, so we have to consider them also.
    TInt topMargin(0);
    TInt bottomMargin(0);
    TAknTextDecorationMetrics metrics(iEditor->Font());
    metrics.GetTopAndBottomMargins(topMargin, bottomMargin);

    // MinimumSize returns the actual size of the control, so we need to set its size,
    // otherwise we will always receive 0.
    iEditor->SetSize(TSize(iEditor->Size().iWidth,
                           iEditor->Font()->FontMaxHeight() + topMargin + bottomMargin));
    TSize editorSize(iEditor->MinimumSize());

    TSize buttonEdSiz(editorSize);
    TPoint editorPos(0, 0);

    // calculates horizontal alignment of date in the editor
    if (swtSize.iWidth > buttonEdSiz.iWidth)
    {
        editorPos.iX += swtPos.iX + static_cast<TInt>((swtSize.iWidth-
                        buttonEdSiz.iWidth)/2.0) ;
    }
    else
    {
        editorPos.iX += swtPos.iX;
    }

    // calculates vertical alignment of date in the editor
    if (swtSize.iHeight > buttonEdSiz.iHeight)
    {
        editorPos.iY = swtPos.iY + static_cast<TInt>((swtSize.iHeight-
                       buttonEdSiz.iHeight)/2.0) ;
    }
    else
    {
        editorPos.iY = swtPos.iY;
    }

    iEditor->SetPosition(TPoint(editorPos.iX + GetBorderWidth(), editorPos.iY + GetBorderWidth()));

    if (iEditor->SupportsFeature(CEikMfne::EClipGcToRect))
    {
        iEditor->SetFeature(CEikMfne::EClipGcToRect, ETrue);
    }

    // places the editor on the center
    TSize newEditorSize(
        (swtSize.iWidth > editorSize.iWidth) ? editorSize.iWidth : swtSize.iWidth,
        (swtSize.iHeight > editorSize.iHeight) ? editorSize.iHeight : swtSize.iHeight);

    iEditor->SetSize(newEditorSize);

    HandleSizeChanged();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::PositionChanged
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::PositionChanged()
{
    HandlePositionChanged();
    // Notify change to UiUtils if this is an editor open for split view editing.
    MSwtUiUtils& utils = iDisplay.UiUtils();
    if (utils.SplitInputView() == this)
    {
        utils.AdjustSplitInputShellPos();
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::MopSupplyObject
// ---------------------------------------------------------------------------------------------
//
TTypeUid::Ptr CSwtDateEditor::MopSupplyObject(TTypeUid aId)
{
    if (iIndicator && aId.iUid == MAknEditingStateIndicator::ETypeId)
    {
        return aId.MakePtr(static_cast<MAknEditingStateIndicator*>(iIndicator));
    }
    TTypeUid::Ptr id = ASwtControlBase::SwtMopSupplyObject(aId);
    if (!id.Pointer())
    {
        return CCoeControl::MopSupplyObject(aId);
    }
    return id;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::CoeControl
// ---------------------------------------------------------------------------------------------
//
CCoeControl& CSwtDateEditor::CoeControl()
{
    return *this;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::CoeControl
// ---------------------------------------------------------------------------------------------
//
const CCoeControl& CSwtDateEditor::CoeControl() const
{
    return *this;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::ComputeSizeL
// ---------------------------------------------------------------------------------------------
//
TSize CSwtDateEditor::ComputeSizeL(TInt aWHint, TInt aHHint)
{
    if (!iEditor)
    {
        // iEditor could be null if the CSwtDateEditor is contained in a CaptionedControl.
        // When the method CaptionedControl::RegisterChildL() is called,
        // a SetSize() is made on its children, hence a call to ComputeSizeL().
        return TSize(0, 0);
    }

    if (aWHint != KSwtDefault && aHHint != KSwtDefault)
    {
        return TSize(aWHint, aHHint);
    }

    TSize size(iEditor->MinimumSize());
    if (iIndicator)
    {
        size.iHeight += KSWTEditIndicatorHeight;
    }
    size.iHeight = Max(iEditor->Font()->FontMaxHeight(), size.iHeight);
    if (GetFont() == &DefaultFont())
    {
        size.iHeight = Max(iDisplay.UiUtils().InlineReferenceFontHeight(), size.iHeight);
    }
    size += iDisplay.UiUtils().InlineReferencePadding().SizeDelta();
    size += BorderSizeDelta();

    if (aWHint != KSwtDefault)
    {
        size.iWidth = aWHint;
    }
    if (aHHint != KSwtDefault)
    {
        size.iHeight = aHHint;
    }

    return size;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetFontL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetFontL(const MSwtFont* aFont)
{
    // Does nothing. The font of the native editor is managed by the system.
    // It can't be modified.
    ASwtControlBase::DoSetFontL(aFont);
    if (iEditor)
    {
        ProcessFontUpdate();
    }
    SizeChanged();
    Redraw();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::DefaultFont
// ---------------------------------------------------------------------------------------------
//
const MSwtFont& CSwtDateEditor::DefaultFont() const
{
    return *iDefaultFont;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::Control
// ---------------------------------------------------------------------------------------------
//
MSwtControl* CSwtDateEditor::Control()
{
    return static_cast<MSwtControl*>(this);
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::GetDate
// ---------------------------------------------------------------------------------------------
//
TInt64 CSwtDateEditor::GetDate()
{
    ASSERT(iEditor);
    TInt64 result(0);

    switch (iDateEditorStyle)
    {
    case ESwtDate:
    {
        // The Date style contains only day infos. No time infos.
        // So we get the original time set in Java, and update only the day.
        // Thus, no need to take TimeZone into account.
        TTime getDate(static_cast<CEikDateEditor*>(iEditor)->Date());
        TDateTime javaDateTime(TTime(iJavaDateInMicroSec).DateTime());
        TDateTime onlyTime(0, EJanuary, 0, javaDateTime.Hour(), javaDateTime.Minute(),
                           javaDateTime.Second(), javaDateTime.MicroSecond());
        TTime clockInTTime(onlyTime);
        result = clockInTTime.Int64() + getDate.Int64() - iEpocDateInMicroSec;
    }
    break;

    case ESwtTime:
    {
        TTime getTime(static_cast<CEikTimeEditor*>(iEditor)->Time());
        TDateTime javaDateTime(TTime(iJavaDateInMicroSec).DateTime());
        TDateTime onlyDay(javaDateTime.Year(), javaDateTime.Month(),
                          javaDateTime.Day(), 0, 0, 0, 0);
        TTime dayInTTime(onlyDay);
        result = dayInTTime.Int64() + getTime.Int64();
    }
    break;

    case ESwtDateTime:
        result = static_cast<CEikTimeAndDateEditor*>(iEditor)->TimeAndDate().Int64()
                 - iEpocDateInMicroSec;
        break;

    default:
        break;
    }

    return result;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::GetOffset
// ---------------------------------------------------------------------------------------------
//
TInt CSwtDateEditor::GetOffset() const
{
    ASSERT(iEditor);

    switch (iDateEditorStyle)
    {
    case ESwtDuration:
        return static_cast<CEikDurationEditor*>(iEditor)->Duration().Int();

    case ESwtOffset:
        return static_cast<CEikTimeOffsetEditor*>(iEditor)->TimeOffset().Int();

    case ESwtTime:
        return static_cast<TInt64>(static_cast<CEikTimeEditor*>(
                                       iEditor)->Time().Int64() / 1000000);

    default:
        break;
    }

    return 0;
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetDate
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetDate(const TInt64& aJavaDate)
{
    ASSERT(iEditor);

    iJavaDateInMicroSec = aJavaDate;
    TTime date(iEpocDateInMicroSec + iJavaDateInMicroSec);

    switch (iDateEditorStyle)
    {
    case ESwtDate:
        static_cast<CEikDateEditor*>(iEditor)->SetDate(date);
        break;

    case ESwtTime:
    {
        TDateTime dateTime(date.DateTime());
        TInt64 onlyTimeInMicroSec(dateTime.Hour() * 3600
                                  + dateTime.Minute() * 60
                                  + dateTime.Second());
        onlyTimeInMicroSec = onlyTimeInMicroSec * 1000000;
        onlyTimeInMicroSec += dateTime.MicroSecond();
        static_cast<CEikTimeEditor*>(iEditor)->SetTime(TTime(onlyTimeInMicroSec));
    }
    break;

    case ESwtDateTime:
        static_cast<CEikTimeAndDateEditor*>(iEditor)->SetTimeAndDate(date);

        break;

    default:
        break;
    }
    Redraw();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetDateEditorStyleL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetDateEditorStyleL(TInt aDateEditorStyle)
{
    TTime initialDate;
    initialDate.HomeTime();
    iJavaDateInMicroSec = initialDate.Int64() - iEpocDateInMicroSec;

    // Create the editor, according to the style
    iDateEditorStyle  = aDateEditorStyle & 0xf;
    iDateEditorFormat = aDateEditorStyle & 0xf0;

    //Clear field counters
    iCurrentFieldLength = 0;
    iLastField = 0;
    iCurrentFieldDecimalPlacesCount = 0;

    TUint32 editorFlags = 0;
    if (iDateEditorFormat == ESwtCompact)
    {
        editorFlags = EEikTimeWithoutSecondsField;
    }

    switch (iDateEditorStyle)
    {
    case ESwtDate:
    {
        TBool withoutPopoutCalendar = EFalse;
        if (iDateEditorFormat == ESwtCompact)
        {
            withoutPopoutCalendar = ETrue;
        }
        iEditor = new(ELeave) CEikDateEditor();
        static_cast<CEikDateEditor*>(iEditor)->ConstructL(
            KAknMinimumDate, KAknMaximumDate, initialDate, withoutPopoutCalendar);
    }
    break;

    case ESwtTime:
    {
        iEditor = new(ELeave) CEikTimeEditor();
        static_cast<CEikTimeEditor*>(iEditor)->ConstructL(
            TTime(TInt64(0)),
            TTime(TInt64(KSwtSecondsInOneDay)*1000000), initialDate, editorFlags);
    }
    break;

    case ESwtDateTime:
    {
        iEditor = new(ELeave) CEikTimeAndDateEditor();
        static_cast<CEikTimeAndDateEditor*>(iEditor)->ConstructL(
            KAknMinimumDate, KAknMaximumDate, initialDate, editorFlags);
    }
    break;

    case ESwtDuration:
    {
        iEditor = new(ELeave) CEikDurationEditor();
        static_cast<CEikDurationEditor*>(iEditor)->ConstructL(
            TTimeIntervalSeconds(0),
            TTimeIntervalSeconds(KSwtSecondsInOneDay),
            TTimeIntervalSeconds(0), editorFlags);
    }
    break;

    case ESwtOffset:
    {
        iEditor = new(ELeave) CEikTimeOffsetEditor();
        static_cast<CEikTimeOffsetEditor*>(iEditor)->ConstructL(
            TTimeIntervalSeconds(-KSwtSecondsInOneDay),
            TTimeIntervalSeconds(KSwtSecondsInOneDay),
            TTimeIntervalSeconds(0), editorFlags);
    }
    break;

    default:
        break;
    }

    if (iEditor)
    {
        iEditor->SetContainerWindowL(*this);
        iEditor->SetFocusing(ETrue);
        iEditor->MakeVisible(IsVisible());
        iEditor->SetFocus(IsFocused());
        iEditor->SetDimmed(IsDimmed());
        RetrieveDefaultFontL();
        iEditor->SetSkinTextColorL(EAknsCIQsnTextColorsCG6);

#ifdef RD_JAVA_S60_RELEASE_9_2
        if (iEditor->SupportsFeature(CEikMfne::EPartialScreenInput))
        {
            iEditor->SetFeature(CEikMfne::EPartialScreenInput, ETrue);
        }
#endif
    }
    ActivateL();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetOffset
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetOffset(TInt aSeconds)
{
    switch (iDateEditorStyle)
    {
    case ESwtDuration:
        static_cast<CEikDurationEditor*>(iEditor)->SetDuration(
            TTimeIntervalSeconds(aSeconds));
        break;

    case ESwtOffset:
        static_cast<CEikTimeOffsetEditor*>(iEditor)->SetTimeOffset(
            TTimeIntervalSeconds(aSeconds));
        break;

    case ESwtTime:
    {
        aSeconds = aSeconds % 86400; // 24 hours.
        TInt hour = aSeconds / 3600;
        TInt minute = (aSeconds - hour * 3600) / 60;
        TInt second = aSeconds - 3600*hour - 60*minute;
        TDateTime datetime(0, EJanuary, 0, hour, minute, second, 0);
        TTime time(datetime);
        static_cast<CEikTimeEditor*>(iEditor)->SetTime(time);
    }
    break;

    default:
        break;
    }
    Redraw();

}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::GetMinimumAndMaximumAndInitialDatesForCalendarL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::GetMinimumAndMaximumAndInitialDatesForCalendarL(
    TTime &aMinimumDate,
    TTime &aMaximumDate,
    TTime &aInitialDate) const
{
    ASSERT(iEditor);

    switch (iDateEditorStyle)
    {
    case ESwtDateTime:
        static_cast<CEikTimeAndDateEditor*>(iEditor)->GetMinimumAndMaximum(
            aMinimumDate, aMaximumDate);
        aInitialDate = static_cast<CEikTimeAndDateEditor*>(iEditor)->TimeAndDate();
        break;

    default:
        break;
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::SetDateFromCalendarAndDrawNow
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::SetDateFromCalendarAndDrawNow(const TTime &aDate)
{
    ASSERT(iEditor);

    switch (iDateEditorStyle)
    {
    case ESwtDateTime:
    {
        TDateTime current(static_cast<CEikTimeAndDateEditor*>(
                              iEditor)->TimeAndDate().DateTime());
        TDateTime setDateTime(aDate.DateTime());
        setDateTime.SetHour(current.Hour());
        setDateTime.SetMinute(current.Minute());
        setDateTime.SetSecond(current.Second());
        setDateTime.SetMicroSecond(current.MicroSecond());
        static_cast<CEikTimeAndDateEditor*>(iEditor)->SetTimeAndDate(
            TTime(setDateTime));
    }
    break;

    default:
        break;
    }
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::MSKLabelL
// ---------------------------------------------------------------------------------------------
//
HBufC* CSwtDateEditor::MSKLabelL() const
{
    if (iEditor && (IsFieldAmPmField(iEditor->CurrentField()) ||
                    IsFieldOffsetStyleField(iEditor->CurrentField())))
    {
        HBufC* label = iEikonEnv->AllocReadResourceL(R_QTN_MSK_CHANGE);
        return label ;
    }
    return ASwtControlBase::MSKLabelL();
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::IsKeyUsed
// ---------------------------------------------------------------------------------------------
//
TBool CSwtDateEditor::IsKeyUsed(TUint aKeyCode) const
{
    if (iEditor && (IsFieldAmPmField(iEditor->CurrentField()) ||
                    IsFieldOffsetStyleField(iEditor->CurrentField())) && aKeyCode == EKeyOK)
    {
        return ETrue;
    }
    return EFalse;
}


void CSwtDateEditor::SetBounds(const TRect& aRect)
{
    // Divert the job to UiUtils if this is an editor open for split view editing.
    MSwtUiUtils& utils = iDisplay.UiUtils();
    if (utils.SplitInputView() == this)
    {
        utils.SetSplitInputViewSize(aRect.Size());
        SetLocation(aRect.iTl);
    }
    else
    {
        ASwtControlBase::SetBounds(aRect);
    }
}

void CSwtDateEditor::SetWidgetSize(const TSize& aSize)
{
    // Divert the job to UiUtils if this is an editor open for split view editing.
    MSwtUiUtils& utils = iDisplay.UiUtils();
    if (utils.SplitInputView() == this)
    {
        utils.SetSplitInputViewSize(aSize);
    }
    else
    {
        ASwtControlBase::SetWidgetSize(aSize);
    }
}

TSwtPeer CSwtDateEditor::Dispose()
{
    // Close VKB.
    if (iEditor->IsFocused())
    {
        CCoeFep* fep = iDisplay.CoeEnv()->Fep();
        if (fep)
        {
            fep->HandleDestructionOfFocusedItem();
        }
    }
    return ASwtControlBase::Dispose();
}


// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::HandlePointerEventL
// ---------------------------------------------------------------------------------------------
//
#if defined( RD_SCALABLE_UI_V2 )
void CSwtDateEditor::HandlePointerEventL(const TPointerEvent& aPointerEvent)
{
    TBool hit = ETrue;

#ifdef RD_JAVA_S60_RELEASE_9_2
    TBool isActiveSplitEditor = iDisplay.UiUtils().SplitInputEditor() == this;
    TBool pressed = iPressed;
    hit = Rect().Contains(aPointerEvent.iPosition);

    if (aPointerEvent.iType == TPointerEvent::EButton1Down)
        iPressed = !isActiveSplitEditor;
    else if (aPointerEvent.iType == TPointerEvent::EButton1Up)
        iPressed = EFalse;
    else if (aPointerEvent.iType == TPointerEvent::EDrag)
        iPressed = hit && !isActiveSplitEditor;
#endif

    if (!(aPointerEvent.iType == TPointerEvent::EButton1Up
            && (iDisplay.RevertPointerEvent() || !hit)))
    {
        iEditor->HandlePointerEventL(aPointerEvent);

        //MSK label update may be needed.
        if (AknLayoutUtils::MSKEnabled())
        {
            MSwtCommandArranger* commandArranger = iDisplay.CommandArranger();
            if (commandArranger)
            {
                commandArranger->UpdateMSKLabelL();
            }
        }
        // End MSK
    }

    //Selected field might changed
    iCurrentFieldLength = 0;
    iCurrentFieldDecimalPlacesCount = 0;
    iLastField = iEditor->CurrentField();

#ifdef RD_JAVA_S60_RELEASE_9_2
    if (pressed != iPressed)
        Redraw();
#endif

    PostMouseEventL(aPointerEvent);
}

// ---------------------------------------------------------------------------------------------
// CSwtDateEditor::HandleControlEventL
// ---------------------------------------------------------------------------------------------
//
void CSwtDateEditor::HandleControlEventL(CCoeControl* /*aControl*/, TCoeEvent /*aEventType*/)
{
}
#endif // RD_SCALABLE_UI_V2