/*
* 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;
}