javauis/lcdui_akn/lcdui/src/CMIDStringItem.cpp
branchRCL_3
changeset 26 2455ef1f5bbc
equal deleted inserted replaced
25:ae942d28ec0e 26:2455ef1f5bbc
       
     1 /*
       
     2 * Copyright (c) 2003-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <eiklabel.h>
       
    20 // AknsUtils used for label and content colors settings
       
    21 #include <AknsDrawUtils.h>
       
    22 // skins for drawing
       
    23 #include <skinlayout.cdl.h>
       
    24 #include <AknUtils.h>
       
    25 #include <applayout.cdl.h>
       
    26 // LAF
       
    27 #include <aknlayoutscalable_avkon.cdl.h>
       
    28 #include <aknconsts.h>
       
    29 #include <avkon.mbg>
       
    30 
       
    31 #include "CMIDStringItem.h"
       
    32 // API for iCommandList
       
    33 #include "CMIDCommandList.h"
       
    34 // some API for text formating before label settings
       
    35 #include "CMIDUtils.h"
       
    36 // CMIDItemLabel* iContentControl
       
    37 #include "CMIDItemLabel.h"
       
    38 
       
    39 #include <j2me/jdebug.h>
       
    40 
       
    41 
       
    42 /** This constant determines the maximum number
       
    43 of lines for button labels and content */
       
    44 const TInt KMaxNumLinesForButtons = 10;
       
    45 
       
    46 /** Content can have unlimited lines */
       
    47 const TInt KMaxNumLinesForContent = -1;
       
    48 
       
    49 // ---------------------------------------------------------------------------
       
    50 //
       
    51 // ---------------------------------------------------------------------------
       
    52 //
       
    53 MMIDStringItem* CMIDStringItem::NewL(
       
    54     const TDesC& aLabel, const TDesC& aText, TAppearance aAppearance, CMIDUIManager* aUIManager)
       
    55 {
       
    56     CMIDStringItem* item=new(ELeave) CMIDStringItem(aAppearance, aUIManager);
       
    57     CleanupStack::PushL(item);
       
    58     item->ConstructL(aLabel,aText);
       
    59     CleanupStack::Pop(item);
       
    60     return item;
       
    61 }
       
    62 
       
    63 /**
       
    64  * Assumes label has been set before in order to work out if a prefix is
       
    65  * required
       
    66  */
       
    67 void CMIDStringItem::SetTextL(const TDesC& aText)
       
    68 {
       
    69     DEBUG("CMIDStringItem::SetTextL - begin");
       
    70 
       
    71     delete iText;
       
    72     iText = NULL;
       
    73 
       
    74     // count the newlines at the beginning and the end of the content
       
    75     CountNewlinesBeforeAndAfter(aText);
       
    76 
       
    77     // create a TPtrC of the string without the beginning and training newlines
       
    78     TPtrC ptr;
       
    79     if (iNumNewlinesBefore < aText.Length())
       
    80     {
       
    81         ptr.Set(aText.Mid(iNumNewlinesBefore, aText.Length() -
       
    82                           (iNumNewlinesBefore + iNumNewlinesAfter)));
       
    83     }
       
    84 
       
    85     iText = ptr.AllocL();
       
    86     if (iText->Length() != 0)
       
    87     {
       
    88         CMIDUtils::MapJavaToETextChars(iText);
       
    89     }
       
    90 
       
    91     iContentControl->SetTextL(*iText);
       
    92     if (iAppearance == MMIDItem::EButton)
       
    93     {
       
    94         // leave only text before line separator, if any
       
    95         TInt i = 0;
       
    96         while ((i < iText->Length()) && (!CMIDUtils::IsLineSeparator((*iText)[i])))
       
    97         {
       
    98             i++;
       
    99         }
       
   100         ptr.Set(iText->Mid(0, i));
       
   101 
       
   102         // if there was line separator add ellipis in the end
       
   103         HBufC* textWithEllipsis = HBufC::NewLC(i + 1);
       
   104         textWithEllipsis->Des().Append(ptr); // text without line separators
       
   105         if (i < iText->Length())
       
   106         {
       
   107             // if there was line separator add ellipsis in the end
       
   108             textWithEllipsis->Des().Append(KEllipsis);
       
   109         }
       
   110 
       
   111         iButton->State()->SetTextL(textWithEllipsis->Des());
       
   112 
       
   113         CleanupStack::PopAndDestroy(textWithEllipsis);
       
   114     }
       
   115 
       
   116     if (iForm)
       
   117     {
       
   118         iForm->RequestLayoutL();
       
   119     }
       
   120     DEBUG("CMIDStringItem::SetTextL - end");
       
   121 }
       
   122 
       
   123 // ---------------------------------------------------------------------------
       
   124 //
       
   125 // ---------------------------------------------------------------------------
       
   126 //
       
   127 CMIDStringItem::CMIDStringItem(TAppearance aAppearance, CMIDUIManager* aUIManager)
       
   128         : CMIDControlItem(EDefault, aUIManager),
       
   129         iAppearance(aAppearance),
       
   130         iIsDivided(EFalse)
       
   131 {
       
   132     iMMidItem = this;
       
   133 }
       
   134 
       
   135 void CMIDStringItem::ConstructL(const TDesC& aLabel,const TDesC& aText)
       
   136 {
       
   137     DEBUG("CMIDStringItem::ConstructL - begin");
       
   138     // Initializes the label control
       
   139     CMIDControlItem::ConstructL();
       
   140 
       
   141     if (iAppearance == MMIDItem::EButton)
       
   142     { //buttons can only have one line
       
   143 
       
   144         iButton = CAknButton::NewL(NULL,   // aIcon
       
   145                                    NULL,  // aDimmedIcon
       
   146                                    NULL,  // aPressedIcon
       
   147                                    NULL,  // aHoverIcon
       
   148                                    aText,
       
   149                                    KNullDesC,
       
   150                                    KAknButtonSizeFitText, // iFlags set to respect text width
       
   151                                    0);
       
   152         iLabelControl->SetMaxNumLines(KMaxNumLinesForButtons);
       
   153     }
       
   154     // iContentControl is always created because RenderedAppearance() can be PLAIN
       
   155     iContentControl = CMIDItemLabel::NewL(FormClientAreaWidth(), ETrue,
       
   156                                           KMaxNumLinesForContent, CMIDFont::EDefaultTextId, ETrue);
       
   157 
       
   158 
       
   159     SetLabelL(aLabel);
       
   160     SetTextL(aText); // Sets CMIDStringitem::iText
       
   161     iContentControl->SetFont(Font());
       
   162     if (iAppearance != MMIDItem::EButton)
       
   163     {
       
   164         MMIDFont* font = Font();
       
   165         if (font)
       
   166         {
       
   167             iButton->SetTextFont(font->Font());
       
   168         }
       
   169     }
       
   170     SetColorL();
       
   171 
       
   172     if (iAppearance == MMIDItem::EButton)
       
   173     {
       
   174         CalculateButtonEllipsedSizeL();
       
   175     }
       
   176     ResetPreferredSize();
       
   177 
       
   178 #ifdef RD_TACTILE_FEEDBACK
       
   179     iFeedback = MTouchFeedback::Instance();
       
   180 #endif
       
   181 
       
   182     DEBUG("CMIDStringItem::ConstructL - end");
       
   183 }
       
   184 
       
   185 CMIDStringItem::~CMIDStringItem()
       
   186 {
       
   187     delete iText;
       
   188     delete iContentControl;
       
   189     delete iButton;
       
   190 }
       
   191 
       
   192 void CMIDStringItem::SetContainerWindowL(const CCoeControl& aContainer)
       
   193 {
       
   194     CMIDControlItem::SetContainerWindowL(aContainer);
       
   195     iContentControl->SetContainerWindowL(*this);
       
   196     if (iAppearance == MMIDItem::EButton)
       
   197     {
       
   198         iButton->SetContainerWindowL(*this);
       
   199     }
       
   200     ActivateL();
       
   201 }
       
   202 
       
   203 void CMIDStringItem::CountNewlinesBeforeAndAfter(const TDesC& aText)
       
   204 {
       
   205     TInt i = 0;
       
   206 
       
   207     iNumNewlinesBefore = 0;
       
   208     iNumNewlinesAfter = 0;
       
   209     while ((i < aText.Length()) && (aText[i] == '\n'))
       
   210     {
       
   211         iNumNewlinesBefore++;
       
   212         i++;
       
   213     }
       
   214 
       
   215     if (iNumNewlinesBefore == aText.Length())
       
   216     {
       
   217         return;
       
   218     }
       
   219 
       
   220     // we get here if the string isn't all newlines
       
   221     i = aText.Length() - 1;
       
   222     while ((i >= 0) && (aText[i] == '\n'))
       
   223     {
       
   224         iNumNewlinesAfter++;
       
   225         i--;
       
   226     }
       
   227 }
       
   228 
       
   229 TBool CMIDStringItem::IsSelectable() const
       
   230 {
       
   231     return (iCommandList->Count() > 0);
       
   232 }
       
   233 
       
   234 /**
       
   235  * Sets the preferred width and height for this Item. If the width is between zero and
       
   236  * the minimum width, inclusive, the minimum width is used. If the height is between
       
   237  * zero and the minimum height, inclusive, the minimum height is used.
       
   238  * By default, the preferred width and height are based entirely on the Item's contents.
       
   239  * If both width and height parameters are -1, the default values for width and height
       
   240  * are established. If neither width nor height is -1, the values specified become the
       
   241  * Item's preferred size.
       
   242  *
       
   243  * If width is -1 and height is a legal value, the width will be computed based on the
       
   244  * item's contents and the given height. If height is -1 and width is a legal value,
       
   245  * the height will be computed based on the item's contents and the given width.
       
   246  *
       
   247  * If a StringItem has been assigned a preferred width or height by
       
   248  * the application, it is wrapped to fit that width and height and
       
   249  * is treated as a rectangle whose minimum and preferred width and height
       
   250  * are the width and height of this rectangle
       
   251  *
       
   252  * iPreferredSize includes margins. Margins are added in CMIDItemLabel class.
       
   253  */
       
   254 void CMIDStringItem::SetPreferredSizeL(const TSize& aSize)
       
   255 {
       
   256 
       
   257     iRequestedPreferredSize = CheckRequestedSize(aSize);
       
   258     iPreferredSize = iRequestedPreferredSize;
       
   259 
       
   260     if (iPreferredSize.iWidth < 0)
       
   261     { // width is not specified
       
   262         if (RenderedAppearance() != MMIDItem::EButton)
       
   263         {
       
   264             iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(),
       
   265                                         iContentControl->PreferredWidth());
       
   266         }
       
   267         else
       
   268         {
       
   269             iPreferredSize.iWidth = Max(iLabelControl->PreferredWidth(),
       
   270                                         iButton->MinimumSize().iWidth);
       
   271             // add margins
       
   272             TAknWindowLineLayout layout =
       
   273                 AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
       
   274             TInt leftMargin = layout.il;
       
   275             TInt rightMargin = layout.ir;
       
   276             iPreferredSize.iWidth += leftMargin + rightMargin; // add left and right margins
       
   277         }
       
   278     }
       
   279 
       
   280     TSize minimumSize = MinimumSize();
       
   281 
       
   282     // make sure the width doesn't get bigger than the form width
       
   283     iPreferredSize.iWidth = Min(iPreferredSize.iWidth, FormClientAreaWidth());
       
   284 
       
   285     // make sure the width doesn't get smaller than the minimum width
       
   286     iPreferredSize.iWidth = Max(iPreferredSize.iWidth, minimumSize.iWidth);
       
   287 
       
   288     // preferred width is set to label and content
       
   289     if (iLabelControl && iLabelControl->Text()->Length() > 0)
       
   290     {
       
   291         iLabelControl->SetWidthL(iPreferredSize.iWidth);
       
   292     }
       
   293     if (RenderedAppearance() != MMIDItem::EButton)
       
   294     {
       
   295         iContentControl->SetWidthL(iPreferredSize.iWidth);
       
   296     }
       
   297     else
       
   298     {
       
   299         SetButtonWidth(iPreferredSize.iWidth);
       
   300     }
       
   301 
       
   302     if (iPreferredSize.iHeight < 0)
       
   303     {  // height is not specified, do text wrapping (call SetWidthL)
       
   304         // so that we can then calculate the height
       
   305         iPreferredSize.iHeight = LabelHeight() + ItemPreferredHeightWithoutLabel();
       
   306     }
       
   307 
       
   308     //make sure the preferred size is not smaller than the minimum size
       
   309     iPreferredSize.iHeight = Max(iPreferredSize.iHeight, minimumSize.iHeight);
       
   310 
       
   311     if ((minimumSize.iWidth == 0) && (minimumSize.iHeight == 0))
       
   312     { //it means there is no control and no label, so set our size to null
       
   313         iPreferredSize.iWidth = 0;
       
   314         iPreferredSize.iHeight = 0;
       
   315     }
       
   316 
       
   317     AdjustToSizeL(iPreferredSize);
       
   318 }
       
   319 
       
   320 TSize CMIDStringItem::MinimumSize() const
       
   321 {
       
   322     TInt numNewLines = iNumNewlinesBefore + iNumNewlinesAfter;
       
   323     TBool labelNotEmpty = (iLabelControl->Text()->Length() > 0);
       
   324 
       
   325     TInt width;
       
   326     TInt height;
       
   327     if (RenderedAppearance() != MMIDItem::EButton)
       
   328     {
       
   329         // if no label and no content then size is zero
       
   330         if (!labelNotEmpty  &&
       
   331                 ((iContentControl->Text()->Length() == 0)) && (numNewLines == 0))
       
   332         {
       
   333             return TSize(0, 0);
       
   334         }
       
   335 
       
   336         width = Max(iLabelControl->MinimumSize().iWidth, iContentControl->MinimumSize().iWidth);
       
   337         height = (
       
   338                      (iLabelControl && iLabelControl->Text()->Length() > 0) ?
       
   339                      OneLineLabelHeight() : 0) +
       
   340                  (iContentControl ?
       
   341                   iContentControl->LineHeight() + iContentControl->ItemLabelMargin() : 0) +
       
   342                  ItemContentBottomMargin();
       
   343 
       
   344         if (width > FormClientAreaWidth())
       
   345         {
       
   346             width = FormClientAreaWidth();
       
   347         }
       
   348     }
       
   349     else
       
   350     {
       
   351         // if no label and no content then size is zero
       
   352         if (!labelNotEmpty
       
   353                 &&((iButton->State()->Text().Length() == 0))
       
   354                 && (numNewLines == 0))
       
   355         {
       
   356             return TSize(0, 0);
       
   357         }
       
   358 
       
   359         TInt width = iEllipsedButtonSize.iWidth;
       
   360         TInt height = iEllipsedButtonSize.iHeight;
       
   361 
       
   362         // add margins
       
   363         TAknWindowLineLayout layout =
       
   364             AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
       
   365         TInt leftMargin = layout.il;
       
   366         TInt rightMargin = layout.ir;
       
   367 
       
   368         width = Max(iLabelControl->MinimumSize().iWidth, width);
       
   369         width += leftMargin + rightMargin; // add left and right margins
       
   370 
       
   371         if (labelNotEmpty)
       
   372         {
       
   373             height += OneLineLabelHeight() + ItemContentBottomMargin(); // add label and bottom margin
       
   374         }
       
   375         else
       
   376         {
       
   377             height += ItemContentBottomMargin(); // use the value for top margin
       
   378         }
       
   379 
       
   380         if (width > FormClientAreaWidth())
       
   381         {
       
   382             width = FormClientAreaWidth();
       
   383         }
       
   384         return TSize(width, height);
       
   385     }
       
   386     return TSize(width, height);
       
   387 }
       
   388 
       
   389 #ifdef RD_SCALABLE_UI_V2
       
   390 void CMIDStringItem::HandlePointerEventL(const TPointerEvent &aPointerEvent)
       
   391 {
       
   392     if (AknLayoutUtils::PenEnabled())
       
   393     {
       
   394         // check if string item is a hyperlink and colour the link according to activation/deactivation with pointer
       
   395         // note that want to colour the link and have tactile feedback even though have long tap
       
   396         if (RenderedAppearance() == EHyperLink)
       
   397         {
       
   398             if (aPointerEvent.iType == TPointerEvent::EButton1Down)
       
   399             {
       
   400                 if (!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) ||
       
   401                         iForm->StringItemContainsPoint(this, aPointerEvent.iPosition))
       
   402                 {
       
   403                     iHyperLinkActivated = ETrue;
       
   404 #ifdef RD_TACTILE_FEEDBACK
       
   405                     // RenderedAppearance returns EHyperlink for initially hyperlink-created StringItem,
       
   406                     // or for plain-created StringItem with commands added later.
       
   407                     // if focus is changing, tactile feedback is given already in Form
       
   408                     if (!iForm->IsFocusChangingWithPen())
       
   409                     {
       
   410 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
   411                         //Feedback for HYPERLINK only on touch down
       
   412                         iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton);
       
   413 #else
       
   414                         iFeedback->InstantFeedback(ETouchFeedbackBasic);
       
   415 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
   416                     }
       
   417 #endif // RD_TACTILE_FEEDBACK
       
   418                 }
       
   419                 else // tap on label
       
   420                 {
       
   421                     iHyperLinkActivated = EFalse;
       
   422                 }
       
   423                 FocusChanged(EDrawNow);
       
   424             }
       
   425         }
       
   426 
       
   427         if (aPointerEvent.iType == TPointerEvent::EButton1Down)
       
   428         {
       
   429             iPointerDownOnContentArea = iForm->StringItemContainsPoint(
       
   430                                             this, aPointerEvent.iPosition);
       
   431         }
       
   432 
       
   433         // pass the event to the button
       
   434         if (iButton)
       
   435         {
       
   436 
       
   437 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
   438             if (aPointerEvent.iType == TPointerEvent::EButton1Down &&
       
   439                     iForm->IsFocusChangingWithPen() &&
       
   440                     !(!HasLabel() || TappingActionRect().Contains(aPointerEvent.iPosition) ||
       
   441                       iForm->StringItemContainsPoint(this, aPointerEvent.iPosition)))
       
   442             {
       
   443                 //On touch down, when focus is changing to this item and user
       
   444                 //tapped to label (if exists), it should give sesitive list feedback
       
   445                 iFeedback->InstantFeedback(ETouchFeedbackSensitiveList);
       
   446             }
       
   447 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
   448 
       
   449             CCoeControl::HandlePointerEventL(aPointerEvent);
       
   450         }
       
   451 
       
   452         TBool consumed = iForm->TryDetectLongTapL(aPointerEvent);
       
   453         if (aPointerEvent.iType == TPointerEvent::EButton1Up)
       
   454         {
       
   455             // always remove hyperlink activated colour
       
   456             iHyperLinkActivated = EFalse;
       
   457             if (!consumed)
       
   458             {
       
   459                 if (!iButton)
       
   460                 {
       
   461                     CMIDControlItem::HandlePointerEventL(aPointerEvent);
       
   462                 }
       
   463                 // check if the pen was dragged out of button and that pointer down has happened on content area,
       
   464                 // i.e. dragging pointer from label to content area should not invoke any action.
       
   465                 if (!iForm->PhysicsScrolling() && (iForm->StringItemContainsPoint(this, aPointerEvent.iPosition) &&
       
   466                                                    iPointerDownOnContentArea))
       
   467                 {
       
   468                     iForm->HandleTouchControlEventL(this, MCoeControlObserver::EEventStateChanged);
       
   469                 }
       
   470             }
       
   471             FocusChanged(EDrawNow);
       
   472         }
       
   473     }
       
   474 }
       
   475 #endif // RD_SCALABLE_UI_V2
       
   476 
       
   477 /** Recalculate the preferred size.*/
       
   478 TSize CMIDStringItem::ResetPreferredSize() const
       
   479 {
       
   480     CMIDStringItem* self = const_cast<CMIDStringItem*>(this);
       
   481     TRAP_IGNORE(self->SetPreferredSizeL(iRequestedPreferredSize));
       
   482     return iPreferredSize;
       
   483 }
       
   484 
       
   485 /** @see CMIDControlItem::AdjustToNewWidthL()
       
   486 * Margins are added in CMIDItemLabel class */
       
   487 void CMIDStringItem::AdjustToNewWidthL(TInt aWidth)
       
   488 {
       
   489     ASSERT(aWidth >= 0);
       
   490 
       
   491     if (aWidth != iPreferredSize.iWidth)
       
   492     {
       
   493         if (RenderedAppearance() != MMIDItem::EButton)
       
   494         {
       
   495             iContentControl->SetWidthL(aWidth);
       
   496         }
       
   497         else
       
   498         {
       
   499             SetButtonWidth(aWidth);
       
   500         }
       
   501     }
       
   502     CMIDControlItem::AdjustToNewWidthL(aWidth);
       
   503 }
       
   504 
       
   505 
       
   506 /** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is
       
   507 called instead, which returns the minimum between iPreferredSize and the minimum size.
       
   508 */
       
   509 TSize CMIDStringItem::PreferredSize() const
       
   510 {
       
   511     return iPreferredSize;
       
   512 }
       
   513 
       
   514 // return Item appearance
       
   515 MMIDItem::TAppearance CMIDStringItem::Appearance() const
       
   516 {
       
   517     return iAppearance;
       
   518 }
       
   519 
       
   520 /** This method is never called by C++ side, only java side. CMIDItem::PreferredSize() is
       
   521 called instead, which returns the minimum between iPreferredSize and the minimum size.
       
   522 */
       
   523 TSize CMIDStringItem::PreferredSize()
       
   524 {
       
   525     return iPreferredSize;
       
   526 }
       
   527 
       
   528 // We display a string as a hyperlink or a button depending on both its appearance and if it has any commands
       
   529 void CMIDStringItem::AddCommandL(MMIDCommand* aCommand)
       
   530 {
       
   531     DEBUG("CMIDStringItem::AddCommandL - begin");
       
   532     CMIDItem::AddCommandL(aCommand);
       
   533 
       
   534     TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
       
   535                        (RenderedAppearance() == EHyperLink);
       
   536 
       
   537     iContentControl->SetUnderlined(underlined);
       
   538     if (iForm)
       
   539     {
       
   540         iForm->RequestLayoutL();
       
   541     }
       
   542     if (RenderedAppearance() == MMIDItem::EButton)
       
   543     {
       
   544         iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
       
   545     }
       
   546     DEBUG("CMIDStringItem::AddCommandL - end");
       
   547 }
       
   548 
       
   549 // We display a string as a hyperlink or a button depending on both its appearance and if it has any commands
       
   550 void CMIDStringItem::RemoveCommand(MMIDCommand* aCommand)
       
   551 {
       
   552     DEBUG("CMIDStringItem::RemoveCommand - begin");
       
   553 
       
   554     CMIDItem::RemoveCommand(aCommand);
       
   555 
       
   556     TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
       
   557                        (RenderedAppearance() == EHyperLink);
       
   558 
       
   559     iContentControl->SetUnderlined(underlined);
       
   560     if (iForm)
       
   561     {
       
   562         TRAP_IGNORE(iForm->RequestLayoutL());
       
   563     }
       
   564     if (RenderedAppearance() == MMIDItem::EButton)
       
   565     {
       
   566         iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
       
   567     }
       
   568     DEBUG("CMIDStringItem::RemoveCommand - end");
       
   569 }
       
   570 
       
   571 void CMIDStringItem::SetDefaultCommand(MMIDCommand* aCommand)
       
   572 {
       
   573     DEBUG("CMIDStringItem::SetDefaultCommand - begin");
       
   574     CMIDItem::SetDefaultCommand(aCommand);
       
   575     DEBUG("CMIDStringItem::SetDefaultCommand - end");
       
   576 }
       
   577 
       
   578 void CMIDStringItem::SetFontL(MMIDFont* aFont)
       
   579 {
       
   580     iFont = aFont;
       
   581 
       
   582     iContentControl->SetFont(iFont);
       
   583 
       
   584     TBool underlined = (iFont ? iFont->IsUnderlined() : EFalse) ||
       
   585                        (RenderedAppearance() == EHyperLink);
       
   586 
       
   587     iContentControl->SetUnderlined(underlined);
       
   588 
       
   589     if (iAppearance == MMIDItem::EButton)
       
   590     {
       
   591         iButton->SetTextFont(aFont->Font());
       
   592         iButton->SetTextUnderlineStyle((underlined?EUnderlineOn:EUnderlineOff));
       
   593         CalculateButtonEllipsedSizeL();
       
   594     }
       
   595     ResetPreferredSize();
       
   596 }
       
   597 
       
   598 /**
       
   599  * Returns the label WITH the prefix if it's not a control, and WITHOUT if it is.
       
   600  */
       
   601 TPtrC CMIDStringItem::Label() const
       
   602 {
       
   603     return *iLabel;
       
   604 }
       
   605 
       
   606 const TDesC& CMIDStringItem::Text() const
       
   607 {
       
   608     return *iText;
       
   609 }
       
   610 
       
   611 /**
       
   612     Because MMIDItem declares a pure virtual const method called MinimumSize()
       
   613     whilst CCoeControl has a virtual non const method called MinimumSize()
       
   614     we are forced to make sure these two methods behave in the same way
       
   615     in every item and hence the non cost method calls the const method.
       
   616 
       
   617     We cannot do this once and for all in CMIDControlItem because only
       
   618     concrete items inherit from the MMID LCDUI framework classes:
       
   619 
       
   620         CCoeControl                 MMIDItem
       
   621             |                           |
       
   622         CMIDItem                  MMIDStringItem
       
   623             |                           |
       
   624       CMIDControlItem                   |
       
   625             |                           |
       
   626        CMISStringItem--------------------
       
   627 
       
   628     This is true for every other item.
       
   629 */
       
   630 TSize CMIDStringItem::MinimumSize()
       
   631 {
       
   632     const CMIDStringItem* self = const_cast<const CMIDStringItem*>(this);
       
   633 
       
   634     return self->MinimumSize();
       
   635 }
       
   636 
       
   637 TInt CMIDStringItem::CountComponentControls() const
       
   638 {
       
   639     return 2;
       
   640 }
       
   641 
       
   642 CCoeControl* CMIDStringItem::ComponentControl(TInt aIndex) const
       
   643 {
       
   644     switch (aIndex)
       
   645     {
       
   646     case 0:
       
   647         return iLabelControl;
       
   648     case 1:
       
   649         if (RenderedAppearance() != MMIDItem::EButton)
       
   650         {
       
   651             return iContentControl;
       
   652         }
       
   653         else
       
   654         {
       
   655             return iButton;
       
   656         }
       
   657     }
       
   658     return NULL;
       
   659 }
       
   660 
       
   661 /**
       
   662  * Sets label and content colors according to the appearance mode and focusing info
       
   663  */
       
   664 void CMIDStringItem::SetColorL()
       
   665 {
       
   666     DEBUG("CMIDStringItem::SetColorL - begin");
       
   667     // Create & initialize a color variable according to the focus & appearance info
       
   668     TBool focused = IsFocused();
       
   669     TRgb labelColor;
       
   670     TRgb contentColor;
       
   671     TRgb color;
       
   672     // Set colors in case of plain
       
   673     // NOTE: All items (e.g hyperlinks) are rendered as plain if there are no commands.
       
   674     if (RenderedAppearance() == MMIDItem::EPlain)
       
   675     {
       
   676         // The appearance mode is the EPlain.
       
   677         DEBUG("CMIDStringItem::SetColorL - EPlain");
       
   678         // Same color - no matter if focused or not
       
   679         AknsUtils::GetCachedColor(
       
   680             AknsUtils::SkinInstance(), color,
       
   681             KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
       
   682         labelColor = color;
       
   683         contentColor = color;
       
   684     }
       
   685     else
       
   686     {
       
   687         // The appearance mode is EHyperLink or EButton
       
   688         DEBUG("CMIDStringItem::SetColorL - not EPlain");
       
   689         if (focused)
       
   690         {
       
   691             // Item is focused
       
   692             // If item is focused, label is always focused,
       
   693             AknsUtils::GetCachedColor(
       
   694                 AknsUtils::SkinInstance(), labelColor,
       
   695                 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10);
       
   696 
       
   697             if (RenderedAppearance() == MMIDItem::EHyperLink)
       
   698             {
       
   699                 if (iHyperLinkActivated)
       
   700                     // link was activated
       
   701                 {
       
   702                     AknsUtils::GetCachedColor(
       
   703                         AknsUtils::SkinInstance(), contentColor,
       
   704                         KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG10);
       
   705                 }
       
   706                 else
       
   707                     // link was not activated
       
   708                 {
       
   709                     AknsUtils::GetCachedColor(
       
   710                         AknsUtils::SkinInstance(), contentColor,
       
   711                         KAknsIIDQsnTextColors, EAknsCIQsnHighlightColorsCG3);
       
   712                 }
       
   713             }
       
   714         }
       
   715         else
       
   716         {
       
   717             // Item is not focused
       
   718             AknsUtils::GetCachedColor(
       
   719                 AknsUtils::SkinInstance(), labelColor,
       
   720                 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
       
   721             AknsUtils::GetCachedColor(
       
   722                 AknsUtils::SkinInstance(), contentColor,
       
   723                 KAknsIIDQsnHighlightColors, EAknsCIQsnHighlightColorsCG3);
       
   724         }
       
   725 
       
   726         if (RenderedAppearance() == MMIDItem::EButton)
       
   727         {
       
   728             // Note: BorderColor() is the color of the border internal background, not the outline
       
   729             ColorUtils::GetRgbDerivedBorderColors(
       
   730                 iBorderColors, BorderColor(), iEikonEnv->DefaultDisplayMode());
       
   731         }
       
   732     }
       
   733     // Set content & label colors
       
   734     if (RenderedAppearance() != MMIDItem::EButton)
       
   735     {
       
   736         iContentControl->SetColorL(contentColor);
       
   737     }
       
   738     iLabelControl->SetColorL(labelColor);
       
   739 
       
   740     // Text color for CAknButton has to be set
       
   741     if (RenderedAppearance() == MMIDItem::EButton)
       
   742     {
       
   743         if (iButton)
       
   744         {
       
   745             iButton->SetTextColorIds(
       
   746                 KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
       
   747         }
       
   748     }
       
   749 
       
   750     DEBUG("CMIDStringItem::SetColorL - end");
       
   751 }
       
   752 
       
   753 
       
   754 /** The color for the border background in buttons.
       
   755 */
       
   756 TRgb CMIDStringItem::BorderColor() const
       
   757 {
       
   758     DEBUG("CMIDStringItem::BorderColor - begin");
       
   759 
       
   760     TRgb color;
       
   761     AknsUtils::GetCachedColor(
       
   762         AknsUtils::SkinInstance(), color,
       
   763         KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG12);
       
   764     DEBUG("CMIDStringItem::BorderColor - end");
       
   765     return color;
       
   766 }
       
   767 
       
   768 /**  Draw a frame (border) for buttons and then draw the grid highlight frame if
       
   769 we have focus. Note: only hyperlinks and buttons can have focus.  */
       
   770 void CMIDStringItem::Draw(const TRect& aRect) const
       
   771 {
       
   772     DEBUG("CMIDStringItem::Draw - begin");
       
   773 
       
   774     if (RenderedAppearance() == MMIDItem::EButton)
       
   775     {
       
   776         // To avoid clipping button's border to the form's client area
       
   777         // we pass entire button's rectangle - Rect() - as parameter
       
   778         Border().Draw(SystemGc(), Rect(), iBorderColors);
       
   779     }
       
   780 
       
   781     if (IsFocused())
       
   782     { //only buttons or hyperlinks
       
   783         DEBUG("CMIDStringItem::Draw - focused");
       
   784 
       
   785         // A focused item e.g. hyperlink
       
   786         TAknLayoutRect topLeft;
       
   787         topLeft.LayoutRect(aRect,
       
   788                            SkinLayout::List_highlight_skin_placing__apps_specific__Line_2());
       
   789 
       
   790         TAknLayoutRect bottomRight;
       
   791         bottomRight.LayoutRect(aRect,
       
   792                                SkinLayout::List_highlight_skin_placing__apps_specific__Line_5());
       
   793 
       
   794         TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr);
       
   795         TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl);
       
   796 
       
   797         AknsDrawUtils::DrawFrame(AknsUtils::SkinInstance(), SystemGc(),
       
   798                                  outerRect, innerRect,
       
   799                                  KAknsIIDQsnFrList, KAknsIIDQsnFrListCenter);
       
   800     }
       
   801     DEBUG("CMIDStringItem::Draw - end");
       
   802 }
       
   803 
       
   804 void CMIDStringItem::SizeChanged()
       
   805 {
       
   806     /* Margins are added in CMIDItemLabel class */
       
   807     // If rects of label and content are layouted according to parent rect
       
   808     // their width should be the same as parent. So text within labels is
       
   809     // placed to proper side: to left in left-to right and to right in
       
   810     // right-to-left variants.
       
   811     iLabelControl->SetExtent(Position(),
       
   812                              TSize(Size().iWidth, iLabelControl->Size().iHeight));
       
   813     iContentControl->SetExtent(Position() + TPoint(0, LabelHeight()),
       
   814                                TSize(Size().iWidth, iContentControl->Size().iHeight));
       
   815 
       
   816     if (RenderedAppearance() == MMIDItem::EButton)
       
   817     {
       
   818         TBool labelEmpty = (iLabelControl->Text()->Length() == 0);
       
   819 
       
   820         TAknWindowLineLayout layout =
       
   821             AknLayoutScalable_Avkon::form2_midp_label_pane_cp(0).LayoutLine();
       
   822 
       
   823         TInt leftMargin = layout.il;
       
   824         TInt rightMargin = layout.ir;
       
   825         TInt topMargin = ItemContentBottomMargin();
       
   826 
       
   827         TPoint buttonPos = Position() + TPoint(0, LabelHeight());
       
   828         TSize buttonSize = iSavedButtonSize;
       
   829 
       
   830         buttonPos += TPoint(leftMargin, 0);
       
   831         buttonSize -= TSize(leftMargin + rightMargin, 0); // these margins were added in MinimumSize()
       
   832 
       
   833         if (labelEmpty)
       
   834         {
       
   835             buttonPos += TPoint(0, topMargin); // shift down, we need some space above
       
   836         }
       
   837 
       
   838         iButton->SetExtent(buttonPos, buttonSize);
       
   839     }
       
   840 
       
   841     CMIDControlItem::SizeChanged();
       
   842 }
       
   843 
       
   844 TKeyResponse CMIDStringItem::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/, TEventCode /*aType*/)
       
   845 {
       
   846     return EKeyWasNotConsumed;
       
   847 }
       
   848 
       
   849 // this assumes that the item has been formatted by the form
       
   850 TInt CMIDStringItem::ItemPreferredHeightWithoutLabel()
       
   851 {
       
   852     if (iAppearance != MMIDItem::EButton)
       
   853     {
       
   854         return iContentControl->Size().iHeight + ItemContentBottomMargin();
       
   855     }
       
   856     else
       
   857     {
       
   858         TInt height =  iButton->Size().iHeight + ItemContentBottomMargin();
       
   859         TBool labelEmpty = (iLabelControl->Text()->Length() == 0);
       
   860         if (labelEmpty)
       
   861         {
       
   862             height += ItemContentBottomMargin(); // add top margin
       
   863         }
       
   864         return height;
       
   865     }
       
   866 }
       
   867 
       
   868 TRect CMIDStringItem::FocusableRect()
       
   869 {
       
   870     TRect rect = Rect();
       
   871 
       
   872     if (rect.iTl.iY > rect.iBr.iY)
       
   873     {
       
   874         TInt tmp = rect.iBr.iY;
       
   875         rect.iBr.iY = rect.iTl.iY;
       
   876         rect.iTl.iY = tmp;
       
   877     }
       
   878 
       
   879     return rect;
       
   880 }
       
   881 
       
   882 
       
   883 
       
   884 /** Set text colors according to the focus: label color stays
       
   885 the same as all other items (currently text entry), see CMIDControlItem::SetLabelColor().
       
   886 Content colors is either NormalColor() or HighlightColor() according to focus.
       
   887 Note: only hyperlinks and buttons can have focus. Currently NormalColor() is text
       
   888 entry color (same as labels) whilst HighlightColor() is grid highlight text color. */
       
   889 void CMIDStringItem::FocusChanged(TDrawNow aDrawNow)
       
   890 {
       
   891     DEBUG("CMIDStringItem::FocusChanged - begin");
       
   892 
       
   893     TRAP_IGNORE(SetColorL());
       
   894 
       
   895     if (EDrawNow == aDrawNow && DrawableWindow())
       
   896     {
       
   897         if (!HasLabel() && RenderedAppearance() == EHyperLink)
       
   898         {
       
   899             // Have to do a call back to Form to draw a hyperlink without label correctly.
       
   900             // Note: a hyperlink without label is a CMIDLabelContainerItem and not a CMIDStringItem
       
   901             // Hyperlink without label is created by Form and this string item has no knowledge of it.
       
   902             // CMIDStringItem FocusChanged() is called when focus changes for drawing all kinds of string items even though
       
   903             // they are not necessarily drawn here. See CMIDLabelContainerItem too.
       
   904             iForm->DrawNow();
       
   905         }
       
   906         else
       
   907         {
       
   908             if (iIsDivided)
       
   909             {
       
   910                 // For correct drawing of StringItem with label which is divided
       
   911                 // to CMIDLabelContainerItem objects due to concatenation of contents contained
       
   912                 // in adjacent string items.
       
   913                 iForm->DrawNow();
       
   914             }
       
   915             else
       
   916             {
       
   917                 DrawNow();
       
   918             }
       
   919         }
       
   920     }
       
   921     DEBUG("CMIDStringItem::FocusChanged - end");
       
   922 }
       
   923 
       
   924 MMIDItem::TAppearance CMIDStringItem::RenderedAppearance() const
       
   925 {
       
   926     TBool hasCommands(CommandList()->Count() > 0);
       
   927     if (hasCommands)
       
   928     {
       
   929         return (iAppearance == EButton) ? EButton : EHyperLink;
       
   930     }
       
   931     return EPlain;
       
   932 }
       
   933 
       
   934 CMIDItemLabel* CMIDStringItem::StringContentControl() const
       
   935 {
       
   936     return iContentControl;
       
   937 }
       
   938 
       
   939 TBool CMIDStringItem::IsUnconstrainedStringItem()
       
   940 {
       
   941     return !(WidthOrHeightSpecified() || (RenderedAppearance() == EButton));
       
   942 }
       
   943 
       
   944 TBool CMIDStringItem::WidthOrHeightSpecified() const
       
   945 {
       
   946     return WidthSpecified() || HeightSpecified();
       
   947 }
       
   948 
       
   949 TBool CMIDStringItem::WidthSpecified() const
       
   950 {
       
   951     return (iRequestedPreferredSize.iWidth != -1);
       
   952 }
       
   953 
       
   954 TBool CMIDStringItem::HeightSpecified() const
       
   955 {
       
   956     return (iRequestedPreferredSize.iHeight != -1);
       
   957 }
       
   958 
       
   959 /**
       
   960   Make sure label and content do not go beyond the available size. This method
       
   961   is called after setting the preferred size and when the row needs to size
       
   962   the items. If the item height (available height) cannot fit label and content
       
   963   then fit the label as much as possible and fit the control with the
       
   964   remaining height. However, reserve to the control at least one line. Because
       
   965   the minimumsize is one line for label (if available) and one line for control
       
   966   then there should always be space at least for one label line and for one control line.
       
   967 */
       
   968 void CMIDStringItem::AdjustToSizeL(const TSize& aSize)
       
   969 {
       
   970     if (iAppearance != MMIDItem::EButton)
       
   971     {
       
   972         TInt availableHeight = aSize.iHeight;
       
   973         TInt requestedHeight = iContentControl->Size().iHeight;
       
   974 
       
   975         if (iLabelControl && iLabelControl->Text()->Length() > 0)
       
   976         {
       
   977             requestedHeight += LabelHeight();
       
   978         }
       
   979 
       
   980         if (requestedHeight > availableHeight)
       
   981         {// label + control do not fit
       
   982             if (iLabelControl && iLabelControl->Text()->Length() > 0)
       
   983             {
       
   984                 //reserve one line to the control
       
   985                 TInt heightForLabel = iContentControl->Text()->Length() > 0 ?
       
   986                                       availableHeight - iContentControl->LineHeight() - iContentControl->ItemLabelMargin() :
       
   987                                       availableHeight;
       
   988 
       
   989                 if (iLabelControl->Size().iHeight > heightForLabel)
       
   990                 { //label does not fit
       
   991 
       
   992                     //By setting a temporary max number of lines and then calling
       
   993                     //SetWidthL() we limit the number of lines to the temporary max number
       
   994                     //However then the max number must be resetted
       
   995                     TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines();
       
   996                     iLabelControl->SetMaxNumLines(
       
   997                         (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight());
       
   998                     iLabelControl->SetWidthL(aSize.iWidth);
       
   999                     iLabelControl->SetMaxNumLines(oldMaxNumLabelLines);
       
  1000                 }
       
  1001 
       
  1002                 //height available for the control
       
  1003                 availableHeight -= iLabelControl->Size().iHeight;
       
  1004             }
       
  1005 
       
  1006             TInt oldMaxNumContentLines = iContentControl->MaxNumLines();
       
  1007             iContentControl->SetMaxNumLines(
       
  1008                 (availableHeight - iLabelControl->ItemLabelMargin()) / iContentControl->LineHeight());
       
  1009             iContentControl->SetWidthL(aSize.iWidth);
       
  1010             iContentControl->SetMaxNumLines(oldMaxNumContentLines);
       
  1011         }
       
  1012     }
       
  1013     else
       
  1014     {
       
  1015         TInt availableHeight = aSize.iHeight;
       
  1016         TInt requestedHeight = iButton->Size().iHeight;
       
  1017 
       
  1018         if (iLabelControl && iLabelControl->Text()->Length() > 0)
       
  1019         {
       
  1020             requestedHeight += LabelHeight();
       
  1021         }
       
  1022 
       
  1023         if (requestedHeight > availableHeight)
       
  1024         {// label + control do not fit
       
  1025             if (iLabelControl && iLabelControl->Text()->Length() > 0)
       
  1026             {
       
  1027                 //reserve one line to the control
       
  1028                 TInt heightForLabel = iButton->Size().iHeight;
       
  1029 
       
  1030                 if (iLabelControl->Size().iHeight > heightForLabel)
       
  1031                 { //label does not fit
       
  1032 
       
  1033                     //By setting a temporary max number of lines and then calling
       
  1034                     //SetWidthL() we limit the number of lines to the temporary max number
       
  1035                     //However then the max number must be resetted
       
  1036                     TInt oldMaxNumLabelLines = iLabelControl->MaxNumLines();
       
  1037                     iLabelControl->SetMaxNumLines(
       
  1038                         (heightForLabel - iLabelControl->ItemLabelMargin())/ iLabelControl->LineHeight());
       
  1039                     iLabelControl->SetWidthL(aSize.iWidth);
       
  1040                     iLabelControl->SetMaxNumLines(oldMaxNumLabelLines);
       
  1041                 }
       
  1042             }
       
  1043 
       
  1044             SetButtonWidth(aSize.iWidth);
       
  1045         }
       
  1046     }
       
  1047 }
       
  1048 
       
  1049 
       
  1050 void CMIDStringItem::SetLabelL(const TDesC& aLabel)
       
  1051 {
       
  1052     CMIDControlItem::SetLabelL(aLabel);
       
  1053 }
       
  1054 
       
  1055 void CMIDStringItem::SetLayoutL(TLayout aLayout)
       
  1056 {
       
  1057     CMIDItem::SetLayoutL(aLayout);
       
  1058 }
       
  1059 
       
  1060 void CMIDStringItem::Dispose()
       
  1061 {
       
  1062     delete this;
       
  1063 }
       
  1064 
       
  1065 MMIDFont* CMIDStringItem::Font() const
       
  1066 {
       
  1067     return iFont;
       
  1068 }
       
  1069 
       
  1070 TInt CMIDStringItem::NumNewlinesBefore()
       
  1071 {
       
  1072     return iNumNewlinesBefore;
       
  1073 }
       
  1074 
       
  1075 TInt CMIDStringItem::NumNewlinesAfter()
       
  1076 {
       
  1077     return iNumNewlinesAfter;
       
  1078 }
       
  1079 
       
  1080 void CMIDStringItem::SetButtonWidth(TInt aNewWidth)
       
  1081 {
       
  1082     TSize buttonSize = iButton->Size();
       
  1083     if (!buttonSize.iWidth || !buttonSize.iHeight)
       
  1084     {
       
  1085         buttonSize = iButton->MinimumSize();
       
  1086     }
       
  1087     buttonSize.iWidth = aNewWidth;
       
  1088     iButton->SetSize(buttonSize);
       
  1089     iSavedButtonSize = buttonSize;
       
  1090 }
       
  1091 
       
  1092 //
       
  1093 // The area sensitive to actions is contentControl label for hyperlink and button for button appearance
       
  1094 //
       
  1095 TRect CMIDStringItem::TappingActionRect()
       
  1096 {
       
  1097     if (iAppearance != MMIDItem::EButton)
       
  1098     {
       
  1099         return iContentControl->Rect();
       
  1100     }
       
  1101     else
       
  1102     {
       
  1103         return iButton->Rect();
       
  1104     }
       
  1105 }
       
  1106 
       
  1107 void CMIDStringItem::ResolutionChange(TInt /*aType*/)
       
  1108 {
       
  1109     iContentControl->SetMaxWidth(FormClientAreaWidth());
       
  1110     iLabelControl->SetMaxWidth(FormClientAreaWidth());
       
  1111 }
       
  1112 
       
  1113 void CMIDStringItem::CalculateButtonEllipsedSizeL()
       
  1114 {
       
  1115     ASSERT(iAppearance == MMIDItem::EButton);
       
  1116 
       
  1117     TBuf<1> ellipsis;
       
  1118     ellipsis.Append(KEllipsis);
       
  1119 
       
  1120     CAknButton* tempButton = CAknButton::NewLC(NULL,   // aIcon
       
  1121                              NULL,  // aDimmedIcon
       
  1122                              NULL,  // aPressedIcon
       
  1123                              NULL,  // aHoverIcon
       
  1124                              ellipsis,
       
  1125                              KNullDesC,
       
  1126                              KAknButtonSizeFitText, // iFlags set to respect text width
       
  1127                              0);
       
  1128 
       
  1129     iEllipsedButtonSize = tempButton->MinimumSize();
       
  1130     CleanupStack::PopAndDestroy(tempButton);
       
  1131 }
       
  1132 
       
  1133 TBool CMIDStringItem::IsDivided()
       
  1134 {
       
  1135     return iIsDivided;
       
  1136 }
       
  1137 
       
  1138 void CMIDStringItem::SetIsDivided(TBool aIsDivided)
       
  1139 {
       
  1140     iIsDivided = aIsDivided;
       
  1141 }
       
  1142