javauis/lcdui_akn/lcdui/src/CMIDStringItem.cpp
branchRCL_3
changeset 19 04becd199f91
child 34 71c436fe3ce0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDStringItem.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1142 @@
+/*
+* Copyright (c) 2003-2007 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:  ?Description
+*
+*/
+
+
+#include <eiklabel.h>
+// AknsUtils used for label and content colors settings
+#include <AknsDrawUtils.h>
+// skins for drawing
+#include <skinlayout.cdl.h>
+#include <AknUtils.h>
+#include <applayout.cdl.h>
+// LAF
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <aknconsts.h>
+#include <avkon.mbg>
+
+#include "CMIDStringItem.h"
+// API for iCommandList
+#include "CMIDCommandList.h"
+// some API for text formating before label settings
+#include "CMIDUtils.h"
+// CMIDItemLabel* iContentControl
+#include "CMIDItemLabel.h"
+
+#include <j2me/jdebug.h>
+
+
+/** This constant determines the maximum number
+of lines for button labels and content */
+const TInt KMaxNumLinesForButtons = 10;
+
+/** Content can have unlimited lines */
+const TInt KMaxNumLinesForContent = -1;
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+MMIDStringItem* CMIDStringItem::NewL(
+    const TDesC& aLabel, const TDesC& aText, TAppearance aAppearance, CMIDUIManager* aUIManager)
+{
+    CMIDStringItem* item=new(ELeave) CMIDStringItem(aAppearance, aUIManager);
+    CleanupStack::PushL(item);
+    item->ConstructL(aLabel,aText);
+    CleanupStack::Pop(item);
+    return item;
+}
+
+/**
+ * Assumes label has been set before in order to work out if a prefix is
+ * required
+ */
+void CMIDStringItem::SetTextL(const TDesC& aText)
+{
+    DEBUG("CMIDStringItem::SetTextL - begin");
+
+    delete iText;
+    iText = NULL;
+
+    // count the newlines at the beginning and the end of the content
+    CountNewlinesBeforeAndAfter(aText);
+
+    // create a TPtrC of the string without the beginning and training newlines
+    TPtrC ptr;
+    if (iNumNewlinesBefore < aText.Length())
+    {
+        ptr.Set(aText.Mid(iNumNewlinesBefore, aText.Length() -
+                          (iNumNewlinesBefore + iNumNewlinesAfter)));
+    }
+
+    iText = ptr.AllocL();
+    if (iText->Length() != 0)
+    {
+        CMIDUtils::MapJavaToETextChars(iText);
+    }
+
+    iContentControl->SetTextL(*iText);
+    if (iAppearance == MMIDItem::EButton)
+    {
+        // leave only text before line separator, if any
+        TInt i = 0;
+        while ((i < iText->Length()) && (!CMIDUtils::IsLineSeparator((*iText)[i])))
+        {
+            i++;
+        }
+        ptr.Set(iText->Mid(0, i));
+
+        // if there was line separator add ellipis in the end
+        HBufC* textWithEllipsis = HBufC::NewLC(i + 1);
+        textWithEllipsis->Des().Append(ptr); // text without line separators
+        if (i < iText->Length())
+        {
+            // if there was line separator add ellipsis in the end
+            textWithEllipsis->Des().Append(KEllipsis);
+        }
+
+        iButton->State()->SetTextL(textWithEllipsis->Des());
+
+        CleanupStack::PopAndDestroy(textWithEllipsis);
+    }
+
+    if (iForm)
+    {
+        iForm->RequestLayoutL();
+    }
+    DEBUG("CMIDStringItem::SetTextL - end");
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CMIDStringItem::CMIDStringItem(TAppearance aAppearance, CMIDUIManager* aUIManager)
+        : CMIDControlItem(EDefault, aUIManager),
+        iAppearance(aAppearance),
+        iIsDivided(EFalse)
+{
+    iMMidItem = this;
+}
+
+void CMIDStringItem::ConstructL(const TDesC& aLabel,const TDesC& aText)
+{
+    DEBUG("CMIDStringItem::ConstructL - begin");
+    // Initializes the label control
+    CMIDControlItem::ConstructL();
+
+    if (iAppearance == MMIDItem::EButton)
+    { //buttons can only have one line
+
+        iButton = CAknButton::NewL(NULL,   // aIcon
+                                   NULL,  // aDimmedIcon
+                                   NULL,  // aPressedIcon
+                                   NULL,  // aHoverIcon
+                                   aText,
+                                   KNullDesC,
+                                   KAknButtonSizeFitText, // iFlags set to respect text width
+                                   0);
+        iLabelControl->SetMaxNumLines(KMaxNumLinesForButtons);
+    }
+    // iContentControl is always created because RenderedAppearance() can be PLAIN
+    iContentControl = CMIDItemLabel::NewL(FormClientAreaWidth(), ETrue,
+                                          KMaxNumLinesForContent, CMIDFont::EDefaultTextId, ETrue);
+
+
+    SetLabelL(aLabel);
+    SetTextL(aText); // Sets CMIDStringitem::iText
+    iContentControl->SetFont(Font());
+    if (iAppearance != MMIDItem::EButton)
+    {
+        MMIDFont* font = Font();
+        if (font)
+        {
+            iButton->SetTextFont(font->Font());
+        }
+    }
+    SetColorL();
+
+    if (iAppearance == MMIDItem::EButton)
+    {
+        CalculateButtonEllipsedSizeL();
+    }
+    ResetPreferredSize();
+
+#ifdef RD_TACTILE_FEEDBACK
+    iFeedback = MTouchFeedback::Instance();
+#endif
+
+    DEBUG("CMIDStringItem::ConstructL - end");
+}
+
+CMIDStringItem::~CMIDStringItem()
+{
+    delete iText;
+    delete iContentControl;
+    delete iButton;
+}
+
+void CMIDStringItem::SetContainerWindowL(const CCoeControl& aContainer)
+{
+    CMIDControlItem::SetContainerWindowL(aContainer);
+    iContentControl->SetContainerWindowL(*this);
+    if (iAppearance == MMIDItem::EButton)
+    {
+        iButton->SetContainerWindowL(*this);
+    }
+    ActivateL();
+}
+
+void CMIDStringItem::CountNewlinesBeforeAndAfter(const TDesC& aText)
+{
+    TInt i = 0;
+
+    iNumNewlinesBefore = 0;
+    iNumNewlinesAfter = 0;
+    while ((i < aText.Length()) && (aText[i] == '\n'))
+    {
+        iNumNewlinesBefore++;
+        i++;
+    }
+
+    if (iNumNewlinesBefore == aText.Length())
+    {
+        return;
+    }
+
+    // we get here if the string isn't all newlines
+    i = aText.Length() - 1;
+    while ((i >= 0) && (aText[i] == '\n'))
+    {
+        iNumNewlinesAfter++;
+        i--;
+    }
+}
+
+TBool CMIDStringItem::IsSelectable() const
+{
+    return (iCommandList->Count() > 0);
+}
+
+/**
+ * Sets the preferred width and height for this Item. If the width is between zero and
+ * the minimum width, inclusive, the minimum width is used. If the height is between
+ * zero and the minimum height, inclusive, the minimum height is used.
+ * By default, the preferred width and height are based entirely on the Item's contents.
+ * If both width and height parameters are -1, the default values for width and height
+ * are established. If neither width nor height is -1, the values specified become the
+ * Item's preferred size.
+ *
+ * If width is -1 and height is a legal value, the width will be computed based on the
+ * item's contents and the given height. If height is -1 and width is a legal value,
+ * the height will be computed based on the item's contents and the given width.
+ *
+ * If a StringItem has been assigned a preferred width or height by
+ * the application, it is wrapped to fit that width and height and
+ * is treated as a rectangle whose minimum and preferred width and height
+ * are the width and height of this rectangle
+ *
+ * iPreferredSize includes margins. Margins are added in CMIDItemLabel class.
+ */
+void CMIDStringItem::SetPreferredSizeL(const TSize& aSize)
+{
+
+    iRequestedPreferredSize = CheckRequestedSize(aSize);
+    iPreferredSize = iRequestedPreferredSize;
+
+    if (iPreferredSize.iWidth < 0)
+    { // width is not specified
+        if (RenderedAppearance() != MMIDItem::EButton)
+        {
+            iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(),
+                                        iContentControl->PreferredWidth());
+        }
+        else
+        {
+            iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(),
+                                        iButton->MinimumSize().iWidth);
+            // add margins
+            TAknWindowLineLayout layout =
+                AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
+            TInt leftMargin = layout.il;
+            TInt rightMargin = layout.ir;
+            iPreferredSize.iWidth += leftMargin + rightMargin; // add left and right margins
+        }
+    }
+
+    TSize minimumSize = MinimumSize();
+
+    // make sure the width doesn't get bigger than the form width
+    iPreferredSize.iWidth = Min(iPreferredSize.iWidth, FormClientAreaWidth());
+
+    // make sure the width doesn't get smaller than the minimum width
+    iPreferredSize.iWidth = Max(iPreferredSize.iWidth, minimumSize.iWidth);
+
+    // preferred width is set to label and content
+    if (iLabelControl && iLabelControl->Text()->Length() > 0)
+    {
+        iLabelControl->SetWidthL(iPreferredSize.iWidth);
+    }
+    if (RenderedAppearance() != MMIDItem::EButton)
+    {
+        iContentControl->SetWidthL(iPreferredSize.iWidth);
+    }
+    else
+    {
+        SetButtonWidth(iPreferredSize.iWidth);
+    }
+
+    if (iPreferredSize.iHeight < 0)
+    {  // height is not specified, do text wrapping (call SetWidthL)
+        // so that we can then calculate the height
+        iPreferredSize.iHeight = LabelHeight() + ItemPreferredHeightWithoutLabel();
+    }
+
+    //make sure the preferred size is not smaller than the minimum size
+    iPreferredSize.iHeight = Max(iPreferredSize.iHeight, minimumSize.iHeight);
+
+    if ((minimumSize.iWidth == 0) && (minimumSize.iHeight == 0))
+    { //it means there is no control and no label, so set our size to null
+        iPreferredSize.iWidth = 0;
+        iPreferredSize.iHeight = 0;
+    }
+
+    AdjustToSizeL(iPreferredSize);
+}
+
+TSize CMIDStringItem::MinimumSize() const
+{
+    TInt numNewLines = iNumNewlinesBefore + iNumNewlinesAfter;
+    TBool labelNotEmpty = (iLabelControl->Text()->Length() > 0);
+
+    TInt width;
+    TInt height;
+    if (RenderedAppearance() != MMIDItem::EButton)
+    {
+        // if no label and no content then size is zero
+        if (!labelNotEmpty  &&
+                ((iContentControl->Text()->Length() == 0)) && (numNewLines == 0))
+        {
+            return TSize(0, 0);
+        }
+
+        width = Max(iLabelControl->MinimumSize().iWidth, iContentControl->MinimumSize().iWidth);
+        height = (
+                     (iLabelControl && iLabelControl->Text()->Length() > 0) ?
+                     OneLineLabelHeight() : 0) +
+                 (iContentControl ?
+                  iContentControl->LineHeight() + iContentControl->ItemLabelMargin() : 0) +
+                 ItemContentBottomMargin();
+
+        if (width > FormClientAreaWidth())
+        {
+            width = FormClientAreaWidth();
+        }
+    }
+    else
+    {
+        // if no label and no content then size is zero
+        if (!labelNotEmpty
+                &&((iButton->State()->Text().Length() == 0))
+                && (numNewLines == 0))
+        {
+            return TSize(0, 0);
+        }
+
+        TInt width = iEllipsedButtonSize.iWidth;
+        TInt height = iEllipsedButtonSize.iHeight;
+
+        // add margins
+        TAknWindowLineLayout layout =
+            AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
+        TInt leftMargin = layout.il;
+        TInt rightMargin = layout.ir;
+
+        width = Max(iLabelControl->MinimumSize().iWidth, width);
+        width += leftMargin + rightMargin; // add left and right margins
+
+        if (labelNotEmpty)
+        {
+            height += OneLineLabelHeight() + ItemContentBottomMargin(); // add label and bottom margin
+        }
+        else
+        {
+            height += ItemContentBottomMargin(); // use the value for top margin
+        }
+
+        if (width > FormClientAreaWidth())
+        {
+            width = FormClientAreaWidth();
+        }
+        return TSize(width, height);
+    }
+    return TSize(width, height);
+}
+
+#ifdef RD_SCALABLE_UI_V2
+void CMIDStringItem::HandlePointerEventL(const TPointerEvent &aPointerEvent)
+{
+    if (AknLayoutUtils::PenEnabled())
+    {
+        // check if string item is a hyperlink and colour the link according to activation/deactivation with pointer
+        // note that want to colour the link and have tactile feedback even though have long tap
+        if (RenderedAppearance() == EHyperLink)
+        {
+            if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+            {
+                if (!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) ||
+                        iForm->StringItemContainsPoint(this, aPointerEvent.iPosition))
+                {
+                    iHyperLinkActivated = ETrue;
+#ifdef RD_TACTILE_FEEDBACK
+                    // RenderedAppearance returns EHyperlink for initially hyperlink-created StringItem,
+                    // or for plain-created StringItem with commands added later.
+                    // if focus is changing, tactile feedback is given already in Form
+                    if (!iForm->IsFocusChangingWithPen())
+                    {
+#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+                        //Feedback for HYPERLINK only on touch down
+                        iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton);
+#else
+                        iFeedback->InstantFeedback(ETouchFeedbackBasic);
+#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+                    }
+#endif // RD_TACTILE_FEEDBACK
+                }
+                else // tap on label
+                {
+                    iHyperLinkActivated = EFalse;
+                }
+                FocusChanged(EDrawNow);
+            }
+        }
+
+        if (aPointerEvent.iType == TPointerEvent::EButton1Down)
+        {
+            iPointerDownOnContentArea = iForm->StringItemContainsPoint(
+                                            this, aPointerEvent.iPosition);
+        }
+
+        // pass the event to the button
+        if (iButton)
+        {
+
+#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+            if (aPointerEvent.iType == TPointerEvent::EButton1Down &&
+                    iForm->IsFocusChangingWithPen() &&
+                    !(!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) ||
+                      iForm->StringItemContainsPoint(this, aPointerEvent.iPosition)))
+            {
+                //On touch down, when focus is changing to this item and user
+                //tapped to label (if exists), it should give sesitive list feedback
+                iFeedback->InstantFeedback(ETouchFeedbackSensitiveList);
+            }
+#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+
+            CCoeControl::HandlePointerEventL(aPointerEvent);
+        }
+
+        TBool consumed = iForm->TryDetectLongTapL(aPointerEvent);
+        if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+        {
+            // always remove hyperlink activated colour
+            iHyperLinkActivated = EFalse;
+            if (!consumed)
+            {
+                if (!iButton)
+                {
+                    CMIDControlItem::HandlePointerEventL(aPointerEvent);
+                }
+                // check if the pen was dragged out of button and that pointer down has happened on content area,
+                // i.e. dragging pointer from label to content area should not invoke any action.
+                if (!iForm->PhysicsScrolling() && (iForm->StringItemContainsPoint(this, aPointerEvent.iPosition) &&
+                                                   iPointerDownOnContentArea))
+                {
+                    iForm->HandleTouchControlEventL(this, MCoeControlObserver::EEventStateChanged);
+                }
+            }
+            FocusChanged(EDrawNow);
+        }
+    }
+}
+#endif // RD_SCALABLE_UI_V2
+
+/** Recalculate the preferred size.*/
+TSize CMIDStringItem::ResetPreferredSize() const
+{
+    CMIDStringItem* self = const_cast<CMIDStringItem*>(this);
+    TRAP_IGNORE(self->SetPreferredSizeL(iRequestedPreferredSize));
+    return iPreferredSize;
+}
+
+/** @see CMIDControlItem::AdjustToNewWidthL()
+* Margins are added in CMIDItemLabel class */
+void CMIDStringItem::AdjustToNewWidthL(TInt aWidth)
+{
+    ASSERT(aWidth >= 0);
+
+    if (aWidth != iPreferredSize.iWidth)
+    {
+        if (RenderedAppearance() != MMIDItem::EButton)
+        {
+            iContentControl->SetWidthL(aWidth);
+        }
+        else
+        {
+            SetButtonWidth(aWidth);
+        }
+    }
+    CMIDControlItem::AdjustToNewWidthL(aWidth);
+}
+
+
+/** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is
+called instead, which returns the minimum between iPreferredSize and the minimum size.
+*/
+TSize CMIDStringItem::PreferredSize() const
+{
+    return iPreferredSize;
+}
+
+// return Item appearance
+MMIDItem::TAppearance CMIDStringItem::Appearance() const
+{
+    return iAppearance;
+}
+
+/** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is
+called instead, which returns the minimum between iPreferredSize and the minimum size.
+*/
+TSize CMIDStringItem::PreferredSize()
+{
+    return iPreferredSize;
+}
+
+// We display a string as a hyperlink or a button depending on both its appearance and if it has any commands
+void CMIDStringItem::AddCommandL(MMIDCommand* aCommand)
+{
+    DEBUG("CMIDStringItem::AddCommandL - begin");
+    CMIDItem::AddCommandL(aCommand);
+
+    TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
+                       (RenderedAppearance() == EHyperLink);
+
+    iContentControl->SetUnderlined(underlined);
+    if (iForm)
+    {
+        iForm->RequestLayoutL();
+    }
+    if (RenderedAppearance() == MMIDItem::EButton)
+    {
+        iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
+    }
+    DEBUG("CMIDStringItem::AddCommandL - end");
+}
+
+// We display a string as a hyperlink or a button depending on both its appearance and if it has any commands
+void CMIDStringItem::RemoveCommand(MMIDCommand* aCommand)
+{
+    DEBUG("CMIDStringItem::RemoveCommand - begin");
+
+    CMIDItem::RemoveCommand(aCommand);
+
+    TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
+                       (RenderedAppearance() == EHyperLink);
+
+    iContentControl->SetUnderlined(underlined);
+    if (iForm)
+    {
+        TRAP_IGNORE(iForm->RequestLayoutL());
+    }
+    if (RenderedAppearance() == MMIDItem::EButton)
+    {
+        iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
+    }
+    DEBUG("CMIDStringItem::RemoveCommand - end");
+}
+
+void CMIDStringItem::SetDefaultCommand(MMIDCommand* aCommand)
+{
+    DEBUG("CMIDStringItem::SetDefaultCommand - begin");
+    CMIDItem::SetDefaultCommand(aCommand);
+    DEBUG("CMIDStringItem::SetDefaultCommand - end");
+}
+
+void CMIDStringItem::SetFontL(MMIDFont* aFont)
+{
+    iFont = aFont;
+
+    iContentControl->SetFont(iFont);
+
+    TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
+                       (RenderedAppearance() == EHyperLink);
+
+    iContentControl->SetUnderlined(underlined);
+
+    if (iAppearance == MMIDItem::EButton)
+    {
+        iButton->SetTextFont(aFont->Font());
+        iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
+        CalculateButtonEllipsedSizeL();
+    }
+    ResetPreferredSize();
+}
+
+/**
+ * Returns the label WITH the prefix if it's not a control, and WITHOUT if it is.
+ */
+TPtrC CMIDStringItem::Label() const
+{
+    return *iLabel;
+}
+
+const TDesC& CMIDStringItem::Text() const
+{
+    return *iText;
+}
+
+/**
+    Because MMIDItem declares a pure virtual const method called MinimumSize()
+    whilst CCoeControl has a virtual non const method called MinimumSize()
+    we are forced to make sure these two methods behave in the same way
+    in every item and hence the non cost method calls the const method.
+
+    We cannot do this once and for all in CMIDControlItem because only
+    concrete items inherit from the MMID LCDUI framework classes:
+
+        CCoeControl                 MMIDItem
+            |                           |
+        CMIDItem                  MMIDStringItem
+            |                           |
+      CMIDControlItem                   |
+            |                           |
+       CMISStringItem--------------------
+
+    This is true for every other item.
+*/
+TSize CMIDStringItem::MinimumSize()
+{
+    const CMIDStringItem* self = const_cast<const CMIDStringItem*>(this);
+
+    return self->MinimumSize();
+}
+
+TInt CMIDStringItem::CountComponentControls() const
+{
+    return 2;
+}
+
+CCoeControl* CMIDStringItem::ComponentControl(TInt aIndex) const
+{
+    switch (aIndex)
+    {
+    case 0:
+        return iLabelControl;
+    case 1:
+        if (RenderedAppearance() != MMIDItem::EButton)
+        {
+            return iContentControl;
+        }
+        else
+        {
+            return iButton;
+        }
+    }
+    return NULL;
+}
+
+/**
+ * Sets label and content colors according to the appearance mode and focusing info
+ */
+void CMIDStringItem::SetColorL()
+{
+    DEBUG("CMIDStringItem::SetColorL - begin");
+    // Create & initialize a color variable according to the focus & appearance info
+    TBool focused = IsFocused();
+    TRgb labelColor;
+    TRgb contentColor;
+    TRgb color;
+    // Set colors in case of plain
+    // NOTE: All items (e.g hyperlinks) are rendered as plain if there are no commands.
+    if (RenderedAppearance() == MMIDItem::EPlain)
+    {
+        // The appearance mode is the EPlain.
+        DEBUG("CMIDStringItem::SetColorL - EPlain");
+        // Same color - no matter if focused or not
+        AknsUtils::GetCachedColor(
+            AknsUtils::SkinInstance(), color,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8);
+        labelColor = color;
+        contentColor = color;
+    }
+    else
+    {
+        // The appearance mode is EHyperLink or EButton
+        DEBUG("CMIDStringItem::SetColorL - not EPlain");
+        if (focused)
+        {
+            // Item is focused
+            // If item is focused, label is always focused,
+            AknsUtils::GetCachedColor(
+                AknsUtils::SkinInstance(), labelColor,
+                KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10);
+
+            if (RenderedAppearance() == MMIDItem::EHyperLink)
+            {
+                if (iHyperLinkActivated)
+                    // link was activated
+                {
+                    AknsUtils::GetCachedColor(
+                        AknsUtils::SkinInstance(), contentColor,
+                        KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10);
+                }
+                else
+                    // link was not activated
+                {
+                    AknsUtils::GetCachedColor(
+                        AknsUtils::SkinInstance(), contentColor,
+                        KAknsIIDQsnTextColors, EAknsCIQsnHighlightColorsCG3);
+                }
+            }
+        }
+        else
+        {
+            // Item is not focused
+            AknsUtils::GetCachedColor(
+                AknsUtils::SkinInstance(), labelColor,
+                KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8);
+            AknsUtils::GetCachedColor(
+                AknsUtils::SkinInstance(), contentColor,
+                KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG3);
+        }
+
+        if (RenderedAppearance() == MMIDItem::EButton)
+        {
+            // Note: BorderColor() is the color of the border internal background, not the outline
+            ColorUtils::GetRgbDerivedBorderColors(
+                iBorderColors, BorderColor(), iEikonEnv->DefaultDisplayMode());
+        }
+    }
+    // Set content & label colors
+    if (RenderedAppearance() != MMIDItem::EButton)
+    {
+        iContentControl->SetColorL(contentColor);
+    }
+    iLabelControl->SetColorL(labelColor);
+
+    // Text color for CAknButton has to be set
+    if (RenderedAppearance() == MMIDItem::EButton)
+    {
+        if (iButton)
+        {
+            iButton->SetTextColorIds(
+                KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG8);
+        }
+    }
+
+    DEBUG("CMIDStringItem::SetColorL - end");
+}
+
+
+/** The color for the border background in buttons.
+*/
+TRgb CMIDStringItem::BorderColor() const
+{
+    DEBUG("CMIDStringItem::BorderColor - begin");
+
+    TRgb color;
+    AknsUtils::GetCachedColor(
+        AknsUtils::SkinInstance(), color,
+        KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG12);
+    DEBUG("CMIDStringItem::BorderColor - end");
+    return color;
+}
+
+/**  Draw a frame (border) for buttons and then draw the grid highlight frame if
+we have focus. Note: only hyperlinks and buttons can have focus.  */
+void CMIDStringItem::Draw(const TRect& aRect) const
+{
+    DEBUG("CMIDStringItem::Draw - begin");
+
+    if (RenderedAppearance() == MMIDItem::EButton)
+    {
+        // To avoid clipping button's border to the form's client area
+        // we pass entire button's rectangle - Rect() - as parameter
+        Border().Draw(SystemGc(), Rect(), iBorderColors);
+    }
+
+    if (IsFocused())
+    { //only buttons or hyperlinks
+        DEBUG("CMIDStringItem::Draw - focused");
+
+        // A focused item e.g. hyperlink
+        TAknLayoutRect topLeft;
+        topLeft.LayoutRect(aRect,
+                           SkinLayout::List_highlight_skin_placing__apps_specific__Line_2());
+
+        TAknLayoutRect bottomRight;
+        bottomRight.LayoutRect(aRect,
+                               SkinLayout::List_highlight_skin_placing__apps_specific__Line_5());
+
+        TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr);
+        TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl);
+
+        AknsDrawUtils::DrawFrame(AknsUtils::SkinInstance(), SystemGc(),
+                                 outerRect, innerRect,
+                                 KAknsIIDQsnFrList, KAknsIIDQsnFrListCenter);
+    }
+    DEBUG("CMIDStringItem::Draw - end");
+}
+
+void CMIDStringItem::SizeChanged()
+{
+    /* Margins are added in CMIDItemLabel class */
+    // If rects of label and content are layouted according to parent rect
+    // their width should be the same as parent. So text within labels is
+    // placed to proper side: to left in left-to right and to right in
+    // right-to-left variants.
+    iLabelControl->SetExtent(Position(),
+                             TSize(Size().iWidth, iLabelControl->Size().iHeight));
+    iContentControl->SetExtent(Position() + TPoint(0, LabelHeight()),
+                               TSize(Size().iWidth, iContentControl->Size().iHeight));
+
+    if (RenderedAppearance() == MMIDItem::EButton)
+    {
+        TBool labelEmpty = (iLabelControl->Text()->Length() == 0);
+
+        TAknWindowLineLayout layout =
+            AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
+
+        TInt leftMargin = layout.il;
+        TInt rightMargin = layout.ir;
+        TInt topMargin = ItemContentBottomMargin();
+
+        TPoint buttonPos = Position() + TPoint(0, LabelHeight());
+        TSize buttonSize = iSavedButtonSize;
+
+        buttonPos += TPoint(leftMargin, 0);
+        buttonSize -= TSize(leftMargin + rightMargin, 0); // these margins were added in MinimumSize()
+
+        if (labelEmpty)
+        {
+            buttonPos += TPoint(0, topMargin); // shift down, we need some space above
+        }
+
+        iButton->SetExtent(buttonPos, buttonSize);
+    }
+
+    CMIDControlItem::SizeChanged();
+}
+
+TKeyResponse CMIDStringItem::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/)
+{
+    return EKeyWasNotConsumed;
+}
+
+// this assumes that the item has been formatted by the form
+TInt CMIDStringItem::ItemPreferredHeightWithoutLabel()
+{
+    if (iAppearance != MMIDItem::EButton)
+    {
+        return iContentControl->Size().iHeight + ItemContentBottomMargin();
+    }
+    else
+    {
+        TInt height =  iButton->Size().iHeight + ItemContentBottomMargin();
+        TBool labelEmpty = (iLabelControl->Text()->Length() == 0);
+        if (labelEmpty)
+        {
+            height += ItemContentBottomMargin(); // add top margin
+        }
+        return height;
+    }
+}
+
+TRect CMIDStringItem::FocusableRect()
+{
+    TRect rect = Rect();
+
+    if (rect.iTl.iY > rect.iBr.iY)
+    {
+        TInt tmp = rect.iBr.iY;
+        rect.iBr.iY = rect.iTl.iY;
+        rect.iTl.iY = tmp;
+    }
+
+    return rect;
+}
+
+
+
+/** Set text colors according to the focus: label color stays
+the same as all other items (currently text entry), see CMIDControlItem::SetLabelColor().
+Content colors is either NormalColor() or HighlightColor() according to focus.
+Note: only hyperlinks and buttons can have focus. Currently NormalColor() is text
+entry color (same as labels) whilst HighlightColor() is grid highlight text color. */
+void CMIDStringItem::FocusChanged(TDrawNow aDrawNow)
+{
+    DEBUG("CMIDStringItem::FocusChanged - begin");
+
+    TRAP_IGNORE(SetColorL());
+
+    if (EDrawNow == aDrawNow && DrawableWindow())
+    {
+        if (!HasLabel() && RenderedAppearance() == EHyperLink)
+        {
+            // Have to do a call back to Form to draw a hyperlink without label correctly.
+            // Note: a hyperlink without label is a CMIDLabelContainerItem and not a CMIDStringItem
+            // Hyperlink without label is created by Form and this string item has no knowledge of it.
+            // CMIDStringItem FocusChanged() is called when focus changes for drawing all kinds of string items even though
+            // they are not necessarily drawn here. See CMIDLabelContainerItem too.
+            iForm->DrawNow();
+        }
+        else
+        {
+            if (iIsDivided)
+            {
+                // For correct drawing of StringItem with label which is divided
+                // to CMIDLabelContainerItem objects due to concatenation of contents contained
+                // in adjacent string items.
+                iForm->DrawNow();
+            }
+            else
+            {
+                DrawNow();
+            }
+        }
+    }
+    DEBUG("CMIDStringItem::FocusChanged - end");
+}
+
+MMIDItem::TAppearance CMIDStringItem::RenderedAppearance() const
+{
+    TBool hasCommands(CommandList()->Count() > 0);
+    if (hasCommands)
+    {
+        return (iAppearance == EButton) ? EButton : EHyperLink;
+    }
+    return EPlain;
+}
+
+CMIDItemLabel* CMIDStringItem::StringContentControl() const
+{
+    return iContentControl;
+}
+
+TBool CMIDStringItem::IsUnconstrainedStringItem()
+{
+    return !(WidthOrHeightSpecified() || (RenderedAppearance() == EButton));
+}
+
+TBool CMIDStringItem::WidthOrHeightSpecified() const
+{
+    return WidthSpecified() || HeightSpecified();
+}
+
+TBool CMIDStringItem::WidthSpecified() const
+{
+    return (iRequestedPreferredSize.iWidth != -1);
+}
+
+TBool CMIDStringItem::HeightSpecified() const
+{
+    return (iRequestedPreferredSize.iHeight != -1);
+}
+
+/**
+  Make sure label and content do not go beyond the available size. This method
+  is called after setting the preferred size and when the row needs to size
+  the items. If the item height (available height) cannot fit label and content
+  then fit the label as much as possible and fit the control with the
+  remaining height. However, reserve to the control at least one line. Because
+  the minimumsize is one line for label (if available) and one line for control
+  then there should always be space at least for one label line and for one control line.
+*/
+void CMIDStringItem::AdjustToSizeL(const TSize& aSize)
+{
+    if (iAppearance != MMIDItem::EButton)
+    {
+        TInt availableHeight = aSize.iHeight;
+        TInt requestedHeight = iContentControl->Size().iHeight;
+
+        if (iLabelControl && iLabelControl->Text()->Length() > 0)
+        {
+            requestedHeight += LabelHeight();
+        }
+
+        if (requestedHeight > availableHeight)
+        {// label + control do not fit
+            if (iLabelControl && iLabelControl->Text()->Length() > 0)
+            {
+                //reserve one line to the control
+                TInt heightForLabel = iContentControl->Text()->Length() > 0 ?
+                                      availableHeight - iContentControl->LineHeight() - iContentControl->ItemLabelMargin() :
+                                      availableHeight;
+
+                if (iLabelControl->Size().iHeight > heightForLabel)
+                { //label does not fit
+
+                    //By setting a temporary max number of lines and then calling
+                    //SetWidthL() we limit the number of lines to the temporary max number
+                    //However then the max number must be resetted
+                    TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines();
+                    iLabelControl->SetMaxNumLines(
+                        (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight());
+                    iLabelControl->SetWidthL(aSize.iWidth);
+                    iLabelControl->SetMaxNumLines(oldMaxNumLabelLines);
+                }
+
+                //height available for the control
+                availableHeight -= iLabelControl->Size().iHeight;
+            }
+
+            TInt oldMaxNumContentLines = iContentControl->MaxNumLines();
+            iContentControl->SetMaxNumLines(
+                (availableHeight - iLabelControl->ItemLabelMargin()) / iContentControl->LineHeight());
+            iContentControl->SetWidthL(aSize.iWidth);
+            iContentControl->SetMaxNumLines(oldMaxNumContentLines);
+        }
+    }
+    else
+    {
+        TInt availableHeight = aSize.iHeight;
+        TInt requestedHeight = iButton->Size().iHeight;
+
+        if (iLabelControl && iLabelControl->Text()->Length() > 0)
+        {
+            requestedHeight += LabelHeight();
+        }
+
+        if (requestedHeight > availableHeight)
+        {// label + control do not fit
+            if (iLabelControl && iLabelControl->Text()->Length() > 0)
+            {
+                //reserve one line to the control
+                TInt heightForLabel = iButton->Size().iHeight;
+
+                if (iLabelControl->Size().iHeight > heightForLabel)
+                { //label does not fit
+
+                    //By setting a temporary max number of lines and then calling
+                    //SetWidthL() we limit the number of lines to the temporary max number
+                    //However then the max number must be resetted
+                    TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines();
+                    iLabelControl->SetMaxNumLines(
+                        (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight());
+                    iLabelControl->SetWidthL(aSize.iWidth);
+                    iLabelControl->SetMaxNumLines(oldMaxNumLabelLines);
+                }
+            }
+
+            SetButtonWidth(aSize.iWidth);
+        }
+    }
+}
+
+
+void CMIDStringItem::SetLabelL(const TDesC& aLabel)
+{
+    CMIDControlItem::SetLabelL(aLabel);
+}
+
+void CMIDStringItem::SetLayoutL(TLayout aLayout)
+{
+    CMIDItem::SetLayoutL(aLayout);
+}
+
+void CMIDStringItem::Dispose()
+{
+    delete this;
+}
+
+MMIDFont* CMIDStringItem::Font() const
+{
+    return iFont;
+}
+
+TInt CMIDStringItem::NumNewlinesBefore()
+{
+    return iNumNewlinesBefore;
+}
+
+TInt CMIDStringItem::NumNewlinesAfter()
+{
+    return iNumNewlinesAfter;
+}
+
+void CMIDStringItem::SetButtonWidth(TInt aNewWidth)
+{
+    TSize buttonSize = iButton->Size();
+    if (!buttonSize.iWidth || !buttonSize.iHeight)
+    {
+        buttonSize = iButton->MinimumSize();
+    }
+    buttonSize.iWidth = aNewWidth;
+    iButton->SetSize(buttonSize);
+    iSavedButtonSize = buttonSize;
+}
+
+//
+// The area sensitive to actions is contentControl label for hyperlink and button for button appearance
+//
+TRect CMIDStringItem::TappingActionRect()
+{
+    if (iAppearance != MMIDItem::EButton)
+    {
+        return iContentControl->Rect();
+    }
+    else
+    {
+        return iButton->Rect();
+    }
+}
+
+void CMIDStringItem::ResolutionChange(TInt /*aType*/)
+{
+    iContentControl->SetMaxWidth(FormClientAreaWidth());
+    iLabelControl->SetMaxWidth(FormClientAreaWidth());
+}
+
+void CMIDStringItem::CalculateButtonEllipsedSizeL()
+{
+    ASSERT(iAppearance == MMIDItem::EButton);
+
+    TBuf<1> ellipsis;
+    ellipsis.Append(KEllipsis);
+
+    CAknButton* tempButton = CAknButton::NewLC(NULL,   // aIcon
+                             NULL,  // aDimmedIcon
+                             NULL,  // aPressedIcon
+                             NULL,  // aHoverIcon
+                             ellipsis,
+                             KNullDesC,
+                             KAknButtonSizeFitText, // iFlags set to respect text width
+                             0);
+
+    iEllipsedButtonSize = tempButton->MinimumSize();
+    CleanupStack::PopAndDestroy(tempButton);
+}
+
+TBool CMIDStringItem::IsDivided()
+{
+    return iIsDivided;
+}
+
+void CMIDStringItem::SetIsDivided(TBool aIsDivided)
+{
+    iIsDivided = aIsDivided;
+}
+