--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdui/src/CMIDCustomItem.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,1651 @@
+/*
+* Copyright (c) 2003-2009 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 <coemain.h>
+#include <eiklabel.h>
+#include <hal.h>
+#include <AknsDrawUtils.h>// skin
+#include <AknsBasicBackgroundControlContext.h> //skin
+
+#ifdef RD_INTELLIGENT_TEXT_INPUT
+#include <PtiEngine.h>
+#endif //RD_INTELLIGENT_TEXT_INPUT
+
+#include "CMIDForm.h"
+#include "CMIDFormPhysics.h"
+#include "CMIDCustomItem.h"
+// API for iLabelControl
+#include "CMIDItemLabel.h"
+// API needed for retrieving current displayable from iForm when background drawing
+#include "CMIDDisplayable.h"
+
+// retrieving CMIDRemConObserver from CMIDKeyDecoder
+#include "CMIDKeyDecoder.h"
+// needed for adding (removing) media keys observer to remConObserver
+#include "CMIDRemConObserver.h"
+#include "CMIDUIManager.h"
+#include <eikenv.h>
+#include <j2me/jdebug.h>
+
+// LAF
+// AknLayoutScalable_Avkon::form2_midp_content_pane
+#include <aknlayoutscalable_avkon.cdl.h>
+
+#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+#include <touchfeedback.h>
+#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+
+/** The custom item uses a different value for limiting the max sizes because
+it needs to draw bitmaps with these sizes. @see KMaxScreenSizeFactor */
+const TInt KCIMaxScreenSizeFactor = 2;
+
+CMIDCustomItem* CMIDCustomItem::NewL(
+ MMIDEnv& aEnv, const TDesC& aLabel, CMIDUIManager* aUIManager)
+{
+ CMIDCustomItem* item = new(ELeave) CMIDCustomItem(aEnv, aUIManager);
+ CleanupStack::PushL(item);
+ item->ConstructL(aLabel);
+ CleanupStack::Pop(item);
+ return item;
+}
+
+CMIDCustomItem::CMIDCustomItem(MMIDEnv& aEnv, CMIDUIManager* aUIManager)
+ : CMIDControlItem(EDefault, aUIManager)
+ , iEntered(EFalse)
+ , iSupportsInternalTraversal(ETrue)
+ , iEnv(aEnv)
+ , iResetFrameBuffer(ETrue)
+ , iDirectAreaAddedToDisplayable(EFalse)
+ , iS60SelectionKeyCompatibility(EFalse)
+#ifndef RD_JAVA_NGA_ENABLED
+ , iDirectPaused(ETrue)
+#endif
+ , iRestoreDirectContentWhenUnfaded(EFalse)
+ , iPreviousVisibility(EFalse)
+ , iConsumerWaitingForDSAResourcesCallback(NULL)
+{
+ iMMidItem = this;
+
+ //Default values for PointerEventSuppressor
+ iPESPointerMovementInTwips = CMIDUIManager::EPESPointerMovementInTwips;
+ iPESTimeInMilliseconds = CMIDUIManager:: EPESTimeInMilliseconds;
+}
+
+void CMIDCustomItem::ConstructL(const TDesC& aLabel)
+{
+ DEBUG("< CMIDCustomItem::ConstructL");
+
+ CMIDControlItem::ConstructL();
+ SetLabelL(aLabel);
+ UpdateMargins();
+ ActivateL();
+
+ // CustomItem listens media key events if CMIDRemConObserver is initialized and media keys keys are enabled
+ ASSERT(iMenuHandler);
+ ASSERT(iUIManager);
+ iKeyDecoder = iUIManager->OpenKeyDecoderL();
+ ASSERT(iKeyDecoder);
+ iRemConObserver = iKeyDecoder->GetRemConObserver();
+ if (iRemConObserver && iKeyDecoder->MediaKeysEnabled())
+ {
+ iRemConObserver->AddMediaKeysListenerL(static_cast<MMIDMediaKeysListener*>(this));
+ }
+
+#ifdef RD_TACTILE_FEEDBACK
+ iTactileFeedback = new(ELeave) CMIDTactileFeedbackExtension(this, 2);
+#endif
+ //Create PointerEventSuppressor with default values or JAD parameter defined values
+ iPointerEventSuppressor = CAknPointerEventSuppressor::NewL();
+ TInt pointerMovementInPixels =
+ ControlEnv()->ScreenDevice()->HorizontalTwipsToPixels(iPESPointerMovementInTwips);
+ TSize suppressorValues =
+ iUIManager->ReadPointerEventSuppressorValues();
+ if (!(suppressorValues.iWidth == KPESErrorValue &&
+ suppressorValues.iHeight == KPESErrorValue))
+ {
+ iPESTimeInMilliseconds = suppressorValues.iHeight;
+ pointerMovementInPixels =
+ ControlEnv()->ScreenDevice()->HorizontalTwipsToPixels(suppressorValues.iWidth);
+ }
+ iPointerEventSuppressor->SetMaxTapDuration(iPESTimeInMilliseconds * 1000);
+ iPointerEventSuppressor->SetMaxTapMove(TSize(pointerMovementInPixels,
+ pointerMovementInPixels));
+
+ DEBUG("> CMIDCustomItem::ConstructL");
+}
+
+void CMIDCustomItem::UpdateMargins()
+{
+ TAknWindowLineLayout layout =
+ AknLayoutScalable_Avkon::form2_midp_content_pane(1).LayoutLine();
+
+ iContentMargins.iTop = layout.it;
+ iContentMargins.iLeft = layout.il;
+ iContentMargins.iRight = layout.ir;
+ iContentMargins.iBottom = layout.ib;
+
+}
+
+/** */
+void CMIDCustomItem::ResetBuffers()
+{
+ delete iFrameBuffer;
+ delete iFrameContext;
+ delete iFrameDevice;
+
+ iFrameBuffer = NULL;
+ iFrameContext = NULL;
+ iFrameDevice = NULL;
+
+ delete iOffScreenBuffer;
+ delete iOffScreenContext;
+ delete iOffScreenDevice;
+
+ iOffScreenBuffer = NULL;
+ iOffScreenContext = NULL;
+ iOffScreenDevice = NULL;
+}
+
+/** Creates the frame buffer with its associated device and context and the
+offscreen buffer with its device and context. They are both of the same size,
+the size of the content rect. The skin background is then printed on the
+frame buffer via the frame context.
+
+Note: This method is called each time the content size changes. If it leaves
+it is trapped in SizeChanged() and then ResetBuffers() is called so that we
+are not left in an unconsistent situation in Out Of Memory. So care must be
+taken in the code to always check that the buffers or their devices or contextes
+do exist - because they may not exist in OOM.
+*/
+void CMIDCustomItem::CreateBuffersL()
+{
+ DEBUG("< CMIDCustomItem::CreateBuffersL");
+ ResetBuffers();
+
+ TRect rect = TRect(0,0,iContentRect.Size().iWidth, iContentRect.Size().iHeight);
+
+ iFrameBuffer = new(ELeave) CFbsBitmap;
+ User::LeaveIfError(iFrameBuffer->Create(rect.Size(), iEnv.DisplayMode()));
+
+ iFrameDevice = CFbsBitmapDevice::NewL(iFrameBuffer);
+ User::LeaveIfError(iFrameDevice->CreateContext(iFrameContext));
+
+ iOffScreenBuffer = new(ELeave) CFbsBitmap;
+ User::LeaveIfError(iOffScreenBuffer->Create(rect.Size(), iEnv.DisplayMode()));
+
+ iOffScreenDevice = CFbsBitmapDevice::NewL(iOffScreenBuffer);
+ User::LeaveIfError(iOffScreenDevice->CreateContext(iOffScreenContext));
+
+ if (iForm)
+ {
+ AknsDrawUtils::DrawBackground(AknsUtils::SkinInstance(),
+ iForm->CurrentDisplayable().BackGroundControlContext(), this,
+ *iFrameContext, TPoint(0,0), iContentRect, KAknsDrawParamDefault);
+ }
+ DEBUG("> CMIDCustomItem::CreateBuffersL");
+}
+
+// Start Direct screen access in order to switch off Transition effects,
+// which could damage the DSA (video)
+void CMIDCustomItem::SetContainerWindowL(const CCoeControl& aWindow)
+{
+ DEBUG("< CMIDCustomItem::SetContainerWindowL");
+#ifndef RD_JAVA_NGA_ENABLED
+ if (iDirectAccess)
+ {
+ iDirectAccess->Cancel();
+ delete iDirectAccess;
+ iDirectAccess = NULL;
+ }
+#endif
+
+ CMIDControlItem::SetContainerWindowL(aWindow);
+
+#ifndef RD_JAVA_NGA_ENABLED
+ RWsSession& session = ControlEnv()->WsSession();
+ CWsScreenDevice* device = ControlEnv()->ScreenDevice();
+
+ iDirectAccess = CDirectScreenAccess::NewL(
+ session,
+ *device,
+ *DrawableWindow(),
+ *this
+ );
+#endif
+
+ if (iConsumerWaitingForDSAResourcesCallback)
+ {
+ // Invoke the pending callback from LCDUI ES thread
+ iEnv.ToLcduiObserver().InvokeDSAResourcesCallback(
+ *this, *iConsumerWaitingForDSAResourcesCallback);
+ iConsumerWaitingForDSAResourcesCallback = NULL;
+ }
+
+ DEBUG("> CMIDCustomItem::SetContainerWindowL");
+}
+
+CMIDCustomItem::~CMIDCustomItem()
+{
+ DEBUG("< CMIDCustomItem::~CMIDCustomItem");
+ if (iDirectContent)
+ {
+ iDirectContent->MdcContainerDestroyed();
+ }
+
+#ifndef RD_JAVA_NGA_ENABLED
+ if (iDirectAccess)
+ {
+ iDirectAccess->Cancel();
+ delete iDirectAccess;
+ iDirectAccess = NULL;
+ }
+#endif
+
+ ResetBuffers();
+
+ // CustomItem removes itself from the CMIDRemConObserver.
+ ASSERT(iKeyDecoder);
+ if (iRemConObserver && iKeyDecoder->MediaKeysEnabled())
+ {
+ iRemConObserver->RemoveMediaKeysListener(static_cast<MMIDMediaKeysListener*>(this));
+ }
+#ifdef RD_TACTILE_FEEDBACK
+ delete iTactileFeedback;
+#endif
+
+ if (iPointerEventSuppressor)
+ {
+ delete iPointerEventSuppressor;
+ iPointerEventSuppressor = NULL;
+ }
+
+ DEBUG("> CMIDCustomItem::~CMIDCustomItem");
+}
+
+/**
+ *
+ */
+TInt CMIDCustomItem::ItemPreferredHeightWithoutLabel()
+{
+ return PreferredContentSize().iHeight + iContentMargins.iTop + iContentMargins.iBottom;
+}
+
+/**
+ * Gets the available interaction modes. This method is intended to be called by
+ * CustomItem subclass code in order for it to determine what kinds of input are
+ * available from this device
+ */
+TInt CMIDCustomItem::InteractionModes() const
+{
+ DEBUG("< CMIDCustomItem::InteractionModes");
+ TInt modes = 0;
+
+ if (AknLayoutUtils::PenEnabled())
+ {
+ // Drag is not supported if physics scrolling is in use
+ if (CMIDFormPhysics::FeatureEnabled())
+ {
+ modes |= ETraverseHorizontal | ETraverseVertical |
+ EPointerPress | EPointerRelease;
+ }
+ else
+ {
+ modes |= ETraverseHorizontal | ETraverseVertical |
+ EPointerPress | EPointerRelease | EPointerDrag;
+ }
+ }
+
+ TRAP_IGNORE(modes |= KeyboardInteractionModesL());
+
+ DEBUG_INT("> CMIDCustomItem::InteractionModes = %d", modes);
+ return modes;
+}
+
+TInt CMIDCustomItem::KeyboardInteractionModesL() const
+{
+ DEBUG("< CMIDCustomItem::KeyboardInteractionModesL");
+ TInt modes = 0;
+
+#ifdef RD_INTELLIGENT_TEXT_INPUT
+ RArray<TPtiKeyboardType> keyboards;
+ CleanupClosePushL(keyboards);
+
+ CPtiEngine* ptiEngine = CPtiEngine::NewL();
+ CleanupStack::PushL(ptiEngine);
+
+ ptiEngine->ListAvailablePhysicalKeyboardsL(keyboards);
+
+ if (keyboards.Count() > 0)
+ {
+ modes |= ETraverseHorizontal | ETraverseVertical |
+ EKeyPress | EKeyRelease | EKeyRepeat;
+ }
+
+ CleanupStack::PopAndDestroy(ptiEngine);
+ CleanupStack::PopAndDestroy(&keyboards);
+#endif //RD_INTELLIGENT_TEXT_INPUT
+
+ DEBUG_INT("> CMIDCustomItem::KeyboardInteractionModesL = %d", modes);
+ return modes;
+}
+
+TBool CMIDCustomItem::SupportsInternalTraversal() const
+{
+ return iSupportsInternalTraversal;
+}
+
+/**
+ * This is a return value from Traverse method in Java.
+ * It returns whether it should traverse within the CustomItem and Rect that it should
+ * traverse to until it returns false and traverse out of CustomItem
+ */
+void CMIDCustomItem::SetFocusAndScroll(TBool aFocus,const TRect* aRect,TInt aDirection)
+{
+ DEBUG("< CMIDCustomItem::SetFocusAndScroll");
+ // Make sure we know if this CustomItem subclass supports internal traversal.
+
+ // When the item is entered for the very first time, check what the traverse
+ // method returned. If false, there is no internal traversal and we will
+ // handle this based on aFocus.
+ // If true, the item supports internal traversal and additional code is needed
+ if (!iEntered)
+ {
+ // iSupportsInternalTraversal is sampled on the first call only
+ iEntered = ETrue;
+ iSupportsInternalTraversal = aFocus;
+ // this will ensure that we get the focus on first traverse
+ aFocus = ETrue;
+
+ // Form must be updated when the focus enters to the non-traversal CustomItem for the first time.
+ // The reason is that the default value of iSupportsInternalTraversal is ETrue,
+ // which means that CMIDCustomItem::Draw() function has not updated focus before.
+ if (iForm && !iSupportsInternalTraversal)
+ {
+
+ iForm->DrawNow();
+ }
+ }
+
+ // Handle focus for items that do not support internal traversal
+ if (!iSupportsInternalTraversal)
+ {
+ // The focus is passed from java side
+ if (!aFocus && iForm)
+ {
+ iForm->Traverse((CMIDForm::TDirection)aDirection);
+ }
+ return;
+ }
+
+ // This calculates top/bottom rect for Form to scroll to.
+ if (aRect && aFocus && iForm)
+ {
+ TRect view = iForm->GetClientArea();
+
+ if (aRect->iTl.iY < view.iTl.iY) //top is off screen
+ {
+ // scroll up so that the focused area top is at the screen top
+ TInt scrollUp = view.iTl.iY - aRect->iTl.iY ;
+ if (iForm)
+ {
+ iForm->RawScroll(scrollUp);
+ }
+ }
+ else if (aRect->iBr.iY > view.iBr.iY) //bottom is off screen
+ {
+ // scroll down so that the focused area bottom is at the screen bottom
+ TInt scrollDown = view.iBr.iY - aRect->iBr.iY ;
+ if (iForm)
+ {
+ iForm->RawScroll(scrollDown);
+ }
+ }
+ }
+
+
+ // If losing focus, tell the Form to advance focus
+ //
+ if (!aFocus && iForm)
+ {
+ iForm->Traverse((CMIDForm::TDirection)aDirection);
+ }
+
+ DEBUG("> CMIDCustomItem::SetFocusAndScroll");
+}
+
+CFbsBitmap* CMIDCustomItem::FrameBuffer() const
+{
+ return iFrameBuffer;
+}
+
+void CMIDCustomItem::SetLabelL(const TDesC& aLabel)
+{
+ CMIDControlItem::SetLabelL(aLabel);
+ SetPreferredSizeL(iRequestedPreferredSize);
+}
+
+/** */
+void CMIDCustomItem::SetPreferredSizeL(const TSize& aSize)
+{
+ DEBUG("< CMIDCustomItem::SetPreferredSizeL");
+ DEBUG_INT2("+ CMIDCustomItem::SetPreferredSizeL - requested size = ( %d x %d )", aSize.iWidth, aSize.iHeight);
+
+ iRequestedPreferredSize = CheckRequestedSize(aSize);
+
+ if (iRequestedPreferredSize.iWidth == -1)
+ { // Width is not locked
+ iPreferredSize.iWidth = Min(FormClientAreaWidth(),
+ PreferredContentSize().iWidth + iContentMargins.iLeft + iContentMargins.iRight);
+ }
+ else
+ {
+ iPreferredSize.iWidth = Min(FormClientAreaWidth(),
+ Max(MinimumSize().iWidth, iRequestedPreferredSize.iWidth));
+ }
+
+ if (iLabelControl)
+ {
+ iLabelControl->SetWidthL(iPreferredSize.iWidth);
+ }
+
+
+ if (iRequestedPreferredSize.iHeight == -1)
+ { // Height is not locked
+ iPreferredSize.iHeight = PreferredContentSize().iHeight + iContentMargins.iTop
+ + iContentMargins.iBottom + LabelHeight();
+ }
+ else
+ {
+ iPreferredSize.iHeight = Max(MinimumSize().iHeight, iRequestedPreferredSize.iHeight);
+ }
+
+ DEBUG_INT2("+ CMIDCustomItem::SetPreferredSizeL - preferred size = ( %d x %d )", iPreferredSize.iWidth, iPreferredSize.iHeight);
+
+ TRAP_IGNORE(AdjustToSizeL(iPreferredSize));
+
+ DEBUG("> CMIDCustomItem::SetPreferredSizeL");
+}
+
+/**
+* Parameter aSize includes margins
+*/
+void CMIDCustomItem::AdjustToSizeL(const TSize& aSize)
+{
+ DEBUG("< CMIDCustomItem::AdjustToSizeL");
+
+ TInt availableHeight = aSize.iHeight - iContentMargins.iTop - iContentMargins.iBottom;
+ DEBUG_INT("+ CMIDCustomItem::AdjustToSizeL - available height = %d", availableHeight);
+ TInt requestedHeight = PreferredContentSize().iHeight + LabelHeight();
+ DEBUG_INT("+ CMIDCustomItem::AdjustToSizeL - requested height = %d", requestedHeight);
+
+ if (requestedHeight > availableHeight)
+ {// label + control do not fit
+ if (iLabelControl && iLabelControl->Text()->Length() > 0)
+ {
+ //reserve one line to the control
+ TInt heightForLabel =
+ ((availableHeight - PreferredContentSize().iHeight) > OneLineLabelHeight()) ?
+ availableHeight - PreferredContentSize().iHeight :
+ availableHeight - MinimumContentSize().iHeight;
+
+ //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);
+ }
+ }
+ DEBUG("> CMIDCustomItem::AdjustToSizeL");
+}
+
+/**
+ * Updates CustomItem with new MinContentSize and PrefContentSize received
+ * from CustomItem subclass
+ *
+ * Parameters doesn't include margins. iMinimumContentSize and iPreferredContentSize
+ * doesn't include margins.
+ */
+void CMIDCustomItem::Invalidate(const TSize& aMinSize, const TSize& aPrefSize)
+{
+ DEBUG("< CMIDCustomItem::Invalidate");
+
+ iMinimumContentSize = CheckRequestedSize(aMinSize);
+
+ if (iMinimumContentSize.iWidth < 1)
+ {
+ iMinimumContentSize.iWidth = 1;
+ }
+ if (iMinimumContentSize.iHeight < 1)
+ {
+ iMinimumContentSize.iHeight = 1;
+ }
+
+ TInt maxContentWidth = FormClientAreaWidth() - iContentMargins.iLeft -
+ iContentMargins.iRight;
+
+ if (iMinimumContentSize.iWidth > maxContentWidth)
+ {
+ iMinimumContentSize.iWidth = maxContentWidth;
+ }
+
+ iPreferredContentSize = CheckRequestedSize(aPrefSize);
+
+ if (iPreferredContentSize.iWidth < iMinimumContentSize.iWidth)
+ {
+ iPreferredContentSize.iWidth = iMinimumContentSize.iWidth;
+ }
+ if (iPreferredContentSize.iHeight < iMinimumContentSize.iHeight)
+ {
+ iPreferredContentSize.iHeight = iMinimumContentSize.iHeight;
+ }
+
+ if (iPreferredContentSize.iWidth > maxContentWidth)
+ {
+ iPreferredContentSize.iWidth = maxContentWidth;
+ }
+
+ if (iForm)
+ {
+ TRAP_IGNORE(iForm->RequestLayoutL());
+ }
+
+ DEBUG("> CMIDCustomItem::Invalidate");
+}
+
+MMIDBufferProcessor* CMIDCustomItem::Processor()
+{
+ return this;
+}
+
+void CMIDCustomItem::Dispose()
+{
+ delete this;
+}
+
+void CMIDCustomItem::AddCommandL(MMIDCommand* aCommand)
+{
+ CMIDItem::AddCommandL(aCommand);
+}
+
+void CMIDCustomItem::RemoveCommand(MMIDCommand* aCommand)
+{
+ CMIDItem::RemoveCommand(aCommand);
+}
+
+void CMIDCustomItem::SetDefaultCommand(MMIDCommand* aCommand)
+{
+ CMIDItem::SetDefaultCommand(aCommand);
+}
+
+TSize CMIDCustomItem::PreferredSize() const
+{
+ return iPreferredSize;
+}
+
+TSize CMIDCustomItem::MinimumSize() const
+{
+ DEBUG("< CMIDCustomItem::MinimumSize");
+ TSize minimumSize = MinimumContentSize() +
+ TSize(iContentMargins.iLeft + iContentMargins.iRight,
+ iContentMargins.iTop + iContentMargins.iBottom);
+
+ if (iLabelControl && (iLabelControl->Text()->Length() > 0))
+ {
+ minimumSize.iHeight += OneLineLabelHeight();
+ }
+ DEBUG_INT2("> CMIDCustomItem::MinimumSize = ( %d x %d )", minimumSize.iWidth, minimumSize.iHeight);
+ return minimumSize;
+}
+
+void CMIDCustomItem::SetLayoutL(TLayout aLayout)
+{
+ CMIDItem::SetLayoutL(aLayout);
+}
+
+const TSize& CMIDCustomItem::MinimumContentSize() const
+{
+ return iMinimumContentSize;
+}
+
+const TSize& CMIDCustomItem::PreferredContentSize() const
+{
+ return iPreferredContentSize;
+}
+
+void CMIDCustomItem::AbortAsync()
+{
+ // nop
+}
+
+enum TOpCode
+{
+ ESync,
+ ESyncRect
+};
+
+/** Copy the content (iFrameBuffer) into iOffScreenBuffer and then draw.
+Either do a full copy or copy only the clipped area.
+*/
+#ifdef RD_JAVA_NGA_ENABLED
+TBool CMIDCustomItem::ProcessL(
+ const TMIDBufferOp*& aOp, const TMIDBufferOp* aEnd,
+ TInt& /*aCycles*/, java::util::Monitor* /*aMonitor*/)
+#else
+TBool CMIDCustomItem::ProcessL(
+ const TMIDBufferOp*& aOp, const TMIDBufferOp* aEnd,
+ TInt& /*aCycles*/, TRequestStatus* /*aStatus*/)
+#endif
+{
+ DEBUG("< CMIDCustomItem::ProcessL");
+
+ // after coping iFrameBuffer to iOffScreenContext
+ // iFrameBuffer should be reset in Draw()
+ iResetFrameBuffer = ETrue;
+
+ while (aOp< aEnd)
+ {
+ switch (aOp->OpCode())
+ {
+ case ESync:
+ if (iFrameBuffer && iOffScreenContext)
+ {
+ iOffScreenContext->BitBlt(TPoint(0,0), iFrameBuffer);
+ }
+ DrawNow();
+
+ break;
+
+ case ESyncRect:
+ TRect clip = *static_cast<const TRect*>(aOp->Data());
+
+ if (iFrameBuffer && iOffScreenContext)
+ {
+ iOffScreenContext->BitBlt(clip.iTl, iFrameBuffer, clip);
+ }
+
+ clip.Move(iContentRect.iTl);
+ clip.Intersection(Rect());
+
+ ActivateGc();
+ Draw(clip);
+ DeactivateGc();
+
+ break;
+ }
+ aOp += aOp->Size();
+ }
+
+ // disable resetting of iFrameBuffer (it has been reset already in Draw())
+ iResetFrameBuffer = EFalse;
+
+ DEBUG("> CMIDCustomItem::ProcessL");
+ return EFalse;
+}
+
+TSize CMIDCustomItem::MinimumSize()
+{
+ return ((MMIDCustomItem*)this)->MinimumSize();
+}
+
+TInt CMIDCustomItem::CountComponentControls() const
+{
+ return 1;
+}
+
+CCoeControl* CMIDCustomItem::ComponentControl(TInt aIndex) const
+{
+ switch (aIndex)
+ {
+ case 0:
+ return iLabelControl;
+ }
+ return NULL;
+}
+
+#ifndef RD_JAVA_NGA_ENABLED
+void CMIDCustomItem::PauseDirectAccess()
+{
+ if (iDirectAccess)
+ {
+ StopDirectAccess();
+ iDirectPaused = ETrue;
+ }
+}
+
+
+void CMIDCustomItem::ResumeDirectAccess()
+{
+ if (iDirectAccess)
+ {
+ iDirectPaused = EFalse;
+ StartDirectAccess();
+ }
+}
+
+void CMIDCustomItem::StartDirectAccess()
+{
+ DEBUG("< CMIDCustomItem::StartDirectAccess");
+
+ if (!iDirectPaused && !iDirectAccess->IsActive())
+ {
+ TRAPD(err, iDirectAccess->StartL());
+ if (KErrNone != err)
+ {
+ iDirectAccess->Cancel();
+ return;
+ }
+
+ if (iDirectContent)
+ {
+ // Check that the dc region is fully visible
+ // to prevent covering of external dialogs.
+ RRegion* dsaRegion = iDirectAccess->DrawingRegion();
+
+ // Form must have four rectangles on drawing region
+ // (form area minus scroll bar)
+ if (dsaRegion->Count() == 4)
+ {
+ TRect itemRect(MdcContentBounds());
+ RRegion dcRegion(itemRect);
+
+ dcRegion.Intersect(*dsaRegion);
+ dcRegion.Tidy();
+ TBool dsaRegionOk = dcRegion.Count() == 1 &&
+ dcRegion[0] == itemRect;
+ dcRegion.Close();
+
+ if (iDirectContent && dsaRegionOk)
+ {
+ // Notify DirectContent to resume DSA
+ iDirectContent->MdcResumeDSA();
+ }
+ }
+ }
+ }
+
+ DEBUG("> CMIDCustomItem::StartDirectAccess");
+}
+void CMIDCustomItem::StopDirectAccess()
+{
+ if (iDirectContent)
+ {
+ // Notify DirectContent to abort DSA
+ iDirectContent->MdcAbortDSA();
+ }
+
+ if (iDirectAccess)
+ {
+ iDirectAccess->Cancel();
+ }
+}
+
+// MDirectScreenAccess
+void CMIDCustomItem::Restart(RDirectScreenAccess::TTerminationReasons /*aReasons*/)
+{
+ DEBUG("< CMIDCustomItem::Restart");
+ if (iDirectAccess)
+ {
+ StartDirectAccess();
+ }
+ DEBUG("> CMIDCustomItem::Restart");
+}
+
+// MDirectScreenAccess
+void CMIDCustomItem::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReasons*/)
+{
+ DEBUG("< CMIDCustomItem::AbortNow");
+
+ if (iDirectAccess)
+ {
+ StopDirectAccess();
+ }
+
+ DEBUG("> CMIDCustomItem::AbortNow");
+}
+#endif
+
+
+/** First draws the skin background and the border. Then draw the
+content. The content is double buffered, hence it must have already
+been copied into iOffScreenBuffer. Finally reset the frame buffer by
+drawing the skin background.
+
+@see: ProcessL() - which copies the content into iOffScreenBuffer
+*/
+void CMIDCustomItem::Draw(const TRect& aRect) const
+{
+ DEBUG("< CMIDCustomItem::Draw");
+
+ CWindowGc& gc = SystemGc();
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+ if (!SupportsInternalTraversal())
+ {
+ // doesn't support internal traversal - CMIDControlItem draws background
+ CMIDControlItem::Draw(aRect);
+ }
+ else
+ {
+ // does support internal traversal, draw background itself
+ AknsDrawUtils::Background(skin, iForm->CurrentDisplayable().BackGroundControlContext(),
+ this, gc, aRect);
+ }
+
+ if (iOffScreenBuffer)
+ {
+ gc.BitBlt(iContentRect.iTl, iOffScreenBuffer);
+ }
+
+ if (iForm && iFrameContext && iResetFrameBuffer)
+ {
+ MAknsControlContext* cc = !SupportsInternalTraversal() ? AknsDrawUtils::ControlContext(this) :
+ iForm->CurrentDisplayable().BackGroundControlContext();
+
+ // Don't do the following action in case of something is rendered into offscreen buffer (GIF)
+ if (!iDirectContent)
+ {
+ AknsDrawUtils::DrawBackground(skin, cc,
+ this, *iFrameContext, TPoint(0,0), iContentRect, KAknsDrawParamDefault);
+ }
+ }
+ DEBUG("> CMIDCustomItem::Draw");
+}
+
+#ifdef RD_SCALABLE_UI_V2
+void CMIDCustomItem::HandlePointerEventL(const TPointerEvent &aPointerEvent)
+{
+ DEBUG("< CMIDCustomItem::HandlePointerEventL");
+
+ if (AknLayoutUtils::PenEnabled())
+ {
+ if (!iForm->TryDetectLongTapL(aPointerEvent))
+ {
+ TRect drawableRect = Rect();
+ drawableRect.SetHeight(
+ drawableRect.Height() - iContentMargins.iTop -
+ iContentMargins.iBottom - iLabelControl->Size().iHeight);
+ drawableRect.SetWidth(drawableRect.Width() -
+ iContentMargins.iLeft - iContentMargins.iRight);
+ drawableRect.Move(iContentMargins.iLeft,
+ iContentMargins.iTop + iLabelControl->Size().iHeight);
+ TPoint point = aPointerEvent.iPosition;
+
+#ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+ if (!drawableRect.Contains(point) && !iForm->IsFocusChangingWithPen())
+ {
+ switch (aPointerEvent.iType)
+ {
+ case TPointerEvent::EButton1Down:
+ case TPointerEvent::EButton1Up:
+ MTouchFeedback* feedback = MTouchFeedback::Instance();
+ if (feedback)
+ {
+ feedback->InstantFeedback(ETouchFeedbackList);
+ }
+ break;
+ }
+ }
+#endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
+
+ point.iX = point.iX - drawableRect.iTl.iX;
+ point.iY = point.iY - drawableRect.iTl.iY;
+ TEventType type;
+ switch (aPointerEvent.iType)
+ {
+ case TPointerEvent::EButton1Down:
+ case TPointerEvent::EButton2Down:
+ case TPointerEvent::EButton3Down:
+ type = EPointerPressed;
+ iPointerPressedCoordinates = TPoint(point.iX, point.iY);
+ break;
+ case TPointerEvent::EButton1Up:
+ case TPointerEvent::EButton2Up:
+ case TPointerEvent::EButton3Up:
+ type = EPointerReleased;
+ if (iPointerEventSuppressionOngoing)
+ {
+ point.iX = iPointerPressedCoordinates.iX;
+ point.iY = iPointerPressedCoordinates.iY;
+ }
+ break;
+ case TPointerEvent::EDrag:
+ type = EPointerDragged;
+ break;
+ default:
+ type = ENoType;
+ }
+
+ if (iPointerEventSuppressor->SuppressPointerEvent(aPointerEvent))
+ {
+ iPointerEventSuppressionOngoing = ETrue;
+ return;
+ }
+ else
+ {
+ iPointerEventSuppressionOngoing = EFalse;
+ }
+
+ iEnv.PostJavaEvent(*this, EItem, type, point.iX, point.iY, 0);
+ }
+ }
+
+ DEBUG("> CMIDCustomItem::HandlePointerEventL");
+}
+#endif //RD_SCALABLE_UI_V2
+
+
+void CMIDCustomItem::HandleCurrentL(TBool aCurrent)
+{
+ DEBUG("< CMIDCustomItem::HandleCurrentL");
+ if (aCurrent)
+ {
+ PostFocusTransferEvent(ETrue, CMIDForm::ENone);
+ }
+ DEBUG("> CMIDCustomItem::HandleCurrentL");
+}
+
+
+void CMIDCustomItem::SizeChanged()
+{
+ DEBUG("< CMIDCustomItem::SizeChanged");
+
+ const TRect oldRect = iContentRect;
+ DEBUG_INT2("+ CMIDCustomItem::SizeChanged - old size = ( %d x %d )", oldRect.Width(), oldRect.Height());
+
+ // Rect() returns control area including content, margins and possible label
+ // iContentRect is the item content area exluding margins
+ iContentRect = Rect();
+
+ if (iLabelControl && iLabelControl->Text()->Length())
+ {
+ TRect rect(iContentRect);
+ rect.iBr.iY = rect.iTl.iY + LabelHeight();
+ iLabelControl->SetRect(rect);
+ // Content
+ iContentRect.iTl.iY += LabelHeight();
+ }
+
+ iContentRect.SetRect(
+ iContentRect.iTl.iX + iContentMargins.iLeft,
+ iContentRect.iTl.iY + iContentMargins.iTop,
+ iContentRect.iBr.iX - iContentMargins.iRight,
+ iContentRect.iBr.iY - iContentMargins.iBottom);
+
+ if (oldRect != iContentRect)
+ {
+#ifndef RD_JAVA_NGA_ENABLED
+ // Pause DSA during framebuffers are being changed
+ PauseDirectAccess();
+#endif
+ const TSize canvasSize(iContentRect.Size());
+ DEBUG_INT2("+ CMIDCustomItem::SizeChanged - new size = ( %d x %d )", canvasSize.iWidth, canvasSize.iHeight);
+ if (!iFrameBuffer || canvasSize != iFrameBuffer->SizeInPixels())
+ {
+ TRAPD(err, CreateBuffersL());
+
+ if (err != KErrNone)
+ {
+ ResetBuffers();
+ }
+ }
+
+ CMIDControlItem::SizeChanged();
+
+ //
+ // send SizeChanged event only if the size changes
+ //
+ if (oldRect.Size() != canvasSize)
+ {
+ iEnv.PostJavaEvent(*this, EItem, ESizeChanged, canvasSize.iWidth , canvasSize.iHeight, 0);
+ }
+#ifdef RD_TACTILE_FEEDBACK
+ UpdateTactileFeedback();
+#endif
+
+ if (iDirectContent && iForm)
+ {
+ // Store the window position to be used later
+ // from non-LCDUI ES thread
+ iLastWindowPosition = DrawableWindow()->Position();
+
+ if (iDirectAreaAddedToDisplayable)
+ {
+ // Update the direct content area according the new size
+ UpdateDirectContentBounds();
+ }
+
+ TRect itemRect(iContentRect);
+ itemRect.Move(iLastWindowPosition);
+ iDirectContent->MdcItemContentRectChanged(itemRect,MdcContentBounds());
+ }
+
+#ifndef RD_JAVA_NGA_ENABLED
+ if (MdcContainerVisibility())
+ {
+ ResumeDirectAccess();
+ }
+#endif
+ }
+ DEBUG("> CMIDCustomItem::SizeChanged");
+}
+
+void CMIDCustomItem::PositionChanged()
+{
+ DEBUG("< CMIDCustomItem::PositionChanged");
+ iContentRect = Rect();
+ iContentRect.iTl.iY += LabelHeight();
+
+ iContentRect.SetRect(
+ iContentRect.iTl.iX + iContentMargins.iLeft,
+ iContentRect.iTl.iY + iContentMargins.iTop,
+ iContentRect.iBr.iX - iContentMargins.iRight,
+ iContentRect.iBr.iY - iContentMargins.iBottom);
+
+ if (iDirectContent && iForm)
+ {
+ // Store the window position to be used later
+ // from non-LCDUI ES thread
+ iLastWindowPosition = DrawableWindow()->Position();
+
+ if (iDirectAreaAddedToDisplayable)
+ {
+ // Update the direct content area according the new size
+ UpdateDirectContentBounds();
+ }
+
+ TRect itemRect(iContentRect);
+ itemRect.Move(iLastWindowPosition);
+ iDirectContent->MdcItemContentRectChanged(itemRect,MdcContentBounds());
+ }
+ DEBUG("> CMIDCustomItem::PositionChanged");
+}
+
+TKeyResponse CMIDCustomItem::OfferKeyEventL(const TKeyEvent& aEvent, TEventCode aType)
+{
+ DEBUG("< CMIDCustomItem::OfferKeyEventL");
+
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - received: iCode = %d", aEvent.iCode);
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - received: iModifiers = %d", aEvent.iModifiers);
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - received: iRepeats = %d", aEvent.iRepeats);
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - received: iScanCode = %d", aEvent.iScanCode);
+
+ // map key event data
+ TKeyEvent wsEvent = aEvent;
+ iEnv.MappingDataForKey(wsEvent, aType);
+
+ TMIDKeyEvent event;
+ if (iEnv.TranslateKeyL(event, wsEvent, aType))
+ {
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - translated: iEvents = %d", event.iEvents);
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - translated: iKeyCode = %d", event.iKeyCode);
+ DEBUG_INT("+ CMIDCustomItem::OfferKeyEventL - translated: iRepeats = %d", event.iRepeats);
+
+ // 9-way Navigation Support
+ // Send two arrow events generated when press diagonal direction
+ switch (event.iKeyCode)
+ {
+ //KeyLeftUpArrow
+ case EKeyLeftUpArrow:
+ {
+ TKeyEvent pevent;
+ pevent.iCode = EKeyUpArrow;
+ pevent.iScanCode = EStdKeyUpArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+ pevent.iCode = EKeyLeftArrow;
+ pevent.iScanCode = EStdKeyLeftArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+
+ break;
+ }
+ //KeyRightUpArrow
+ case EKeyRightUpArrow:
+ {
+ TKeyEvent pevent;
+ pevent.iCode = EKeyUpArrow;
+ pevent.iScanCode = EStdKeyUpArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+ pevent.iCode = EKeyRightArrow;
+ pevent.iScanCode = EStdKeyRightArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+
+ break;
+ }
+ //KeyRightDownArrow
+ case EKeyRightDownArrow:
+ {
+ TKeyEvent pevent;
+ pevent.iCode = EKeyDownArrow;
+ pevent.iScanCode = EStdKeyDownArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+ pevent.iCode = EKeyRightArrow;
+ pevent.iScanCode = EStdKeyRightArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+
+ break;
+ }
+ //KeyLeftDownArrow
+ case EKeyLeftDownArrow:
+ {
+ TKeyEvent pevent;
+ pevent.iCode = EKeyDownArrow;
+ pevent.iScanCode = EStdKeyDownArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+ pevent.iCode = EKeyLeftArrow;
+ pevent.iScanCode = EStdKeyLeftArrow;
+ pevent.iModifiers = aEvent.iModifiers;
+ pevent.iRepeats = event.iRepeats;
+ this->OfferKeyEventL(pevent, aType);
+
+ break;
+ }
+ default:
+ iEnv.PostKeyEvent(*this, event);
+ }//switch
+ }
+ // }
+
+ if (aType != EEventKey)
+ return EKeyWasNotConsumed;
+
+ if (!SupportsInternalTraversal() || aEvent.iCode == EKeyDevice3)
+ {
+ DEBUG("> CMIDCustomItem::OfferKeyEventL - returns EKeyWasNotConsumed");
+ return EKeyWasNotConsumed;
+ }
+
+ CMIDForm::TDirection direction = TranslateKey(aEvent);
+ if (direction != CMIDForm::ENone)
+ {
+ PostFocusTransferEvent(ETrue, direction);
+ }
+
+ DEBUG("> CMIDCustomItem::OfferKeyEventL - returns EKeyWasConsumed");
+ return EKeyWasConsumed;
+}
+
+TSize CMIDCustomItem::ResetPreferredSize() const
+{
+ TRAP_IGNORE(const_cast<CMIDCustomItem*>(this)->SetPreferredSizeL(iRequestedPreferredSize));
+ return iPreferredSize;
+}
+
+/** If the specified height or width or the requested size are bigger that the
+screen height or width times KCIMaxScreenSizeFactor then return these limit values.
+Otherwise return the size unchanged. @see KCIMaxScreenSizeFactor */
+TSize CMIDCustomItem::CheckRequestedSize(const TSize& aRequestedSize) const
+{
+ DEBUG("< CMIDCustomItem::CheckRequestedSize");
+ TSize size = aRequestedSize;
+
+ const TRect formClientAreaRect = FormClientAreaRect();
+
+ size.iWidth = size.iWidth < KCIMaxScreenSizeFactor * formClientAreaRect.Width() ?
+ size.iWidth : KCIMaxScreenSizeFactor * formClientAreaRect.Width();
+
+ size.iHeight = size.iHeight < KCIMaxScreenSizeFactor * formClientAreaRect.Height() ?
+ size.iHeight : KCIMaxScreenSizeFactor * formClientAreaRect.Height();
+
+ DEBUG_INT2("> CMIDCustomItem::CheckRequestedSize = ( %d x %d )", size.iWidth, size.iHeight);
+ return size;
+}
+
+void CMIDCustomItem::FocusChanged(TDrawNow aDrawNow)
+{
+ DEBUG("< CMIDCustomItem::FocusChanged");
+ if (iForm)
+ {
+ //Item is on Form:
+ //Check if CustomItem changed its visibility (previous state is
+ //stored in iPreviousVisibility).
+ //current visibility:
+ TBool contentRectVisible = MdcContainerVisibility();
+ if (iPreviousVisibility != contentRectVisible)
+ {
+ //Event is sent only if CustomItem changed visibility:
+ //1. CustomItem is now at least partially visible,
+ // when it previously had been completely invisible
+ // -> CustomItem gains visibility,
+ // showNotify is invoked on java side
+ //2. CustomItem is now completely invisible, when it previously
+ // had been at least partially visible
+ // -> CustomItem loses visibility,
+ // hideNotify is invoked on java side
+ iEnv.PostJavaEvent(*this, EItem, EVisible, contentRectVisible);
+
+ if (!iRestoreDirectContentWhenUnfaded)
+ {
+ ChangeDirectContainerVisibility(contentRectVisible);
+ }
+
+ //Current status of visibility is always stored
+ iPreviousVisibility = contentRectVisible;
+ }
+ }
+
+ CMIDControlItem::FocusChanged(aDrawNow);
+
+ DEBUG("> CMIDCustomItem::FocusChanged");
+}
+
+void CMIDCustomItem::ChangeDirectContainerVisibility(TBool aVisible)
+{
+ DEBUG("< CMIDCustomItem::ChangeDirectContainerVisibility");
+ if (iForm)
+ {
+ iLastWindowPosition = DrawableWindow()->Position();
+ }
+
+#ifndef RD_JAVA_NGA_ENABLED
+ if (iDirectAccess && (iDirectPaused == aVisible))
+ {
+ if (aVisible)
+ {
+ ResumeDirectAccess();
+ }
+ else
+ {
+ PauseDirectAccess();
+ }
+ }
+#endif
+
+ if (iDirectContent)
+ {
+ // Restore direct content
+ iDirectContent->MdcContainerVisibilityChanged(aVisible);
+ }
+
+ DEBUG("> CMIDCustomItem::ChangeDirectContainerVisibility");
+}
+
+/** Handles change in displaying item - calls same
+events as in focus change.
+*/
+void CMIDCustomItem::HandleVisibilityChange()
+{
+ FocusChanged(ENoDrawNow);
+}
+
+void CMIDCustomItem::SetForm(CMIDForm* aForm)
+{
+ DEBUG("< CMIDCustomItem::SetForm");
+ CMIDItem::SetForm(aForm);
+
+ if (iForm)
+ {
+ // Set S60 Selection Key Compatibility
+ // to provide MSK key events to canvas
+ iS60SelectionKeyCompatibility = iEnv.MidletAttributeIsSetToVal(
+ LcduiMidletAttributes::KAttribS60SelectionKeyCompatibility,
+ LcduiMidletAttributeValues::KTrueValue
+ );
+ }
+ DEBUG("> CMIDCustomItem::SetForm");
+}
+
+void CMIDCustomItem::ItemAddedToFormL()
+{
+ CMIDItem::ItemAddedToFormL();
+
+ if (iDirectContent)
+ {
+ iDirectContent->MdcContainerWindowRectChanged(MdcContainerWindowRect());
+ }
+
+ if (iPreviousVisibility)
+ {
+ ChangeDirectContainerVisibility(ETrue);
+ }
+}
+
+void CMIDCustomItem::ItemRemovedFromForm()
+{
+ CMIDItem::ItemRemovedFromForm();
+
+ ChangeDirectContainerVisibility(EFalse);
+}
+
+void CMIDCustomItem::PostFocusTransferEvent(
+ TBool aFocus,CMIDForm::TDirection aDirection)
+{
+ DEBUG("< CMIDCustomItem::PostFocusTransferEvent");
+
+ TRect customItemRect = iContentRect;
+
+ if (iForm)
+ {
+ iForm->CurrentDisplayable().SetS60SelectionKeyCompatibility(
+ iS60SelectionKeyCompatibility && aFocus
+ );
+ TRect formRect = iForm->GetClientArea();
+ if (customItemRect.Intersects(formRect))
+ {
+ customItemRect.Intersection(formRect);
+ }
+ else
+ {
+ customItemRect.SetRect(0, 0, 0, 0);
+ }
+
+ TInt eventData = aFocus << 16 | aDirection;
+ TInt eventData1 = customItemRect.iTl.iX << 16 | customItemRect.iTl.iY;
+ TInt eventData2 = customItemRect.Width() << 16 | customItemRect.Height();
+ iEnv.PostJavaEvent(*this, EItem, EFocusTraversal,
+ eventData, eventData1, eventData2);
+ }
+ DEBUG("> CMIDCustomItem::PostFocusTransferEvent");
+}
+
+CMIDForm::TDirection CMIDCustomItem::TranslateKey(const TKeyEvent& aEvent)
+{
+ switch (aEvent.iCode)
+ {
+ case EKeyLeftArrow:
+ return CMIDForm::ELeft;
+ case EKeyRightArrow:
+ return CMIDForm::ERight;
+ case EKeyUpArrow:
+ return CMIDForm::EUp;
+ case EKeyDownArrow:
+ return CMIDForm::EDown;
+ }
+ return CMIDForm::ENone;
+}
+
+MDirectContainer& CMIDCustomItem::DirectContainer()
+{
+ return *this;
+}
+
+void CMIDCustomItem::MdcAddContent(MDirectContent* aContent)
+{
+ // Item can only have one content.
+ iDirectContent = aContent;
+
+ // Register this control to observer
+ // in order to provide calls to this control from
+ // non-LCDUI ES thread.
+ // Unregistration is done in MdcRemoveContent.
+ iEnv.ToLcduiObserver().RegisterControl(*this);
+}
+
+void CMIDCustomItem::MdcRemoveContent(MDirectContent* /*aContent*/)
+{
+ iDirectContent = NULL;
+
+ // Unregister the component from the observer
+ // if it were previously registered from MdcAddContent.
+ iEnv.ToLcduiObserver().UnregisterControl(*this);
+}
+
+TRect CMIDCustomItem::MdcContainerWindowRect() const
+{
+ TRect rect;
+ if (iForm)
+ {
+ // Form has always the same size as the RWindow
+ rect = TRect(iForm->PositionRelativeToScreen(), iForm->Size());
+ }
+ return rect;
+}
+
+/** Return the item visibility. If the form has lost focus it is probably
+because we have a menu or something else in front so we assume we have lost
+visibility.
+The direct container uses this to start/stop direct screen access.
+*/
+TBool CMIDCustomItem::MdcContainerVisibility() const
+{
+ return (iForm ? iForm->IsFocused() : EFalse) &&
+ (MdcContentBounds().Size().iHeight > 0);
+}
+
+TRect CMIDCustomItem::MdcContentBounds() const
+{
+ DEBUG("< CMIDCustomItem::MdcContentBounds");
+
+ TRect visibleRect;
+
+ // Cannot use iContentRect because it's not updated
+ // if the CustomItem is scrolled out
+ TRect contentRect = Rect();
+ contentRect.SetRect(
+ contentRect.iTl.iX + iContentMargins.iLeft,
+ contentRect.iTl.iY + iContentMargins.iTop,
+ contentRect.iBr.iX - iContentMargins.iRight,
+ contentRect.iBr.iY - iContentMargins.iBottom);
+
+ DEBUG_INT2("+ CMIDCustomItem::MdcContentBounds - contentRect.iTl = [ %d, %d ]", contentRect.iTl.iX, contentRect.iTl.iY);
+ DEBUG_INT2("+ CMIDCustomItem::MdcContentBounds - contentRect.iBr = [ %d, %d ]", contentRect.iBr.iX, contentRect.iBr.iY);
+ if (iForm)
+ {
+ TRect formRect = iForm->GetClientArea();
+ if (contentRect.Intersects(formRect))
+ {
+ visibleRect = contentRect;
+ visibleRect.Intersection(formRect);
+
+ visibleRect.Move(iLastWindowPosition);
+ }
+ }
+
+ DEBUG_INT2("+ CMIDCustomItem::MdcContentBounds - visibleRect.iTl = [ %d, %d ]", visibleRect.iTl.iX, visibleRect.iTl.iY);
+ DEBUG_INT2("+ CMIDCustomItem::MdcContentBounds - visibleRect.iBr = [ %d, %d ]", visibleRect.iBr.iX, visibleRect.iBr.iY);
+ DEBUG("> CMIDCustomItem::MdcContentBounds");
+ return visibleRect;
+}
+
+void CMIDCustomItem::MdcItemContentRect(TRect& aContentRect,
+ TRect& aScreenRect) const
+{
+ DEBUG("< CMIDCustomItem::MdcItemContentRect");
+
+ aScreenRect = MdcContentBounds(); //The clipped rect
+
+ aContentRect = iContentRect; //The item rect
+ aContentRect.Move(iLastWindowPosition);
+
+ DEBUG("> CMIDCustomItem::MdcItemContentRect");
+}
+
+void CMIDCustomItem::MdcHandlePointerEventL(TPointerEvent& /*aPointerEvent*/)
+{
+ // This method should not be called
+ __ASSERT_DEBUG(EFalse, User::Invariant());
+}
+
+void CMIDCustomItem::MdcFlushContainer(const TRect& aRect)
+{
+ if (iFrameBuffer && iOffScreenContext)
+ {
+ iOffScreenContext->BitBlt(TPoint(0,0), iFrameBuffer);
+
+ // Flush the framebuffer on screen
+ iEnv.ToLcduiObserver().FlushControl(*this, aRect);
+ }
+}
+
+void CMIDCustomItem::MdcGetDSAResources(MUiEventConsumer& aConsumer)
+{
+ if (DrawableWindow())
+ {
+ // May run in non-LCDUI ES thread
+ // Invoke the callback from LCDUI ES thread
+ iEnv.ToLcduiObserver().InvokeDSAResourcesCallback(*this, aConsumer);
+ }
+ else
+ {
+ // Drawable window is not set
+ // Callback will be invoked from within
+ // SetContainerWindowL method.
+ iConsumerWaitingForDSAResourcesCallback = &aConsumer;
+ }
+}
+
+void CMIDCustomItem::MdcGetUICallback(
+ MUiEventConsumer& aConsumer,
+ TInt aCallbackId)
+{
+ // May run in non-LCDUI ES thread
+ // Invoke the callback from LCDUI ES thread
+ iEnv.ToLcduiObserver().InvokeUICallback(aConsumer, aCallbackId);
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDCustomItem::MdcAddContentBounds(const TRect& /*aRect*/)
+{
+ iDirectAreaAddedToDisplayable = UpdateDirectContentBounds();
+}
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CMIDCustomItem::MdcRemoveContentBounds(const TRect& /*aRect*/)
+{
+ if (iForm && iDirectAreaAddedToDisplayable)
+ {
+ // Remove clipping rect
+ Form()->CurrentDisplayable().RemoveDirectContentArea(iDirectArea);
+ iDirectAreaAddedToDisplayable = EFalse;
+ }
+}
+
+void CMIDCustomItem::ResolutionChange(TInt /*aType*/)
+{
+ UpdateMargins();
+ if (iDirectContent)
+ {
+ iDirectContent->MdcContainerWindowRectChanged(MdcContainerWindowRect());
+ }
+}
+
+void CMIDCustomItem::HandleWindowFade(TBool aFaded)
+{
+ if (iDirectContent)
+ {
+ TBool contentRectVisible = MdcContainerVisibility();
+ if ((contentRectVisible))
+ {
+ ChangeDirectContainerVisibility(!aFaded);
+ }
+ }
+ iRestoreDirectContentWhenUnfaded = aFaded;
+}
+
+void CMIDCustomItem::HandleMediaKeyEvent(TMIDKeyEvent& aKeyEvent)
+{
+ DEBUG_INT3("CMIDCustomItem::HandleMediaKeyEvent - PostKeyEvent() - JAVA code %d type %d repeats %d", aKeyEvent.iKeyCode, aKeyEvent.iEvents, aKeyEvent.iRepeats);
+ iEnv.PostKeyEvent(*this, aKeyEvent);
+}
+
+#ifdef RD_TACTILE_FEEDBACK
+
+MMIDTactileFeedbackComponent* CMIDCustomItem::TactileFeedbackComponent()
+{
+ return this;
+}
+
+void CMIDCustomItem::UpdateTactileFeedback()
+{
+ DEBUG("< CMIDCustomItem::UpdateTactileFeedback");
+ TInt areaCount = iTactileFeedback->GetAreasCount();
+
+ for (TInt i=0; i < areaCount; i++)
+ {
+ CMIDTactileFeedbackExtension::FeedbackArea* area = iTactileFeedback->GetArea(i);
+ TRect physicalRect = area->rect;
+ physicalRect.Move(iContentRect.iTl.iX,
+ iContentRect.iTl.iY);
+
+ iTactileFeedback->SetFeedbackArea(area->id, physicalRect, (TInt)area->style);
+ }
+ DEBUG("> CMIDCustomItem::UpdateTactileFeedback");
+}
+
+void CMIDCustomItem::RegisterFeedbackArea(TInt aId, TRect aRect, TInt aStyle)
+{
+ iTactileFeedback->RegisterFeedbackArea(aId, aRect, aStyle);
+}
+
+void CMIDCustomItem::UnregisterFeedbackArea(TInt aId)
+{
+ iTactileFeedback->UnregisterFeedbackArea(aId);
+}
+
+void CMIDCustomItem::UnregisterFeedbackForControl()
+{
+ iTactileFeedback->UnregisterFeedbackForControl();
+}
+
+void CMIDCustomItem::MoveAreaToFirstPriority(TInt aId)
+{
+ iTactileFeedback->MoveAreaToFirstPriority(aId);
+}
+#endif //RD_TACTILE_FEEDBACK
+
+
+// ---------------------------------------------------------------------------
+// CMIDCustomItem::UpdateDirectContentBounds
+// Notifies the current displayable about the direct content position update
+// ---------------------------------------------------------------------------
+//
+TBool CMIDCustomItem::UpdateDirectContentBounds()
+{
+ if (iForm)
+ {
+ TRect currentDirectArea(MdcContentBounds());
+
+ currentDirectArea.Move(-iLastWindowPosition);
+
+ if (iDirectAreaAddedToDisplayable)
+ {
+ Form()->CurrentDisplayable().RemoveDirectContentArea(
+ iDirectArea);
+ }
+
+ iDirectArea = currentDirectArea;
+
+ // Add clipping rect to protect direct content from being redrawn
+ this->Form()->CurrentDisplayable().AddDirectContentArea(
+ iDirectArea);
+
+ return ETrue;
+ }
+ return EFalse;
+}