javauis/lcdui_akn/lcdui/src/CMIDForm.cpp
branchRCL_3
changeset 26 2455ef1f5bbc
child 27 d5e927d5853b
equal deleted inserted replaced
25:ae942d28ec0e 26:2455ef1f5bbc
       
     1 /*
       
     2 * Copyright (c) 2003-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implements the Form LCDUI component.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 //RD_SCALABLE_UI definition
       
    20 #include <bldvariant.hrh>
       
    21 // using CEikScrollBarFrame API for iSBFrame
       
    22 #include <eiksbfrm.h>
       
    23 
       
    24 // API used for retrieving layout for initial alignment (in ConstructL)
       
    25 #include <centralrepository.h>
       
    26 // constants used in retrieving layout for initial alignment (in ConstructL)
       
    27 #include <AvkonInternalCRKeys.h>
       
    28 
       
    29 // control context that provides a layout background
       
    30 #include <AknsListBoxBackgroundControlContext.h>
       
    31 // highlight background
       
    32 #include <AknsFrameBackgroundControlContext.h>
       
    33 // API for text formatting used in DrawNoDataStringL function
       
    34 #include <AknBidiTextUtils.h>
       
    35 
       
    36 #include "CMIDForm.h"
       
    37 #include "CMIDFormRow.h"
       
    38 // API for iDisplayable
       
    39 #include "CMIDDisplayable.h"
       
    40 #include "CMIDItem.h"
       
    41 #include "CMIDControlItem.h"
       
    42 #include "CMIDGaugeItem.h"
       
    43 #include "CMIDImageItem.h"
       
    44 #include "CMIDStringItem.h"
       
    45 // CMIDLabelContainerItem API used to obtain CMIDStringItem item
       
    46 #include "CMIDLabelContainerItem.h"
       
    47 #include "CMIDTextFieldItem.h"
       
    48 #include "CMIDChoiceGroupItem.h"
       
    49 #include "CMIDSpacer.h"
       
    50 #include "CMIDCustomItem.h"
       
    51 #include "CMIDDateFieldItem.h"
       
    52 #include "CMIDComponentFactory.h"
       
    53 #include "CMIDUtils.h"
       
    54 #include "CMIDItemLabel.h"
       
    55 #include "CMIDTicker.h"
       
    56 #include "CMIDFont.h"
       
    57 #include "CMIDPopupNoteController.h"
       
    58 // Kinetic scrolling
       
    59 #include "CMIDFormPhysics.h"
       
    60 
       
    61 #include <applayout.cdl.h>
       
    62 // LAF
       
    63 #include <aknlayoutscalable_avkon.cdl.h>
       
    64 // LAF
       
    65 #include <layoutmetadata.cdl.h>
       
    66 
       
    67 // Api for skin layout
       
    68 #include <skinlayout.cdl.h>
       
    69 using namespace SkinLayout;
       
    70 
       
    71 #include <j2me/jdebug.h>
       
    72 
       
    73 #undef  TRAP_INSTRUMENTATION_LEAVE
       
    74 #define TRAP_INSTRUMENTATION_LEAVE(aResult) DEBUG_INT2("In CMIDForm.cpp, trapped method was called at line %D and got exception %D", __LINE__, aResult);
       
    75 
       
    76 #ifdef RD_SCALABLE_UI_V2
       
    77 /** Dividers used when the the scroll amount is calculated*/
       
    78 const TInt KScrollAmountDivider = 4;
       
    79 const TInt KScrollAmountDividerForThumbDrag = 10;
       
    80 
       
    81 /** Interval for scrolling when stylus is dragged outside the form and held down */
       
    82 const TInt KScrollInterval = 100000; // 0,1 sec
       
    83 #endif //RD_SCALABLE_UI_V2
       
    84 
       
    85 /** The minimum amount to scroll */
       
    86 const TInt KMinScrollAmount = 40;
       
    87 
       
    88 /** The timeout in microseconds for visual updates. When items are added or removed
       
    89 or modified, the form is not redrawn immediately but only after this timeout. This way
       
    90 if more items are being added or removed or changed we reduce the number of redraws.
       
    91 */
       
    92 const TInt KLayoutTimeout = 60000; //60 msecs
       
    93 
       
    94 /** If layout has been requested for a period longer than the cap then perform layout
       
    95 even if the midlet is still performing form insert/delete operations. */
       
    96 const TInt KLayoutCap = 1000000; // 1 sec
       
    97 
       
    98 ///////////////////////////////////////////////////////////////////////////////////////////////////
       
    99 // MMIDForm interface
       
   100 ///////////////////////////////////////////////////////////////////////////////////////////////////
       
   101 
       
   102 /**
       
   103  * Add items list. Note: this is no longer called by framework!!
       
   104  */
       
   105 void CMIDForm::SetAllItemsL(const RArray<MMIDItem*>& aItems)
       
   106 {
       
   107     DEBUG("CMIDForm::SetAllItemsL");
       
   108 
       
   109     ASSERT(iItems.Count() == 0);
       
   110     //
       
   111     TInt count = aItems.Count();
       
   112     for (TInt i=0; i<count; i++)
       
   113     {
       
   114         User::LeaveIfError(iItems.Append(aItems[i]));
       
   115         CMIDControlItem& ci = ControlItem(i);
       
   116 
       
   117         AddItemToFormL(ci);
       
   118         ci.MakeVisible(ETrue);
       
   119     }
       
   120 
       
   121     RequestLayoutL();
       
   122 }
       
   123 
       
   124 /**
       
   125  * Replaces an item. Keeps the same item focused which had focus before,
       
   126  * and if that's the one that this is replacing, then this will be focused
       
   127  * if possible.
       
   128  */
       
   129 void CMIDForm::SetItemL(MMIDItem& aItem,TInt aIndex)
       
   130 {
       
   131     DEBUG("CMIDForm::SetItemL");
       
   132 
       
   133     CMIDControlItem& oldCi = ControlItem(aIndex);
       
   134     RemoveItemFromForm(oldCi);
       
   135 
       
   136     iItems[aIndex] = &aItem;
       
   137     CMIDControlItem& ci = ControlItem(aIndex);
       
   138     AddItemToFormL(ci);
       
   139 
       
   140     ci.MakeVisible(ETrue);
       
   141 
       
   142     if (iFocused == aIndex)
       
   143     {
       
   144         iDisplayable.MenuHandler()->HideMenuIfVisible();
       
   145 
       
   146         if (ci.IsSelectable())
       
   147         {
       
   148             SetFocusedItem(aIndex);
       
   149         }
       
   150         else
       
   151         {
       
   152             SetFocusedItem(KErrNotFound);
       
   153         }
       
   154     }
       
   155 
       
   156     RequestLayoutL();
       
   157 }
       
   158 
       
   159 /**
       
   160  * Inserts a new Item.
       
   161  */
       
   162 void CMIDForm::InsertItemL(MMIDItem& aItem, TInt aIndex)
       
   163 {
       
   164     DEBUG("CMIDForm::InsertItemL");
       
   165 
       
   166     User::LeaveIfError(iItems.Insert(&aItem,aIndex));
       
   167     CMIDControlItem& ci = ControlItem(aIndex);
       
   168 
       
   169     AddItemToFormL(ci);
       
   170     ci.MakeVisible(ETrue);
       
   171     // if insert item then index of pointed control is increase
       
   172     if (aIndex <= iIndexPointedControl)
       
   173     {
       
   174         iIndexPointedControl++;
       
   175     }
       
   176 
       
   177     // If there isn't any focused item yet, we have to set focus
       
   178     // to first item which is focusable. Once the item has focus,
       
   179     // we can skip this step.
       
   180     if (iFocused == KErrNotFound)
       
   181     {
       
   182         SetFocusedItem(ci.IsSelectable() ? aIndex : KErrNotFound);
       
   183     }
       
   184     else if (aIndex <= iFocused)
       
   185     {
       
   186         // If new item is inserted to Form above the current item,
       
   187         // index must increase
       
   188         iFocused++;
       
   189     }
       
   190 
       
   191     RequestLayoutL();
       
   192 }
       
   193 
       
   194 void CMIDForm::DeleteItemL(TInt aIndex)
       
   195 {
       
   196     DEBUG("CMIDForm::DeleteItemL");
       
   197 
       
   198     TBool updateFocused = EFalse;
       
   199     // if delete item then index of pointed control is decrease
       
   200     if (iIndexPointedControl > aIndex)
       
   201     {
       
   202         iIndexPointedControl--;
       
   203     }
       
   204     else
       
   205         // if delete item is same as index of pointed control then index is set to not active
       
   206     {
       
   207         if (iIndexPointedControl == aIndex)
       
   208         {
       
   209             iIndexPointedControl = -1;
       
   210         }
       
   211     }
       
   212     if (iFocused > aIndex)
       
   213     {
       
   214         iFocused--;
       
   215     }
       
   216     else if (iFocused == aIndex)
       
   217     {
       
   218         iDisplayable.MenuHandler()->HideMenuIfVisible();
       
   219         ReplaceFocusedItem();
       
   220         updateFocused = ETrue;
       
   221     }
       
   222 
       
   223     CMIDControlItem& ci = ControlItem(aIndex);
       
   224     RemoveItemFromForm(ci);
       
   225     if (&ci == iPointedControl)
       
   226     {
       
   227         iPointedControl = NULL;
       
   228     }
       
   229 
       
   230     iItems.Remove(aIndex);
       
   231 
       
   232     if (iFocused != KErrNotFound && updateFocused)
       
   233     {
       
   234         iFocused--;
       
   235     }
       
   236 
       
   237     RequestLayoutL();
       
   238 }
       
   239 
       
   240 void CMIDForm::DeleteAllItemsL()
       
   241 {
       
   242     DEBUG("CMIDForm::DeleteAllItemsL");
       
   243     iDisplayable.MenuHandler()->HideMenuIfVisible();
       
   244     SetFocusedItem(KErrNotFound);
       
   245 
       
   246     TInt itemCount = iItems.Count();
       
   247     for (TInt i=0; i < itemCount; i++)
       
   248     {
       
   249         CMIDControlItem& ci = ControlItem(i);
       
   250         RemoveItemFromForm(ci);
       
   251     }
       
   252     iItems.Reset();
       
   253 
       
   254     iScroll = 0;
       
   255     // if delete all then index of pointed control is set to not active
       
   256     iIndexPointedControl = -1;
       
   257 
       
   258     iPointedControl = NULL;
       
   259     RequestLayoutL();
       
   260 }
       
   261 
       
   262 /**
       
   263  * Called when the item has changed its appearance in some way.
       
   264  */
       
   265 void CMIDForm::RefreshItemL(TInt aIndex)
       
   266 {
       
   267     DEBUG("CMIDForm::RefreshItemL");
       
   268 
       
   269     if (aIndex != KErrNotFound)
       
   270     {
       
   271         RequestLayoutL();
       
   272     }
       
   273 }
       
   274 
       
   275 /**
       
   276  * Returns whether the item is actually visible to the user. Must therefore take into
       
   277  * account the visibility of the entire form, and whether the specific item is scrolled
       
   278  * in/out of the viewable area.
       
   279  */
       
   280 TBool CMIDForm::IsItemVisible(TInt aIndex)
       
   281 {
       
   282     DEBUG("CMIDForm::IsItemVisible");
       
   283 
       
   284     CMIDControlItem& control = ControlItem(aIndex);
       
   285 
       
   286     if ((control.Position().iY > Height()) ||
       
   287             ((control.Position().iY + control.Size().iHeight) < 0))
       
   288     {
       
   289         return EFalse;
       
   290     }
       
   291     return ETrue;
       
   292 }
       
   293 
       
   294 /**
       
   295  * Called prior to the Form itself being made the current Displayable.
       
   296  * It provides an opportunity to prepare the form such that this item will
       
   297  * be visible and focused when the form is eventually made current
       
   298  */
       
   299 void CMIDForm::SetCurrentItemL(TInt aIndex)
       
   300 {
       
   301     DEBUG("CMIDForm::SetCurrentItemL");
       
   302 
       
   303     // If it is pending request for layout, than layout now.
       
   304     if (LayoutPending())
       
   305     {
       
   306         LayoutAndDrawL();
       
   307     }
       
   308 
       
   309     // Set focus of item to aIndex and scroll to it.
       
   310     SetFocusedItem(aIndex);
       
   311 
       
   312 }
       
   313 
       
   314 
       
   315 //
       
   316 // End of MMIDForm interface
       
   317 //
       
   318 
       
   319 TInt CMIDForm::CountComponentControls() const
       
   320 {
       
   321     return iRows.Count();
       
   322 }
       
   323 
       
   324 CCoeControl* CMIDForm::ComponentControl(TInt aIndex) const
       
   325 {
       
   326     return iRows[aIndex];
       
   327 }
       
   328 
       
   329 TKeyResponse CMIDForm::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
       
   330 {
       
   331     DEBUG("< CMIDForm::OfferKeyEventL");
       
   332 
       
   333     TBool isArrowKey = (aKeyEvent.iCode == EKeyDownArrow || aKeyEvent.iCode == EKeyUpArrow ||
       
   334                         aKeyEvent.iCode == EKeyLeftArrow || aKeyEvent.iCode == EKeyRightArrow);
       
   335 
       
   336     if (iFocused != KErrNotFound)
       
   337     {
       
   338         CMIDControlItem& controlItem = ControlItem(iFocused);
       
   339         TRect controlRect = GetControlRect(iFocused);
       
   340         TBool visible = RectPartiallyVisible(controlRect);
       
   341 
       
   342 #ifdef RD_JAVA_S60_RELEASE_9_2
       
   343         TInt numItemCommands = controlItem.CommandList()->Count();
       
   344 
       
   345         // If focused form item does not have any commands,
       
   346         // and select key was pressed try to show screen\help option menu.
       
   347         // ChoiceGroup and DateField handles this case separately.
       
   348         // Gauge enter key is also handled here,
       
   349         // so it would behave the same way as selection key.
       
   350         if (numItemCommands == 0 && aType == EEventKey &&
       
   351                 controlItem.Type() != MMIDComponent::EChoiceGroup &&
       
   352                 controlItem.Type() != MMIDComponent::EDateField &&
       
   353                 (aKeyEvent.iScanCode == EStdKeyDevice3 ||
       
   354                  (aKeyEvent.iScanCode == EStdKeyEnter &&
       
   355                   controlItem.Type() == MMIDComponent::EGauge)))
       
   356         {
       
   357             iDisplayable.ShowScreenOrHelpOptionsMenuL();
       
   358         }
       
   359 #endif // RD_JAVA_S60_RELEASE_9_2
       
   360 
       
   361         // arrow key events are not sent to the hidden focused item
       
   362         if ((visible || !isArrowKey) &&
       
   363                 controlItem.OfferKeyEventL(aKeyEvent,aType) == EKeyWasConsumed)
       
   364         {
       
   365             DEBUG("CMIDForm::OfferKeyEventL - out after item consumed key");
       
   366 
       
   367 #ifdef RD_SCALABLE_UI_V2
       
   368             // If focused TextField or DateField item is at least partly out of
       
   369             // Form viewport, then key event (excluding arrow keys and soft keys)
       
   370             // scrolls the item completely visible. This situation
       
   371             // is possible when scrolling has been done with scrollbar.
       
   372 
       
   373             // Soft keys and arrow keys are ignored. Filtering must be done comparing
       
   374             // scan codes because the aEventType.iCode is not available for all key presses.
       
   375             TBool ignoreKey = (aKeyEvent.iScanCode == EStdKeyRightArrow ||
       
   376                                aKeyEvent.iScanCode == EStdKeyUpArrow ||
       
   377                                aKeyEvent.iScanCode == EStdKeyDownArrow ||
       
   378                                aKeyEvent.iScanCode == EStdKeyLeftArrow ||
       
   379                                aKeyEvent.iScanCode == EStdKeyDevice0 ||
       
   380                                aKeyEvent.iScanCode == EStdKeyDevice1 ||
       
   381                                aKeyEvent.iScanCode == EStdKeyDevice3);
       
   382 
       
   383             if ((controlItem.Type() == MMIDComponent::ETextField ||
       
   384                     controlItem.Type() == MMIDComponent::EDateField) &&
       
   385                     !RectFullyVisible(controlRect) && !ignoreKey)
       
   386             {
       
   387                 // Scroll up if controlItem is above the Form viewport.
       
   388                 // Otherwise scroll down.
       
   389                 if (controlRect.iTl.iY < 0)
       
   390                 {
       
   391                     ScrollToFocused(EUp, ETrue);
       
   392                 }
       
   393                 else
       
   394                 {
       
   395                     ScrollToFocused(EDown, ETrue);
       
   396                 }
       
   397 
       
   398             }
       
   399 #endif // RD_SCALABLE_UI_V2
       
   400 
       
   401             return EKeyWasConsumed;
       
   402         }
       
   403     }
       
   404 
       
   405     DEBUG("CMIDForm::OfferKeyEventL - got chance to scroll");
       
   406 
       
   407     if ((aType == EEventKey) && isArrowKey && (iItems.Count() > 0))
       
   408     {
       
   409         DEBUG("CMIDForm::OfferKeyEventL - about to call Traverse");
       
   410 
       
   411         Traverse(ConvertKeyToDirection(aKeyEvent.iCode));
       
   412 
       
   413         DEBUG("CMIDForm::OfferKeyEventL - out after Traverse");
       
   414         return EKeyWasConsumed;
       
   415     }
       
   416 
       
   417     // msk: this is needed if MSK is not enabled
       
   418     if ((aType == EEventKey) &&
       
   419             ((aKeyEvent.iScanCode == EStdKeyDevice3) || (aKeyEvent.iCode == EKeyEnter))
       
   420        )
       
   421     {
       
   422         if (!DoDefaultCommand())
       
   423         {
       
   424             iDisplayable.ShowOkOptionsMenuL();
       
   425         }
       
   426 
       
   427         DEBUG("CMIDForm::OfferKeyEventL - out after default command or ok menu");
       
   428         return EKeyWasConsumed;
       
   429     }
       
   430     // end msk
       
   431     DEBUG("> CMIDForm::OfferKeyEventL");
       
   432     return EKeyWasNotConsumed;
       
   433 }
       
   434 
       
   435 /**  Handle a focus change. Make sure there is no layout pending and if there is
       
   436 one then do it, see TrappedLayoutAndDraw(). This is because when there is a layout
       
   437 pending we are in a temporary inconsistent phase with no rows and the rows are the
       
   438 intermediary to the items via the CountComponentControl() and ComponentControl() calls.
       
   439 Then pass on focus to our children according to the value stored in iFocused. Finally
       
   440 update the scroll bars if gaining focus and draw. */
       
   441 void CMIDForm::FocusChanged(TDrawNow /*aDrawNow*/)
       
   442 {
       
   443     DEBUG("CMIDForm::FocusChanged");
       
   444 
       
   445     TrappedLayoutAndDraw(ETrue);
       
   446 
       
   447     TInt i = -1;
       
   448     TInt itemCount = iItems.Count();
       
   449     while (++i < itemCount)
       
   450     {
       
   451         if (i == iFocused)
       
   452         {
       
   453             ControlItem(iFocused).SetFocus(IsFocused());
       
   454         }
       
   455         else
       
   456         {
       
   457             ControlItem(i).SetFocus(EFalse);
       
   458         }
       
   459     }
       
   460 
       
   461     // make sure scrollbar is up to date when we get focus
       
   462     if (IsFocused())
       
   463     {
       
   464         UpdateScrollBar();
       
   465     }
       
   466 
       
   467     DrawNow();
       
   468 }
       
   469 
       
   470 void CMIDForm::SizeChanged()
       
   471 {
       
   472     DEBUG("CMIDForm::SizeChanged");
       
   473 
       
   474     iBackgroundControlContext->SetParentPos(PositionRelativeToScreen()) ;
       
   475     iBackgroundControlContext->SetRect(Rect()) ;
       
   476 }
       
   477 
       
   478 /** Before calling CCoeControl::InputCapabilities(), make sure there is
       
   479 no outstanding layout. This is because if there is one outstanding, we have
       
   480 no rows and hence ComponentControls() returns zero. This means that, for example
       
   481 if there are any editors in the items, CCoeControl::InputCapabilities() will not
       
   482 reach them and the FEP will not be initialised. @see TrappedLayoutAndDraw(),
       
   483 CCoeControl::InputCapabilities(), CAknFepManager::HandleChangeInFocusL() and
       
   484 CCoeAppUi::InputCapabilities() */
       
   485 TCoeInputCapabilities CMIDForm::InputCapabilities() const
       
   486 {
       
   487     if (iFocused != KErrNotFound)
       
   488     {
       
   489         return ControlItem(iFocused).InputCapabilities();
       
   490     }
       
   491     return     CCoeControl::InputCapabilities(); //TCoeInputCapabilities::ENone
       
   492 }
       
   493 
       
   494 TTypeUid::Ptr CMIDForm::MopSupplyObject(TTypeUid aId)
       
   495 {
       
   496     if (aId.iUid == MAknsControlContext::ETypeId && iBackgroundControlContext)
       
   497     {
       
   498         return MAknsControlContext::SupplyMopObject(aId, iBackgroundControlContext);
       
   499     }
       
   500 
       
   501     CMIDMenuHandler* menuHandler = iDisplayable.MenuHandler();
       
   502     return SupplyMopObject(aId, menuHandler->Cba(), menuHandler->MenuBar());
       
   503 }
       
   504 
       
   505 
       
   506 #ifdef RD_SCALABLE_UI_V2
       
   507 void CMIDForm::HandlePointerEventL(const TPointerEvent& aPointerEvent)
       
   508 {
       
   509     if (!AknLayoutUtils::PenEnabled())
       
   510     {
       
   511         return;
       
   512     }
       
   513 
       
   514     if (iPhysics)
       
   515     {
       
   516         HandlePhysicsPointerEventL(aPointerEvent);
       
   517         return;
       
   518     }
       
   519 
       
   520     switch (aPointerEvent.iType)
       
   521     {
       
   522     case TPointerEvent::EButton1Down:
       
   523     {
       
   524         DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   525                    aPointerEvent.iType, aPointerEvent.iPosition.iX, aPointerEvent.iPosition.iY);
       
   526         iLastValidPointerEvent = aPointerEvent;
       
   527 
       
   528         CMIDControlItem* ci = ControlItemAtPoint(aPointerEvent.iPosition);
       
   529         // stored on ButtonDown value
       
   530 
       
   531         if (ci && ci->IsSelectable())
       
   532         {
       
   533             TInt itemIndex = ItemIndex(*ci);
       
   534             iIndexPointedControl = itemIndex;
       
   535             iLastValidPointedItemPosition = ci->Position();
       
   536             TBool changeFocus = (itemIndex != iFocused);
       
   537 
       
   538             if (changeFocus)
       
   539             {
       
   540                 // changing the focused item by dragging must start from unfocused item
       
   541                 iCanDragFocus = ETrue;
       
   542                 iFocusChangingWithPen = ETrue;
       
   543                 // give basic tactile feedback on button down when move focus
       
   544 #ifdef RD_TACTILE_FEEDBACK
       
   545                 DoFeedbackOnFocusChange(*ci);
       
   546 #endif // RD_TACTILE_FEEDBACK
       
   547                 SetFocusedItem(itemIndex, ENone, EFalse);
       
   548             }
       
   549 
       
   550             TInt scroll = ScrollDistanceToTappedItem(ci);
       
   551 
       
   552             iScrollOnPointerDown = (scroll != 0);
       
   553 
       
   554             CCoeControl::HandlePointerEventL(aPointerEvent);
       
   555 
       
   556             if (iScrollOnPointerDown)
       
   557             {
       
   558                 ScrollRelative(scroll);
       
   559                 ControlItem(iFocused).NotifyScrollingCompleted();
       
   560             }
       
   561             else if (changeFocus)
       
   562             {
       
   563                 HandleItemVisibilityChange();
       
   564                 DrawNow();
       
   565             }
       
   566             else
       
   567             {
       
   568                 iCanDragFocus = ETrue;
       
   569             }
       
   570         }
       
   571         else // pointer down did not happen on any control item, allow starting drag
       
   572         {
       
   573             iCanDragFocus = ETrue;
       
   574         }
       
   575 
       
   576         break;
       
   577     }
       
   578 
       
   579     case TPointerEvent::EButton1Up:
       
   580     {
       
   581         if (iIndexPointedControl>-1 && &ControlItem(iIndexPointedControl) == ControlItemAtPoint(aPointerEvent.iPosition))
       
   582             // When this is item where TPointerEvent::EButton1Down was happened,
       
   583             // then event is forwarded to item. It is its responsibility check that
       
   584             // up event occured if it have some actions on up event.
       
   585         {
       
   586             DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   587                        aPointerEvent.iType, aPointerEvent.iPosition.iX, aPointerEvent.iPosition.iY);
       
   588 
       
   589             HandleDragEventL(aPointerEvent, ETrue);
       
   590         }
       
   591         else
       
   592         {
       
   593             // When this is not item where TPointerEvent::EButton1Down was happened,
       
   594             // then e`vent is forwarded to item where originally. It is its responsibility
       
   595             // check that up event occured if it have some actions on up event.
       
   596             // Setting default values of related variables.
       
   597 
       
   598             if (iIndexPointedControl>-1 && &ControlItem(iIndexPointedControl))
       
   599             {
       
   600                 TBool bbutton = EFalse;
       
   601 
       
   602                 if (IsStringItem(ControlItem(iIndexPointedControl)))
       
   603                 {
       
   604                     // get appearance from StringItem
       
   605                     CMIDStringItem *strItem = static_cast< CMIDStringItem* >(&ControlItem(iIndexPointedControl));
       
   606                     MMIDItem::TAppearance appearance = strItem->Appearance();
       
   607                     bbutton = (appearance == MMIDItem::EButton || appearance == MMIDItem::EHyperLink);
       
   608                 }
       
   609 
       
   610                 if (ControlItem(iIndexPointedControl).Type() != MMIDComponent::EChoiceGroup && !bbutton)
       
   611                 {
       
   612                     TPointerEvent pointerevent;
       
   613                     pointerevent.iType = TPointerEvent::EButton1Up;
       
   614                     pointerevent.iModifiers = aPointerEvent.iModifiers;
       
   615                     pointerevent.iPosition = iLastValidPointerEvent.iPosition +
       
   616                                              ControlItem(iIndexPointedControl).Position() - iLastValidPointedItemPosition;
       
   617                     pointerevent.iParentPosition = iLastValidPointerEvent.iParentPosition;
       
   618 
       
   619                     ControlItem(iIndexPointedControl).HandlePointerEventL(pointerevent);
       
   620 
       
   621                     DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   622                                pointerevent.iType, pointerevent.iPosition.iX, pointerevent.iPosition.iY);
       
   623 
       
   624                 }
       
   625 
       
   626                 // forward event for aPointerEvent
       
   627                 CCoeControl::HandlePointerEventL(aPointerEvent);
       
   628             }
       
   629         }
       
   630 
       
   631         // If it is pending request for layout, than layout form now and refresh.
       
   632         if (LayoutPending())
       
   633         {
       
   634             LayoutFormL();
       
   635             DrawDeferred();
       
   636         }
       
   637 
       
   638         iCanDragFocus = EFalse;
       
   639         iFocusChangingWithPen = EFalse;
       
   640         iScrollOnPointerDown = EFalse;
       
   641         iIndexPointedControl = -1;
       
   642 
       
   643         break;
       
   644     }
       
   645 
       
   646     case TPointerEvent::EDrag:
       
   647         // for dragging
       
   648     {
       
   649         if (iIndexPointedControl>-1 && &ControlItem(iIndexPointedControl) == ControlItemAtPoint(aPointerEvent.iPosition))
       
   650         {
       
   651             // When this is item where TPointerEvent::EButton1Down was happened,
       
   652             // then it is updated iLastValidPointerEvent.
       
   653             iLastValidPointerEvent = aPointerEvent;
       
   654             // If it is pending request for layout, than layout Form now and refresh
       
   655             // elsewhere call HandleDragEventL and forward EDrag events to event.
       
   656             if (LayoutPending())
       
   657             {
       
   658                 LayoutFormL();
       
   659                 DrawDeferred();
       
   660             }
       
   661             else
       
   662             {
       
   663                 HandleDragEventL(aPointerEvent, ETrue);
       
   664             }
       
   665             DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   666                        aPointerEvent.iType, aPointerEvent.iPosition.iX,
       
   667                        aPointerEvent.iPosition.iY);
       
   668         }
       
   669         else
       
   670         {
       
   671             // When this is not item where TPointerEvent::EButton1Down was happened,
       
   672             // then we do only dragging. There it is not send event to item.
       
   673             HandleDragEventL(aPointerEvent, EFalse);
       
   674         }
       
   675         break;
       
   676     }
       
   677 
       
   678     case TPointerEvent::EButtonRepeat:
       
   679         // For button repeating
       
   680     {
       
   681         DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   682                    aPointerEvent.iType, aPointerEvent.iPosition.iX,
       
   683                    aPointerEvent.iPosition.iY);
       
   684 
       
   685         RequestPointerRepeat(aPointerEvent);
       
   686 
       
   687         if (iCanDragFocus)
       
   688         {
       
   689             if (aPointerEvent.iPosition.iY < 0  && CanScrollUp())
       
   690             {
       
   691                 TimedScroll(EUp);
       
   692             }
       
   693             else if (aPointerEvent.iPosition.iY > Height() && CanScrollDown())
       
   694             {
       
   695                 TimedScroll(EDown);
       
   696             }
       
   697         }
       
   698         else
       
   699         {
       
   700             CCoeControl::HandlePointerEventL(aPointerEvent);
       
   701         }
       
   702 
       
   703         break;
       
   704     }
       
   705     default:
       
   706         // By defalt only implementation of base class.
       
   707     {
       
   708         CCoeControl::HandlePointerEventL(aPointerEvent);
       
   709         DEBUG_INT3("CMIDForm::HandlePointerEventL(): event=%D, x,y=%D,%D",
       
   710                    aPointerEvent.iType, aPointerEvent.iPosition.iX,
       
   711                    aPointerEvent.iPosition.iY);
       
   712         break;
       
   713     }
       
   714     }
       
   715 }
       
   716 
       
   717 
       
   718 void CMIDForm::HandleDragEventL(const TPointerEvent& aPointerEvent, TBool aForItem)
       
   719 {
       
   720     RequestPointerRepeat(aPointerEvent);
       
   721 
       
   722     if (iCanDragFocus)
       
   723     {
       
   724         // formRect covers the whole vertical form area, but excludes
       
   725         // the left and right margins and the scroll bar area
       
   726         TRect formRect(TPoint(iFormRect.Rect().iTl.iX, 0),
       
   727                        TPoint(iFormRect.Rect().iBr.iX, Height()));
       
   728 
       
   729         // Try to find the new focused item, if needed
       
   730         if (formRect.Contains(aPointerEvent.iPosition) &&
       
   731                 !FocusedItemContainsPoint(aPointerEvent.iPosition))
       
   732         {
       
   733             CMIDControlItem* ci = ControlItemAtPoint(aPointerEvent.iPosition);
       
   734 
       
   735             if (ci && ci->IsSelectable())
       
   736             {
       
   737                 TInt itemIndex = ItemIndex(*ci);
       
   738 
       
   739                 // Find the direction to which the focus is dragged
       
   740                 TDirection direction = ENone;
       
   741                 if (iFocused != KErrNotFound)
       
   742                 {
       
   743                     TRect rect = ControlItem(iFocused).Rect();
       
   744 
       
   745                     if (aPointerEvent.iPosition.iY < rect.iTl.iY)
       
   746                     {
       
   747                         direction = EUp;
       
   748                     }
       
   749                     else if (aPointerEvent.iPosition.iY >= rect.iBr.iY)
       
   750                     {
       
   751                         direction = EDown;
       
   752                     }
       
   753                     else // focus is moved horizontally
       
   754                     {
       
   755                         direction = (itemIndex < iFocused) ? ELeft : ERight;
       
   756                     }
       
   757                 }
       
   758 
       
   759 #ifdef RD_TACTILE_FEEDBACK
       
   760                 if (iFocused != itemIndex)
       
   761                 {
       
   762                     iFeedback->InstantFeedback(ETouchFeedbackSensitive);
       
   763                 }
       
   764 #endif
       
   765                 SetFocusedItem(itemIndex, direction, EFalse);
       
   766                 HandleItemVisibilityChange();
       
   767                 DrawNow();
       
   768             }
       
   769         }
       
   770 
       
   771         if (FocusedItemContainsPoint(aPointerEvent.iPosition))
       
   772         {
       
   773             // forward EDrag events to the focused so that the focus can
       
   774             // move inside the item
       
   775             // (only when this is item where TPointerEvent::EButton1Down was occured)
       
   776 
       
   777             CMIDControlItem* focusedControl = ControlItemAtPoint(aPointerEvent.iPosition);
       
   778 
       
   779             if (aForItem || (iIndexPointedControl > -1 && &ControlItem(iIndexPointedControl) &&
       
   780                              (IsChoiceGroup(ControlItem(iIndexPointedControl)) || IsCustomItem(ControlItem(iIndexPointedControl)))) ||
       
   781                     focusedControl && IsChoiceGroup(*focusedControl) ||
       
   782                     focusedControl && IsCustomItem(*focusedControl))
       
   783             {
       
   784                 ControlItem(iFocused).HandlePointerEventL(aPointerEvent);
       
   785             }
       
   786             else
       
   787             {
       
   788                 if (iIndexPointedControl > -1 && &ControlItem(iIndexPointedControl))
       
   789                 {
       
   790                     TBool bbutton = EFalse;
       
   791 
       
   792                     if (IsStringItem(ControlItem(iIndexPointedControl)))
       
   793                     {
       
   794                         CMIDStringItem *strItem = static_cast< CMIDStringItem* >(&ControlItem(iIndexPointedControl));
       
   795                         MMIDItem::TAppearance appearance = strItem->Appearance();
       
   796                         bbutton = (appearance == MMIDItem::EButton || appearance == MMIDItem::EHyperLink);
       
   797                     }
       
   798 
       
   799                     //forward event (only for changing focus) for Button & Hyperlink
       
   800                     if (bbutton && &ControlItem(iIndexPointedControl))
       
   801                     {
       
   802                         ControlItem(iIndexPointedControl).HandlePointerEventL(aPointerEvent);
       
   803                     }
       
   804                     else
       
   805                     {
       
   806                         iDisplayable.TryDetectLongTapL(aPointerEvent);
       
   807                     }
       
   808                 }
       
   809                 else
       
   810                 {
       
   811                     iDisplayable.TryDetectLongTapL(aPointerEvent);
       
   812                 }
       
   813             }
       
   814         }
       
   815         else
       
   816         {
       
   817             // make sure that long tap animation is canceled in this case
       
   818             iDisplayable.TryDetectLongTapL(aPointerEvent);
       
   819         }
       
   820     }
       
   821     else // cannot drag focus
       
   822     {
       
   823         CCoeControl::HandlePointerEventL(aPointerEvent);
       
   824     }
       
   825 }
       
   826 
       
   827 
       
   828 void CMIDForm::RequestPointerRepeat(const TPointerEvent& aPointerEvent)
       
   829 {
       
   830     if (aPointerEvent.iPosition.iY < 0 ||
       
   831             aPointerEvent.iPosition.iY > Height())
       
   832     {
       
   833         TRect screen;
       
   834         AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screen);
       
   835 
       
   836         TRect repeatRect = screen;
       
   837         if (aPointerEvent.iPosition.iY < 0)
       
   838         {
       
   839             repeatRect.iBr.iY = iMidpFormRect.Rect().iTl.iY;
       
   840         }
       
   841         else
       
   842         {
       
   843             repeatRect.iTl.iY = iMidpFormRect.Rect().iBr.iY;
       
   844         }
       
   845 
       
   846         // repeatRect must be given in propotion to form's window, move it up
       
   847         repeatRect.Move(0, -iMidpFormRect.Rect().iTl.iY);
       
   848         Window().RequestPointerRepeatEvent(KScrollInterval, repeatRect);
       
   849     }
       
   850 }
       
   851 
       
   852 
       
   853 void CMIDForm::TimedScroll(TDirection aDirection)
       
   854 {
       
   855     ASSERT(aDirection == EDown || aDirection == EUp);
       
   856 
       
   857     // First find the row that is the first or last row (depending on
       
   858     // the scroll direction) that is at least partailly visible on the form.
       
   859     // Search direction is opposite to aDirection.
       
   860     TDirection searchDirection = (aDirection == EUp) ? EDown : EUp;
       
   861     TInt idx = FirstRowOnScreen(searchDirection);
       
   862 
       
   863     if (idx == KErrNotFound)
       
   864     {
       
   865         return;
       
   866     }
       
   867 
       
   868     TInt scroll = Height() / KScrollAmountDividerForThumbDrag;
       
   869 
       
   870     // Find the row that will be visible (at least partially) after
       
   871     // after the scrolling.
       
   872     if (aDirection == EUp)
       
   873     {
       
   874         while (idx > 0 && (iRows[idx]->Rect().iTl.iY + scroll > 0))
       
   875         {
       
   876             --idx;
       
   877         }
       
   878     }
       
   879     else
       
   880     {
       
   881         while ((idx < iRows.Count() - 1) &&
       
   882                 (iRows[idx]->Rect().iBr.iY - scroll < Height()))
       
   883         {
       
   884             ++idx;
       
   885         }
       
   886     }
       
   887 
       
   888     TBool rowFocused = EFalse;
       
   889     if (iFocused != KErrNotFound)
       
   890     {
       
   891         rowFocused = GetControlRect(iFocused).Intersects(iRows[idx]->Rect());
       
   892     }
       
   893 
       
   894     // If the focus is not yet on the row, try to set one of its items focused
       
   895     if (!rowFocused)
       
   896     {
       
   897         for (TInt i = 0; i < iRows[idx]->NumItems(); ++i)
       
   898         {
       
   899             CMIDControlItem* item = iRows[idx]->Item(i);
       
   900             if (item->IsSelectable())
       
   901             {
       
   902                 SetFocusedItem(ItemIndex(*item), aDirection, EFalse);
       
   903             }
       
   904         }
       
   905     }
       
   906 
       
   907 #ifdef RD_TACTILE_FEEDBACK
       
   908     iFeedback->InstantFeedback(ETouchFeedbackSensitive);
       
   909 #endif
       
   910 
       
   911     ScrollRelative((aDirection == EUp) ? scroll : -scroll);
       
   912 }
       
   913 
       
   914 
       
   915 TBool CMIDForm::CanScrollUp() const
       
   916 {
       
   917     return (iScroll < 0);
       
   918 }
       
   919 
       
   920 
       
   921 TBool CMIDForm::CanScrollDown() const
       
   922 {
       
   923     return ((iFormHeight - iScroll) < iTotalFormHeight);
       
   924 }
       
   925 
       
   926 
       
   927 TBool CMIDForm::FocusedItemContainsPoint(const TPoint& aPoint) const
       
   928 {
       
   929     if (iFocused != KErrNotFound)
       
   930     {
       
   931         if (ItemIsUnconstrained(iFocused))
       
   932         {
       
   933             return StringItemContainsPoint(
       
   934                        static_cast<CMIDStringItem*>(&ControlItem(iFocused)), aPoint);
       
   935         }
       
   936         else
       
   937         {
       
   938             return ControlItem(iFocused).Rect().Contains(aPoint);
       
   939         }
       
   940     }
       
   941     else
       
   942     {
       
   943         return EFalse;
       
   944     }
       
   945 }
       
   946 
       
   947 CMIDControlItem* CMIDForm::ControlItemAtPoint(const TPoint& aPoint) const
       
   948 {
       
   949     TInt idx = RowAtPoint(aPoint);
       
   950 
       
   951     if (idx != KErrNotFound)
       
   952     {
       
   953         for (TInt i = 0; i < iRows[idx]->NumItems(); ++i)
       
   954         {
       
   955             CMIDControlItem* ci = iRows[idx]->Item(i);
       
   956             if (ci && ci->Rect().Contains(aPoint))
       
   957             {
       
   958                 return ci;
       
   959             }
       
   960         }
       
   961     }
       
   962 
       
   963     return NULL;
       
   964 }
       
   965 
       
   966 
       
   967 TInt CMIDForm::RowAtPoint(const TPoint& aPoint) const
       
   968 {
       
   969     TInt rowCount = iRows.Count();
       
   970     // loop until the first row fully below the visible form area
       
   971     for (TInt i = 0; i < rowCount && (iRows[i]->Position().iY < iFormHeight); ++i)
       
   972     {
       
   973         if (iRows[i]->Rect().Contains(aPoint))
       
   974         {
       
   975             return i;
       
   976         }
       
   977     }
       
   978     return KErrNotFound;
       
   979 }
       
   980 
       
   981 #endif // #ifdef RD_SCALABLE_UI_V2
       
   982 
       
   983 
       
   984 void CMIDForm::SetFocusedItemIfNone(CMIDItem* aItem)
       
   985 {
       
   986     if (iFocused == KErrNotFound)
       
   987     {
       
   988         ASSERT(aItem);
       
   989         TInt index = Index(aItem);
       
   990 
       
   991         if (index >= 0 && index < iItems.Count())
       
   992         {
       
   993             CMIDControlItem& ci = ControlItem(iItems[index]);
       
   994             if (ci.IsSelectable())
       
   995             {
       
   996                 SetFocusedItem(index);
       
   997                 ScrollToFocused();
       
   998             }
       
   999         }
       
  1000     }
       
  1001 }
       
  1002 
       
  1003 /** This method is called when an item loses focusability,
       
  1004 for example because it loses all its commands. If this item
       
  1005 is focused, call ReplaceFocusedItem() to find another focusable
       
  1006 item. @see CMIDItem::RemoveCommand() and  ReplaceFocusedItem*/
       
  1007 void CMIDForm::RemoveFocusIfFocused(CMIDItem* aItem)
       
  1008 {
       
  1009     ASSERT(aItem);
       
  1010     TInt index = Index(aItem);
       
  1011     if (iFocused == index)
       
  1012     {
       
  1013         // Hide menu because item has lost all item commands and
       
  1014         // another item may have become focused behind the menu.
       
  1015         iDisplayable.MenuHandler()->HideMenuIfVisible();
       
  1016         ReplaceFocusedItem();
       
  1017     }
       
  1018 }
       
  1019 
       
  1020 /**
       
  1021  * Traverse is a method to go thorough the form; it includes moving focus from
       
  1022  * item to another possibly scrolling the form. Note that sometimes traversal
       
  1023  * does not move focus, because an item is larger that the screen and thus form
       
  1024  * is scrolled little by little so that the user can see the whole content. On
       
  1025  * other cases, traversing means only moving focus from item to another as both
       
  1026  * items are visible on the screen.
       
  1027  *
       
  1028  * @param  aDirection defines the direction of the traversing (up, down, left, right).
       
  1029  **/
       
  1030 void CMIDForm::Traverse(TDirection aDirection)
       
  1031 {
       
  1032     DEBUG("< CMIDForm::Traverse");
       
  1033     DEBUG_INT("< CMIDForm::Traverse Direction is %D", aDirection);
       
  1034     TBool horizontalScroll = EFalse;
       
  1035 
       
  1036     if (LayoutPending())
       
  1037     {
       
  1038         DEBUG("CMIDForm::Traverse - calling layout");
       
  1039         // lets do the layout now so we can always assume that we are layed out before doing this stuff
       
  1040         TrappedLayoutAndDraw();
       
  1041     }
       
  1042 
       
  1043 #ifdef RD_SCALABLE_UI_V2
       
  1044     TBool focusHidden = EFalse;
       
  1045     // If the focused item is currently fully outside the visible form area,
       
  1046     // it means that form has been scrolled by moving the scrollbar with pen. In this case
       
  1047     // set iFocused (temporarily) to KErrNone in order that scrolling with arrow keys works ok.
       
  1048     if (iFocused != KErrNotFound && !RectPartiallyVisible(GetControlRect(iFocused)))
       
  1049     {
       
  1050         focusHidden = ETrue;
       
  1051         SetFocusedItem(KErrNotFound, ENone, EFalse);
       
  1052     }
       
  1053 #endif
       
  1054 
       
  1055     if (aDirection == ELeft || aDirection == ERight)
       
  1056     {
       
  1057         DEBUG("CMIDForm::Traverse - move focus horizontally");
       
  1058         if (!TryMovingFocusHorizontally(aDirection))
       
  1059         {
       
  1060             if (iInitialAlignment == MMIDItem::ERight)
       
  1061             {//RIGHT TO LEFT
       
  1062                 TryMovingFocusVertically(aDirection == ELeft ? EDown : EUp, EFalse);
       
  1063             }
       
  1064             else
       
  1065             {//LEFT TO RIGHT
       
  1066                 TryMovingFocusVertically(aDirection == ELeft ? EUp : EDown, EFalse);
       
  1067             }
       
  1068         }
       
  1069         else
       
  1070         {
       
  1071             horizontalScroll = ETrue;
       
  1072         }
       
  1073     }
       
  1074     else if (aDirection == EUp || aDirection == EDown)
       
  1075     {
       
  1076         DEBUG("CMIDForm::Traverse - move focus vertically");
       
  1077         TryMovingFocusVertically(aDirection, ETrue);
       
  1078     }
       
  1079 
       
  1080     // if there is still a focused item, make sure it is still on the screen.
       
  1081     // if it isn't remove focus as we've already tried out best to have a
       
  1082     // focussed item on screen
       
  1083     if (iFocused != KErrNotFound)
       
  1084     {
       
  1085         TRect rect = GetControlRect(iFocused);
       
  1086         if (!RectPartiallyVisible(rect))
       
  1087         {
       
  1088             SetFocusedItem(KErrNotFound, ENone);
       
  1089         }
       
  1090     }
       
  1091 #ifdef RD_SCALABLE_UI_V2
       
  1092     else if (focusHidden)
       
  1093     {
       
  1094         // Try to bring the focus back to visible area by setting the last focusable
       
  1095         // item in the scroll direction focused.
       
  1096         TDirection searchDirection = (aDirection == EDown || aDirection == ERight) ?
       
  1097                                      EUp : EDown;
       
  1098         TInt newFocusIndex  = IndexOfFirstFocusableItemOnScreen(searchDirection);
       
  1099         if (newFocusIndex != KErrNotFound)
       
  1100         {
       
  1101             // Pass searchDirection also to SetFocusedItem(). This is needed at least
       
  1102             // for choice group and custom item cases, so that they can set there
       
  1103             // internal focus to the last element in the actual scroll direction.
       
  1104             SetFocusedItem(newFocusIndex, searchDirection, EFalse);
       
  1105             DrawDeferred();
       
  1106         }
       
  1107     }
       
  1108 #endif
       
  1109 
       
  1110     RawScrollFinalize(horizontalScroll);
       
  1111     DEBUG("> CMIDForm::Traverse");
       
  1112 }
       
  1113 
       
  1114 
       
  1115 // -----------------------------------------------------------------------------
       
  1116 // Form scrolling methods
       
  1117 // -----------------------------------------------------------------------------
       
  1118 /**
       
  1119  * Scroll to the focused control if there is one and update form visibility (draw) and scroll bar.
       
  1120  * @see ScrollToRect() and SetRowExtentsWithRespectToScrolledLocation().
       
  1121  **/
       
  1122 void CMIDForm::ScrollToFocused(TDirection aDirection /*=EDown*/, TBool aReset /*= ETrue*/)
       
  1123 {
       
  1124     DEBUG("< CMIDForm::ScrollToFocused");
       
  1125     if (!LayoutPending())
       
  1126     {
       
  1127         if (iFocused != KErrNotFound)
       
  1128         {
       
  1129             TRect rect = GetControlRect(iFocused);
       
  1130             DEBUG_INT4("CMIDForm::ScrollToFocused - rect is %D %D %D %D",
       
  1131                        rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY);
       
  1132             RawScrollToRect(rect, aDirection, aReset);
       
  1133         }
       
  1134 
       
  1135         RawScrollFinalize(ETrue);
       
  1136 
       
  1137         if (iFocused != KErrNotFound)
       
  1138         {
       
  1139             ControlItem(iFocused).NotifyScrollingCompleted();
       
  1140         }
       
  1141     }
       
  1142 
       
  1143     UpdatePhysics();
       
  1144 
       
  1145     DEBUG("> CMIDForm::ScrollToFocused");
       
  1146 }
       
  1147 
       
  1148 TInt CMIDForm::ScrollDistanceToTappedItem(CMIDControlItem* aPointedControl)
       
  1149 {
       
  1150     TRect focusedRect = aPointedControl->Rect();
       
  1151     TInt scroll = 0;
       
  1152 
       
  1153     // Calculate how much we need to scroll to make the tapped item fully/more visible
       
  1154     if (!RectFullyVisible(focusedRect))
       
  1155     {
       
  1156         TInt topMargin = iFormRect.Rect().iTl.iY - iMidpFormRect.Rect().iTl.iY;
       
  1157         TInt bottomMargin = iMidpFormRect.Rect().iBr.iY - iFormRect.Rect().iBr.iY;
       
  1158 
       
  1159         if (focusedRect.Height() <= Height())
       
  1160         {
       
  1161             scroll = (focusedRect.iBr.iY > Height()) ?
       
  1162                      Height() - focusedRect.iBr.iY : -focusedRect.iTl.iY;
       
  1163         }
       
  1164         // Scroll long item so that it fills the whole form height.
       
  1165         // No scroll in case item already fills the whole screen or if there would
       
  1166         // be just few pixels (~margins) to scroll.
       
  1167         else if ((focusedRect.iTl.iY > 0 && focusedRect.iTl.iY > topMargin) ||
       
  1168                  (focusedRect.iBr.iY < Height() &&
       
  1169                   Height() - focusedRect.iBr.iY > bottomMargin))
       
  1170         {
       
  1171             scroll = (focusedRect.iTl.iY > 0) ?
       
  1172                      -focusedRect.iTl.iY : -(focusedRect.iBr.iY - Height());
       
  1173         }
       
  1174     }
       
  1175     return scroll;
       
  1176 }
       
  1177 
       
  1178 /**
       
  1179  * Scrolls to the rect corresponding to the row specified by aIdx using
       
  1180  * the direction indicated by aDirection. @see ScrollToRect()
       
  1181  **/
       
  1182 void CMIDForm::RawScrollToRow(TInt aIdx, TDirection aDirection)
       
  1183 {
       
  1184     DEBUG("< CMIDForm::RawScrollToRow");
       
  1185     if (aIdx >= 0 && aIdx < iRows.Count())
       
  1186     {
       
  1187         TRect rect = iRows[aIdx]->Rect();
       
  1188         DEBUG("CMIDForm::RawScrollToRow - scroll to rect");
       
  1189         RawScrollToRect(rect, aDirection);
       
  1190     }
       
  1191     DEBUG("> CMIDForm::RawScrollToRow");
       
  1192 }
       
  1193 
       
  1194 /** */
       
  1195 void CMIDForm::RawScrollToRect(const TRect& aRect, TDirection aDirection, TBool aReset)
       
  1196 {
       
  1197     DEBUG("< CMIDForm::RawScrollToRect");
       
  1198     DEBUG_INT4("CMIDForm::RawScrollToRect - rect is %D %D %D %D", aRect.iTl.iX, aRect.iTl.iY,
       
  1199                aRect.iBr.iX, aRect.iBr.iY);
       
  1200 
       
  1201     if (RectFullyVisible(aRect))
       
  1202     {
       
  1203         DEBUG("CMIDForm::RawScrollToRect - return rect fully visible");
       
  1204         TInt maxScrollValue = Height() - HeightOfAllItems();
       
  1205         // Avoid scrolling out of the form (i.e. after the view port has lower height)
       
  1206 
       
  1207         if (iScroll < maxScrollValue)
       
  1208         {
       
  1209             RawScroll(maxScrollValue);
       
  1210         }
       
  1211         return;
       
  1212     }
       
  1213 
       
  1214     TInt scrollOffset = 0;
       
  1215     if (aRect.Size().iHeight > Height())
       
  1216     {//rect higher than screen height
       
  1217         if (RectPartiallyVisible(aRect) && !aReset)
       
  1218         {//if already visible, scroll only of KMinScrollAmount (panning)
       
  1219             scrollOffset = (aDirection == EDown) ? -KMinScrollAmount : KMinScrollAmount;
       
  1220         }
       
  1221         else
       
  1222         {//if not visible and scrolling down scroll to top - KMinScrollAmount
       
  1223             // or to bottom + KMinScrollAmount if scrolling up
       
  1224             scrollOffset = (aDirection == EDown) ? (Height() - (aRect.iTl.iY + KMinScrollAmount))
       
  1225                            : -(aRect.iBr.iY - KMinScrollAmount);
       
  1226         }
       
  1227     }
       
  1228     else
       
  1229     {//if it fits on screen make sure its BR is at the bottom if scrolling down
       
  1230         //or its TL is at the top if scrolling up
       
  1231         scrollOffset = (aDirection == EDown) ? (Height() - aRect.iBr.iY) : (-aRect.iTl.iY);
       
  1232     }
       
  1233 
       
  1234     RawScroll(iScroll + scrollOffset);
       
  1235     DEBUG("> CMIDForm::RawScrollToRect");
       
  1236 }
       
  1237 
       
  1238 void CMIDForm::ScrollRelative(TInt aScroll)
       
  1239 {
       
  1240     DEBUG("CMIDForm::ScrollRelative");
       
  1241     RawScrollRelative(aScroll);
       
  1242     RawScrollFinalize(EFalse);
       
  1243 }
       
  1244 
       
  1245 void CMIDForm::RawScrollRelative(TInt aScroll)
       
  1246 {
       
  1247     TInt scroll = iScroll + aScroll;
       
  1248     RawScroll(scroll);
       
  1249 }
       
  1250 
       
  1251 void CMIDForm::RawScroll(TInt aScroll)
       
  1252 {
       
  1253     TInt contentHeight  = HeightOfAllItems();
       
  1254     TInt viewPortHeight = Height();
       
  1255     if (aScroll > 0 || contentHeight <= viewPortHeight)
       
  1256     { // make sure that top does not slide down
       
  1257         aScroll = 0;
       
  1258     }
       
  1259     if (contentHeight > viewPortHeight && ((-aScroll) + viewPortHeight) > contentHeight)
       
  1260     { // scroll only as long as there is content
       
  1261         aScroll = -(contentHeight - viewPortHeight);
       
  1262     }
       
  1263     iHasScrolled = iScroll != aScroll;
       
  1264     iScrollDelta = aScroll - iScroll;
       
  1265     iScroll = aScroll;
       
  1266 
       
  1267     SetRowPositionsWithRespectToScrolledLocation();
       
  1268 }
       
  1269 
       
  1270 void CMIDForm::SetRowExtentsWithRespectToScrolledLocation()
       
  1271 {
       
  1272     iTotalFormHeight = 0;
       
  1273     TInt xMargin = iFormRect.Rect().iTl.iX;
       
  1274     TInt yTopMargin = iFormRect.Rect().iTl.iY - iMidpFormRect.Rect().iTl.iY;
       
  1275     TInt yBottomMargin = iMidpFormRect.Rect().iBr.iY - iFormRect.Rect().iBr.iY;
       
  1276 
       
  1277     iTotalFormHeight = yTopMargin;
       
  1278 
       
  1279     TInt rowCount = iRows.Count();
       
  1280     for (TInt i=0; i < rowCount; i++)
       
  1281     {
       
  1282         // Form left margin is added in the beginning of each row
       
  1283         iRows[i]->SetExtent(TPoint(xMargin, iScroll + iTotalFormHeight),
       
  1284                             TSize(Width(), iRows[i]->Size().iHeight));
       
  1285         iTotalFormHeight += iRows[i]->Size().iHeight;
       
  1286     }
       
  1287     // Form bottom margin is added
       
  1288     iTotalFormHeight += yBottomMargin;
       
  1289 }
       
  1290 
       
  1291 void CMIDForm::SetRowPositionsWithRespectToScrolledLocation()
       
  1292 {
       
  1293     TInt rowCount = iRows.Count();
       
  1294     for (TInt i=0; i < rowCount; i++)
       
  1295     {
       
  1296         // Form left margin is added in the beginning of each row
       
  1297         TPoint pos = iRows[i]->Position();
       
  1298         pos.iY += ScrollDelta();
       
  1299         iRows[i]->SetPosition(pos);
       
  1300     }
       
  1301 }
       
  1302 
       
  1303 // Finalizes scrolling after any RawScrollXxxx method call, e.g. causes repaint.
       
  1304 // Draw can be prevented e.g. because of the performance reasons.
       
  1305 void CMIDForm::RawScrollFinalize(TBool forseAction, TBool aDraw /*= ETrue*/)
       
  1306 {
       
  1307     if (iHasScrolled || forseAction)
       
  1308     {
       
  1309         UpdateHighlightBackgroundPosition();
       
  1310         HandleItemVisibilityChange();
       
  1311         UpdateScrollBar();
       
  1312         if (iFocused != KErrNotFound)
       
  1313         {
       
  1314             CMIDControlItem& ci = ControlItem(iFocused);
       
  1315             if (IsTextFieldItem(ci))
       
  1316             {
       
  1317                 if (RectPartiallyVisible(ci.Rect()))
       
  1318                 {
       
  1319                     ((CMIDTextFieldItem&) ci).SetCursorVisibility(ETrue);
       
  1320                 }
       
  1321                 else
       
  1322                 {
       
  1323                     ((CMIDTextFieldItem&) ci).SetCursorVisibility(EFalse);
       
  1324                 }
       
  1325             }
       
  1326             if (IsDateField(ci))
       
  1327             {
       
  1328                 // Update right cursor position on Datefiled
       
  1329                 ((CMIDDateFieldItem&) ci).CursorUpdate();
       
  1330             }
       
  1331         }
       
  1332         if (aDraw)
       
  1333         {
       
  1334             DrawDeferred();
       
  1335         }
       
  1336         iHasScrolled = EFalse;
       
  1337     }
       
  1338 }
       
  1339 
       
  1340 /** Returns the client area */
       
  1341 TRect CMIDForm::GetClientArea()
       
  1342 {
       
  1343     TRect scrolledClientArea = TRect(Position(), TSize(Width(), Height()));
       
  1344     return scrolledClientArea;
       
  1345 }
       
  1346 
       
  1347 // returns ETrue if it moved the focus
       
  1348 // returns EFalse otherwise
       
  1349 TBool CMIDForm::TryMovingFocusHorizontally(TDirection aDirection)
       
  1350 {
       
  1351     ASSERT(aDirection == ELeft || aDirection == ERight);
       
  1352 
       
  1353     TInt idx = NextFocusableHorizontalIdx(aDirection);
       
  1354     if (idx != KErrNotFound)
       
  1355     {
       
  1356         SetFocusedItem(idx, aDirection);
       
  1357         return ETrue;
       
  1358     }
       
  1359 
       
  1360     return EFalse;
       
  1361 }
       
  1362 
       
  1363 /**
       
  1364   Moves the focus vertically.
       
  1365 
       
  1366   We check if there is a focussable item,
       
  1367   which is on a row totally or partially visible and if there is such
       
  1368   an item we then select that row. This is done by calling
       
  1369   NextPartiallyVisibleRowWithFocusableItem(). If no such item was found we pick
       
  1370   the top or bottom (depending on scrolling direction) row that is partially
       
  1371   visible or the first not visible if the last one is completely shown.
       
  1372   This is done by FirstRowWithBottomBelowScreen() and LastRowWithTopAboveScreen().
       
  1373 
       
  1374   At this point if we have a row,  we select a focussable item on it and
       
  1375   scroll to it if aScroll is true. Calling scroll methods doesn't mean there is going to be
       
  1376   scrolling of the form,
       
  1377   if the item is already visible no scrolling is done. We select the
       
  1378   next focussable item according to the value of the parameter aSelectClosest.
       
  1379   If this paramerter is true we call SelectClosestFocussableItem() otherwise
       
  1380   we either select the first or the last selectable item on the row depending
       
  1381   on the direction.
       
  1382 
       
  1383   If we find a control we scroll to it by calling ScrollToFocused() (if aScroll is true) and move
       
  1384   the focus to it by calling SetFocusedItem(). Otherwise we
       
  1385   scroll to the row by calling ScrollToRow() if aScroll is true.
       
  1386 
       
  1387   If we could not find any row with a focusable item on it, we scroll the form
       
  1388   of a fixed quantity, KMinScrollAmount, if aScroll is true.
       
  1389 
       
  1390   We return ETrue if the focus was moved, EFalse otherwise. Note: Currently the
       
  1391   return value of this method is ignored.
       
  1392 
       
  1393   @see  NextPartiallyVisibleRowWithFocusableItem(), FirstRowWithBottomBelowScreen(),
       
  1394               LastRowWithTopAboveScreen(), SelectClosestFocussableItem()
       
  1395                    ScrollToRow(), SetFocusedItem() and DoScrollRelative().
       
  1396            Also see ReplaceFocusedItem(), called when the focused item is removed or
       
  1397            loses focusability - in this case no scrolling will occur.
       
  1398   */
       
  1399 TBool CMIDForm::TryMovingFocusVertically(TDirection aDirection, TBool aSelectClosest,
       
  1400         TBool aScroll /*=ETrue*/)
       
  1401 {
       
  1402     DEBUG("> CMIDForm::TryMovingFocusVertically");
       
  1403     ASSERT(aDirection == EUp || aDirection == EDown);
       
  1404 
       
  1405     // is VKB opened
       
  1406     if (iDisplayable.IsVKBOnScreen())
       
  1407     {
       
  1408         return ETrue;
       
  1409     }
       
  1410 
       
  1411     TInt rowIdx = NextPartiallyVisibleRowWithFocusableItem(aDirection);
       
  1412 
       
  1413     if (rowIdx == KErrNotFound)
       
  1414     {
       
  1415         DEBUG("CMIDForm::TryMovingFocusVertically - no partially visible focusable control found");
       
  1416         rowIdx = aDirection == EDown ? FirstRowWithBottomBelowScreen() : LastRowWithTopAboveScreen();
       
  1417     }
       
  1418 
       
  1419     if (rowIdx != KErrNotFound)
       
  1420     {
       
  1421         CMIDControlItem* ci = aSelectClosest ? SelectClosestFocussableItem(rowIdx) :
       
  1422                               (aDirection == EDown ? iRows[rowIdx]->FirstFocusableItem() :
       
  1423                                iRows[rowIdx]->LastFocusableItem());
       
  1424 
       
  1425 
       
  1426         if (ci)
       
  1427         {
       
  1428             DEBUG("CMIDForm::TryMovingFocusVertically - got control");
       
  1429             TInt index = Index(ci);
       
  1430 
       
  1431             if (index == KErrNotFound && IsLabelContainerItem(*ci))
       
  1432             {
       
  1433                 CMIDLabelContainerItem* ucsi = static_cast<CMIDLabelContainerItem*>(ci);
       
  1434                 CMIDStringItem& si = ucsi->StringItem();
       
  1435                 index = Index(&si);
       
  1436             }
       
  1437 
       
  1438             if (index != KErrNotFound)
       
  1439             {
       
  1440                 TRect rect = GetControlRect(index);
       
  1441 
       
  1442                 if (aScroll)
       
  1443                 {
       
  1444                     SetFocusedItem(index, aDirection, ETrue);
       
  1445                 }
       
  1446                 else if (RectPartiallyVisible(rect))
       
  1447                 {
       
  1448                     SetFocusedItem(index, aDirection);
       
  1449                 }
       
  1450                 else
       
  1451                 {
       
  1452                     SetFocusedItem(KErrNotFound);
       
  1453                 }
       
  1454 
       
  1455                 DEBUG("CMIDForm::TryMovingFocusVertically - out after scroll to control");
       
  1456                 return ETrue;
       
  1457             }
       
  1458         }
       
  1459 
       
  1460         DEBUG("CMIDForm::TryMovingFocusVertically - scrolling to row");
       
  1461         if (aScroll)
       
  1462         {
       
  1463             RawScrollToRow(rowIdx, aDirection);
       
  1464         }
       
  1465     }
       
  1466     else
       
  1467     {
       
  1468         DEBUG("CMIDForm::TryMovingFocusVertically - small default scrolling");
       
  1469         if (aScroll)
       
  1470         {
       
  1471             RawScrollRelative((aDirection == EDown) ? -KMinScrollAmount : KMinScrollAmount);
       
  1472         }
       
  1473     }
       
  1474 
       
  1475     DEBUG("< CMIDForm::TryMovingFocusVertically");
       
  1476     return EFalse;
       
  1477 }
       
  1478 
       
  1479 /** Given a row index, selects on this row the focusable control whose center on
       
  1480 the x axis is closes to the center of the currently focused item, if there is one.
       
  1481 If no control is found, returns the first selectable item on the row. */
       
  1482 CMIDControlItem* CMIDForm::SelectClosestFocussableItem(TInt aRowIndex) const
       
  1483 {
       
  1484     ASSERT(aRowIndex >= 0 && aRowIndex < iRows.Count());
       
  1485     TInt selectedIndex = -1;
       
  1486 
       
  1487     if (iFocused != -1)
       
  1488     {
       
  1489         TRect rect = GetControlRect(iFocused);
       
  1490         TInt focusedCenter = rect.iTl.iX + rect.Width()/2;
       
  1491 
       
  1492         TInt diff = iInnerWidth;
       
  1493 
       
  1494         TInt numItemsOnRow = iRows[aRowIndex]->NumItems();
       
  1495         for (TInt i = 0; i < numItemsOnRow; i++)
       
  1496         {
       
  1497             CMIDControlItem* item = iRows[aRowIndex]->Item(i);
       
  1498             if (item->IsSelectable())
       
  1499             {
       
  1500                 TInt center = item->Position().iX + (item->Size().iWidth / 2);
       
  1501                 TInt itemDiff = focusedCenter > center ? (focusedCenter - center) : (center - focusedCenter);
       
  1502 
       
  1503                 if (itemDiff < diff)
       
  1504                 {
       
  1505                     selectedIndex = i;
       
  1506                     diff = itemDiff;
       
  1507                 }
       
  1508             }
       
  1509         }
       
  1510     }
       
  1511 
       
  1512     return selectedIndex == -1 ? iRows[aRowIndex]->FirstFocusableItem() :
       
  1513            iRows[aRowIndex]->Item(selectedIndex);
       
  1514 }
       
  1515 
       
  1516 TInt CMIDForm::IndexOfFirstFocusableItemOnScreen(TDirection aDirection)
       
  1517 {
       
  1518     ASSERT(aDirection == EUp || aDirection == EDown);
       
  1519 
       
  1520     TInt startIdx = FirstRowOnScreen(aDirection);
       
  1521 
       
  1522     if (startIdx == KErrNotFound)
       
  1523     {
       
  1524         return KErrNotFound;
       
  1525     }
       
  1526 
       
  1527     CMIDControlItem* ci = NULL;
       
  1528 
       
  1529     if (aDirection == EDown)
       
  1530     {
       
  1531         TInt idx = startIdx - 1;
       
  1532         TInt rowCount = iRows.Count();
       
  1533         while (++idx < rowCount)
       
  1534         {
       
  1535             CMIDFormRow* row = iRows[idx];
       
  1536             if (row->Position().iY > Height())
       
  1537             {
       
  1538                 break;
       
  1539             }
       
  1540             ci = row->FirstFocusableItemOnScreen();
       
  1541             if (ci)
       
  1542             {
       
  1543                 break;
       
  1544             }
       
  1545         }
       
  1546     }
       
  1547     else
       
  1548     {
       
  1549         TInt idx = startIdx + 1;
       
  1550         while (--idx >= 0)
       
  1551         {
       
  1552             CMIDFormRow* row = iRows[idx];
       
  1553             if ((row->Position().iY + row->Size().iHeight) < 0)
       
  1554             {
       
  1555                 break;
       
  1556             }
       
  1557             ci = row->FirstFocusableItemOnScreen();
       
  1558             if (ci)
       
  1559             {
       
  1560                 break;
       
  1561             }
       
  1562         }
       
  1563     }
       
  1564 
       
  1565     if (!ci)
       
  1566     {
       
  1567         return KErrNotFound;
       
  1568     }
       
  1569 
       
  1570     TInt index = Index(ci);
       
  1571     if (index == KErrNotFound)
       
  1572     {
       
  1573         if (IsLabelContainerItem(*ci))
       
  1574         {
       
  1575             CMIDLabelContainerItem* ucsi = static_cast<CMIDLabelContainerItem*>(ci);
       
  1576             CMIDStringItem& si = ucsi->StringItem();
       
  1577             index = Index(&si);
       
  1578         }
       
  1579     }
       
  1580 
       
  1581     return index;
       
  1582 }
       
  1583 
       
  1584 /** Return the rect for a control, taking into account if the control is an
       
  1585 unconstrained string item which has been split over more than one label container
       
  1586 */
       
  1587 TRect CMIDForm::GetControlRect(TInt aIdx) const
       
  1588 {
       
  1589     CMIDControlItem& ci = ControlItem(aIdx);
       
  1590     TRect rect;
       
  1591 
       
  1592     if (ItemIsUnconstrained(aIdx))
       
  1593     {
       
  1594         rect = GetUnconstrainedStringItemRect(static_cast<CMIDStringItem*>(&ci));
       
  1595     }
       
  1596     else
       
  1597     {
       
  1598         rect = ci.Rect();
       
  1599     }
       
  1600 
       
  1601     return rect;
       
  1602 }
       
  1603 
       
  1604 /** Collate rects for unconstrained string items that have been split across more
       
  1605 than one lable container */
       
  1606 TRect CMIDForm::GetUnconstrainedStringItemRect(CMIDStringItem* aStringItem) const
       
  1607 {
       
  1608     TRect rect(0,0,0,0);
       
  1609     TBool found = EFalse;
       
  1610 
       
  1611     TInt rowIdx = FirstRowOfUnconstrainedStringItem(*aStringItem);
       
  1612     TInt rowCount = iRows.Count();
       
  1613 
       
  1614     // if the first row of unconstrained string item cannot be found
       
  1615     // it means that string item is placed as default item
       
  1616     // so simply return item's rect
       
  1617     if (rowIdx == KErrNotFound)
       
  1618     {
       
  1619         return aStringItem->Rect();
       
  1620     }
       
  1621 
       
  1622     while (rowIdx != KErrNotFound && rowIdx < rowCount)
       
  1623     {
       
  1624         CMIDFormRow* row = iRows[rowIdx];
       
  1625         for (TInt idxOnRow = 0; idxOnRow < row->NumItems(); idxOnRow++)
       
  1626         {
       
  1627             CMIDControlItem* ci = row->Item(idxOnRow);
       
  1628             if (ci && IsLabelContainerItem(*ci))
       
  1629             {
       
  1630                 CMIDLabelContainerItem* usil = static_cast<CMIDLabelContainerItem*>(ci);
       
  1631                 CMIDStringItem* si = &(usil->StringItem());
       
  1632 
       
  1633                 if (si == aStringItem)
       
  1634                 {
       
  1635                     if (!found)
       
  1636                     {
       
  1637                         rect.iTl = usil->Rect().iTl;
       
  1638                         found = ETrue;
       
  1639                     }
       
  1640                     rect.iBr = usil->Rect().iBr;
       
  1641                 }
       
  1642                 else if (found)
       
  1643                 {
       
  1644                     return rect;
       
  1645                 }
       
  1646             }
       
  1647             else if (found)
       
  1648             {
       
  1649                 return rect;
       
  1650             }
       
  1651         }
       
  1652         rowIdx++;
       
  1653     }
       
  1654 
       
  1655     return rect;
       
  1656 }
       
  1657 
       
  1658 TBool CMIDForm::RectPartiallyVisible(const TRect& aRect)
       
  1659 {
       
  1660     return ((aRect.iTl.iY >= 0) && (aRect.iTl.iY < Height())) ||
       
  1661            ((aRect.iBr.iY >= 0) && (aRect.iBr.iY < Height())) ||
       
  1662            ((aRect.iTl.iY < 0) && (aRect.iBr.iY >= Height()));
       
  1663 }
       
  1664 
       
  1665 TBool CMIDForm::RectFullyVisible(const TRect& aRect)
       
  1666 {
       
  1667     return (aRect.iTl.iY >= 0) && (aRect.iBr.iY <= Height());
       
  1668 }
       
  1669 
       
  1670 TInt CMIDForm::FirstRowWithBottomBelowScreen()
       
  1671 {
       
  1672     TInt idx = -1;
       
  1673     TInt rowWithFocus = iFocused == KErrNotFound ? -1 : Row(ControlItem(iFocused));
       
  1674     TInt rowCount = iRows.Count();
       
  1675     while (++idx < rowCount)
       
  1676     {
       
  1677         CMIDFormRow* row = iRows[idx];
       
  1678         TInt height = row->Size().iHeight;
       
  1679         TInt yPos = row->Position().iY;
       
  1680         if ((height + yPos) > Height() && row->HasNonSpacerItems() && idx != rowWithFocus)
       
  1681         {
       
  1682             return idx;
       
  1683         }
       
  1684     }
       
  1685 
       
  1686     return KErrNotFound;
       
  1687 }
       
  1688 
       
  1689 TInt CMIDForm::LastRowWithTopAboveScreen()
       
  1690 {
       
  1691     TInt idx = iRows.Count();
       
  1692     TInt rowWithFocus = iFocused == KErrNotFound ? -1 : Row(ControlItem(iFocused));
       
  1693 
       
  1694     while (--idx >= 0)
       
  1695     {
       
  1696         CMIDFormRow* row = iRows[idx];
       
  1697         TInt yPos = row->Position().iY;
       
  1698         if (yPos < 0 && row->HasNonSpacerItems() && idx != rowWithFocus)
       
  1699         {
       
  1700             return idx;
       
  1701         }
       
  1702     }
       
  1703 
       
  1704     return KErrNotFound;
       
  1705 }
       
  1706 
       
  1707 // note: inspite of the name of this method, we only consider rows with
       
  1708 // a focusable item that has not already been scrolled off the screen.
       
  1709 // For Example:
       
  1710 //
       
  1711 //  ----
       
  1712 // | A  | This is a
       
  1713 // |    | string item
       
  1714 //  ----  that is placed
       
  1715 //----------------------- <- top of form
       
  1716 //        next to item A.
       
  1717 //        This
       
  1718 //        string
       
  1719 //        item
       
  1720 //        is
       
  1721 //        quite
       
  1722 //        tall
       
  1723 //        and
       
  1724 //----------------------- <- botom of form
       
  1725 //        fills
       
  1726 //        the
       
  1727 //        screen
       
  1728 //
       
  1729 // Assuming that A is focusable, and we are scrolling down, and also assuming
       
  1730 // that the string item is not focusable, we do not consider A when looking
       
  1731 // for focusable items, because we are scrolling down and A is already above
       
  1732 // the screen.
       
  1733 TInt CMIDForm::NextPartiallyVisibleRowWithFocusableItem(TDirection aDirection)
       
  1734 {
       
  1735     ASSERT(aDirection == EUp || aDirection == EDown);
       
  1736 
       
  1737     TInt startIdx = 0;
       
  1738     if (iFocused != KErrNotFound)
       
  1739     {
       
  1740         //If there is layout request pending, the array of rows is probably
       
  1741         //empty. So we need to do layout of form, which fills the array of rows.
       
  1742         //Then row, where current focused item is, will be found.
       
  1743         if (iRows.Count() == 0)
       
  1744         {
       
  1745             TrappedLayoutAndDraw(ETrue);
       
  1746         }
       
  1747         TInt row = Row(ControlItem(iFocused));
       
  1748         if (row == KErrNotFound)
       
  1749         {
       
  1750             CMIDControlItem& ci = ControlItem(iFocused);
       
  1751             if (IsStringItem(ci))
       
  1752             {
       
  1753                 // find the first row either above or below (depends on direction)
       
  1754                 // this unconstrained stringItem
       
  1755                 CMIDStringItem& stringItem =
       
  1756                     *(static_cast<CMIDStringItem*>(&ci));
       
  1757                 if (aDirection == EDown)
       
  1758                 {
       
  1759                     startIdx = FirstRowBelowUnconstrainedStringItem(stringItem);
       
  1760                 }
       
  1761                 else
       
  1762                 {
       
  1763                     startIdx = FirstRowAboveUnconstrainedStringItem(stringItem);
       
  1764                 }
       
  1765             }
       
  1766             else
       
  1767             {
       
  1768                 // shouldn't get here
       
  1769                 ASSERT(EFalse);
       
  1770             }
       
  1771         }
       
  1772         else
       
  1773         {
       
  1774             startIdx = row + ((aDirection == EDown) ? 1 : -1);
       
  1775         }
       
  1776     }
       
  1777     else
       
  1778     {
       
  1779         // There is no focused item on Form (iFocused value is KErrNotFound).
       
  1780         // So we need to try to find another Item which could gain focus.
       
  1781         startIdx = FirstRowOnScreen(aDirection);
       
  1782     }
       
  1783 
       
  1784     if (startIdx == KErrNotFound)
       
  1785     {
       
  1786         return KErrNotFound;
       
  1787     }
       
  1788 
       
  1789     if (aDirection == EDown)
       
  1790     {
       
  1791         TInt idx = startIdx - 1;
       
  1792         TInt rowCount = iRows.Count();
       
  1793         while (++idx < rowCount)
       
  1794         {
       
  1795             CMIDFormRow* row = iRows[idx];
       
  1796             if (row->Position().iY > Height())
       
  1797             {
       
  1798                 break;
       
  1799             }
       
  1800             if (row->HasFocusableItemOnOrBelowScreen())
       
  1801             {
       
  1802                 return idx;
       
  1803             }
       
  1804         }
       
  1805     }
       
  1806     else
       
  1807     {
       
  1808         TInt idx = startIdx + 1;
       
  1809         while (--idx >= 0)
       
  1810         {
       
  1811             CMIDFormRow* row = iRows[idx];
       
  1812 
       
  1813             if (row->HasFocusableItemOnOrAboveScreen())
       
  1814             {
       
  1815                 return idx;
       
  1816             }
       
  1817 
       
  1818             if ((row->Position().iY + row->Size().iHeight) < 0)
       
  1819             {
       
  1820                 break;
       
  1821             }
       
  1822         }
       
  1823     }
       
  1824 
       
  1825     return KErrNotFound;
       
  1826 }
       
  1827 
       
  1828 // if aFromTop is false we look from the bottom up
       
  1829 TInt CMIDForm::FirstRowOnScreen(TDirection aDirection)
       
  1830 {
       
  1831     ASSERT(aDirection == EUp || aDirection == EDown);
       
  1832 
       
  1833     TInt idx = 0;
       
  1834     if (aDirection == EDown)
       
  1835     {
       
  1836         idx = -1;
       
  1837         TInt rowCount = iRows.Count();
       
  1838         while (++idx < rowCount)
       
  1839         {
       
  1840             CMIDFormRow* row = iRows[idx];
       
  1841             TInt bottom = row->Position().iY + row->Size().iHeight;
       
  1842             if (bottom > 0)
       
  1843             {
       
  1844                 return idx;
       
  1845             }
       
  1846         }
       
  1847     }
       
  1848     else
       
  1849     {
       
  1850         idx = iRows.Count();
       
  1851         while (--idx >= 0)
       
  1852         {
       
  1853             CMIDFormRow* row = iRows[idx];
       
  1854             TInt top = row->Position().iY;
       
  1855             if (top < Height())
       
  1856             {
       
  1857                 return idx;
       
  1858             }
       
  1859         }
       
  1860     }
       
  1861 
       
  1862     return KErrNotFound;
       
  1863 }
       
  1864 
       
  1865 // Returns the item index of the next focusable item in the given direction.
       
  1866 // Note: this may return an object that is not on the current row if there is
       
  1867 //       an unconstrained string item on the current row.
       
  1868 //
       
  1869 //       --------
       
  1870 //       |      |
       
  1871 //       |  A   |
       
  1872 //       |      | --------
       
  1873 //       -------- --------
       
  1874 //       -----------------
       
  1875 //       __________ ------
       
  1876 //                  |    |
       
  1877 //                  | B  |
       
  1878 //                  |    |
       
  1879 //                  ------
       
  1880 // In the above diagram we see a selectable item A, an unconstrained stringItem,
       
  1881 // and another selectable item B. If A has focus and the stringItem is not focusable
       
  1882 // then calling NextFocusableHorizontalIdx( ERight ) should return the index of B.
       
  1883 // If the string item is selectable then its index would get returned and a further
       
  1884 // call to NextFocusableHorizontalIdx( ERight ) would return the index of B.
       
  1885 // If B has focus calling NextFocusableHorizontalIdx( ELeft ) would simply return the
       
  1886 // index of the stringItem if it is selectable or A if not.
       
  1887 TInt CMIDForm::NextFocusableHorizontalIdx(TDirection aDirection)
       
  1888 {
       
  1889     ASSERT(aDirection == ELeft || aDirection == ERight);
       
  1890 
       
  1891     TInt idx = KErrNotFound;
       
  1892 
       
  1893     if (iFocused != KErrNotFound)
       
  1894     {
       
  1895         CMIDFormRow* rowPtr = NULL;
       
  1896         CMIDControlItem& controlItem = ControlItem(iFocused);
       
  1897 
       
  1898         TInt rowIdx = Row(controlItem, rowPtr);
       
  1899 
       
  1900         if (rowIdx != KErrNotFound)
       
  1901         {
       
  1902 
       
  1903             idx = rowPtr->Find(&controlItem);
       
  1904 
       
  1905             if (aDirection == ELeft)
       
  1906             {
       
  1907                 while (--idx >= 0)
       
  1908                 {
       
  1909                     if (rowPtr->Item(idx)->IsSelectable())
       
  1910                     {
       
  1911                         return ItemIndex(*(rowPtr->Item(idx)));
       
  1912                     }
       
  1913                 }
       
  1914 
       
  1915             }
       
  1916             else
       
  1917             {
       
  1918                 // direction is ERight
       
  1919                 while (++idx < rowPtr->NumItems())
       
  1920                 {
       
  1921                     if (rowPtr->Item(idx)->IsSelectable())
       
  1922                     {
       
  1923                         return ItemIndex(*(rowPtr->Item(idx)));
       
  1924                     }
       
  1925                 }
       
  1926 
       
  1927             }
       
  1928         }
       
  1929         else
       
  1930         {
       
  1931             // there is something focused but we failed to find a row index for it,
       
  1932             // so it is probably an unconstrained stringItem
       
  1933             if (aDirection == ELeft)
       
  1934             {
       
  1935                 if (IsStringItem(controlItem))
       
  1936                 {
       
  1937                     CMIDStringItem* si = static_cast<CMIDStringItem*>(&controlItem);
       
  1938                     idx = FirstFocusableItemBeforeStartOfUnconstrainedStringItemIdx(*si);
       
  1939                     return idx;
       
  1940                 }
       
  1941             }
       
  1942             else
       
  1943             {
       
  1944                 // direction ie ERight
       
  1945                 if (IsStringItem(controlItem))
       
  1946                 {
       
  1947                     CMIDStringItem* si = static_cast<CMIDStringItem*>(&controlItem);
       
  1948                     idx = FirstFocusableItemOnLastLineOfUnconstrainedStringItemIdx(*si);
       
  1949                     return idx;
       
  1950                 }
       
  1951             }
       
  1952         }
       
  1953     }
       
  1954 
       
  1955     return KErrNotFound;
       
  1956 }
       
  1957 
       
  1958 /** Replaces the currently focused item. This is called when the focused item is removed
       
  1959 or it loses focusability, for example a string item that loses all its commands. So this
       
  1960 is always triggered by a java call, never by the user. We call the same methods that are
       
  1961 used by Scroll(), ie TryMovingFocusHorizontally() and TryMovingFocusVertically(). However
       
  1962 in this case we don't want the form to scroll if the focused item is not on screen. So
       
  1963 these two methods will move the focus if a focusable item is either completely or partially
       
  1964 visible on screen following the good direction (right-down for left to right devices and
       
  1965 vice-versa for right to left devices). TryMovingFocusVertically() will set the focused item
       
  1966 to KErrNotFound if no focusable item is currently visible. */
       
  1967 void CMIDForm::ReplaceFocusedItem()
       
  1968 {
       
  1969     if (LayoutPending())
       
  1970     {
       
  1971         DEBUG("CMIDForm::ReplaceFocusedItem - calling layout");
       
  1972         TRAP_IGNORE(LayoutFormL());
       
  1973     }
       
  1974 
       
  1975     CMIDForm::TDirection direction = (iInitialAlignment == MMIDItem::ERight) ? ELeft : ERight;
       
  1976 
       
  1977     if (!TryMovingFocusHorizontally(direction))
       
  1978     {
       
  1979         if (iInitialAlignment == MMIDItem::ERight)
       
  1980         {//RIGHT TO LEFT
       
  1981             if (!TryMovingFocusVertically(direction == ELeft ? EDown : EUp, EFalse, EFalse))
       
  1982             {
       
  1983                 SetFocusedItem(KErrNotFound);
       
  1984             }
       
  1985         }
       
  1986         else
       
  1987         {//LEFT TO RIGHT
       
  1988             if (!TryMovingFocusVertically(direction == ELeft ? EUp : EDown, EFalse, EFalse))
       
  1989             {
       
  1990                 SetFocusedItem(KErrNotFound);
       
  1991             }
       
  1992         }
       
  1993     }
       
  1994 }
       
  1995 
       
  1996 void CMIDForm::SetFocusedItem(TInt aFocusIdx, TDirection aDirection /*= ENone*/,
       
  1997                               TBool aDoScroll /*= ETrue*/)
       
  1998 {
       
  1999     TInt oldFocused = iFocused;
       
  2000     TInt focusIndexDelta = aFocusIdx - iFocused;
       
  2001     if (iFocused != KErrNotFound)
       
  2002     { // actions for the item loosing focus
       
  2003         CMIDControlItem& control = ControlItem(iFocused);
       
  2004         control.PostFocusTransferEvent(EFalse, aDirection);
       
  2005         // setting highlight must be called before setting focus
       
  2006         control.SetHighlight(EFalse);
       
  2007         control.SetFocus(EFalse);
       
  2008         UpdateItemCommands(NULL, NULL);
       
  2009     }
       
  2010 
       
  2011     iFocused = aFocusIdx;
       
  2012 
       
  2013     //If there is traverse from visible to invisible TextField, Form has to scroll first
       
  2014     //before actions for the item which gaining focus are done. Form scrolling provides
       
  2015     //position settings to all visible items in form.
       
  2016     //When TextField gains focus, cursor values are calculated. Because this step was done before
       
  2017     //scrolling, position of edwin in TextField was not set (@see CMIDFormRow::SizeChanged())
       
  2018     //and cursor was drawn to wrong position.
       
  2019     //So Form has to scroll first -> this action provides proper position settings
       
  2020     //to item and items which are part of it (e.g. edwin in TextField) and after that
       
  2021     //changing focus makes proper cursor drawing.
       
  2022     if (focusIndexDelta != 0 && aDoScroll)
       
  2023     {
       
  2024         if (oldFocused != KErrNotFound)
       
  2025         {
       
  2026             aDirection = (focusIndexDelta > 0) ? EDown : EUp;
       
  2027         }
       
  2028 
       
  2029         ScrollToFocused(aDirection, EFalse);
       
  2030     }
       
  2031 
       
  2032     if (iFocused != KErrNotFound)
       
  2033     { // actions for the item gaining focus
       
  2034         CMIDControlItem& control = ControlItem(iFocused);
       
  2035 
       
  2036         SetHighlightBackgroundRects();
       
  2037 
       
  2038         control.PostFocusTransferEvent(ETrue, aDirection);
       
  2039         control.SetHighlight(ETrue);
       
  2040         control.SetFocus(ETrue);
       
  2041         // msk: deliver also the possible MSK command to displayable
       
  2042         UpdateItemCommands(control.CommandList(), control.GetMSKCommand());
       
  2043     }
       
  2044 }
       
  2045 
       
  2046 /** Updates the model of the scrollbar and moves the thumb. Scroll bar must have
       
  2047 already been layouted.*/
       
  2048 void CMIDForm::UpdateScrollBar()
       
  2049 {
       
  2050     ASSERT(iSBFrame);
       
  2051     DEBUG_INT("CMIDForm::UpdateScrollBar - iScroll is %D", iScroll);
       
  2052 
       
  2053     TInt heightOfAllItems = HeightOfAllItems();
       
  2054     TInt height = heightOfAllItems > Height() ? heightOfAllItems : Height();
       
  2055 
       
  2056     TEikScrollBarModel vSbarModel(height, Height(), -iScroll);
       
  2057     iSBFrame->Tile(&vSbarModel);
       
  2058     iSBFrame->MoveVertThumbTo(-iScroll);
       
  2059 
       
  2060     iPopupController->HidePopup(); // hide info popup window if visible
       
  2061 }
       
  2062 
       
  2063 CMIDForm* CMIDForm::NewL(MMIDEnv& aEnv,MMIDDisplayable& aDisplayable)
       
  2064 {
       
  2065     CMIDForm* form = new(ELeave) CMIDForm(aEnv, static_cast<CMIDDisplayable&>(aDisplayable));
       
  2066     CleanupStack::PushL(form);
       
  2067     form->ConstructL();
       
  2068     CleanupStack::Pop(form);
       
  2069     return form;
       
  2070 }
       
  2071 
       
  2072 CMIDForm::CMIDForm(MMIDEnv& aEnv, CMIDDisplayable& aDisplayable)
       
  2073         : iDisplayable(aDisplayable), iEnv(&aEnv), iFocused(KErrNotFound),
       
  2074         iInitialAlignment(MMIDItem::ELeft), iHasScrolled(EFalse),
       
  2075         iLastFadeMessage(0)
       
  2076 {
       
  2077 }
       
  2078 
       
  2079 CMIDForm::~CMIDForm()
       
  2080 {
       
  2081     TRAP_IGNORE(DeleteAllItemsL());
       
  2082     DeleteRows();
       
  2083     iCurrentRow = NULL;
       
  2084 
       
  2085     delete iSBFrame;
       
  2086     SetItemsFormPointersToVal(NULL);
       
  2087     iItems.Close();
       
  2088     iRows.Close();
       
  2089 
       
  2090     delete iLayoutTimer;
       
  2091     delete iNoDataText;
       
  2092 
       
  2093     if (iBackgroundControlContext)
       
  2094     {
       
  2095         delete iBackgroundControlContext;
       
  2096         iBackgroundControlContext = NULL;
       
  2097     }
       
  2098     if (iHighlightedBackgroundCc)
       
  2099     {
       
  2100         delete iHighlightedBackgroundCc;
       
  2101         iHighlightedBackgroundCc = NULL;
       
  2102     }
       
  2103 
       
  2104     // Displayable is notified about content control deletion
       
  2105     iDisplayable.NotifyContentDestroyed();
       
  2106 
       
  2107     delete iPopupController;
       
  2108 
       
  2109     if (iHighlightTimer)
       
  2110     {
       
  2111         iHighlightTimer->Cancel();
       
  2112     }
       
  2113     delete iHighlightTimer;
       
  2114 
       
  2115     delete iPhysics;
       
  2116 }
       
  2117 
       
  2118 #include "javaoslayer.h"
       
  2119 
       
  2120 void CMIDForm::Draw(const TRect& aRect) const
       
  2121 {
       
  2122     if (!iStartUpTraceDone)
       
  2123     {
       
  2124         java::util::JavaOsLayer::startUpTrace("MIDP: CMIDForm::Draw starts", -1, -1);
       
  2125     }
       
  2126     if (LayoutPending())
       
  2127     {
       
  2128         return;
       
  2129     }
       
  2130 
       
  2131     CWindowGc& gc = SystemGc();
       
  2132 
       
  2133     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
  2134     AknsDrawUtils::Background(skin, iBackgroundControlContext, this, gc, aRect);
       
  2135 
       
  2136     // Draw focus highlight
       
  2137     if (iFocused != KErrNotFound)
       
  2138     {
       
  2139         TRect focusedRect = ControlItem(iFocused).Rect();
       
  2140         if (focusedRect.Intersects(aRect))
       
  2141         {
       
  2142             AknsDrawUtils::Background(AknsUtils::SkinInstance(),
       
  2143                                       iHighlightedBackgroundCc, this,
       
  2144                                       SystemGc(), focusedRect);
       
  2145         }
       
  2146     }
       
  2147 
       
  2148     // If there is no items, "No data" string is printed to the middle of the screen
       
  2149     if (iItems.Count() == 0)
       
  2150     {
       
  2151         TRAP_IGNORE(DrawNoDataStringL());
       
  2152     }
       
  2153     if (!iStartUpTraceDone)
       
  2154     {
       
  2155         java::util::JavaOsLayer::startUpTrace("MIDP: CMIDForm::Draw done", -1, -1);
       
  2156         iStartUpTraceDone = ETrue;
       
  2157     }
       
  2158 }
       
  2159 
       
  2160 void CMIDForm::DrawNoDataStringL() const
       
  2161 {
       
  2162     CWindowGc& gc = SystemGc();
       
  2163 
       
  2164     // Actual skin instance
       
  2165     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
  2166 
       
  2167     // If there is not the color fot the particular skin and id found, default (black) is used
       
  2168     TRgb color;
       
  2169     // Try to receive the color by skin and color Id, if not successful, black is used
       
  2170     TInt err = AknsUtils::GetCachedColor(skin, color, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG6);
       
  2171     if (err != KErrNone)
       
  2172     {
       
  2173         color = AKN_LAF_COLOR(AknLayout::Title_pane_texts_Line_1(0, 0).iC);
       
  2174     }
       
  2175 
       
  2176     const CFont* font = CMIDFont::DefaultFont(CMIDFont::EDefaultTextId);
       
  2177     TInt textWidth = font->TextWidthInPixels(iNoDataText->Des());
       
  2178 
       
  2179     // Rectangle for computing the center
       
  2180     TRect screenRect;
       
  2181     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screenRect);
       
  2182 
       
  2183     // Centers the string to the middle of the screen
       
  2184     TInt x = (screenRect.Width() - textWidth) / 2;
       
  2185     TInt y = (iInnerHeight - font->HeightInPixels()) / 2;
       
  2186     TPoint point(x, y);
       
  2187     //Reserve extra space for biditext formatting
       
  2188     HBufC* bidiTextBuffer = HBufC::NewLC(iNoDataText->Size() + KAknBidiExtraSpacePerLine);
       
  2189     TPtr bidiText = bidiTextBuffer->Des();
       
  2190     TPtr caption = iNoDataText->Des();
       
  2191     bidiText = caption;
       
  2192     // Handle (bidi)text formatting for all languages
       
  2193     AknBidiTextUtils::ConvertToVisualAndClipL(bidiText, *font, textWidth, textWidth);
       
  2194 
       
  2195     gc.SetPenColor(color);
       
  2196     gc.UseFont(font);
       
  2197     gc.DrawText(bidiText, point);
       
  2198     CleanupStack::PopAndDestroy(bidiTextBuffer);
       
  2199     gc.DiscardFont();
       
  2200 }
       
  2201 
       
  2202 
       
  2203 /** Request a layout operaiton. We must delete the rows if postponing layout
       
  2204 in case java side some of the controls have been deleted. Otherwise because those
       
  2205 controls may be on existing rows we would get a panic in a draw request outside
       
  2206 our control. By deleting the rows in the worse scenario we'll get a blank form
       
  2207 drawn temporarily until the next layout operation. */
       
  2208 void CMIDForm::RequestLayoutL(TBool aImmediately /*= EFalse*/)
       
  2209 {
       
  2210     if (aImmediately)
       
  2211     {
       
  2212         iLayoutTimer->Cancel();
       
  2213         LayoutAndDrawL();
       
  2214     }
       
  2215     else
       
  2216     {
       
  2217         if (LayoutPending())
       
  2218         {
       
  2219             TTime now;
       
  2220             now.HomeTime();
       
  2221 
       
  2222             if (now.MicroSecondsFrom(iLayoutRequestTime) > KLayoutCap)
       
  2223             {
       
  2224                 LayoutAndDrawL();
       
  2225             }
       
  2226             else
       
  2227             {
       
  2228                 iLayoutTimer->Cancel();
       
  2229             }
       
  2230         }
       
  2231         else
       
  2232         {
       
  2233             iLayoutRequestTime.HomeTime();
       
  2234             DeleteRows();
       
  2235         }
       
  2236 
       
  2237         if (iLayoutRequestTime != -1)
       
  2238         {
       
  2239             iLayoutTimer->After(KLayoutTimeout);
       
  2240         }
       
  2241     }
       
  2242 }
       
  2243 
       
  2244 /** Return true if a layout request has been made. */
       
  2245 TBool CMIDForm::LayoutPending() const
       
  2246 {
       
  2247     return (iLayoutRequestTime != -1) && (iLayoutTimer->IsActive());
       
  2248 }
       
  2249 
       
  2250 /**
       
  2251 Layout the form, do scrolling and draw. Reset any previous layout request.
       
  2252 
       
  2253 @see RequestLayout(), LayoutPending(), LayoutFormL() and DoScroll()
       
  2254 */
       
  2255 void CMIDForm::LayoutAndDrawL()
       
  2256 {
       
  2257     DEBUG("CMIDForm::LayoutAndDrawL");
       
  2258 
       
  2259     LayoutFormL();
       
  2260 
       
  2261     HandleItemVisibilityChange();
       
  2262     UpdateScrollBar();
       
  2263     SetHighlightBackgroundRects();
       
  2264     DrawDeferred();
       
  2265 
       
  2266     UpdatePhysics();
       
  2267 }
       
  2268 
       
  2269 /** Call LayoutAndDrawL() inside a trap harness and log an error message if it
       
  2270 levaes.
       
  2271 
       
  2272     @param aOnlyIfPending Call LayoutAndDrawL() only if there is one pending,
       
  2273            @see LayoutPending(). By default this parameter is EFalse, i.e. always do layout
       
  2274 
       
  2275     @return The leave code returned by LayoutAndDrawL()
       
  2276 */
       
  2277 TInt CMIDForm::TrappedLayoutAndDraw(TBool aOnlyIfPending /* = EFalse */)
       
  2278 {
       
  2279     if (aOnlyIfPending  && !LayoutPending())
       
  2280     {
       
  2281         return KErrNone;
       
  2282     }
       
  2283 
       
  2284     TRAPD(err, LayoutAndDrawL());
       
  2285     return err;
       
  2286 }
       
  2287 
       
  2288 /* Called when the form becomes current and after the focus was set
       
  2289  * @see CMIDDisplayable::HandleCurrentL()
       
  2290  */
       
  2291 void CMIDForm::HandleCurrentL(TBool aCurrent)
       
  2292 {
       
  2293     if (iFocused != KErrNotFound)
       
  2294     {
       
  2295         CMIDControlItem& control = ControlItem(iFocused);
       
  2296         control.HandleCurrentL(aCurrent);
       
  2297     }
       
  2298 
       
  2299     if (!aCurrent)
       
  2300     {
       
  2301         iPopupController->HidePopup();
       
  2302     }
       
  2303 
       
  2304 #ifdef RD_SCALABLE_UI_V2
       
  2305     iCanDragFocus = EFalse;
       
  2306 #endif
       
  2307 }
       
  2308 
       
  2309 void CMIDForm::ConstructL()
       
  2310 {
       
  2311     UpdateMemberVariables();
       
  2312 
       
  2313     SetContainerWindowL(iDisplayable);
       
  2314 
       
  2315     iPopupController = CMIDPopupNoteController::NewL();
       
  2316 
       
  2317     // Scroll initialisations
       
  2318 #ifdef RD_SCALABLE_UI_V2
       
  2319     iSBFrame = new(ELeave) CEikScrollBarFrame(this, this, ETrue);
       
  2320     Window().SetPointerGrab(ETrue);
       
  2321 #else
       
  2322     iSBFrame = new(ELeave) CEikScrollBarFrame(this, NULL, ETrue);
       
  2323 #endif //RD_SCALABLE_UI_V2
       
  2324 
       
  2325     iSBFrame->SetScrollBarVisibilityL(
       
  2326         CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
       
  2327     iSBFrame->CreateDoubleSpanScrollBarsL(ETrue, EFalse);
       
  2328 
       
  2329     // Background initialisation
       
  2330     iBackgroundControlContext = CAknsListBoxBackgroundControlContext::NewL(
       
  2331                                     KAknsIIDQsnBgAreaMainListGene, Rect(), ETrue,
       
  2332                                     KAknsIIDQsnBgColumnAB, Rect())  ;  // Rect parameters are only place-holders
       
  2333 
       
  2334     // Background for highlighted item, frame rects are set later
       
  2335     iHighlightedBackgroundCc = CAknsFrameBackgroundControlContext::NewL(
       
  2336                                    KAknsIIDQsnFrInput,
       
  2337                                    TRect(), TRect(), ETrue);
       
  2338 
       
  2339     iDisplayable.SetComponentL(*this);
       
  2340 
       
  2341     // get the layout from shared data so we can tell what our
       
  2342     // initial alignment should be
       
  2343     TInt layoutId = 0;
       
  2344 
       
  2345     CRepository* repository = CRepository::NewL(KCRUidAvkon);
       
  2346     repository->Get(KAknLayoutId, layoutId);
       
  2347     delete repository;
       
  2348 
       
  2349     if (layoutId == EAknLayoutIdABRW)
       
  2350     {
       
  2351         iInitialAlignment = MMIDItem::ERight;
       
  2352     }
       
  2353 
       
  2354     iLayoutTimer = CTimeOutTimer::NewL(CActive::EPriorityIdle, *this);
       
  2355     iNoDataText =  iEikonEnv->AllocReadResourceL(R_AVKON_NO_DATA);
       
  2356 
       
  2357 #ifdef RD_TACTILE_FEEDBACK
       
  2358     iFeedback = MTouchFeedback::Instance();
       
  2359 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  2360     UpdateTactileFeedbackDensity();
       
  2361 #endif // RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  2362 #endif // RD_TACTILE_FEEDBACK
       
  2363 
       
  2364     //index of pointed control is set to not active
       
  2365     iIndexPointedControl=-1;
       
  2366 
       
  2367     if (CMIDFormPhysics::FeatureEnabled())
       
  2368     {
       
  2369         iPhysics = CMIDFormPhysics::NewL(*this);
       
  2370 
       
  2371         // Destroy iPhysics immediately if physics is not allowed.
       
  2372         // This should happen in error situation only, when implementation
       
  2373         // dll couldn't be loaded although the feature was enabled.
       
  2374         if (iPhysics && !iPhysics->PhysicsAllowed())
       
  2375         {
       
  2376             delete iPhysics;
       
  2377             iPhysics = NULL;
       
  2378         }
       
  2379         else
       
  2380         {
       
  2381             iHighlightTimer = CPeriodic::NewL(CActive::EPriorityStandard);
       
  2382         }
       
  2383     }
       
  2384 
       
  2385     LayoutAndDrawL();
       
  2386 }
       
  2387 
       
  2388 void CMIDForm::UpdateMemberVariables()
       
  2389 {
       
  2390     TAknLayoutRect mainMidpPane;
       
  2391 
       
  2392 #ifdef RD_JAVA_S60_RELEASE_9_2
       
  2393     TRect mainPaneRect;
       
  2394     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
       
  2395     mainMidpPane.LayoutRect(mainPaneRect,
       
  2396                             AknLayoutScalable_Avkon::main_midp_pane().LayoutLine());
       
  2397 #else
       
  2398     mainMidpPane.LayoutRect(iEikonEnv->ScreenDevice()->SizeInPixels(),
       
  2399                             AknLayoutScalable_Avkon::main_midp_pane().LayoutLine());
       
  2400 #endif // RD_JAVA_S60_RELEASE_9_2
       
  2401 
       
  2402     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
  2403     iMidpFormRect.LayoutRect(mainMidpPane.Rect(),
       
  2404                              AknLayoutScalable_Avkon::midp_form_pane(variety).LayoutLine());
       
  2405 
       
  2406     TAknLayoutRect listForm2MidpPane;
       
  2407     listForm2MidpPane.LayoutRect(iMidpFormRect.Rect(),
       
  2408                                  AknLayoutScalable_Avkon::list_form2_midp_pane().LayoutLine());
       
  2409 
       
  2410     iFormRect.LayoutRect(listForm2MidpPane.Rect(),
       
  2411                          AknLayoutScalable_Avkon::form2_midp_field_pane().LayoutLine());
       
  2412 
       
  2413     iInnerWidth = iFormRect.Rect().Width();
       
  2414 
       
  2415     iInnerHeight = iFormRect.Rect().Height();
       
  2416     iFormHeight = iMidpFormRect.Rect().Height();
       
  2417 }
       
  2418 
       
  2419 MMIDItem* CMIDForm::CurrentItem() const
       
  2420 {
       
  2421     return iFocused == KErrNotFound ? NULL : iItems[iFocused];
       
  2422 }
       
  2423 
       
  2424 CMIDItem& CMIDForm::Item(TInt aIndex) const
       
  2425 {
       
  2426     MMIDItem* item = iItems[aIndex];
       
  2427     return ControlItem(item->Type());
       
  2428 }
       
  2429 
       
  2430 CMIDControlItem& CMIDForm::ControlItem(TInt aIndex) const
       
  2431 {
       
  2432     return ControlItem(iItems[aIndex]);
       
  2433 }
       
  2434 
       
  2435 CMIDControlItem& CMIDForm::ControlItem(MMIDItem* aMMidItem)
       
  2436 {
       
  2437     CMIDControlItem* base = NULL;
       
  2438     TInt type  = (TInt) aMMidItem->Type();
       
  2439     switch (type)
       
  2440     {
       
  2441     case MMIDComponent::EImageItem:
       
  2442         base = static_cast<CMIDImageItem*>(aMMidItem);
       
  2443         break;
       
  2444     case MMIDComponent::EStringItem:
       
  2445         base = static_cast<CMIDStringItem*>(aMMidItem);
       
  2446         break;
       
  2447     case MMIDComponent::ESpacer:
       
  2448         base = static_cast<CMIDSpacer*>(aMMidItem);
       
  2449         break;
       
  2450     case MMIDComponent::EGauge:
       
  2451         base = static_cast<CMIDGaugeItem*>(aMMidItem);
       
  2452         break;
       
  2453     case MMIDComponent::ETextField:
       
  2454         base = static_cast<CMIDTextFieldItem*>(aMMidItem);
       
  2455         break;
       
  2456     case MMIDComponent::EChoiceGroup:
       
  2457         base = static_cast<CMIDChoiceGroupItem*>(aMMidItem);
       
  2458         break;
       
  2459     case MMIDComponent::EDateField:
       
  2460         base = static_cast<CMIDDateFieldItem*>(aMMidItem);
       
  2461         break;
       
  2462     case MMIDComponent::ECustomItem:
       
  2463         base = static_cast<CMIDCustomItem*>(aMMidItem);
       
  2464         break;
       
  2465     default:
       
  2466         ASSERT(EFalse);
       
  2467         break;
       
  2468     }
       
  2469 
       
  2470     return *base;
       
  2471 }
       
  2472 
       
  2473 TInt CMIDForm::Index(CCoeControl* aControl) const
       
  2474 {
       
  2475     TInt itemCount = iItems.Count();
       
  2476     for (TInt i=0; i < itemCount; i++)
       
  2477     {
       
  2478         CCoeControl* control = static_cast<CCoeControl*>(&(ControlItem(i)));
       
  2479         if (control == aControl)
       
  2480         {
       
  2481             return i;
       
  2482         }
       
  2483     }
       
  2484     return KErrNotFound;
       
  2485 }
       
  2486 
       
  2487 TInt CMIDForm::FormWidth()
       
  2488 {
       
  2489     return CMIDForm::StaticFormRect().Width();
       
  2490 }
       
  2491 
       
  2492 /*static*/ TRect CMIDForm::StaticFormRect()
       
  2493 {
       
  2494     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
  2495     TRect mainPaneRect;
       
  2496 
       
  2497 #ifdef RD_JAVA_S60_RELEASE_9_2
       
  2498     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPaneRect);
       
  2499 #else
       
  2500     mainPaneRect = iAvkonAppUi->ApplicationRect();
       
  2501 #endif // RD_JAVA_S60_RELEASE_9_2
       
  2502 
       
  2503     TAknLayoutRect mainMidpPane;
       
  2504     mainMidpPane.LayoutRect(mainPaneRect,
       
  2505                             AknLayoutScalable_Avkon::main_midp_pane().LayoutLine());
       
  2506 
       
  2507     TAknLayoutRect midpFormRect;
       
  2508     midpFormRect.LayoutRect(mainMidpPane.Rect(),
       
  2509                             AknLayoutScalable_Avkon::midp_form_pane(variety).LayoutLine());
       
  2510 
       
  2511     TAknLayoutRect listForm2MidpPane;
       
  2512     listForm2MidpPane.LayoutRect(midpFormRect.Rect(),
       
  2513                                  AknLayoutScalable_Avkon::list_form2_midp_pane().LayoutLine());
       
  2514 
       
  2515     TAknLayoutRect formRect;
       
  2516     formRect.LayoutRect(listForm2MidpPane.Rect(),
       
  2517                         AknLayoutScalable_Avkon::form2_midp_field_pane().LayoutLine());
       
  2518 
       
  2519     return formRect.Rect();
       
  2520 }
       
  2521 
       
  2522 
       
  2523 TBool CMIDForm::IsCurrentItem(CMIDItem* aItem) const
       
  2524 {
       
  2525     return (iFocused != KErrNotFound) &&
       
  2526            (iFocused == Index(static_cast<CCoeControl*>(aItem)));
       
  2527 }
       
  2528 
       
  2529 
       
  2530 void CMIDForm::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
       
  2531 {
       
  2532     switch (aEventType)
       
  2533     {
       
  2534     case MCoeControlObserver::EEventStateChanged:
       
  2535     {
       
  2536         TInt index = KErrNotFound;
       
  2537         User::LeaveIfError(index = Index(aControl));
       
  2538         MMIDComponent::TType type = iItems[index]->Type();
       
  2539         if (type == EStringItem || type == EImageItem || type == ECustomItem)
       
  2540         {
       
  2541             // These don't change state in the MIDP sense, so it must be a button
       
  2542             // press so we need to post a default command event, if there is one
       
  2543 
       
  2544             // msk: this is needed if msk is not enabled
       
  2545             PostDefaultItemCommandEvent(index);
       
  2546         }
       
  2547         else
       
  2548         {
       
  2549             iEnv->PostJavaEvent(*this,EDisplayable,index);
       
  2550         }
       
  2551     }
       
  2552     break;
       
  2553     case MCoeControlObserver::EEventRequestFocus:
       
  2554         if (!aControl->IsNonFocusing())
       
  2555         {
       
  2556             SetFocusedItem(Index(aControl));
       
  2557         }
       
  2558         break;
       
  2559     default:
       
  2560         break;
       
  2561     }
       
  2562 }
       
  2563 
       
  2564 
       
  2565 /*
       
  2566  * Pointer events from different Items are are routed via this function to private HandleControlEventL.
       
  2567  * Focus is not accepted if Item is not focusable.
       
  2568  */
       
  2569 void CMIDForm::HandleTouchControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
       
  2570 {
       
  2571 
       
  2572     CMIDControlItem& ci = ControlItem(Index(aControl));
       
  2573     if (ci.IsSelectable())
       
  2574     {
       
  2575         HandleControlEventL(aControl, aEventType);
       
  2576     }
       
  2577 }
       
  2578 
       
  2579 
       
  2580 void CMIDForm::TimerExpired()
       
  2581 {
       
  2582     TrappedLayoutAndDraw();
       
  2583 }
       
  2584 
       
  2585 /*
       
  2586  * Called whenever something's happened which could change the visibility of an item
       
  2587  * controls. e.g. when made current, when update Items, when scroll.
       
  2588  */
       
  2589 void CMIDForm::HandleItemVisibilityChange()
       
  2590 {
       
  2591 
       
  2592     // CUSTOM ITEM ONLY
       
  2593     TInt count = iItems.Count();
       
  2594     for (TInt i=0; i<count; i++)
       
  2595     {
       
  2596         if (iItems[i]->Type() == MMIDComponent::ECustomItem)
       
  2597         {
       
  2598             // this will get the CustomItem's FocusChanged method called which will cause
       
  2599             // some visibility events to be sent
       
  2600             CMIDControlItem& ci = ControlItem(i);
       
  2601             ((CMIDCustomItem&) ci).HandleVisibilityChange();
       
  2602         }
       
  2603     }
       
  2604     // END CUSTOM ITEM
       
  2605 
       
  2606 }
       
  2607 
       
  2608 /** Handles an item size change event. This is called by within the plugin, not by java
       
  2609 side unlike RefreshItemL(TInt).
       
  2610 
       
  2611 First of all we check if there is a layout pending operation.
       
  2612 If there is one we don't do anything. This is because this method is called during
       
  2613 control creation when items are inserted in the form. However, it is also called later
       
  2614 on when the control is already displaying and its size changes. During control creation
       
  2615 we should do a delayed layout (for performance reasons) wheras if we delay layout in the
       
  2616 second case we get an unpleasant redraw effect because the item control usually draws
       
  2617 immediately. So we should try and layout+draw immediately in the second case.
       
  2618 We distinguish between the two cases by checking if there is a layout
       
  2619 operation (which is requested by InsertItemL()). Also, in the second case, instead of
       
  2620 doing a full LayoutAndDrawL() we only resize elements already assigned to rows and
       
  2621 update the scroll bars. And then we draw. This is a bit more efficient than recreating
       
  2622 the rows. Because this method is only called by items that fill an entire row anyway,
       
  2623 we shouln't need to re-create rows.
       
  2624 */
       
  2625 void CMIDForm::RefreshItemL(MMIDItem* aItem)
       
  2626 {
       
  2627     TInt index = iItems.Find(aItem);
       
  2628 
       
  2629     if (!LayoutPending() && index != KErrNotFound)
       
  2630     {
       
  2631         SizeItemsInFormRowsL();
       
  2632         SetRowExtentsWithRespectToScrolledLocation();
       
  2633 
       
  2634         if ((aItem->Type() == MMIDComponent::ETextField) && (index == iFocused))
       
  2635         {
       
  2636             CMIDTextFieldItem* tf = static_cast<CMIDTextFieldItem*>(aItem);
       
  2637             TPoint p;
       
  2638             TBool success = tf->GetCursorPosL(p);
       
  2639             if (success)
       
  2640             {
       
  2641                 if (p.iY < 0)
       
  2642                 {
       
  2643                     RawScrollRelative(p.iY + 10);
       
  2644                 }
       
  2645                 else if (p.iY > Height())
       
  2646                 {
       
  2647                     RawScrollRelative(Height() - (p.iY + 10));
       
  2648                 }
       
  2649             }
       
  2650         }
       
  2651         RawScrollFinalize(ETrue);
       
  2652     }
       
  2653 }
       
  2654 
       
  2655 /**
       
  2656  * If the item at aIndex has a default command set for it, then this will be invoked and True
       
  2657  * will be returned. False if a command has not been posted
       
  2658  */
       
  2659 // msk: this method is needed if msk is not enabled
       
  2660 TBool CMIDForm::PostDefaultItemCommandEvent(TInt aIndex)
       
  2661 {
       
  2662     if (aIndex != KErrNotFound)
       
  2663     {
       
  2664         CMIDCommand* defaultCommand = ControlItem(iItems[aIndex]).DefaultCommand();
       
  2665         if (defaultCommand)
       
  2666         {
       
  2667             iEnv->PostJavaEvent(*iItems[aIndex],EItem,ECommand,defaultCommand->Id());
       
  2668             return ETrue;
       
  2669         }
       
  2670     }
       
  2671     return EFalse;
       
  2672 }
       
  2673 
       
  2674 void CMIDForm::AddItemToFormL(CMIDControlItem& aControlItem)
       
  2675 {
       
  2676     aControlItem.SetForm(this);
       
  2677     aControlItem.SetContainerWindowL(*this);
       
  2678     aControlItem.ItemAddedToFormL();
       
  2679 }
       
  2680 
       
  2681 void CMIDForm::RemoveItemFromForm(CMIDControlItem& aControlItem)
       
  2682 {
       
  2683     aControlItem.MakeVisible(EFalse);
       
  2684     aControlItem.SetPosition(TPoint(-Width(), 0));
       
  2685     // Item is not allowed to access container window from now.
       
  2686     aControlItem.ItemRemovedFromForm();
       
  2687     aControlItem.SetForm(NULL);
       
  2688 }
       
  2689 
       
  2690 void CMIDForm::UpdateItemCommands(CMIDCommandList* aCommandList, CMIDCommand* aMSKCommand)
       
  2691 {
       
  2692     iDisplayable.SetItemCommandList(aCommandList, aMSKCommand);
       
  2693 }
       
  2694 
       
  2695 // msk: this method is needed if msk is not enabled
       
  2696 TBool CMIDForm::DoDefaultCommand()
       
  2697 {
       
  2698     if (iFocused != KErrNotFound)
       
  2699     {
       
  2700         CMIDControlItem& ci = ControlItem(iFocused);
       
  2701 
       
  2702         CMIDCommand* defaultCommand = ci.DefaultCommand();
       
  2703         if (defaultCommand)
       
  2704         {
       
  2705             iEnv->PostJavaEvent(*(iItems[iFocused]), EItem, ECommand, defaultCommand->Id());
       
  2706             return ETrue;
       
  2707         }
       
  2708     }
       
  2709 
       
  2710     return EFalse;
       
  2711 }
       
  2712 
       
  2713 
       
  2714 TInt CMIDForm::Row(const CMIDControlItem& aItem) const
       
  2715 {
       
  2716     CMIDFormRow* rowPtr = NULL;
       
  2717     return Row(aItem, rowPtr);
       
  2718 }
       
  2719 
       
  2720 TInt CMIDForm::Row(const CMIDControlItem& aItem, CMIDFormRow*& aRowPtr) const
       
  2721 {
       
  2722     aRowPtr = NULL;
       
  2723     TInt rowCount = iRows.Count();
       
  2724     for (TInt i=0; i < rowCount; i++)
       
  2725     {
       
  2726         TInt idx = iRows[i]->Find(&aItem);
       
  2727         if (idx != KErrNotFound)
       
  2728         {
       
  2729             aRowPtr = iRows[i];
       
  2730             return i;
       
  2731         }
       
  2732     }
       
  2733     return KErrNotFound;
       
  2734 }
       
  2735 
       
  2736 CMIDForm::TDirection CMIDForm::ConvertKeyToDirection(TUint aCode)
       
  2737 {
       
  2738     switch (aCode)
       
  2739     {
       
  2740     case EKeyDownArrow:
       
  2741         return EDown;
       
  2742     case EKeyUpArrow:
       
  2743         return EUp;
       
  2744     case EKeyLeftArrow:
       
  2745         return ELeft;
       
  2746     case EKeyRightArrow:
       
  2747         return ERight;
       
  2748     default:
       
  2749         return ENone;
       
  2750     }
       
  2751 }
       
  2752 
       
  2753 // returns the index of a CMIDControlItem in the iItems array. If the
       
  2754 // CMIDControlItem is a CMIDLabelContainerItem, then the index
       
  2755 // of the stringItem associated with it is returned.
       
  2756 TInt CMIDForm::ItemIndex(CMIDControlItem& aItem)
       
  2757 {
       
  2758     MMIDItem* item = aItem.iMMidItem;
       
  2759 
       
  2760     TInt idx = 0;
       
  2761     TInt itemCount = iItems.Count();
       
  2762     while (idx < itemCount)
       
  2763     {
       
  2764         if (iItems[idx] == item)
       
  2765         {
       
  2766             return idx;
       
  2767         }
       
  2768         idx++;
       
  2769     }
       
  2770 
       
  2771     // OK, so we didn't find it. Maybe it is a CMIDLabelContainerItem
       
  2772     if (IsLabelContainerItem(aItem))
       
  2773     {
       
  2774         CMIDLabelContainerItem* usil = static_cast<CMIDLabelContainerItem*>(&aItem);
       
  2775         return ItemIndex(usil->StringItem());
       
  2776     }
       
  2777 
       
  2778     return KErrNotFound;
       
  2779 }
       
  2780 
       
  2781 // this method will return the index of the row ABOVE the indicated unconstrained string item
       
  2782 // if the string item was on the top row then KErrNotFound is returned, also if the string item
       
  2783 // could not be found or was not an unconstrained string item.
       
  2784 TInt CMIDForm::FirstRowAboveUnconstrainedStringItem(CMIDStringItem& aStringItem) const
       
  2785 {
       
  2786     TInt idx = FirstRowOfUnconstrainedStringItem(aStringItem);
       
  2787     return (idx == KErrNotFound) ? KErrNotFound : idx - 1;
       
  2788 }
       
  2789 
       
  2790 // returns the index of the first row of an unconstrained string item.
       
  2791 // Returns KErrNotFound if the string item could not be found (or if it was not
       
  2792 // an unconstrained string item).
       
  2793 TInt CMIDForm::FirstRowOfUnconstrainedStringItem(CMIDStringItem& aStringItem) const
       
  2794 {
       
  2795     TInt idx = -1;
       
  2796     TInt rowCount = iRows.Count();
       
  2797     while (++idx < rowCount)
       
  2798     {
       
  2799         CMIDFormRow* row = iRows[idx];
       
  2800         TInt innerIdx = -1;
       
  2801         while (++innerIdx < row->NumItems())
       
  2802         {
       
  2803             CMIDControlItem* ci = row->Item(innerIdx);
       
  2804             if (IsLabelContainerItem(*ci))
       
  2805             {
       
  2806                 CMIDLabelContainerItem* ucsi = static_cast<CMIDLabelContainerItem*>(ci);
       
  2807                 if (&(ucsi->StringItem()) == &aStringItem)
       
  2808                 {
       
  2809                     return idx;
       
  2810                 }
       
  2811             }
       
  2812         }
       
  2813     }
       
  2814     return KErrNotFound;
       
  2815 }
       
  2816 
       
  2817 TInt CMIDForm::FirstRowBelowUnconstrainedStringItem(CMIDStringItem& aStringItem) const
       
  2818 {
       
  2819     TInt idx = iRows.Count();
       
  2820     TInt rowCount = iRows.Count();
       
  2821     while (--idx < rowCount)
       
  2822     {
       
  2823         CMIDFormRow* row = iRows[idx];
       
  2824         TInt innerIdx = -1;
       
  2825         while (++innerIdx < row->NumItems())
       
  2826         {
       
  2827             CMIDControlItem* ci = row->Item(innerIdx);
       
  2828             if (IsLabelContainerItem(*ci))
       
  2829             {
       
  2830                 CMIDLabelContainerItem* ucsi = static_cast<CMIDLabelContainerItem*>(ci);
       
  2831                 if (&(ucsi->StringItem()) == &aStringItem)
       
  2832                 {
       
  2833                     return ((idx + 1) >= rowCount) ? KErrNotFound : idx + 1;
       
  2834                 }
       
  2835             }
       
  2836         }
       
  2837     }
       
  2838     return KErrNotFound;
       
  2839 }
       
  2840 
       
  2841 TInt CMIDForm::FirstFocusableItemBeforeStartOfUnconstrainedStringItemIdx(CMIDStringItem& aStringItem)
       
  2842 {
       
  2843     TInt rowIdx = FirstRowOfUnconstrainedStringItem(aStringItem);
       
  2844     if (rowIdx != KErrNotFound)
       
  2845     {
       
  2846         CMIDFormRow* row = iRows[rowIdx];
       
  2847         TInt idxOnRow = row->NumItems();
       
  2848         while (--idxOnRow >= 0)  // search backward along the row for the unconstrained string item
       
  2849             // we probably could assume it is the last element
       
  2850         {
       
  2851             CMIDControlItem* ci = row->Item(idxOnRow);
       
  2852             if (IsLabelContainerItem(*ci))
       
  2853             {
       
  2854                 CMIDLabelContainerItem* usil = static_cast<CMIDLabelContainerItem*>(ci);
       
  2855                 CMIDStringItem* si = &(usil->StringItem());
       
  2856                 if (si == &aStringItem)
       
  2857                 {
       
  2858                     break;
       
  2859                 }
       
  2860             }
       
  2861         }
       
  2862         if (idxOnRow > 0)
       
  2863         {
       
  2864             // there are some items on the row before the start of the unconstrained string item
       
  2865             while (--idxOnRow >= 0)  // search backward along the row for the first focusable item
       
  2866             {
       
  2867                 CMIDControlItem* ci = row->Item(idxOnRow);
       
  2868                 if (ci->IsSelectable())
       
  2869                 {
       
  2870                     return ItemIndex(*ci);
       
  2871                 }
       
  2872             }
       
  2873         }
       
  2874     }
       
  2875     return KErrNotFound;
       
  2876 }
       
  2877 
       
  2878 TInt CMIDForm::FirstFocusableItemOnLastLineOfUnconstrainedStringItemIdx(CMIDStringItem& aStringItem)
       
  2879 {
       
  2880     TInt rowIdx = FirstRowBelowUnconstrainedStringItem(aStringItem) - 1;
       
  2881 
       
  2882     if (rowIdx == -2)
       
  2883     {
       
  2884         rowIdx = iRows.Count() -1;
       
  2885     }
       
  2886 
       
  2887     if (rowIdx > KErrNotFound)  // if FirstRowBelowUnconstrainedStringItem returned KErrNotFound then we have -2 so check with '>'
       
  2888     {
       
  2889         CMIDFormRow* row = iRows[rowIdx];
       
  2890         TInt idxOnRow = -1;
       
  2891 
       
  2892         TBool found = EFalse;
       
  2893         while (++idxOnRow < row->NumItems())
       
  2894         {
       
  2895             CMIDControlItem* ci = row->Item(idxOnRow);
       
  2896 
       
  2897             if (ControlBelongsToSameUnconstrainedItem(ci,aStringItem))
       
  2898             {//ok we found our item, if the next one is selectable we return
       
  2899                 found = ETrue;
       
  2900             }
       
  2901             else if (found && ci->IsSelectable())
       
  2902             {
       
  2903                 return ItemIndex(*ci);
       
  2904             }
       
  2905         }
       
  2906     }
       
  2907     return KErrNotFound;
       
  2908 }
       
  2909 
       
  2910 /** Return true if aCi belongs to the same unconstrained string item (aStringItem) */
       
  2911 TBool CMIDForm::ControlBelongsToSameUnconstrainedItem(CMIDControlItem* aCi, CMIDStringItem& aStringItem) const
       
  2912 {
       
  2913     if (IsLabelContainerItem(*aCi))
       
  2914     {
       
  2915         CMIDLabelContainerItem* usil = static_cast<CMIDLabelContainerItem*>(aCi);
       
  2916         if (&(usil->StringItem()) == &aStringItem)
       
  2917         {
       
  2918             return ETrue;
       
  2919         }
       
  2920     }
       
  2921 
       
  2922     return EFalse;
       
  2923 }
       
  2924 
       
  2925 /** */
       
  2926 void CMIDForm::RemoveDeletedItem(CMIDControlItem& aItem)
       
  2927 {
       
  2928     iFocused = KErrNotFound;
       
  2929     TInt i=-1;
       
  2930     TInt rowCount = iRows.Count();
       
  2931     while (++i < rowCount)
       
  2932     {
       
  2933         CMIDFormRow* row = iRows[i];
       
  2934         if (row->RemoveItemIfExists(aItem))
       
  2935         {
       
  2936             break;
       
  2937         }
       
  2938     }
       
  2939 
       
  2940     i = -1;
       
  2941     TInt itemCount = iItems.Count();
       
  2942     while (++i < itemCount)
       
  2943     {
       
  2944         if (aItem.iMMidItem)
       
  2945         {
       
  2946             if (aItem.iMMidItem == iItems[i])
       
  2947             {
       
  2948                 iItems.Remove(i);
       
  2949                 break;
       
  2950             }
       
  2951         }
       
  2952     }
       
  2953 
       
  2954 }
       
  2955 
       
  2956 
       
  2957 /////////////////////////////////////////////////////////////////////////////////////////
       
  2958 // new layout methods
       
  2959 /////////////////////////////////////////////////////////////////////////////////////////
       
  2960 
       
  2961 // does the layout for the entire form
       
  2962 void CMIDForm::LayoutFormL()
       
  2963 {
       
  2964     DEBUG("CMIDForm::LayoutFormL");
       
  2965 
       
  2966     if (LayoutPending())
       
  2967     {
       
  2968         iLayoutRequestTime = -1;
       
  2969         iLayoutTimer->Cancel();
       
  2970     }
       
  2971 
       
  2972     TReal prevHeight = HeightOfAllItems() - Height();
       
  2973     TInt prevFocusedYPos = 0; // by default it is on top of screen
       
  2974     TInt focusedItem = iFocused;
       
  2975 
       
  2976     if (focusedItem != KErrNotFound)
       
  2977     {
       
  2978         TRect rect = GetControlRect(focusedItem);
       
  2979         prevFocusedYPos    = rect.iTl.iY;
       
  2980     }
       
  2981 
       
  2982 
       
  2983     // scroll bar layouting
       
  2984     AknLayoutUtils::LayoutVerticalScrollBar(iSBFrame, Rect(),
       
  2985                                             AknLayoutScalable_Avkon::scroll_pane_cp51().LayoutLine());
       
  2986     ResetItemsPreferredSizes();
       
  2987 
       
  2988     // this prevents items from calling layout recursively
       
  2989     SetItemsFormPointersToVal(NULL);
       
  2990 
       
  2991     AssignItemsToRowsL();
       
  2992     SizeItemsInFormRowsL();
       
  2993 
       
  2994     SetItemsFormPointersToVal(this);
       
  2995 
       
  2996     SetRowExtentsWithRespectToScrolledLocation();
       
  2997 
       
  2998     TReal newHeight = HeightOfAllItems() - Height();
       
  2999 
       
  3000     if (newHeight != prevHeight)
       
  3001     {
       
  3002         // layout has changed significantly, but we need to keep focused component scrolled so that
       
  3003         // user sees it at the same level in viewport
       
  3004         TInt newFocusedYPos = 0;
       
  3005         if (focusedItem != KErrNotFound)
       
  3006         {
       
  3007             TRect rect = GetControlRect(focusedItem);
       
  3008             newFocusedYPos    = rect.iTl.iY;
       
  3009             TInt delta = prevFocusedYPos - newFocusedYPos;
       
  3010             if (iScroll != 0)
       
  3011             {
       
  3012                 // correct only if not on top of window
       
  3013                 ScrollRelative(delta);
       
  3014             }
       
  3015         }
       
  3016         else
       
  3017         {
       
  3018             if (newHeight < prevHeight)
       
  3019             {
       
  3020                 // no focused item, just try to keep same component visible
       
  3021                 iScroll  = newHeight > 0 ? ((TReal) iScroll * (newHeight / prevHeight)) : 0;
       
  3022             }
       
  3023         }
       
  3024 
       
  3025         SetRowExtentsWithRespectToScrolledLocation();
       
  3026     }
       
  3027 }
       
  3028 
       
  3029 void CMIDForm::ResetItemsPreferredSizes()
       
  3030 {
       
  3031     TInt itemCount = iItems.Count();
       
  3032     for (TInt i=0; i < itemCount; i++)
       
  3033     {
       
  3034         CMIDControlItem& ci = ControlItem(i);
       
  3035         ci.ResetPreferredSize();
       
  3036     }
       
  3037 }
       
  3038 
       
  3039 void CMIDForm::SetItemsFormPointersToVal(CMIDForm* aVal)
       
  3040 {
       
  3041     TInt itemCount = iItems.Count();
       
  3042     for (TInt i=0; i < itemCount; i++)
       
  3043     {
       
  3044         CMIDControlItem& ci = ControlItem(i);
       
  3045         ci.SetForm(aVal);
       
  3046     }
       
  3047 }
       
  3048 
       
  3049 /** If an items preferred size is zero
       
  3050 we shouldn't add it to the form row and so we skip it */
       
  3051 TBool CMIDForm::SkipNullItem(TInt aIndex)
       
  3052 {
       
  3053     CMIDControlItem& ci = ControlItem(iItems[aIndex]);
       
  3054     if (ci.PreferredSize() == TSize(0, 0))
       
  3055     {
       
  3056         if (iFocused == aIndex)
       
  3057         {
       
  3058             SetFocusedItem(KErrNotFound);
       
  3059         }
       
  3060 
       
  3061         return ETrue;
       
  3062     }
       
  3063 
       
  3064     return EFalse;
       
  3065 }
       
  3066 
       
  3067 /**
       
  3068     If the current row index is the same as the row count,
       
  3069     create and append to iRows a new row and store it into
       
  3070     iCurrentRow. Increment the current row index. Also reset
       
  3071     the current alignment.
       
  3072 */
       
  3073 void CMIDForm::CreateNewRowAndSetAsCurrentL()
       
  3074 {
       
  3075     CMIDFormRow* row = CMIDFormRow::NewL(*this);
       
  3076     CleanupStack::PushL(row);
       
  3077 
       
  3078     User::LeaveIfError(iRows.Append(row));
       
  3079     CleanupStack::Pop(row);
       
  3080 
       
  3081     iCurrentRow = row;
       
  3082     iCurrentRow->SetAlignment(iCurrentAlignment);
       
  3083 }
       
  3084 
       
  3085 /** Verify the current alignment and change it if the current row
       
  3086 is empty. If the row is not empty and the item alignement is different
       
  3087 and the item requires a row break, then add a new row. */
       
  3088 void CMIDForm::VerifyRowAlignmentL(TInt aIndex)
       
  3089 {
       
  3090     TInt leftRightMask = MMIDItem::ELeft | MMIDItem::ERight;
       
  3091     CMIDControlItem& ci = ControlItem(iItems[aIndex]);
       
  3092 
       
  3093     if (iCurrentRow->NumItems() == 0)
       
  3094     {
       
  3095         // this is the first item in the row
       
  3096         if (!LayoutDefault(ci))
       
  3097         {
       
  3098             // we take the items alignment for the row
       
  3099             iCurrentAlignment = MMIDItem::TLayout(ci.Layout() & leftRightMask);
       
  3100             iCurrentRow->SetAlignment(iCurrentAlignment);
       
  3101         }
       
  3102     }
       
  3103     else if (!LayoutMatchesCurrentAlignment(ci, iCurrentAlignment))
       
  3104     {
       
  3105         // the new layout doesn't match the current so go to the next row
       
  3106         CreateNewRowAndSetAsCurrentL();
       
  3107         iCurrentAlignment = MMIDItem::TLayout(ci.Layout() & leftRightMask);
       
  3108         iCurrentRow->SetAlignment(iCurrentAlignment);
       
  3109     }
       
  3110 }
       
  3111 
       
  3112 /**
       
  3113      Inserts the specified number of new rows (aNumNewLines). If there is a control
       
  3114     item passed as a parameter it means the lines to be inserted are empty lines
       
  3115     preceeding the control and therefore should have their empty size set to the
       
  3116     size of the control.
       
  3117 
       
  3118      @param aControlItem The control item used to set the size of empty rows.
       
  3119 
       
  3120     @param aNumNewLines    The number of rows to be added, if equal to zero this method does
       
  3121                         nothing
       
  3122  */
       
  3123 void CMIDForm::InsertNewlinesL(TInt aNumNewlines, CMIDControlItem* aControlItem)
       
  3124 {
       
  3125     for (TInt idx = 0; idx < aNumNewlines; idx++)
       
  3126     {
       
  3127         if (aControlItem && aControlItem->LabelControl() && iCurrentRow && iCurrentRow->NumItems() == 0)
       
  3128         {
       
  3129             iCurrentRow->SetEmptyRowSize(TSize(iInnerWidth,aControlItem->OneLineLabelHeight()));
       
  3130         }
       
  3131 
       
  3132         CreateNewRowAndSetAsCurrentL();
       
  3133     }
       
  3134 }
       
  3135 
       
  3136 
       
  3137 /**
       
  3138  * Creates a new string item, using special type CMIDLabelContainerItem.
       
  3139  * This is a special string item which has no label and is added to wrap
       
  3140  * content of a previous string item across several rows.
       
  3141  *
       
  3142  *  @see CMIDLabelContainerItem
       
  3143  */
       
  3144 void CMIDForm::CreateAndAddLabelContainerItemL(CMIDStringItem& aStringItem,
       
  3145         CEikLabel& aLabel, TBool aIsStringItemContent)
       
  3146 {
       
  3147     // Label container items items have an horizontal margin only
       
  3148     // when at the beginning of the row
       
  3149     TBool hasHMargin = (iCurrentRow->NumItems() == 0);
       
  3150 
       
  3151     CMIDLabelContainerItem* usil =
       
  3152         CMIDLabelContainerItem::NewL(aStringItem, aLabel, hasHMargin);
       
  3153 
       
  3154     CleanupStack::PushL(usil);
       
  3155     usil->SetContainerWindowL(*this);
       
  3156     // sets flag for detecting if label container item is created
       
  3157     // from string item label or content
       
  3158     usil->SetIsStringItemContent(aIsStringItemContent);
       
  3159 
       
  3160     iCurrentRow->AppendL(usil);
       
  3161     CleanupStack::Pop(usil);
       
  3162 }
       
  3163 
       
  3164 /**
       
  3165  *  Inserts a CMIDLabelContainerItem for each line in aTextControl.
       
  3166  *
       
  3167  *  @see CreateAndAddLabelContainerItemL()
       
  3168  */
       
  3169 void CMIDForm::InsertContainerItemsL(CMIDStringItem& aStringItem,
       
  3170                                      CMIDItemLabel& aTextControl, TBool aIsStringItemContent)
       
  3171 {
       
  3172     TInt numLines = aTextControl.NumLines();
       
  3173     for (TInt j = 0; j < numLines; j++)
       
  3174     {
       
  3175         CEikLabel* label = aTextControl.LabelAtIdx(j);
       
  3176 
       
  3177         if (label)
       
  3178         {
       
  3179             CGraphicsContext::TTextAlign align = aTextControl.LabelAtIdx(j)->iAlignment.TextAlign();
       
  3180 
       
  3181             // If aLabel aligment is incorrect relayout aLabel
       
  3182             if ((align != CGraphicsContext::ERight &&
       
  3183                     iInitialAlignment == MMIDItem::ERight) ||
       
  3184                     (align != CGraphicsContext::ELeft &&
       
  3185                      iInitialAlignment == MMIDItem::ELeft) ||
       
  3186                     (align != CGraphicsContext::ECenter &&
       
  3187                      iInitialAlignment == MMIDItem::ECenter))
       
  3188             {
       
  3189                 aTextControl.LayoutItemLabel();
       
  3190             }
       
  3191 
       
  3192             // insert every line as a CMIDLabelContainerItem
       
  3193             CreateAndAddLabelContainerItemL(
       
  3194                 aStringItem, *(label), aIsStringItemContent);
       
  3195         }
       
  3196 
       
  3197         if (j != (numLines-1))
       
  3198         { // insert a row break except for the last line
       
  3199             CreateNewRowAndSetAsCurrentL();
       
  3200         }
       
  3201     }
       
  3202 }
       
  3203 
       
  3204 /**
       
  3205     Adds an unconstrained string item to one or more rows. If the item
       
  3206     has a label always insert a line break (new row) before and if it
       
  3207     is followed by constrained item also after the label. Crop the label
       
  3208     to the full line width and insert is as a CMIDLabelContainerItem.
       
  3209 
       
  3210     If the item has no label we can start anywhere in the current row.
       
  3211     Split its content across the remaining width for the first line
       
  3212     and then across the full line width. Insert a CMIDLabelContainerItem
       
  3213     for each line and insert a row break after each CMIDLabelContainerItem
       
  3214     except the last one.
       
  3215 
       
  3216     Item with label can be inserted as default item when one of this
       
  3217     situation occurs:
       
  3218     - it is the last item in form
       
  3219     - following item is constrained
       
  3220     - following item is unconstrained but has a label
       
  3221 
       
  3222     Item without label can be inserted as default item when:
       
  3223     - it is the only item in form
       
  3224     - it is the first item in form and following item is
       
  3225     unconstrained but has a label (it starts in a new row)
       
  3226 
       
  3227     @see CMILabelContainerItem, InsertContainerItemsL(),
       
  3228          CreateNewRowAndSetAsCurrentL(), InsertNewlinesL()
       
  3229 */
       
  3230 void CMIDForm::AddUnconstrainedStringItemL(TInt& aIndex)
       
  3231 {
       
  3232     CMIDStringItem* si = (CMIDStringItem*)iItems[aIndex];
       
  3233 
       
  3234     TInt widthForText = Width();
       
  3235 
       
  3236     // check if next item is unconstrained and has label
       
  3237     TBool nextUnconstrainedHasLabel(EFalse);
       
  3238     if (aIndex < iItems.Count()-1 && ItemIsUnconstrained(aIndex + 1))
       
  3239     {
       
  3240         CMIDStringItem* nextItem = (CMIDStringItem*)iItems[aIndex+1];
       
  3241         if (nextItem->LabelControl() &&
       
  3242                 (nextItem->LabelControl()->Text()->Length() > 0))
       
  3243         {
       
  3244             nextUnconstrainedHasLabel = ETrue;
       
  3245         }
       
  3246     }
       
  3247 
       
  3248     if (si->LabelControl() && (si->LabelControl()->Text()->Length() > 0))
       
  3249     {//item has a label - it should be placed in a new row
       
  3250         if (iCurrentRow->NumItems() > 0)
       
  3251         {
       
  3252             CreateNewRowAndSetAsCurrentL();
       
  3253         }
       
  3254 
       
  3255         // If the item is last or next item is constrained or next item
       
  3256         // is unconstrained but has a label (it will be placed in a new row)
       
  3257         // this item is placed as default item.
       
  3258         if ((aIndex == iItems.Count()-1) || !ItemIsUnconstrained(aIndex + 1)
       
  3259                 || nextUnconstrainedHasLabel)
       
  3260         {
       
  3261             AddDefaultItemL(aIndex);
       
  3262             return;
       
  3263         }
       
  3264 
       
  3265         // otherwise place the label in one row and then insert the text
       
  3266         si->LabelControl()->SetWidthL(widthForText);
       
  3267         // label of string item is inserted as label container item
       
  3268         // EFalse identifies that label container item is created from string item label
       
  3269         InsertContainerItemsL(*si, *(si->LabelControl()), EFalse);
       
  3270         // string items is divided to label container items due to concatenation of contents
       
  3271         // contained in adjacent string items
       
  3272         si->SetIsDivided(ETrue);
       
  3273         CreateNewRowAndSetAsCurrentL();
       
  3274     }
       
  3275     else
       
  3276     { // item has no label
       
  3277 
       
  3278         // If the item is the only item in form or it is the first item in form
       
  3279         // and the next item is unconstrained with label (it starts at a new row)
       
  3280         // this item is placed as default item
       
  3281         if ((iItems.Count() == 1) || (aIndex == 0 && nextUnconstrainedHasLabel))
       
  3282         {
       
  3283             AddDefaultItemL(aIndex);
       
  3284             return;
       
  3285         }
       
  3286     }
       
  3287 
       
  3288     // this is either the remaining width on the current row or the full
       
  3289     // line width if we are on a new row
       
  3290     TInt remainingLineWidth = widthForText - iCurrentRow->CurrentWidth();
       
  3291 
       
  3292     if ((remainingLineWidth < si->StringContentControl()->FirstWordWidth())
       
  3293             && (iCurrentRow->NumItems() != 0))
       
  3294     { // if not even one word fits then go to the next line unless
       
  3295         // we are already on a new line
       
  3296         CreateNewRowAndSetAsCurrentL();
       
  3297         remainingLineWidth = widthForText;
       
  3298     }
       
  3299 
       
  3300     // wrap the content to the remaining width for the first line and to
       
  3301     // the full width for any other line
       
  3302     si->StringContentControl()->SetVariableWidthL(remainingLineWidth, widthForText);
       
  3303     // content of string item is inserted as label container item
       
  3304     // ETrue identifies that label container item is created from string item content
       
  3305     InsertContainerItemsL(*si, *(si->StringContentControl()), ETrue);
       
  3306 }
       
  3307 
       
  3308 /**
       
  3309  * Adds a standard case item to the current row. It verifies if a new
       
  3310  * row should be added and adds one if so. Then it appends the item
       
  3311  * to the current row.
       
  3312  *
       
  3313  * @see CMIDControlItem, OkToMoveToNextRow()
       
  3314  */
       
  3315 void CMIDForm::AddDefaultItemL(TInt& aIndex)
       
  3316 {
       
  3317     CMIDControlItem& ci = ControlItem(iItems[aIndex]);
       
  3318 
       
  3319     TSize itemSize = LayoutShrink(ci) ? ci.MinimumSize() : ci.PreferredSize();
       
  3320     ci.SetSizeQuiet(itemSize);
       
  3321 
       
  3322     if (OkToMoveToNextRow(itemSize))
       
  3323     {
       
  3324         CreateNewRowAndSetAsCurrentL();
       
  3325     }
       
  3326 
       
  3327     iCurrentRow->AppendL(&ci);
       
  3328 }
       
  3329 
       
  3330 /**
       
  3331     Return true if the given size does not fit into the current
       
  3332     row and the row is not empty and the size is not bigger than
       
  3333     an empty row.
       
  3334 */
       
  3335 TBool CMIDForm::OkToMoveToNextRow(const TSize& aItemSize) const
       
  3336 {
       
  3337     return ((iCurrentRow->CurrentWidth() + aItemSize.iWidth) > iInnerWidth) &&
       
  3338            !((aItemSize.iWidth > iInnerWidth) && (iCurrentRow->NumItems() == 0));
       
  3339 }
       
  3340 
       
  3341 /**
       
  3342     Assigns the items to the rows, which are re-created.
       
  3343 */
       
  3344 void CMIDForm::AssignItemsToRowsL()
       
  3345 {
       
  3346     DeleteRows();
       
  3347 
       
  3348     //reset current alignment
       
  3349     iCurrentAlignment = InitialAlignment();
       
  3350 
       
  3351     //Create a row, the form must have at least an empty row
       
  3352     CreateNewRowAndSetAsCurrentL();
       
  3353 
       
  3354     for (TInt i = 0;  i < iItems.Count(); i++)
       
  3355     {
       
  3356         if (SkipNullItem(i))
       
  3357         { //zero size items are ignored
       
  3358             continue;
       
  3359         }
       
  3360 
       
  3361         // if the current alignment changes we may need to change row
       
  3362         VerifyRowAlignmentL(i);
       
  3363 
       
  3364         CMIDControlItem& ci = ControlItem(iItems[i]);
       
  3365 
       
  3366         // add any extra rows before the current item if needed
       
  3367         InsertNewlinesL(NumNewLinesBefore(ci), &ci);
       
  3368 
       
  3369         if (ItemIsUnconstrained(i))
       
  3370         { // unconstrained string items are processed specially
       
  3371             AddUnconstrainedStringItemL(i);
       
  3372         }
       
  3373         else
       
  3374         { // any other item is processed in here
       
  3375             AddDefaultItemL(i);
       
  3376         }
       
  3377 
       
  3378         // add any additional row breaks if needed
       
  3379         InsertNewlinesL(NumNewLinesAfter(ci), &ci);
       
  3380     }
       
  3381 }
       
  3382 
       
  3383 /** Return true if the item is an unconstrained string item, false otherwise */
       
  3384 TBool CMIDForm::ItemIsUnconstrained(TInt aIndex) const
       
  3385 {
       
  3386     if (aIndex >= 0 && aIndex < iItems.Count())
       
  3387     {
       
  3388         CMIDControlItem& ci = ControlItem(iItems[aIndex]);
       
  3389         return (IsStringItem(ci) && ((CMIDStringItem*)&ci)->IsUnconstrainedStringItem());
       
  3390     }
       
  3391 
       
  3392     return EFalse;
       
  3393 }
       
  3394 
       
  3395 TBool CMIDForm::LayoutMatchesCurrentAlignment(CMIDControlItem& aControlItem,
       
  3396         MMIDItem::TLayout aCurrentAlignment)
       
  3397 {
       
  3398     TInt leftRightMask = MMIDItem::ELeft | MMIDItem::ERight;
       
  3399 
       
  3400     return ((aControlItem.Layout() & leftRightMask) == MMIDItem::EDefault) ||
       
  3401            ((aControlItem.Layout() & leftRightMask) == aCurrentAlignment);
       
  3402 }
       
  3403 
       
  3404 TBool CMIDForm::LayoutDefault(CMIDControlItem& aControlItem)
       
  3405 {
       
  3406     TInt leftRightMask = MMIDItem::ELeft | MMIDItem::ERight;
       
  3407 
       
  3408     return ((aControlItem.Layout() & leftRightMask) == MMIDItem::EDefault);
       
  3409 }
       
  3410 
       
  3411 TBool CMIDForm::LayoutNewLineBefore(CMIDControlItem& aControlItem)
       
  3412 {
       
  3413     return (aControlItem.Layout() & MMIDItem::ENewLineBefore);
       
  3414 }
       
  3415 
       
  3416 TBool CMIDForm::LayoutNewLineAfter(CMIDControlItem& aControlItem)
       
  3417 {
       
  3418     return (aControlItem.Layout() & MMIDItem::ENewLineAfter);
       
  3419 }
       
  3420 
       
  3421 /** Return true if the LAYOUT_SHRINK directive has been set. For
       
  3422 string items which have one or both dimensions of the preferred
       
  3423 size set the layout shrink directive is ignored. */
       
  3424 TBool CMIDForm::LayoutShrink(CMIDControlItem& aControlItem)
       
  3425 {
       
  3426     if (IsStringItem(aControlItem))
       
  3427     {
       
  3428         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3429 
       
  3430         if (si->WidthOrHeightSpecified())
       
  3431         {
       
  3432             return EFalse;
       
  3433         }
       
  3434     }
       
  3435 
       
  3436     return (aControlItem.Layout() & MMIDItem::EShrink);
       
  3437 }
       
  3438 
       
  3439 /** Return true if the LAYOUT_EXPAND directive has been set. For
       
  3440 string items which have one or both dimensions of the preferred
       
  3441 size set the layout expand directive is ignored. */
       
  3442 TBool CMIDForm::LayoutExpand(CMIDControlItem& aControlItem)
       
  3443 {
       
  3444     if (IsStringItem(aControlItem))
       
  3445     {
       
  3446         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3447 
       
  3448         if (si->WidthOrHeightSpecified())
       
  3449         {
       
  3450             return EFalse;
       
  3451         }
       
  3452     }
       
  3453 
       
  3454     return (aControlItem.Layout() & MMIDItem::EExpand);
       
  3455 }
       
  3456 
       
  3457 /** Return true if the LAYOUT_VSHIRNK directive has been set. For
       
  3458 string items which have one or both dimensions of the preferred
       
  3459 size set the layout vertical shrink directive is ignored. */
       
  3460 TBool CMIDForm::LayoutVerticalShrink(CMIDControlItem& aControlItem)
       
  3461 {
       
  3462     if (IsStringItem(aControlItem))
       
  3463     {
       
  3464         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3465 
       
  3466         if (si->WidthOrHeightSpecified())
       
  3467         {
       
  3468             return EFalse;
       
  3469         }
       
  3470     }
       
  3471 
       
  3472     return (aControlItem.Layout() & MMIDItem::EVerticalShrink);
       
  3473 }
       
  3474 
       
  3475 /** Return true if the LAYOUT_VEXPAND directive has been set. For
       
  3476 string items which have one or both dimensions of the preferred
       
  3477 size set the layout vertical expand directive is ignored. */
       
  3478 TBool CMIDForm::LayoutVerticalExpand(CMIDControlItem& aControlItem)
       
  3479 {
       
  3480     if (IsStringItem(aControlItem))
       
  3481     {
       
  3482         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3483 
       
  3484         if (si->WidthOrHeightSpecified())
       
  3485         {
       
  3486             return EFalse;
       
  3487         }
       
  3488     }
       
  3489 
       
  3490     return (aControlItem.Layout() & MMIDItem::EVerticalExpand);
       
  3491 }
       
  3492 
       
  3493 TBool CMIDForm::LayoutVerticalCenter(CMIDControlItem& aControlItem)
       
  3494 {
       
  3495     TInt layout = aControlItem.Layout();
       
  3496     layout &= MMIDItem::EVerticalCenter;
       
  3497     return (layout == MMIDItem::EVerticalCenter);
       
  3498 }
       
  3499 
       
  3500 TBool CMIDForm::LayoutBottom(CMIDControlItem& aControlItem)
       
  3501 {
       
  3502     TInt layout = aControlItem.Layout();
       
  3503     layout &= MMIDItem::EVerticalCenter;
       
  3504     return (layout == MMIDItem::EBottom) || (layout == 0);
       
  3505 }
       
  3506 
       
  3507 TBool CMIDForm::IsStringItem(CMIDControlItem& aControlItem)
       
  3508 {
       
  3509     if (!aControlItem.iMMidItem)
       
  3510     {
       
  3511         return EFalse;
       
  3512     }
       
  3513     return (aControlItem.iMMidItem->Type() == MMIDComponent::EStringItem);
       
  3514 }
       
  3515 
       
  3516 TBool CMIDForm::IsStringItemHyperlink(CMIDControlItem& aControlItem)
       
  3517 {
       
  3518     if (!aControlItem.iMMidItem)
       
  3519     {
       
  3520         return EFalse;
       
  3521     }
       
  3522     if (aControlItem.iMMidItem->Type() == MMIDComponent::EStringItem)
       
  3523     {
       
  3524         return (((CMIDStringItem&) aControlItem).Appearance() == MMIDItem::EHyperLink);
       
  3525     }
       
  3526     else
       
  3527     {
       
  3528         return EFalse;
       
  3529     }
       
  3530 }
       
  3531 
       
  3532 TBool CMIDForm::IsStringItemButton(CMIDControlItem& aControlItem)
       
  3533 {
       
  3534     if (!aControlItem.iMMidItem)
       
  3535     {
       
  3536         return EFalse;
       
  3537     }
       
  3538     if (aControlItem.iMMidItem->Type() == MMIDComponent::EStringItem)
       
  3539     {
       
  3540         return (((CMIDStringItem&) aControlItem).Appearance() == MMIDItem::EButton);
       
  3541     }
       
  3542     else
       
  3543     {
       
  3544         return EFalse;
       
  3545     }
       
  3546 }
       
  3547 
       
  3548 TBool CMIDForm::IsCustomItem(CMIDControlItem& aControlItem)
       
  3549 {
       
  3550     if (!aControlItem.iMMidItem)
       
  3551     {
       
  3552         return EFalse;
       
  3553     }
       
  3554     return (aControlItem.iMMidItem->Type() == MMIDComponent::ECustomItem);
       
  3555 }
       
  3556 
       
  3557 TBool CMIDForm::IsGaugeItem(CMIDControlItem& aControlItem)
       
  3558 {
       
  3559     if (!aControlItem.iMMidItem)
       
  3560     {
       
  3561         return EFalse;
       
  3562     }
       
  3563     return (aControlItem.iMMidItem->Type() == MMIDComponent::EGauge);
       
  3564 }
       
  3565 
       
  3566 TBool CMIDForm::IsTextFieldItem(CMIDControlItem& aControlItem)
       
  3567 {
       
  3568     if (!aControlItem.iMMidItem)
       
  3569     {
       
  3570         return EFalse;
       
  3571     }
       
  3572     return (aControlItem.iMMidItem->Type() == MMIDComponent::ETextField);
       
  3573 }
       
  3574 
       
  3575 TBool CMIDForm::IsChoiceGroup(CMIDControlItem& aControlItem)
       
  3576 {
       
  3577     if (!aControlItem.iMMidItem)
       
  3578     {
       
  3579         return EFalse;
       
  3580     }
       
  3581     return (aControlItem.iMMidItem->Type() == MMIDComponent::EChoiceGroup);
       
  3582 }
       
  3583 
       
  3584 TBool CMIDForm::IsPopupChoiceGroup(CMIDControlItem& aControlItem)
       
  3585 {
       
  3586     if (aControlItem.iMMidItem
       
  3587             && aControlItem.iMMidItem->Type() == MMIDComponent::EChoiceGroup)
       
  3588     {
       
  3589         CMIDChoiceGroupItem& cgItem = static_cast<CMIDChoiceGroupItem&>(aControlItem);
       
  3590         CMIDChoiceGroupControl* cgControl =
       
  3591             static_cast<CMIDChoiceGroupControl*>(cgItem.ComponentControl(1));
       
  3592         if (cgControl && cgControl->ChoiceType() == MMIDChoiceGroup::EPopup)
       
  3593         {
       
  3594             return ETrue;
       
  3595         }
       
  3596     }
       
  3597     return EFalse;
       
  3598 }
       
  3599 
       
  3600 TBool CMIDForm::IsDateField(CMIDControlItem& aControlItem)
       
  3601 {
       
  3602     if (!aControlItem.iMMidItem)
       
  3603     {
       
  3604         return EFalse;
       
  3605     }
       
  3606     return (aControlItem.iMMidItem->Type() == MMIDComponent::EDateField);
       
  3607 }
       
  3608 
       
  3609 TBool CMIDForm::IsLabelContainerItem(CMIDControlItem& aControlItem)
       
  3610 {
       
  3611     return (aControlItem.Type() == KLabelContainerItem);
       
  3612 }
       
  3613 
       
  3614 TBool CMIDForm::IsSpacerUsedForFormatting(CMIDControlItem& aControlItem)
       
  3615 {
       
  3616     if (!aControlItem.iMMidItem)
       
  3617     {
       
  3618         return EFalse;
       
  3619     }
       
  3620     if (aControlItem.iMMidItem->Type() == MMIDComponent::ESpacer)
       
  3621     {
       
  3622         CMIDSpacer* spacer = static_cast<CMIDSpacer*>(&aControlItem);
       
  3623         return spacer->UsedForStringFormatting();
       
  3624     }
       
  3625     return EFalse;
       
  3626 }
       
  3627 
       
  3628 TBool CMIDForm::IsImageItem(CMIDControlItem& aControlItem)
       
  3629 {
       
  3630     if (!aControlItem.iMMidItem)
       
  3631     {
       
  3632         return EFalse;
       
  3633     }
       
  3634     return (aControlItem.iMMidItem->Type() == MMIDItem::EImageItem);
       
  3635 }
       
  3636 
       
  3637 #ifdef RD_JAVA_S60_RELEASE_9_2
       
  3638 void CMIDForm::PostPendingUpEventL()
       
  3639 {
       
  3640     MMIDItem* curItem = CurrentItem();
       
  3641     if (curItem)
       
  3642     {
       
  3643         CMIDControlItem& item = ControlItem(curItem);
       
  3644 
       
  3645         if (IsChoiceGroup(item))
       
  3646         {
       
  3647             CMIDChoiceGroupItem* cgItem = static_cast<CMIDChoiceGroupItem*>(&item);
       
  3648             cgItem->PostPendingUpEventL();
       
  3649         }
       
  3650     }
       
  3651 }
       
  3652 
       
  3653 TInt CMIDForm::FormRowIndex(CMIDFormRow* aRow)
       
  3654 {
       
  3655     return iRows.Find(aRow);
       
  3656 }
       
  3657 
       
  3658 CMIDFormRow* CMIDForm::FormRow(TInt aIndex)
       
  3659 {
       
  3660     if (iRows.Count() > aIndex)
       
  3661     {
       
  3662         return iRows[aIndex];
       
  3663     }
       
  3664     return NULL;
       
  3665 }
       
  3666 #endif // RD_JAVA_S60_RELEASE_9_2
       
  3667 
       
  3668 // returns: The number of new lines before an item.
       
  3669 //          This only takes into account new lines that come from
       
  3670 //          preceeding a string item with new line characters.
       
  3671 TInt CMIDForm::NumNewLinesBefore(CMIDControlItem& aControlItem)
       
  3672 {
       
  3673     if (IsStringItem(aControlItem))
       
  3674     {
       
  3675         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3676         TInt nLinesBefore = si->NumNewlinesBefore();
       
  3677         if (nLinesBefore > 0)
       
  3678         {
       
  3679             return nLinesBefore;
       
  3680         }
       
  3681     }
       
  3682     if (iCurrentRow && iCurrentRow->NumItems() == 0)
       
  3683     {
       
  3684         return 0;
       
  3685     }
       
  3686     return LayoutNewLineBefore(aControlItem) ? 1 : 0;
       
  3687 }
       
  3688 
       
  3689 // returns: The number of new lines that should appear after an item
       
  3690 //          This takes into account the new lines that can occour from
       
  3691 //          newlines at the end of a string item, and if there are none
       
  3692 //          of these, then it returns 1 if the Layout NewLineAfter
       
  3693 //          directive has been used and 0 otherwise.
       
  3694 TInt CMIDForm::NumNewLinesAfter(CMIDControlItem& aControlItem)
       
  3695 {
       
  3696     if (IsStringItem(aControlItem))
       
  3697     {
       
  3698         CMIDStringItem* si = (CMIDStringItem*)(&aControlItem);
       
  3699         if (si->NumNewlinesAfter() > 0)
       
  3700         {
       
  3701             TInt nLinesAfter = si->NumNewlinesAfter();
       
  3702             if (nLinesAfter > 0)
       
  3703             {
       
  3704                 return nLinesAfter;
       
  3705             }
       
  3706         }
       
  3707     }
       
  3708     return LayoutNewLineAfter(aControlItem) ? 1 : 0;
       
  3709 }
       
  3710 
       
  3711 // effects:  Sizes the items within the rows based on their layout characteristics
       
  3712 // modifies: CMIDFormRow
       
  3713 void CMIDForm::SizeItemsInFormRowsL()
       
  3714 {
       
  3715     TInt rowCount = iRows.Count();
       
  3716     for (TInt i=0; i < rowCount; i++)
       
  3717     {
       
  3718         iRows[i]->SizeItemsL();
       
  3719     }
       
  3720 }
       
  3721 
       
  3722 // effects:  Deletes all rows in the Form. It doesn't affect the items that have
       
  3723 //           been added to the form.
       
  3724 // modifies: CMIDForm, CMIDFormRow
       
  3725 void CMIDForm::DeleteRows()
       
  3726 {
       
  3727     // By deleting rows we are losing pointers to original items.
       
  3728     // To avoid any problems with using iPointedControl, which
       
  3729     // could points to invalid object (e.g. used in
       
  3730     // CMIDForm::HandleHighlightTimer or
       
  3731     // in CMIDForm::HandlePhysicsPointerEventL),
       
  3732     // iPointedControl must be set to NULL.
       
  3733     iPointedControl = NULL;
       
  3734 
       
  3735     for (TInt i=0; i < iRows.Count(); i++)
       
  3736     {
       
  3737         delete iRows[i];
       
  3738     }
       
  3739 
       
  3740     iRows.Reset();
       
  3741     iCurrentRow = NULL;
       
  3742 }
       
  3743 
       
  3744 TInt CMIDForm::HeightOfAllItems()
       
  3745 {
       
  3746     return iTotalFormHeight;
       
  3747 }
       
  3748 
       
  3749 void CMIDForm::UpdateHeightOfAllItems()
       
  3750 {
       
  3751     TInt yTopMargin = iFormRect.Rect().iTl.iY - iMidpFormRect.Rect().iTl.iY;
       
  3752     TInt yBottomMargin = iMidpFormRect.Rect().iBr.iY - iFormRect.Rect().iBr.iY;
       
  3753 
       
  3754     iTotalFormHeight = yTopMargin;
       
  3755 
       
  3756     TInt rowCount = iRows.Count();
       
  3757     for (TInt i=0; i < rowCount; i++)
       
  3758     {
       
  3759         iTotalFormHeight += iRows[i]->Size().iHeight;
       
  3760     }
       
  3761     // Form bottom margin is added
       
  3762     iTotalFormHeight += yBottomMargin;
       
  3763 }
       
  3764 
       
  3765 /* HandleResourceChange
       
  3766  *
       
  3767  * This method is called after a resource change event, for example after
       
  3768  * screen dynamic resolution change.
       
  3769  *
       
  3770  * In the case of a screen dynamic resolution change we notify all items and
       
  3771  * repeat the entire form layout.
       
  3772  *
       
  3773  * We calculate the % of form that has been scrolled so far and we
       
  3774  * modify iScroll so that we have scrolled the same % of form after resolution
       
  3775  * change. Note that the max extent of iScroll is HeightOfAllItems() - Height()
       
  3776  * and not simply HeightOfAllItems() as one may think, see
       
  3777  * SetRowExtentsWithRespectToScrolledLocation(). Also note that applying a %
       
  3778  * scrolling does not necessarily mean the same items will be on screen after a
       
  3779  * resolution change.
       
  3780  * Especially when changing from portrait to landscape or vice-versa the
       
  3781  * number of items on a row vary greatly and as a consequence the number of
       
  3782  * rows may vary. Therefore, if there is a focused item on screen before
       
  3783  * resolution change (iFocused not KErrNotFound) we make sure this item is
       
  3784  * visible and focused after res change by scrolling to it, see SetFocusedItem()
       
  3785  * and ScrollToFocused().
       
  3786  */
       
  3787 void CMIDForm::HandleResourceChange(TInt aType)
       
  3788 {
       
  3789     TInt maxScrollExtentOld = HeightOfAllItems() - Height(); //max extent of iScroll
       
  3790     CCoeControl::HandleResourceChange(aType);
       
  3791 
       
  3792     if (aType == KEikDynamicLayoutVariantSwitch)
       
  3793     { // dynamic resolution change
       
  3794         TInt focusedItem = iFocused;
       
  3795 
       
  3796         UpdateMemberVariables();
       
  3797         UpdateHeightOfAllItems();
       
  3798 
       
  3799         TInt itemCount = iItems.Count();
       
  3800         for (TInt i=0; i < itemCount; i++)
       
  3801         {
       
  3802             CMIDControlItem& controlItem = ControlItem(i);
       
  3803             controlItem.ResolutionChange(aType);
       
  3804 
       
  3805             if (controlItem.LabelControl())
       
  3806             {
       
  3807                 controlItem.LabelControl()->ResolutionChange();
       
  3808             }
       
  3809         }
       
  3810 
       
  3811         TInt maxScrollExtentNew = HeightOfAllItems() - Height(); //max extent of iScroll
       
  3812 
       
  3813         TRAPD(err,LayoutFormL());
       
  3814 
       
  3815         if (err == KErrNone)
       
  3816         {
       
  3817             if ((maxScrollExtentNew <= 0) && (maxScrollExtentOld > 0))
       
  3818             {
       
  3819                 // scroll on top
       
  3820                 RawScroll(0);
       
  3821                 if (focusedItem != KErrNotFound)
       
  3822                 {
       
  3823                     // restore the form item focus
       
  3824                     CMIDControlItem& control = ControlItem(focusedItem);
       
  3825                     control.RestoreInnerFocus();
       
  3826                 }
       
  3827             }
       
  3828             else
       
  3829             {
       
  3830                 if ((maxScrollExtentNew > 0) || (maxScrollExtentOld > 0))
       
  3831                 {
       
  3832                     // if there is something focused
       
  3833                     if (focusedItem != KErrNotFound)
       
  3834                     {
       
  3835                         // restore the form item focus
       
  3836                         CMIDControlItem& control = ControlItem(focusedItem);
       
  3837                         ScrollToFocused();
       
  3838                         control.RestoreInnerFocus();
       
  3839                     }
       
  3840                     // if scroll out of maxScrollExtent
       
  3841                     if (maxScrollExtentNew+iScroll < 0)
       
  3842                     {
       
  3843                         // scroll to bottom
       
  3844                         RawScroll(-maxScrollExtentNew);
       
  3845                     }
       
  3846 
       
  3847                 }
       
  3848             }
       
  3849         }
       
  3850 
       
  3851         SetHighlightBackgroundRects();
       
  3852         HandleItemVisibilityChange();
       
  3853         UpdateScrollBar();
       
  3854         DrawDeferred();
       
  3855     }
       
  3856     else if (aType == KEikColorResourceChange || aType == KAknsMessageSkinChange ||
       
  3857              aType == KUidValueCoeColorSchemeChangeEvent)
       
  3858     {//skin or color scheme change
       
  3859         TInt itemCount = iItems.Count();
       
  3860         for (TInt i=0; i < itemCount; i++)
       
  3861         {
       
  3862             CMIDControlItem& controlItem = ControlItem(i);
       
  3863             controlItem.ColorChange(aType);
       
  3864         }
       
  3865 
       
  3866         // send this event also to form scrollbar
       
  3867         CEikScrollBar* sb = iSBFrame->GetScrollBarHandle(CEikScrollBar::EVertical);
       
  3868         if (sb)
       
  3869         {
       
  3870             sb->HandleResourceChange(aType);
       
  3871         }
       
  3872     }
       
  3873     else if ((aType == KEikMessageUnfadeWindows) ||
       
  3874              (aType == KEikMessageFadeAllWindows))
       
  3875     {
       
  3876         iLastFadeMessage = aType;
       
  3877     }
       
  3878     else if ((aType == KEikMessageWindowsFadeChange) &&
       
  3879              ((iLastFadeMessage == KEikMessageUnfadeWindows) ||
       
  3880               (iLastFadeMessage == KEikMessageFadeAllWindows)))
       
  3881     {
       
  3882         TInt itemCount = iItems.Count();
       
  3883         for (TInt i=0; i < itemCount; i++)
       
  3884         {
       
  3885             CMIDControlItem& controlItem = ControlItem(i);
       
  3886             controlItem.HandleWindowFade(iLastFadeMessage == KEikMessageFadeAllWindows);
       
  3887         }
       
  3888         iLastFadeMessage = 0;
       
  3889     }
       
  3890 
       
  3891     UpdatePhysics();
       
  3892 
       
  3893 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  3894     UpdateTactileFeedbackDensity();
       
  3895 #endif // RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  3896 }
       
  3897 
       
  3898 TBool CMIDForm::TryDetectLongTapL(const TPointerEvent &aPointerEvent)
       
  3899 {
       
  3900     return iDisplayable.TryDetectLongTapL(aPointerEvent);
       
  3901 }
       
  3902 
       
  3903 #ifdef RD_SCALABLE_UI_V2
       
  3904 void CMIDForm::HandleScrollEventL(CEikScrollBar* aScrollBar, TEikScrollEvent aEventType)
       
  3905 {
       
  3906     if (AknLayoutUtils::PenEnabled())
       
  3907     {
       
  3908 
       
  3909         if (LayoutPending())
       
  3910         {
       
  3911             LayoutFormL();
       
  3912         }
       
  3913 
       
  3914         TInt pixelIndex;
       
  3915 
       
  3916         switch (aEventType)
       
  3917         {
       
  3918         case EEikScrollUp:
       
  3919         {
       
  3920             pixelIndex = iScroll + (Height() / KScrollAmountDivider);
       
  3921             break;
       
  3922         }
       
  3923 
       
  3924         case EEikScrollDown:
       
  3925         {
       
  3926             pixelIndex = iScroll - (Height() / KScrollAmountDivider);
       
  3927             break;
       
  3928         }
       
  3929 
       
  3930         case EEikScrollPageUp:
       
  3931         {
       
  3932             pixelIndex = iScroll + Height();
       
  3933             break;
       
  3934         }
       
  3935 
       
  3936         case EEikScrollPageDown:
       
  3937         {
       
  3938             pixelIndex = iScroll - Height();
       
  3939             break;
       
  3940         }
       
  3941 
       
  3942         default://thumb drag
       
  3943         {
       
  3944             //scroll form if thumb position has moved more than 1/10 of the screen height either up or down
       
  3945             //or thumb position is at top or at bottom of the scrollbar.
       
  3946             if (-aScrollBar->ThumbPosition() < (iScroll - (Height() / KScrollAmountDividerForThumbDrag))
       
  3947                     || -aScrollBar->ThumbPosition() > (iScroll + (Height() / KScrollAmountDividerForThumbDrag))
       
  3948                     || aScrollBar->ThumbPosition() == 0
       
  3949                     || aScrollBar->ThumbPosition() == aScrollBar->Model()->MaxThumbPos())
       
  3950             {
       
  3951                 aScrollBar->DrawNow();
       
  3952                 pixelIndex = - aScrollBar->ThumbPosition();
       
  3953             }
       
  3954             else
       
  3955             {
       
  3956                 return;
       
  3957             }
       
  3958             break;
       
  3959         }
       
  3960         }
       
  3961         RawScroll(pixelIndex);
       
  3962         RawScrollFinalize(ETrue);
       
  3963         UpdatePhysics();
       
  3964     }
       
  3965 }
       
  3966 
       
  3967 
       
  3968 TBool CMIDForm::StringItemContainsPoint(CMIDStringItem* aStringItem, const TPoint& aPoint) const
       
  3969 {
       
  3970     CMIDControlItem* ci = ControlItemAtPoint(aPoint);
       
  3971 
       
  3972     if (ci)
       
  3973     {
       
  3974         if (IsLabelContainerItem(*ci))
       
  3975         {
       
  3976             CMIDLabelContainerItem *lci = static_cast<CMIDLabelContainerItem*>(ci);
       
  3977             CMIDStringItem& si = lci->StringItem();
       
  3978             if (&si == aStringItem)
       
  3979             { // LabelContainer item is (part of) StringItem
       
  3980                 if (si.IsDivided())
       
  3981                 { // StringItem was divided due to concatenation of contents
       
  3982                     if (lci->IsStringItemContent())
       
  3983                     { // return ETrue if is pointed to StringItem content
       
  3984                         return ETrue;
       
  3985                     }
       
  3986                     else
       
  3987                     { // return EFasle if is pointed to StringItem label
       
  3988                         return EFalse;
       
  3989                     }
       
  3990                 }
       
  3991                 else
       
  3992                 { // StringItem was not divided, pointed directly to unconstrained StringItem
       
  3993                     return ETrue;
       
  3994                 }
       
  3995             }
       
  3996         }
       
  3997         else
       
  3998         {
       
  3999             return (ci == aStringItem && aStringItem->TappingActionRect().Contains(aPoint));
       
  4000         }
       
  4001     }
       
  4002 
       
  4003     return EFalse;
       
  4004 }
       
  4005 
       
  4006 TBool CMIDForm::IsFocusChangingWithPen() const
       
  4007 {
       
  4008     return iFocusChangingWithPen;
       
  4009 }
       
  4010 
       
  4011 #endif //RD_SCALABLE_UI_V2
       
  4012 
       
  4013 
       
  4014 void CMIDForm::HandleForegroundL(TBool aForeground)
       
  4015 {
       
  4016     // send HandleForegroundL notification to gauge items
       
  4017     TInt itemsCount = iItems.Count();
       
  4018     for (TInt i=0; i < itemsCount; i++)
       
  4019     {
       
  4020         if (iItems[i]->Type() == MMIDComponent::EGauge)
       
  4021         {
       
  4022             CMIDGaugeItem* gauge = static_cast<CMIDGaugeItem*>(iItems[i]);
       
  4023             ASSERT(gauge);
       
  4024             gauge->HandleForegroundL(aForeground);
       
  4025         }
       
  4026     }
       
  4027 }
       
  4028 
       
  4029 CMIDPopupNoteController* CMIDForm::GetPopupNoteController() const
       
  4030 {
       
  4031     return  iPopupController;
       
  4032 }
       
  4033 
       
  4034 TInt CMIDForm::GetMidpNaviPos()
       
  4035 {
       
  4036     TAknLayoutRect mainMidpPane;
       
  4037 
       
  4038     // get main pane size from Avkon (size in pixels)
       
  4039 #ifdef RD_JAVA_S60_RELEASE_9_2
       
  4040     TRect mainPane;
       
  4041     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, mainPane);
       
  4042     mainMidpPane.LayoutRect(mainPane,
       
  4043                             AknLayoutScalable_Avkon::main_midp_pane().LayoutLine());
       
  4044 #else
       
  4045     mainMidpPane.LayoutRect(iEikonEnv->ScreenDevice()->SizeInPixels(),
       
  4046                             AknLayoutScalable_Avkon::main_midp_pane().LayoutLine());
       
  4047 #endif // RD_JAVA_S60_RELEASE_9_2
       
  4048 
       
  4049     // getting form size depends on screen orientation
       
  4050     TInt variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
       
  4051     iMidpFormRect.LayoutRect(mainMidpPane.Rect(),
       
  4052                              AknLayoutScalable_Avkon::midp_form_pane(variety).LayoutLine());
       
  4053 
       
  4054     // different between screen size and form size
       
  4055     TInt xFormDiff = mainMidpPane.Rect().iBr.iX - iMidpFormRect.Rect().iBr.iX;
       
  4056     // width of navi bar position only for ( iAlignment == MMIDItem::ERight )
       
  4057     TInt xNaviPos  = iMidpFormRect.Rect().iTl.iX - xFormDiff;
       
  4058 
       
  4059     return xNaviPos;
       
  4060 }
       
  4061 
       
  4062 void CMIDForm::UpdatePhysics()
       
  4063 {
       
  4064     if (iPhysics)
       
  4065     {
       
  4066         TSize worldSize(Width(), HeightOfAllItems());
       
  4067         TSize viewSize(Width(), Height());
       
  4068         TPoint viewCenter(Width() / 2, -iScroll + Height() / 2);
       
  4069         TRAP_IGNORE(iPhysics->InitPhysicsL(worldSize, viewSize, viewCenter));
       
  4070     }
       
  4071 }
       
  4072 
       
  4073 TInt CMIDForm::HighlightTimerCallback(TAny* aPtr)
       
  4074 {
       
  4075     CMIDForm* me = static_cast<CMIDForm*>(aPtr);
       
  4076     me->HandleHighlightTimer();
       
  4077     return 0;
       
  4078 }
       
  4079 
       
  4080 void CMIDForm::HandleHighlightTimer()
       
  4081 {
       
  4082     iHighlightTimer->Cancel();
       
  4083 
       
  4084     if (iPointedControl && iPointedControl->IsSelectable())
       
  4085     {
       
  4086         // If tactile feedback has not been given already
       
  4087         // give basic tactile feedback when focus changes.
       
  4088         // Don't give tactile feedback for button because it is handled
       
  4089         // by button implementation.
       
  4090 #ifdef RD_TACTILE_FEEDBACK
       
  4091         if (!iFeedbackExecutedInPointerDown)
       
  4092         {
       
  4093             DoFeedbackOnFocusChange(*iPointedControl);
       
  4094             iFeedbackExecutedInPointerDown = ETrue;
       
  4095         }
       
  4096 #endif // RD_TACTILE_FEEDBACK
       
  4097 
       
  4098         TInt itemIndex = ItemIndex(*iPointedControl);
       
  4099 
       
  4100         if (itemIndex != iFocused)
       
  4101         {
       
  4102             SetFocusedItem(itemIndex, ENone, EFalse);
       
  4103             DrawDeferred();
       
  4104         }
       
  4105 
       
  4106         if (!PhysicsScrolling() && !iUpEventSent)
       
  4107         {
       
  4108             TRAP_IGNORE(ForwardPointerEventToItemL(iLastPointerDownEvent));
       
  4109         }
       
  4110     }
       
  4111 }
       
  4112 
       
  4113 void CMIDForm::SetHighlightBackgroundRects()
       
  4114 {
       
  4115     if (iFocused == KErrNotFound)
       
  4116     {
       
  4117         return;
       
  4118     }
       
  4119 
       
  4120     CMIDControlItem& ci = ControlItem(iFocused);
       
  4121 
       
  4122     // Limit rect size to screen size. If Rect() is way larger
       
  4123     // than screen, the svg engine will not cope handling that.
       
  4124     TRect r(ci.Size());
       
  4125     TRect s;
       
  4126     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, s);
       
  4127 
       
  4128     if (r.Intersects(s))
       
  4129     {
       
  4130         s.Intersection(r);
       
  4131     }
       
  4132 
       
  4133     TRect rect(s);
       
  4134     rect.Normalize(); // ensure positive w & h, just in case
       
  4135 
       
  4136     TAknLayoutRect topLeft ;
       
  4137     topLeft.LayoutRect(rect, SkinLayout::Input_field_skin_placing__general__Line_2());
       
  4138 
       
  4139     TAknLayoutRect bottomRight;
       
  4140     bottomRight.LayoutRect(rect, SkinLayout::Input_field_skin_placing__general__Line_5());
       
  4141 
       
  4142     TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr);
       
  4143     TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl);
       
  4144 
       
  4145     iHighlightedBackgroundCc->SetParentContext(iDisplayable.BackGroundControlContext());
       
  4146     iHighlightedBackgroundCc->SetFrameRects(outerRect, innerRect);
       
  4147 
       
  4148     UpdateHighlightBackgroundPosition();
       
  4149 }
       
  4150 
       
  4151 void CMIDForm::UpdateHighlightBackgroundPosition()
       
  4152 {
       
  4153 
       
  4154     if (iFocused != KErrNotFound)
       
  4155     {
       
  4156         CMIDControlItem& ci = ControlItem(iFocused);
       
  4157         TPoint highlightPosition = ci.PositionRelativeToScreen();
       
  4158         TRect focusedRect = ci.Rect();
       
  4159 
       
  4160         // Max size of the higlight background is limited to screen size,
       
  4161         // see SetHighlightBackgroundRects().
       
  4162         // Need to adjust the highlight position if focused item is partially visible
       
  4163         // on top of the form and it is larger than screen.
       
  4164         if (focusedRect.iTl.iY < 0 && focusedRect.iBr.iY > 0)
       
  4165         {
       
  4166             TRect screen;
       
  4167             AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screen);
       
  4168             if (focusedRect.Height() > screen.Height())
       
  4169             {
       
  4170                 if (focusedRect.iBr.iY > iSize.iHeight)
       
  4171                 {
       
  4172                     // Focused item fills the visible form area fully
       
  4173                     highlightPosition.iY = 0;
       
  4174                 }
       
  4175                 else
       
  4176                 {
       
  4177                     // Bottom of focused item is in the visible form area
       
  4178                     highlightPosition.iY += focusedRect.Height() - screen.Height();
       
  4179                 }
       
  4180             }
       
  4181         }
       
  4182 
       
  4183         iHighlightedBackgroundCc->SetParentPos(highlightPosition);
       
  4184     }
       
  4185 }
       
  4186 
       
  4187 void CMIDForm::HandlePhysicsPointerEventL(const TPointerEvent& aPointerEvent)
       
  4188 {
       
  4189 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4190     iLastPointerEventType = aPointerEvent.iType;
       
  4191 #endif
       
  4192 
       
  4193     if (iPhysics && iPhysics->CanBeStopped())
       
  4194     {
       
  4195         switch (aPointerEvent.iType)
       
  4196         {
       
  4197         case TPointerEvent::EButton1Down:
       
  4198         {
       
  4199             iPreventPhysicsScrolling = EFalse;
       
  4200             iFlickStoppedOnDownEvent = iFlickOngoing;
       
  4201             iFeedbackExecutedInPointerDown = EFalse;
       
  4202             iPhysics->Stop();
       
  4203             CMIDControlItem* ci = ControlItemAtPoint(aPointerEvent.iPosition);
       
  4204 
       
  4205             // Physics scrolling was not ongoing and tap hit already selected item.
       
  4206             // Then forward pointer event to the item.
       
  4207             if (ci && IsCurrentItem((CMIDItem*)ci) && !iFlickStoppedOnDownEvent)
       
  4208             {
       
  4209                 iPointedControl = ci;
       
  4210                 ForwardPointerEventToItemL(aPointerEvent);
       
  4211             }
       
  4212             else
       
  4213             {
       
  4214                 // Tactile fedback is executed when kinetic scrolling is stopped on down event.
       
  4215                 if (iFlickStoppedOnDownEvent)
       
  4216                 {
       
  4217 #ifdef RD_TACTILE_FEEDBACK
       
  4218 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4219                     iFeedback->InstantFeedback(ETouchFeedbackList);
       
  4220 #else
       
  4221                     iFeedback->InstantFeedback(ETouchFeedbackBasic);
       
  4222 #endif // RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4223                     iFeedbackExecutedInPointerDown = ETrue;
       
  4224 #endif // RD_TACTILE_FEEDBACK
       
  4225                 }
       
  4226 
       
  4227                 // Pointed control changes.
       
  4228                 if (ci && ci->IsSelectable() && (MMIDItem*)ci != CurrentItem())
       
  4229                 {
       
  4230                     iFocusChangingWithPen = ETrue;
       
  4231                 }
       
  4232 
       
  4233                 // Start highlight timer
       
  4234                 iPointedControl = ci;
       
  4235                 iHighlightTimer->Cancel();
       
  4236                 // Start highlight timer if some any control is tapped.
       
  4237                 if (iPointedControl)
       
  4238                 {
       
  4239                     TInt highlightTimeout = iPhysics->HighlightDelay() * 1000;
       
  4240                     if (IsPopupChoiceGroup(*iPointedControl))
       
  4241                     {
       
  4242                         highlightTimeout /= 2;
       
  4243                     }
       
  4244                     iHighlightTimer->Start(TTimeIntervalMicroSeconds32(highlightTimeout),
       
  4245                                            TTimeIntervalMicroSeconds32(highlightTimeout),
       
  4246                                            TCallBack(HighlightTimerCallback, this));
       
  4247                 }
       
  4248             }
       
  4249             // Setup members
       
  4250             iStartPosition = aPointerEvent.iPosition;
       
  4251             iLastPointerDownEvent = aPointerEvent;
       
  4252             iUpEventSent = EFalse;
       
  4253             iStartTime.HomeTime();
       
  4254             iLastDragPosition = aPointerEvent.iPosition;
       
  4255 
       
  4256             break;
       
  4257         }
       
  4258         // EDrag
       
  4259         case TPointerEvent::EDrag:
       
  4260         {
       
  4261             TInt dragY = iStartPosition.iY - aPointerEvent.iPosition.iY;
       
  4262             TInt dragX = iStartPosition.iX - aPointerEvent.iPosition.iX;
       
  4263             iDisplayable.TryDetectLongTapL(aPointerEvent);
       
  4264 
       
  4265             // Override triggering of physicsScrolling in case of doing text painting in TextField-item
       
  4266             // or moving slider in Gauge-item.
       
  4267             if (!iPreventPhysicsScrolling && iPointedControl && iPointedControl->iMMidItem &&
       
  4268                     iPointedControl->iMMidItem->Type() == MMIDComponent::ETextField)
       
  4269             {
       
  4270                 // If physics scrolling is not ongoing (abs(dragY) < DragTreshold)
       
  4271                 // then stop flicking and forward event to the item (iPreventPhysicsScrolling = ETrue).
       
  4272                 if ((Abs(dragX) > iPhysics->DragThreshold()) && (Abs(dragY) < iPhysics->DragThreshold()
       
  4273                         && !iPanningOngoing))
       
  4274                 {
       
  4275                     iPreventPhysicsScrolling = ETrue;
       
  4276                 }
       
  4277             }
       
  4278 
       
  4279             // Check whether DragTreshold for panning is exceeded. If yes, then cancel timer and longtap.
       
  4280             if (!iPanningOngoing && Abs(dragY) > iPhysics->DragThreshold() && !iPreventPhysicsScrolling)
       
  4281             {
       
  4282                 iPanningOngoing = ETrue;
       
  4283                 iHighlightTimer->Cancel();
       
  4284                 // Start panning from aPointerEvent.iPosition with iPhysics->DragThreshold() margin
       
  4285                 iLastDragPosition = aPointerEvent.iPosition;
       
  4286                 iPhysics->SetPanningPosition(iLastDragPosition - aPointerEvent.iPosition);
       
  4287                 //Forward one drag event to the focused textField or Gauge when panning is triggered
       
  4288                 if ((iFocused != KErrNotFound)
       
  4289                         && IsTextFieldItem(ControlItem(iFocused)))
       
  4290                 {
       
  4291                     ControlItem(iFocused).HandlePointerEventL(aPointerEvent);
       
  4292                 }
       
  4293             }
       
  4294             // If panning is already ongoing. Update panning position. Also we redraw entire Form
       
  4295             // to prevent unexpected behavior(artifacts on the screen) during flick scrolling and
       
  4296             // to make scrolling smoother.
       
  4297             else if (iPanningOngoing)
       
  4298             {
       
  4299                 iPhysics->SetPanningPosition(iLastDragPosition - aPointerEvent.iPosition);
       
  4300                 iLastDragPosition = aPointerEvent.iPosition;
       
  4301                 DrawDeferred();
       
  4302             }
       
  4303             // If dragged outside of StringItem area or panning starts, then up event is sent to the item.
       
  4304             if (!iUpEventSent && iPointedControl && IsStringItem(*iPointedControl)  && (iPanningOngoing ||
       
  4305                     (iPointedControl && !iPointedControl->Rect().Contains(aPointerEvent.iPosition)))
       
  4306                )
       
  4307             {
       
  4308                 TPointerEvent pointerEvent = aPointerEvent;
       
  4309                 pointerEvent.iType = TPointerEvent::EButton1Up;
       
  4310                 ForwardPointerEventToItemL(pointerEvent);
       
  4311                 iPointedControl = ControlItemAtPoint(aPointerEvent.iPosition);
       
  4312                 iUpEventSent = ETrue;
       
  4313             }
       
  4314             // If physics scrolling is not ongoing forward event to the item.
       
  4315             else if (!iHighlightTimer->IsActive() && !PhysicsScrolling() &&
       
  4316                      (iPointedControl && iPointedControl->Rect().Contains(aPointerEvent.iPosition)))
       
  4317             {
       
  4318                 ForwardPointerEventToItemL(aPointerEvent);
       
  4319             }
       
  4320 #ifdef RD_JAVA_S60_RELEASE_9_2
       
  4321             // ChoiceGroup gets drag events while physics scrolling.
       
  4322             // Enables internal highlight disappearing when panning begins.
       
  4323             // We have control if there is any Item on Form.
       
  4324             else if (!iHighlightTimer->IsActive()
       
  4325                      && (iFocused > KErrNotFound)
       
  4326                      && IsChoiceGroup(ControlItem(iFocused))
       
  4327                      && PhysicsScrolling())
       
  4328             {
       
  4329                 ForwardPointerEventToItemL(aPointerEvent);
       
  4330             }
       
  4331 
       
  4332 #endif // RD_JAVA_S60_RELEASE_9_2             
       
  4333             break;
       
  4334         }
       
  4335 
       
  4336         // EButton1Up
       
  4337         case TPointerEvent::EButton1Up:
       
  4338         {
       
  4339             // If physics scrolling is ongoing then start flicking
       
  4340             // and forward event to the item.
       
  4341             if (iPanningOngoing && !iPreventPhysicsScrolling)
       
  4342             {
       
  4343                 TPoint distance = iStartPosition - aPointerEvent.iPosition;
       
  4344                 iFlickOngoing = iPhysics->StartFlick(distance, iStartTime);
       
  4345             }
       
  4346 
       
  4347             // If physics scrolling is not ongoing then only
       
  4348             // forward event to the item.
       
  4349             if (!iUpEventSent)
       
  4350             {
       
  4351                 ForwardPointerEventToItemL(aPointerEvent);
       
  4352                 iUpEventSent = ETrue;
       
  4353             }
       
  4354 
       
  4355             iPanningOngoing = EFalse;
       
  4356             iCanDragFocus = EFalse;
       
  4357             break;
       
  4358         }
       
  4359         default:
       
  4360         {
       
  4361             ForwardPointerEventToItemL(aPointerEvent);
       
  4362             break;
       
  4363         }
       
  4364         }
       
  4365     }
       
  4366     else
       
  4367     {
       
  4368         IgnoreEventsUntilNextPointerUp();
       
  4369         return;
       
  4370     }
       
  4371 }
       
  4372 
       
  4373 void CMIDForm::ForwardPointerEventToItemL(const TPointerEvent& aPointerEvent)
       
  4374 {
       
  4375     if (iPointedControl)
       
  4376     {
       
  4377         // Drag events are not forwarded to CustomItem
       
  4378         if (!iFlickStoppedOnDownEvent &&
       
  4379                 !(IsCustomItem(*iPointedControl) && aPointerEvent.iType == TPointerEvent::EDrag))
       
  4380         {
       
  4381             if (iFocused != KErrNotFound)
       
  4382             {
       
  4383                 if (IsPopupChoiceGroup(*iPointedControl))
       
  4384                 {
       
  4385                     iPointedControl->HandlePointerEventL(aPointerEvent);
       
  4386                 }
       
  4387                 else
       
  4388                 {
       
  4389                     ControlItem(iFocused).HandlePointerEventL(aPointerEvent);
       
  4390                 }
       
  4391             }
       
  4392 
       
  4393             if (LayoutPending())
       
  4394             {
       
  4395                 LayoutFormL();
       
  4396                 DrawDeferred();
       
  4397             }
       
  4398         }
       
  4399 
       
  4400         if (aPointerEvent.iType == TPointerEvent::EButton1Up)
       
  4401         {
       
  4402             iFocusChangingWithPen = EFalse;
       
  4403         }
       
  4404     }
       
  4405 }
       
  4406 
       
  4407 void CMIDForm::HandlePhysicsScroll(TInt aScroll, TBool aDrawNow, TUint /*aFlags*/)
       
  4408 {
       
  4409     iScroll = iScroll + aScroll;
       
  4410     if (aScroll)
       
  4411     {
       
  4412         iHasScrolled = ETrue;
       
  4413     }
       
  4414     iScrollDelta = aScroll;
       
  4415     SetRowPositionsWithRespectToScrolledLocation();
       
  4416 
       
  4417     if (aDrawNow)
       
  4418     {
       
  4419         RawScrollFinalize(ETrue, ETrue);
       
  4420         DrawNow();
       
  4421     }
       
  4422     else
       
  4423     {
       
  4424         RawScrollFinalize(ETrue, EFalse);
       
  4425     }
       
  4426 
       
  4427 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4428     //Tactile feedback on dragging/flicking.
       
  4429     DoScrollingFeedback();
       
  4430 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4431 }
       
  4432 
       
  4433 void CMIDForm::PhysicsScrollingEnd()
       
  4434 {
       
  4435     iFlickOngoing = EFalse;
       
  4436     iPanningOngoing = EFalse;
       
  4437 }
       
  4438 
       
  4439 TBool CMIDForm::PhysicsEnabled()
       
  4440 {
       
  4441     if (iPhysics)
       
  4442     {
       
  4443         return ETrue;
       
  4444     }
       
  4445     else
       
  4446     {
       
  4447         return EFalse;
       
  4448     }
       
  4449 }
       
  4450 
       
  4451 TBool CMIDForm::PhysicsScrolling()
       
  4452 {
       
  4453     return iFlickOngoing | iPanningOngoing;
       
  4454 }
       
  4455 
       
  4456 TInt CMIDForm::ScrollDelta()
       
  4457 {
       
  4458     return iScrollDelta;
       
  4459 }
       
  4460 
       
  4461 void CMIDForm::DoFeedbackOnFocusChange(CMIDControlItem& aControlItem)
       
  4462 {
       
  4463     //Tapping on StringItem BUTTON should not do feedback, here.
       
  4464     //Native class CAknButton does it by itself
       
  4465     if (!IsStringItemButton(aControlItem))
       
  4466     {
       
  4467         //Other items should do some feedback
       
  4468 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4469         if (IsStringItemHyperlink(aControlItem))
       
  4470         {
       
  4471             //if StringItem is HYPERLIK it should give sensitive button feedback
       
  4472             iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton);
       
  4473         }
       
  4474         else if (IsImageItem(aControlItem))
       
  4475         {
       
  4476             //if pointed control is ImageItem, its focusable, it has to be either
       
  4477             //HYPERLIK ot BUTTON, so it should give sensitive button feedback
       
  4478             iFeedback->InstantFeedback(ETouchFeedbackSensitiveButton);
       
  4479         }
       
  4480         else if (IsChoiceGroup(aControlItem))
       
  4481         {
       
  4482             //tapping on unfocused ChoiceGroup makes also activation, so it should
       
  4483             //give basic list feedback
       
  4484             iFeedback->InstantFeedback(ETouchFeedbackList);
       
  4485         }
       
  4486         else
       
  4487         {
       
  4488             //changing focus to other items should give sensitive list feedback
       
  4489             iFeedback->InstantFeedback(ETouchFeedbackSensitiveList);
       
  4490         }
       
  4491 #else
       
  4492         iFeedback->InstantFeedback(ETouchFeedbackBasic);
       
  4493 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK                
       
  4494     }
       
  4495 }
       
  4496 
       
  4497 #ifdef RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4498 void CMIDForm::UpdateTactileFeedbackDensity()
       
  4499 {
       
  4500     TAknLayoutRect layoutRect;
       
  4501     layoutRect.LayoutRect(TRect(), AknLayoutScalable_Avkon::
       
  4502                           list_single_heading_pane(0).LayoutLine());
       
  4503     iTactileFeedbackDensity = layoutRect.Rect().Height();
       
  4504 }
       
  4505 
       
  4506 void CMIDForm::DoScrollingFeedback()
       
  4507 {
       
  4508     TRect formRect(Rect());
       
  4509     TInt topEdgePos = iScroll;
       
  4510     TInt bottomEdgePos = iScroll + HeightOfAllItems();
       
  4511     // Calculate distance between current Form content position
       
  4512     // and previous position, where last feedback happened.
       
  4513     TInt lastFeedbackDistanceY = Abs(iLastTactileFeedbackPos - iScroll);
       
  4514     TTouchLogicalFeedback feedbackType(ETouchFeedbackNone);
       
  4515     if (lastFeedbackDistanceY >= iTactileFeedbackDensity)
       
  4516     {
       
  4517         if ((topEdgePos < formRect.iTl.iY)
       
  4518                 && (bottomEdgePos > formRect.iBr.iY))
       
  4519         {
       
  4520             // If top (or bottom) edge of the content is outside
       
  4521             // of visible area of Form, do feedback every time.
       
  4522             feedbackType = ETouchFeedbackSensitiveList;
       
  4523         }
       
  4524         else if (iLastPointerEventType != TPointerEvent::EButton1Up)
       
  4525         {
       
  4526             // Begining or end of the content reached (i.e. top or bottom
       
  4527             // egde of the contont is now visible): feedback is given
       
  4528             // only if user do panning. No feedback, if touch release
       
  4529             // happened.
       
  4530             feedbackType = ETouchFeedbackSensitiveList;
       
  4531         }
       
  4532         // Store the position of the content.
       
  4533         iLastTactileFeedbackPos = iScroll;
       
  4534     }
       
  4535 
       
  4536     if (iFeedback && feedbackType != ETouchFeedbackNone)
       
  4537     {
       
  4538         if (iLastPointerEventType != TPointerEvent::EButton1Up)
       
  4539         {
       
  4540             iFeedback->EnableFeedbackForControl(this, ETrue, ETrue);
       
  4541         }
       
  4542         else
       
  4543         {
       
  4544             // Disable audion feedback on flicking (i.e. user don't pan by
       
  4545             // touch input).
       
  4546             iFeedback->EnableFeedbackForControl(this, ETrue, EFalse);
       
  4547         }
       
  4548         // Do the feedback if needed.
       
  4549         iFeedback->InstantFeedback(this, feedbackType);
       
  4550     }
       
  4551 }
       
  4552 #endif //RD_JAVA_ADVANCED_TACTILE_FEEDBACK
       
  4553