diff -r ae942d28ec0e -r 2455ef1f5bbc javauis/lcdui_akn/lcdui/src/CMIDStringItem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdui/src/CMIDStringItem.cpp Wed Sep 01 12:33:18 2010 +0100 @@ -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 +// AknsUtils used for label and content colors settings +#include +// skins for drawing +#include +#include +#include +// LAF +#include +#include +#include + +#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 + + +/** 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(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(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, EAknsCIQsnTextColorsCG6); + 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, EAknsCIQsnTextColorsCG6); + 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, EAknsCIQsnTextColorsCG6); + } + } + + 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; +} +