javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swthyperlink.cpp
branchRCL_3
changeset 19 04becd199f91
child 34 71c436fe3ce0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/eswt_akn/org.eclipse.ercp.swt.s60/native/src/swthyperlink.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,655 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Nokia Corporation - S60 implementation
+ *******************************************************************************/
+
+
+#include <swtlaffacade.h>
+#include <swtbrowserschemehandler.h>
+#include <AknBidiTextUtils.h>
+#include <AknsUtils.h>
+#ifdef RD_TACTILE_FEEDBACK
+#include <touchfeedback.h>
+#endif // RD_TACTILE_FEEDBACK
+#include "swtfont.h"
+#include "swthyperlink.h"
+
+
+// The scheme prefixes used by the scheme handler to recognise the content type
+_LIT(KSwtHyperLinkMail, "mailto:");
+_LIT(KSwtHyperLinkTel, "tel:");
+_LIT(KSwtHyperLinkHttp, "http://");
+
+
+// ======== MEMBER FUNCTIONS ========
+
+
+CSwtHyperLink* CSwtHyperLink::NewL(MSwtDisplay&   aDisplay,
+                                   TSwtPeer       aPeer,
+                                   MSwtComposite& aParent,
+                                   TInt           aStyle)
+{
+    CSwtHyperLink* self = new(ELeave) CSwtHyperLink(aDisplay,
+            aPeer,
+            aParent,
+            aStyle);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    self->InitControlBaseL();
+    CleanupStack::Pop(self);
+    return self;
+}
+
+
+CSwtHyperLink::~CSwtHyperLink()
+{
+#ifdef RD_TACTILE_FEEDBACK
+    if (iFeedback)
+    {
+        iFeedback->RemoveFeedbackForControl(this);
+    }
+#endif // RD_TACTILE_FEEDBACK
+    if (iDefaultFont)
+    {
+        iDefaultFont->RemoveRef();
+        iDefaultFont = NULL;
+    }
+    iFormattedText.Close();
+    iOriginalText.Close();
+}
+
+
+CSwtHyperLink::CSwtHyperLink(MSwtDisplay&   aDisplay,
+                             TSwtPeer       aPeer,
+                             MSwtComposite& aParent,
+                             TInt           aStyle)
+        : ASwtControlBase(aDisplay, aPeer, &aParent, aStyle)
+        , iFormat(MSwtHyperLink::EInvalid)
+{
+}
+
+
+void CSwtHyperLink::ConstructL()
+{
+    CCoeControl& coeParent = iParent->Control()->CoeControl();
+
+    SetContainerWindowL(coeParent);
+    CAknControl::MakeVisible(coeParent.IsVisible());
+    CAknControl::SetDimmed(coeParent.IsDimmed());
+
+    UpdateDefaultFontL();
+    iFormattedText.CreateL(KNullDesC);
+    iOriginalText.CreateL(KNullDesC);
+    UpdateSkinColor();
+    SetBackground(this);   // Back will be drawn by ASwtControlBase::Draw
+
+#ifdef RD_TACTILE_FEEDBACK
+    iFeedback = MTouchFeedback::Instance();
+#endif // RD_TACTILE_FEEDBACK
+
+    ActivateL();
+}
+
+
+void CSwtHyperLink::SwtHandleResourceChangeL(TInt aType)
+{
+    if (aType == KEikDynamicLayoutVariantSwitch)
+    {
+        UpdateDefaultFontL();
+    }
+    else if (aType == KAknsMessageSkinChange)
+    {
+        if (!iCustomTextColor)
+        {
+            UpdateSkinColor();
+        }
+    }
+}
+
+
+void CSwtHyperLink::DrawText(CWindowGc& aGc,
+                             const CFont* aFont,
+                             const TDesC& aText,
+                             const TRect& aTextRect,
+                             const CGraphicsContext::TTextAlign& aAlignment) const
+{
+    if (!aFont)
+    {
+        return;
+    }
+
+    // Vertically center the text inside the text rect
+    const TInt excessSpace = aTextRect.Height() - aFont->FontMaxHeight();
+    const TInt baseLineY = (excessSpace / 2) + aFont->FontMaxAscent();
+
+    TPtrC textToDraw(aText.Ptr(), aText.Length());
+    RBuf convertedText;
+
+    TInt error = convertedText.Create(aText.Length() + KAknBidiExtraSpacePerLine);
+    if (error == KErrNone)
+    {
+        TInt availableWidth(aTextRect.Width());
+        TBool clipped = AknBidiTextUtils:: ConvertToVisualAndClip(
+                            aText,
+                            convertedText,
+                            *aFont,
+                            availableWidth,
+                            availableWidth);
+
+        textToDraw.Set(convertedText.Ptr(), convertedText.Length());
+    }
+
+    CFont::TMeasureTextInput::TFlags order = CFont::TMeasureTextInput::EFVisualOrder;
+    if (AknLayoutUtils::LayoutMirrored())
+    {
+        order = CFont::TMeasureTextInput::EFVisualOrderRightToLeft;
+    }
+
+    TInt textWidth = AknBidiTextUtils::MeasureTextBoundsWidth(*aFont,
+                     textToDraw,
+                     order);
+    TInt alignmentSpace = aTextRect.Width() - textWidth;
+    TPoint textLocation(aTextRect.iTl.iX, aTextRect.iTl.iY + baseLineY);
+    if (aAlignment == CGraphicsContext::ECenter)
+    {
+        textLocation.iX += (alignmentSpace / 2);
+    }
+    else if (aAlignment == CGraphicsContext::ERight)
+    {
+        textLocation.iX += alignmentSpace;
+    }
+
+    TRgb textColor = iLinkColor;
+    // Same background highlight as that of Link
+    if (iPressed || (iDisplay.UiUtils().NaviKeyInput() && IsFocused()))
+    {
+        textColor = iHighlightedLinkColor;
+        aGc.SetPenStyle(CGraphicsContext::ENullPen);
+        aGc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+        aGc.SetBrushColor(iHighlightColor);
+        aGc.DrawRect(TRect(TPoint(textLocation.iX, textLocation.iY - aFont->FontMaxAscent()),
+                           TSize(textWidth, aFont->FontLineGap())));
+    }
+
+    aGc.UseFont(aFont);
+    aGc.SetPenStyle(CGraphicsContext::ESolidPen);
+    aGc.SetBrushStyle(CGraphicsContext::ENullBrush);
+    aGc.SetUnderlineStyle(EUnderlineOn);
+    aGc.SetPenColor(textColor);
+
+    aGc.DrawText(textToDraw, textLocation);
+    convertedText.Close();
+}
+
+
+void CSwtHyperLink::UpdateSkinColor()
+{
+    AknsUtils::GetCachedColor(AknsUtils::SkinInstance(),
+                              iLinkColor,
+                              KAknsIIDQsnHighlightColors,
+                              EAknsCIQsnHighlightColorsCG3);
+    AknsUtils::GetCachedColor(AknsUtils::SkinInstance(),
+                              iHighlightColor,
+                              KAknsIIDQsnHighlightColors,
+                              EAknsCIQsnHighlightColorsCG2);
+    AknsUtils::GetCachedColor(AknsUtils::SkinInstance(),
+                              iHighlightedLinkColor,
+                              KAknsIIDQsnTextColors,
+                              EAknsCIQsnTextColorsCG24);
+}
+
+
+void CSwtHyperLink::UpdateDefaultFontL()
+{
+    if (iDefaultFont)
+    {
+        iDefaultFont->RemoveRef();
+        iDefaultFont = NULL;
+    }
+    iDefaultFont = CSwtFont::NewL(iDisplay.Device(), iDisplay.Device().GetSystemFont()->Font());
+}
+
+
+void CSwtHyperLink::LaunchHandler()
+{
+    TPtrC scheme;
+    scheme.Set(Scheme());
+
+    RBuf textForHandler;
+    TInt err = textForHandler.Create(scheme.Length() + iFormattedText.Length());
+    if (err != KErrNone)
+    {
+        ASSERT(EFalse);
+        return;
+    }
+    textForHandler.Append(scheme);
+    textForHandler.Append(iFormattedText);
+
+    CSwtBrowserSchemeHandler* handler = NULL;
+    TRAP(err, handler = CSwtBrowserSchemeHandler::NewL(textForHandler));
+    if (err != KErrNone)
+    {
+        ASSERT(EFalse);
+    }
+    else
+    {
+        TRAP(err, handler->HandleUrlStandaloneL());
+        if (err != KErrNone)
+        {
+            ASSERT(EFalse);
+        }
+        delete handler;
+        handler = NULL;
+    }
+    textForHandler.Close();
+}
+
+
+TPtrC CSwtHyperLink::Scheme()
+{
+    TPtrC scheme;
+    switch (iFormat)
+    {
+    case MSwtHyperLink::EPhone:
+        scheme.Set(KSwtHyperLinkTel);
+        break;
+    case MSwtHyperLink::EUrl:
+        scheme.Set(KSwtHyperLinkHttp);
+        break;
+    case MSwtHyperLink::EEmail:
+        scheme.Set(KSwtHyperLinkMail);
+        break;
+    default:
+        ASSERT(EFalse);
+        break;
+    }
+    return scheme;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CSwtHyperLink::OfferKeyEventL(const TKeyEvent& aKeyEvent,
+        TEventCode       aType)
+{
+    TBool traversalDoIt(ETrue);
+    if (aKeyEvent.iCode == EKeyOK || aKeyEvent.iCode == EKeyEnter)
+    {
+        traversalDoIt = EFalse;
+    }
+    return HandleKeyL(aKeyEvent, aType, traversalDoIt);
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::HandleResourceChange(TInt aType)
+{
+    CAknControl::HandleResourceChange(aType);
+    TRAP_IGNORE(SwtHandleResourceChangeL(aType));
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+TTypeUid::Ptr CSwtHyperLink::MopSupplyObject(TTypeUid aId)
+{
+    return ASwtControlBase::SwtMopSupplyObject(aId);
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::SizeChanged()
+{
+    HandleSizeChanged();
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::PositionChanged()
+{
+    HandlePositionChanged();
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::FocusChanged(TDrawNow aDrawNow)
+{
+    HandleFocusChanged(aDrawNow);
+}
+
+
+// ---------------------------------------------------------------------------
+// From class CCoeControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::Draw(const TRect& /*aRect*/) const
+{
+    CGraphicsContext::TTextAlign alignment;
+    if (iStyle & KSwtStyleCenter)
+    {
+        alignment = CGraphicsContext::ECenter;
+    }
+    else if (iStyle & KSwtStyleTrail)
+    {
+        if (AknLayoutUtils::LayoutMirrored())
+        {
+            alignment = CGraphicsContext::ELeft;
+        }
+        else
+        {
+            alignment = CGraphicsContext::ERight;
+        }
+    }
+    else // default is left
+    {
+        if (AknLayoutUtils::LayoutMirrored())
+        {
+            alignment = CGraphicsContext::ERight;
+        }
+        else
+        {
+            alignment = CGraphicsContext::ELeft;
+        }
+    }
+
+    TRect textRect(Rect());
+    TMargins8 padding = iDisplay.UiUtils().InlineReferencePadding();
+
+    textRect.iTl.iX += padding.iLeft;
+    textRect.iTl.iY += padding.iTop;
+    textRect.iBr.iX -= padding.iRight;
+    textRect.iBr.iY -= padding.iBottom;
+
+    DrawText(SystemGc(),
+             &GetFont()->Font(),
+             iFormattedText,
+             textRect,
+             alignment);
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+CCoeControl& CSwtHyperLink::CoeControl()
+{
+    return *this;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+const CCoeControl& CSwtHyperLink::CoeControl() const
+{
+    return *this;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::ProcessKeyEventL(const TKeyEvent& aKeyEvent,
+                                     TEventCode       aType)
+{
+    if (aType == EEventKey &&
+            (aKeyEvent.iCode == EKeyOK || aKeyEvent.iCode == EKeyEnter))
+    {
+        LaunchHandler();
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+{
+    switch (aPointerEvent.iType)
+    {
+    case TPointerEvent::EButton1Down:
+    {
+        iPressed = ETrue;
+#ifdef RD_TACTILE_FEEDBACK
+        if (iFeedback)
+        {
+#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+            iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton);
+#else
+            iFeedback->InstantFeedback(ETouchFeedbackBasic);
+#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+        }
+#endif //RD_TACTILE_FEEDBACK
+        Redraw();
+        break;
+    }
+
+    case TPointerEvent::EDrag:
+    {
+        TBool pressed = iPressed;
+        if (Rect().Contains(aPointerEvent.iPosition))
+        {
+            iPressed = ETrue;
+        }
+        else
+        {
+            iPressed = EFalse;
+        }
+        if (pressed != iPressed)
+        {
+            Redraw();
+        }
+        break;
+    }
+
+    case TPointerEvent::EButton1Up:
+    {
+        TBool pressed = iPressed;
+        iPressed = EFalse;
+        if (!iDisplay.RevertPointerEvent() && Rect().Contains(aPointerEvent.iPosition))
+        {
+            LaunchHandler();
+        }
+        if (pressed != iPressed)
+        {
+            Redraw();
+        }
+        break;
+    }
+
+    default:
+        break;
+    }
+}
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::SetForegroundL(const MSwtColor* aColor)
+{
+    ASwtControlBase::DoSetForegroundL(aColor);
+    aColor ? iCustomTextColor = ETrue : iCustomTextColor = EFalse;
+    if (iCustomTextColor)
+    {
+        TRgb rgb;
+        TBool overrideColorSet(GetColor(EColorControlText, rgb));
+        ASSERT(overrideColorSet);
+        iLinkColor = rgb;
+    }
+    else
+    {
+        UpdateSkinColor();
+    }
+    Redraw();
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtControl.
+// ---------------------------------------------------------------------------
+//
+TSize CSwtHyperLink::ComputeSizeL(TInt aWHint, TInt aHHint)
+{
+    const MSwtFont* font = GetFont();
+    ASSERT(font);
+    TSize res(font->TextWidthInPixels(iFormattedText), font->Font().FontMaxHeight());
+    if (font == &DefaultFont())
+    {
+        res.iHeight = Max(iDisplay.UiUtils().InlineReferenceFontHeight(), res.iHeight);
+    }
+
+    res += iDisplay.UiUtils().InlineReferencePadding().SizeDelta();
+    res += BorderSizeDelta();
+
+    if (aWHint != KSwtDefault)
+    {
+        res.iWidth = aWHint;
+    }
+    if (aHHint != KSwtDefault)
+    {
+        res.iHeight = aHHint;
+    }
+
+    return res;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class ASwtControlBase.
+// ---------------------------------------------------------------------------
+//
+const MSwtFont& CSwtHyperLink::DefaultFont() const
+{
+    return *iDefaultFont;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class ASwtControlBase.
+// ---------------------------------------------------------------------------
+//
+HBufC* CSwtHyperLink::MSKLabelL() const
+{
+    return iEikonEnv->AllocReadResourceL(R_QTN_MSK_SELECT);
+}
+
+
+// ---------------------------------------------------------------------------
+// From class ASwtControlBase.
+// ---------------------------------------------------------------------------
+//
+TBool CSwtHyperLink::IsKeyUsed(TUint aKeyCode) const
+{
+    TBool keyUsed(EFalse);
+    if (aKeyCode == EKeyOK || aKeyCode == EKeyEnter)
+    {
+        keyUsed = ETrue;
+    }
+    return keyUsed;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtHyperLink.
+// Note that this function is called already before SetFormat has been
+// called.
+// ---------------------------------------------------------------------------
+//
+MSwtControl* CSwtHyperLink::Control()
+{
+    return this;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtHyperLink.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::SetTextL(const TDesC& aText)
+{
+    ASSERT(iFormat != MSwtHyperLink::EInvalid);
+
+    iFormattedText.Close();
+    iOriginalText.Close();
+    iFormattedText.CreateL(aText);
+    iOriginalText.CreateL(aText);
+
+    iFormattedText.TrimAll();
+    iFormattedText.LowerCase();
+
+    TInt pos(KErrNotFound);
+    TPtrC scheme;
+    scheme.Set(Scheme());
+    pos = iFormattedText.Find(scheme);
+
+    TBool schemeAlreadyValid(pos == 0);
+    if (schemeAlreadyValid)
+    {
+        RBuf tmp;
+        tmp.CreateL(iFormattedText.Length() - scheme.Length());
+        tmp.CleanupClosePushL();
+        tmp.Append(iFormattedText.Mid(scheme.Length()));
+        iFormattedText.Close();
+        iFormattedText.CreateL(tmp);
+        CleanupStack::PopAndDestroy(&tmp);
+        iFormattedText.Trim();
+    }
+
+    Redraw();
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtHyperLink.
+// ---------------------------------------------------------------------------
+//
+const TDesC* CSwtHyperLink::GetText()
+{
+    ASSERT(iFormat != MSwtHyperLink::EInvalid);
+    return &iOriginalText;
+}
+
+
+// ---------------------------------------------------------------------------
+// From class MSwtHyperLink.
+// This is called right after the ConstructL via another JNI call.
+// This is called only once.
+// ---------------------------------------------------------------------------
+//
+void CSwtHyperLink::SetFormat(TInt aFormat)
+{
+    ASSERT(iFormat == MSwtHyperLink::EInvalid);
+
+    // Only these formats are recognised by this implementation.
+    ASSERT(aFormat == MSwtHyperLink::EUrl ||
+           aFormat == MSwtHyperLink::EEmail ||
+           aFormat == MSwtHyperLink::EPhone);
+    iFormat = static_cast<MSwtHyperLink::TFormat>(aFormat);
+}