uiacceltk/hitchcock/coretoolkit/src/HuiRosterImpl.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2006-2007 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:   Implementation of CHuiRosterImpl. CHuiRosterImpl implements 
       
    15 *                the interface defined by CHuiRoster.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "HuiRosterImpl.h"  // Class definition
       
    22 #include "HuiRosterEntry.h"
       
    23 #include "uiacceltk/HuiEnv.h"
       
    24 #include "uiacceltk/HuiControlGroup.h"
       
    25 #include "uiacceltk/HuiControl.h"
       
    26 #include "uiacceltk/HuiDisplay.h"
       
    27 #include "uiacceltk/HuiEvent.h"
       
    28 #include "uiacceltk/HuiTransformation.h"
       
    29 #include "uiacceltk/HuiPanic.h"
       
    30 #include "uiacceltk/HuiUtil.h"
       
    31 #include "uiacceltk/HuiProbe.h"
       
    32 #include "uiacceltk/HuiCanvasVisual.h"
       
    33 #include "huilongtapdetector.h"
       
    34 #include "HuiFxEffect.h"
       
    35 #include "huieffectable.h"
       
    36 #include "huicanvasrenderbuffer.h"
       
    37 #include "huicanvasgc.h"
       
    38 #include "HuiRenderPlugin.h"
       
    39 
       
    40 #ifdef RD_TACTILE_FEEDBACK
       
    41 #include <touchfeedback.h>
       
    42 #endif //RD_TACTILE_FEEDBACK
       
    43 
       
    44 const TReal32 KHuiVisualOutlineWidth = 1.f;
       
    45 
       
    46 struct THuiPointerEventDetails 
       
    47 	{
       
    48 	MHuiEventHandler* iEventHandler;
       
    49 	THuiXYMetric iXYMetric;
       
    50 	TBool iDisableLongTapWhenDragging;
       
    51 	TBool iDragging;
       
    52 	};
       
    53 
       
    54 
       
    55 
       
    56 CHuiRosterImpl::CHuiRosterImpl(CHuiDisplay* aDisplay)
       
    57         : iDisplay(aDisplay), iInitialDownEvent(NULL), iEffectOpacity(1.f)
       
    58     {
       
    59     }
       
    60 
       
    61 CHuiRosterImpl::~CHuiRosterImpl()
       
    62     {
       
    63     FreezeVisibleContentL(EFalse);
       
    64     
       
    65     delete iLongTapDetector;
       
    66     iEntries.ResetAndDestroy();
       
    67     iPointerDragObservers.Close();
       
    68     iDisplay = NULL;
       
    69     iInputFocus = NULL;
       
    70     iUnhandledPointerObservers.Close();
       
    71     iLongTapObservers.Close();
       
    72     while(iPointerEventDetails.Count()>0)
       
    73     	{
       
    74     	delete iPointerEventDetails[0];
       
    75 		iPointerEventDetails.Remove(0);    	
       
    76     	}
       
    77     iPointerEventDetails.ResetAndDestroy();
       
    78     }
       
    79 
       
    80 
       
    81 void CHuiRosterImpl::SetDisplay(CHuiDisplay* aDisplay)
       
    82     {
       
    83     iDisplay = aDisplay;    
       
    84     }
       
    85     
       
    86     
       
    87 void CHuiRosterImpl::SetRect(const TRect& aRect)
       
    88     {
       
    89     iRect = TRect(0, 0, aRect.Width(), aRect.Height());
       
    90     UpdateLayout();
       
    91 
       
    92     SetChanged();
       
    93     }
       
    94     
       
    95  
       
    96 TRect CHuiRosterImpl::Rect() const
       
    97 	{
       
    98 	return(iRect);
       
    99 	}
       
   100    
       
   101     
       
   102 void CHuiRosterImpl::ShowL(CHuiControlGroup& aGroup, TInt aWhere)
       
   103     {
       
   104     // If the group is already shown on the display, just adjust its position
       
   105     // according to the parameters.
       
   106     if(Find(&aGroup) != KErrNotFound)
       
   107         {
       
   108         // It is already shown. Only adjust position.
       
   109         TInt newPos = aWhere;
       
   110         if(newPos == KHuiRosterShowAtTop)
       
   111             {
       
   112             newPos = Count() - 1;
       
   113             }
       
   114         else if(newPos == KHuiRosterShowAtBottom)
       
   115             {
       
   116             newPos = 0;
       
   117             }
       
   118         else
       
   119             {
       
   120             // for PC lint
       
   121             }
       
   122         Move(&aGroup, newPos);            
       
   123         return;
       
   124         }
       
   125 
       
   126     if(aWhere == KHuiRosterShowAtTop)
       
   127         {
       
   128         // Put the group on top of the roster.
       
   129         AppendL(&aGroup);
       
   130         }
       
   131     else if(aWhere == KHuiRosterShowAtBottom)
       
   132         {
       
   133         InsertL(&aGroup, 0);
       
   134         }
       
   135     else
       
   136         {
       
   137         InsertL(&aGroup, aWhere);
       
   138         }
       
   139 
       
   140     // The group will automatically accept input events once shown.
       
   141     aGroup.SetAcceptInput(ETrue);
       
   142 
       
   143     // Show all the controls of the group.
       
   144     for(TInt i = 0; i < aGroup.Count(); ++i)
       
   145         {
       
   146         aGroup.Control(i).ShowL(*iDisplay);
       
   147         }
       
   148     }
       
   149 
       
   150 
       
   151 void CHuiRosterImpl::Hide(CHuiControlGroup& aGroup)
       
   152     {
       
   153     // Hide all the controls of the group.
       
   154     for(TInt i = 0; i < aGroup.Count(); ++i)
       
   155         {
       
   156         aGroup.Control(i).Hide(*iDisplay);
       
   157         }
       
   158 
       
   159     Remove(&aGroup);
       
   160     }
       
   161 
       
   162 
       
   163 void CHuiRosterImpl::AppendL(CHuiControlGroup* aGroup)
       
   164     {
       
   165     ASSERT( aGroup );
       
   166     CHuiRosterEntry* entry = new (ELeave) CHuiRosterEntry(*aGroup);
       
   167     CleanupStack::PushL(entry);
       
   168     User::LeaveIfError(iEntries.Append(entry));
       
   169     CleanupStack::Pop(entry);
       
   170 
       
   171     if(iDisplay)
       
   172         {
       
   173         iDisplay->Env().ContinueRefresh();
       
   174         }
       
   175         
       
   176     SetChanged();
       
   177     }
       
   178 
       
   179 
       
   180 void CHuiRosterImpl::InsertL(CHuiControlGroup* aGroup, TInt aPos)
       
   181     {
       
   182     ASSERT( aGroup );
       
   183     if(Find(aGroup) != KErrNotFound)
       
   184         {
       
   185         User::Leave(KErrAlreadyExists);
       
   186         }
       
   187 
       
   188     CHuiRosterEntry* entry = new (ELeave) CHuiRosterEntry(*aGroup);
       
   189     CleanupStack::PushL(entry);
       
   190     User::LeaveIfError(iEntries.Insert(entry, aPos));
       
   191     CleanupStack::Pop(entry);
       
   192     
       
   193     if(iDisplay)
       
   194         {
       
   195         iDisplay->Env().ContinueRefresh();
       
   196         }
       
   197 
       
   198     SetChanged();
       
   199     }
       
   200 
       
   201 void CHuiRosterImpl::Move(CHuiVisual* aVisual, TInt aPos)
       
   202     {
       
   203     CHuiRosterEntry* entry = EntryForVisual(aVisual);
       
   204     if (entry)
       
   205         {
       
   206         Move(&entry->ControlGroup(), aPos);        
       
   207         }    
       
   208     }
       
   209 
       
   210 void CHuiRosterImpl::Move(CHuiControlGroup* aGroup, TInt aPos)
       
   211     {
       
   212     TInt index = Find(aGroup);
       
   213     TInt k = 0;
       
   214     
       
   215     if(index != KErrNotFound && index != aPos)
       
   216         {
       
   217         CHuiRosterEntry* moving = iEntries[index];
       
   218         
       
   219         if(aPos > index)
       
   220             {
       
   221             for(k = index; k < aPos; ++k)
       
   222                 {
       
   223                 iEntries[k] = iEntries[k + 1];
       
   224                 }
       
   225             }
       
   226         else 
       
   227             {
       
   228             for(k = index; k > aPos; --k)
       
   229                 {
       
   230                 iEntries[k] = iEntries[k - 1];
       
   231                 }
       
   232             }
       
   233         iEntries[aPos] = moving;                
       
   234         }
       
   235         
       
   236     if(iDisplay)
       
   237         {
       
   238         iDisplay->Env().ContinueRefresh();        
       
   239         }
       
   240 
       
   241     SetChanged();
       
   242     }
       
   243 
       
   244 
       
   245 TInt CHuiRosterImpl::Find(CHuiControlGroup* aGroup) const
       
   246     {
       
   247     for(TInt i = 0; i < iEntries.Count(); ++i)
       
   248         {
       
   249         if(&iEntries[i]->ControlGroup() == aGroup)
       
   250             {
       
   251             return i;
       
   252             }
       
   253         }
       
   254     return KErrNotFound;
       
   255     }
       
   256 
       
   257 
       
   258 void CHuiRosterImpl::Remove(CHuiControlGroup* aGroup)
       
   259     {
       
   260     TInt index = Find(aGroup);
       
   261     if(index != KErrNotFound)
       
   262         {
       
   263         delete iEntries[index];
       
   264         iEntries.Remove(index);
       
   265 
       
   266         if(iDisplay)
       
   267             {
       
   268             iDisplay->Env().ContinueRefresh();
       
   269             }
       
   270 
       
   271         SetChanged();
       
   272         }
       
   273     }
       
   274 
       
   275 
       
   276 TInt CHuiRosterImpl::Count() const
       
   277     {
       
   278     return iEntries.Count();
       
   279     }
       
   280 
       
   281 
       
   282 CHuiControlGroup& CHuiRosterImpl::ControlGroup(TInt aIndex) const
       
   283     {
       
   284     return iEntries[aIndex]->ControlGroup();
       
   285     }
       
   286 
       
   287 
       
   288 CHuiControl* CHuiRosterImpl::FindControl(TInt aControlId) const
       
   289     {
       
   290     CHuiControl* control = 0;
       
   291     for(TInt i = 0; i < iEntries.Count(); ++i)
       
   292         {
       
   293         control = iEntries[i]->ControlGroup().FindControl(aControlId);
       
   294         if(control)
       
   295             {
       
   296             break;
       
   297             }
       
   298         }
       
   299     return control;
       
   300     }
       
   301 
       
   302 
       
   303 CHuiRosterEntry* CHuiRosterImpl::EntryForVisual(const CHuiVisual* aVisual)
       
   304     {
       
   305     ASSERT( aVisual != NULL );
       
   306     CHuiControlGroup* group = aVisual->Owner().ControlGroup();
       
   307     TInt index = Find(group);
       
   308     if(index == KErrNotFound)
       
   309         {
       
   310         // The group is not in this roster.
       
   311         return NULL;
       
   312         }
       
   313     return iEntries[index];
       
   314     }
       
   315 
       
   316 
       
   317 void CHuiRosterImpl::ShowVisualL(CHuiVisual* aVisual)
       
   318     {
       
   319     CHuiRosterEntry* entry = EntryForVisual(aVisual);
       
   320 
       
   321     if(!entry)
       
   322         {
       
   323         User::Leave(KErrNotFound);
       
   324         }
       
   325     
       
   326     if(entry->iRootVisuals.Find(aVisual) != KErrNotFound)
       
   327         {
       
   328         User::Leave(KErrAlreadyExists);
       
   329         }
       
   330     
       
   331     User::LeaveIfError( entry->iRootVisuals.Append(aVisual) );
       
   332 
       
   333     SetVisualToFullArea(aVisual);    
       
   334     }
       
   335 
       
   336 
       
   337 void CHuiRosterImpl::HideVisual(CHuiVisual* aVisual)
       
   338     {
       
   339     ASSERT( aVisual );
       
   340     aVisual->SetDisplay(NULL);
       
   341     
       
   342     CHuiRosterEntry* entry = EntryForVisual(aVisual);
       
   343     if(entry)
       
   344         {
       
   345         TInt index = entry->iRootVisuals.Find(aVisual);
       
   346         if(index != KErrNotFound) // do nothing if visual was not found
       
   347             {
       
   348             entry->iRootVisuals.Remove(index);
       
   349     
       
   350             if(iDisplay)
       
   351                 {
       
   352                 iDisplay->Env().ContinueRefresh();
       
   353                 }
       
   354             }
       
   355         }
       
   356     }
       
   357 
       
   358 
       
   359 void CHuiRosterImpl::SetFocus(CHuiControl& aControl)
       
   360     {
       
   361     ChangeInputFocus(&aControl);
       
   362     }
       
   363 
       
   364 
       
   365 void CHuiRosterImpl::ClearFocus()
       
   366     {
       
   367     ChangeInputFocus(NULL);
       
   368     }
       
   369 
       
   370 
       
   371 void CHuiRosterImpl::ChangeInputFocus(CHuiControl* aControl)
       
   372     {
       
   373     if(aControl)
       
   374         {
       
   375         // The control must be in one of groups of the roster.
       
   376         CHuiControl* control = FindControl(aControl->Id());
       
   377         if(control != aControl)
       
   378             {
       
   379             // Illegal focus.
       
   380             return;
       
   381             }
       
   382         }
       
   383 
       
   384     iInputFocus = aControl;
       
   385     }
       
   386 
       
   387 TBool CHuiRosterImpl::PrepareDraw() const
       
   388     {
       
   389     HUI_PROBE_PROGRAMFLOW_ENTER(MHuiProbe::EProgramFlowPointRefreshPrepareDraw)
       
   390     
       
   391     TInt i = 0;
       
   392     TInt j = 0;
       
   393 
       
   394     TInt visualCount = 0;
       
   395     TInt entryCount = iEntries.Count();
       
   396     // Prepare the visuals tree in the display.
       
   397     for(j = 0; j < entryCount; ++j)
       
   398         {
       
   399         CHuiRosterEntry& entry = *iEntries[j]; 
       
   400         
       
   401         visualCount = entry.iRootVisuals.Count();
       
   402         for(i = 0; i < visualCount; ++i)
       
   403             {
       
   404             CHuiVisual* visual = entry.iRootVisuals[i];
       
   405             //Ignore inactive visuals
       
   406             if ( visual->Flags()& EHuiVisualFlagInactive )
       
   407             	{
       
   408             	continue; 
       
   409             	}
       
   410             TBool successfullyPrepared = ETrue;
       
   411             TRAPD(err, successfullyPrepared = visual->PrepareDrawL());
       
   412             if (err != KErrNone)
       
   413 	            {
       
   414 	            // Handle the error by calling the visual owner
       
   415 	            // errorhandling callback
       
   416                 visual->Owner().VisualPrepareDrawFailed(*visual, err);
       
   417 
       
   418                 HUI_PROBE_PROGRAMFLOW_EXIT(MHuiProbe::EProgramFlowPointRefreshPrepareDraw)
       
   419                 return EFalse;
       
   420 	            }
       
   421 	        if (!successfullyPrepared) 
       
   422 		        {
       
   423 		        // we can stop preparing the rest of the root visuals
       
   424 		        // if one prepare failed (we won't be drawing 
       
   425 		        // anything anyway)
       
   426 
       
   427 		        // also if the prepare failed but it didn't leave,
       
   428 		        // we assume it was already handled 
       
   429 
       
   430                 HUI_PROBE_PROGRAMFLOW_EXIT(MHuiProbe::EProgramFlowPointRefreshPrepareDraw)
       
   431 		        return EFalse;
       
   432 		        }
       
   433             }
       
   434         }
       
   435 
       
   436     HUI_PROBE_PROGRAMFLOW_EXIT(MHuiProbe::EProgramFlowPointRefreshPrepareDraw)
       
   437     return ETrue;
       
   438     }
       
   439 
       
   440 
       
   441 void CHuiRosterImpl::Draw(CHuiGc& aGc) const
       
   442     {
       
   443     Draw(aGc, NULL);
       
   444     }
       
   445 
       
   446 void CHuiRosterImpl::Draw(CHuiGc& aGc, CHuiDisplay* aDisplay) const
       
   447     {
       
   448     CHuiDisplay* display = aDisplay ? aDisplay : iDisplay;
       
   449     THuiRealRect displayRect = display->VisibleArea();
       
   450     TBool refreshCache = ETrue; // TODO: Could this be optimized ?
       
   451     TBool opaque = EFalse;  
       
   452 
       
   453     // Init projection matrix
       
   454     aGc.LoadIdentity(EHuiGcMatrixProjection);
       
   455 
       
   456     // Init model matrix 
       
   457     aGc.LoadIdentity(EHuiGcMatrixModel);        
       
   458     
       
   459     // Set up display-specifc window transformations e.g. scaling for tv out        
       
   460     aGc.SetWindowTransformation(&(display->WindowTransformation()));
       
   461     aGc.UpdateProjection();                            
       
   462 
       
   463     TBool didDrawEffect = EFalse;
       
   464     if (iEffect)
       
   465         {
       
   466         //RDebug::Print(_L("CHuiRosterImpl::Draw trying to use effect"));
       
   467         TRgb oldColor = aGc.PenColor(); 
       
   468         TInt oldAlpha = aGc.PenAlpha(); 
       
   469 
       
   470         // Clear
       
   471         aGc.SetPenColor(KRgbBlack);
       
   472         aGc.SetPenAlpha(0);
       
   473         aGc.Disable(CHuiGc::EFeatureBlending);
       
   474         aGc.Disable(CHuiGc::EFeatureClipping);
       
   475         aGc.Clear();
       
   476 
       
   477         // Restore Gc values
       
   478         aGc.SetPenColor(oldColor);
       
   479         aGc.SetPenAlpha(oldAlpha);
       
   480         aGc.Enable(CHuiGc::EFeatureBlending);
       
   481         aGc.Enable(CHuiGc::EFeatureClipping);
       
   482 
       
   483         // Note: Opacity implementation in effect system  does not really work visually 
       
   484         // correct if there are semitransparent child windows. Child window opacity becomes too
       
   485         // large, because opacity is applied during visual tree drawing and thus blending child
       
   486         // visuals on top of the parent produces wrong transparency level.
       
   487         //
       
   488         // We workaround this issue here so that we force rendering to cached render
       
   489         // target (with opacity 255) and give the real opacity as a parameter to effect
       
   490         // drawing so the whole operation gets correct opacity. However there is possibility
       
   491         // that complex effect fxml would assume transparency to be handled *before*
       
   492         // some other part of the effect, so this workaround won't work correctly in those cases. 
       
   493         // To get those working, propably whole opacity effect handling should be re-written 
       
   494         // differently.
       
   495         if (iEffect->IsSemitransparent() || iEffectOpacity < 1.f)
       
   496             {
       
   497             iEffect->ForceCachedRenderTargetUsage(ETrue);
       
   498             }        
       
   499         RRegion dummy;
       
   500         didDrawEffect = iEffect->CachedDraw(aGc, displayRect, refreshCache, opaque, dummy, iEffectOpacity*255);        
       
   501         dummy.Close();
       
   502         }
       
   503     
       
   504     if (!didDrawEffect)
       
   505         {
       
   506         DrawSelf(aGc, aDisplay);
       
   507         }
       
   508     else
       
   509         {
       
   510         // Effect was drawn, OpenGLES/OpenVG may be in different state than what Gc thinks so we restore it.
       
   511         aGc.RestoreState();                
       
   512         }
       
   513 
       
   514     // Undo display-specifc window transformations                          
       
   515     aGc.SetWindowTransformation(NULL);
       
   516     aGc.UpdateProjection();            
       
   517 
       
   518     // Undo changes to model matrix
       
   519     aGc.LoadIdentity(EHuiGcMatrixModel);    
       
   520     }
       
   521 
       
   522 void CHuiRosterImpl::DrawSelf(CHuiGc& aGc, CHuiDisplay* aDisplay) const
       
   523     {
       
   524     HUI_PROBE_PROGRAMFLOW_ENTER(MHuiProbe::EProgramFlowPointRefreshDraw)
       
   525 
       
   526     TInt i = 0;
       
   527     TInt j = 0;
       
   528 
       
   529     CHuiDisplay* display = aDisplay ? aDisplay : iDisplay;
       
   530 
       
   531     if (iCanvasRenderBuffer && iCanvasGc)
       
   532         {
       
   533         DrawSelfFrozen(aGc, aDisplay);
       
   534         return;
       
   535         }
       
   536 
       
   537     TInt visualCount = 0;
       
   538     TInt entryCount = iEntries.Count();
       
   539     // Draw the visuals tree in the display.
       
   540     for(j = 0; j < entryCount; ++j)
       
   541         {
       
   542         CHuiRosterEntry& entry = *iEntries[j]; 
       
   543         CHuiControlGroup& group = entry.ControlGroup();
       
   544 
       
   545         // Init model matrix always for every group
       
   546         //aGc.LoadIdentity(EHuiGcMatrixModel);        
       
   547         aGc.Push(EHuiGcMatrixModel);
       
   548         
       
   549         // Set up display-specifc transformations i.e. camera transformations    	
       
   550         display->Transformation().Execute(EHuiGcMatrixModel, aGc);
       
   551         
       
   552         // Set up a group-specific transformation.
       
   553         if(group.IsTransformed())
       
   554             {
       
   555    	        group.Transformation().Execute(EHuiGcMatrixModel, aGc);
       
   556             }
       
   557         
       
   558         // Draw visuals
       
   559         visualCount = entry.iRootVisuals.Count();
       
   560         for(i = 0; i < visualCount; ++i)
       
   561             {
       
   562             CHuiVisual* visual = entry.iRootVisuals[i];
       
   563             //Ignore inactive visuals
       
   564             if ( visual->Flags()& EHuiVisualFlagInactive || visual->LoadingEffect() )
       
   565             	{
       
   566             	continue; 
       
   567             	}
       
   568             visual->Draw(aGc);
       
   569             }       
       
   570 
       
   571         if( display->DrawVisualOutline() != CHuiDisplay::EDrawVisualOutlineNone )
       
   572             {        	
       
   573             for(i = 0; i < visualCount; ++i)
       
   574                 {	
       
   575                 // Draw Visual Outline depending on central repository setting
       
   576                 // and visual flag value
       
   577                 const TBool drawOutline =
       
   578                     ( entry.iRootVisuals[i]->Flags() & EHuiVisualFlagEnableDebugMode ) ||  
       
   579                     ( display->DrawVisualOutline() == CHuiDisplay::EDrawVisualOutlineAllVisuals );
       
   580                 
       
   581                 DrawBoundaries( aGc, entry.iRootVisuals[i], drawOutline );        
       
   582                 }
       
   583             }
       
   584         
       
   585         aGc.Pop(EHuiGcMatrixModel);        
       
   586         }
       
   587     
       
   588     HUI_PROBE_PROGRAMFLOW_EXIT(MHuiProbe::EProgramFlowPointRefreshDraw)
       
   589     }
       
   590 
       
   591 void CHuiRosterImpl::DrawSelfFrozen(CHuiGc& aGc, CHuiDisplay* aDisplay) const
       
   592     {
       
   593     if (iCanvasGc && iCanvasRenderBuffer)
       
   594         {
       
   595         iCanvasGc->SetGc(aGc);
       
   596         iCanvasGc->SetDefaults();
       
   597         iCanvasGc->PushTransformationMatrix();
       
   598                 
       
   599         // Calculate rotation as relative to the current display rotation.
       
   600         CHuiGc::TOrientation relativeOrientation = CHuiGc::EOrientationNormal;    
       
   601         CHuiGc::TOrientation displayOrientation = aDisplay->Orientation(); 
       
   602         CHuiGc::TOrientation renderBufferOrientation = iCanvasRenderBufferOrientation; 
       
   603         
       
   604         TInt rotationAngle[] =
       
   605             {
       
   606             0, 
       
   607             270, 
       
   608             90, 
       
   609             180
       
   610             };
       
   611             
       
   612         TInt displayOrientationAngle = rotationAngle[displayOrientation];
       
   613         TInt renderBufferOrientationAngle = rotationAngle[renderBufferOrientation];    
       
   614         TInt relativeOrientationAngle = renderBufferOrientationAngle - displayOrientationAngle;
       
   615         
       
   616         // Check over/underflow
       
   617         if (relativeOrientationAngle > 360)
       
   618             {
       
   619             relativeOrientationAngle -= 360;
       
   620             }
       
   621         else if (relativeOrientationAngle < 0)
       
   622             {
       
   623             relativeOrientationAngle += 360;
       
   624             }
       
   625         
       
   626         switch (relativeOrientationAngle)
       
   627             {
       
   628             case 0:
       
   629                 {
       
   630                 relativeOrientation = CHuiGc::EOrientationNormal;
       
   631                 break;
       
   632                 }
       
   633             case 90:
       
   634                 {
       
   635                 relativeOrientation = CHuiGc::EOrientationCW90;            
       
   636                 break;
       
   637                 }
       
   638             case 270:
       
   639                 {
       
   640                 relativeOrientation = CHuiGc::EOrientationCCW90;            
       
   641                 break;
       
   642                 }
       
   643             case 180:
       
   644                 {
       
   645                 relativeOrientation = CHuiGc::EOrientation180;            
       
   646                 break;
       
   647                 }
       
   648             default:
       
   649                 {
       
   650                 // As usual, this should not happen...but just in case it does use normal rotation
       
   651                 relativeOrientation = CHuiGc::EOrientationNormal;
       
   652                 break;
       
   653                 }        
       
   654             }
       
   655         
       
   656         TRect displayArea = aDisplay->VisibleArea();
       
   657         TInt w = displayArea.Width();
       
   658         TInt h = displayArea.Height();
       
   659 
       
   660        
       
   661         // ...select right rotation...
       
   662         if (relativeOrientation == CHuiGc::EOrientationCW90)
       
   663             {
       
   664             // Rotate around origo and move back to displayarea
       
   665             iCanvasGc->Rotate(-90, 0, 0, 1.f);
       
   666             iCanvasGc->Translate(-h, 0, 0);
       
   667             }
       
   668         else if (relativeOrientation == CHuiGc::EOrientationCCW90)
       
   669             {
       
   670             // Rotate around origo and move back to displayarea
       
   671             iCanvasGc->Rotate(90, 0, 0, 1.f);
       
   672             iCanvasGc->Translate(0, -w, 0);
       
   673             }
       
   674         else if (relativeOrientation == CHuiGc::EOrientation180)
       
   675             {
       
   676             // Rotate around origo and move back to displayarea
       
   677             iCanvasGc->Rotate(180, 0, 0, 1.f);
       
   678             iCanvasGc->Translate(-w, -h, 0);            
       
   679             }
       
   680         else
       
   681             {
       
   682             // Nothing
       
   683             }            
       
   684 
       
   685         // Pixels are upside down in OpenVG canvas render buffer
       
   686         if (CHuiStatic::Env().Renderer() == EHuiRendererVg10)
       
   687             {
       
   688             TInt height = h;
       
   689             if (relativeOrientation == CHuiGc::EOrientationCW90 || relativeOrientation == CHuiGc::EOrientationCCW90)
       
   690                 {
       
   691                 height = w;    
       
   692                 }            
       
   693             iCanvasGc->Translate(0.0f, height, 0.0f);            
       
   694             iCanvasGc->Scale(1.f, -1.f, 1.f);
       
   695             }
       
   696         
       
   697         iCanvasGc->DrawImage(*iCanvasRenderBuffer, TPoint(0,0));        
       
   698         iCanvasGc->PopTransformationMatrix();
       
   699         }
       
   700     }
       
   701 
       
   702 void CHuiRosterImpl::DrawBoundaries( CHuiGc& aGc, CHuiVisual* aVisual, TBool aDrawOutline ) const
       
   703 	{
       
   704     if( aDrawOutline )
       
   705         {
       
   706         const THuiRealRect content = aVisual->DisplayRect();
       
   707         
       
   708         if (aVisual->Flags()& EHuiVisualFlagInactive)
       
   709             {
       
   710             aGc.SetPenColor( KRgbDarkGray );           
       
   711             }
       
   712         else
       
   713             {
       
   714             aGc.SetPenColor( TUint32(aVisual)&0x00ffffff/*KRgbBlack*/ );  // Use "random" color
       
   715             }
       
   716         aGc.DrawBorders(content.Round(), 
       
   717             KHuiVisualOutlineWidth, KHuiVisualOutlineWidth,
       
   718             KHuiVisualOutlineWidth, KHuiVisualOutlineWidth,
       
   719             CHuiGc::EBorderFixedCorners);
       
   720         }
       
   721         
       
   722     for( TInt k = 0; k < aVisual->Count(); ++k )
       
   723         {
       
   724         DrawBoundaries( 
       
   725             aGc, 
       
   726             &aVisual->Visual( k ), 
       
   727             ( (  aVisual->Visual( k ).Flags() & EHuiVisualFlagEnableDebugMode ) || 
       
   728                 aDrawOutline ) );
       
   729         }
       
   730     }
       
   731 
       
   732 
       
   733 TBool CHuiRosterImpl::HasTransformedControlGroups() const
       
   734     {
       
   735     TInt j = 0;
       
   736     for(j = 0; j < iEntries.Count(); ++j)
       
   737         {
       
   738         CHuiRosterEntry& entry = *iEntries[j]; 
       
   739         CHuiControlGroup& group = entry.ControlGroup();
       
   740         if(group.IsTransformed())
       
   741             {
       
   742             return ETrue;    
       
   743             }
       
   744         }
       
   745     return EFalse;    
       
   746     }
       
   747 
       
   748 
       
   749 TBool CHuiRosterImpl::HandleEventL(const THuiEvent& aEvent)
       
   750     {
       
   751     TInt i = 0;
       
   752     TInt k = 0;
       
   753 
       
   754     if(iDisplay)
       
   755         {
       
   756         iDisplay->Env().ContinueRefresh();
       
   757         }
       
   758 
       
   759     if(aEvent.IsPointerEvent())
       
   760         {
       
   761         iTactileFeedbackHandled = EFalse;
       
   762         
       
   763         // Put event details array up to date
       
   764         CleanEventDetails();
       
   765         
       
   766         if ( !iLongTapDetector )
       
   767             {
       
   768             iLongTapDetector = CHuiLongTapDetector::NewL( *this );
       
   769             }
       
   770         iLongTapDetector->OfferPointerEvent( aEvent );
       
   771         
       
   772         if ( aEvent.PointerDown() )
       
   773         	{
       
   774         	iInitialDownEvent = aEvent;
       
   775         	CleanDraggingFlags();
       
   776         	}
       
   777 		
       
   778         
       
   779         // Restricted distribution?
       
   780         if(aEvent.iPointerEvent.iType == TPointerEvent::EDrag)
       
   781             {
       
   782             // Only send these if there are observers.
       
   783             for(i = 0; i < iPointerDragObservers.Count(); ++i)
       
   784                 {
       
   785                 if( DragEventOutOfRangeL( &iPointerDragObservers[i], aEvent) )
       
   786                 	{
       
   787 	                if(iPointerDragObservers[i].OfferEventL(aEvent))
       
   788 	                    {
       
   789 	                    return ETrue;
       
   790 	                    }                                    	
       
   791                 	}
       
   792                 }
       
   793             return EFalse;
       
   794             }
       
   795             
       
   796         // The event is generated by the long tap detector
       
   797         if(aEvent.iPointerEvent.iType == TPointerEvent::EButtonRepeat)
       
   798             {
       
   799             // Only send these if there are observers.
       
   800             for(i = 0; i < iLongTapObservers.Count(); ++i)
       
   801                 {
       
   802                 if(IsLongTapEventAllowed(&iLongTapObservers[i]))
       
   803                 	{
       
   804 	                if(iLongTapObservers[i].OfferEventL(aEvent))
       
   805 	                    {
       
   806 	                    return ETrue;
       
   807 	                    }                	
       
   808                 	}
       
   809                 }
       
   810             return EFalse;
       
   811             }  
       
   812         
       
   813         // The other pointer events are offered depending on the visuals.
       
   814         for(i = iEntries.Count() - 1; i >= 0; --i)
       
   815             {
       
   816             CHuiRosterEntry& entry = *iEntries[i];
       
   817             CHuiControlGroup& group = entry.ControlGroup();
       
   818             
       
   819             if(!group.AcceptInput())
       
   820                 {
       
   821                 // The group will not be receiving input events.
       
   822                 continue;
       
   823                 }
       
   824            
       
   825             for(k = entry.iRootVisuals.Count() - 1; k >= 0; --k)
       
   826                 {
       
   827                 if(OfferPointerEventWithinTreeL(*entry.iRootVisuals[k], aEvent))
       
   828                     {
       
   829                     return ETrue;
       
   830                     }
       
   831                 }    
       
   832                 
       
   833             // Offer to the fallback handlers of the group.
       
   834             for(k = 0; k < group.iUnhandledEventObservers.Count(); ++k)
       
   835                 {
       
   836                 if(group.iUnhandledEventObservers[k].OfferEventL(aEvent))
       
   837                     {
       
   838                     return ETrue;
       
   839                     }
       
   840                 }
       
   841             }
       
   842             
       
   843         // No one handled the event.
       
   844         for(i = 0; i < iUnhandledPointerObservers.Count(); ++i)
       
   845             {
       
   846             if(iUnhandledPointerObservers[i].OfferEventL(aEvent))
       
   847                 {
       
   848                 return ETrue;
       
   849                 }
       
   850             }
       
   851         }
       
   852     else 
       
   853         {
       
   854         // First offer to the input control.
       
   855         if(aEvent.IsKeyEvent() && iInputFocus && iInputFocus->AcceptInput())
       
   856             {
       
   857             if(iInputFocus->OfferEventL(aEvent))
       
   858                 {
       
   859                 return ETrue;
       
   860                 }
       
   861             }
       
   862 
       
   863         // Iterate through the groups and controls in priority order.
       
   864         for(i = iEntries.Count() - 1; i >= 0; --i)
       
   865             {
       
   866             CHuiControlGroup& group = iEntries[i]->ControlGroup();
       
   867             
       
   868             if(!group.AcceptInput())
       
   869                 {
       
   870                 // The group will not be receiving input events.
       
   871                 continue;
       
   872                 }
       
   873             
       
   874             for(k = group.Count() - 1; k >= 0; --k)
       
   875                 {
       
   876                 CHuiControl& control = group.Control(k);
       
   877                 if(control.OfferEventL(aEvent))
       
   878                     {
       
   879                     // The event was consumed, now it can't be handled by
       
   880                     // anyone else.
       
   881                     return ETrue;
       
   882                     }
       
   883                 }
       
   884             // Notify observer that group didn't handle event?
       
   885             }
       
   886         }
       
   887 
       
   888     return EFalse;
       
   889     }
       
   890     
       
   891     
       
   892 TBool CHuiRosterImpl::OfferPointerEventWithinTreeL(CHuiVisual& aVisual, const THuiEvent& aEvent, TBool aUseDispRect)
       
   893     {
       
   894     //Ignore inactive visuals
       
   895     if( ( aVisual.Flags() & EHuiVisualFlagIgnorePointer ) || 
       
   896     		( aVisual.Flags() & EHuiVisualFlagInactive ) )
       
   897         {
       
   898         // Discard the entire branch of visuals.
       
   899         return EFalse;
       
   900         }
       
   901 
       
   902     const TPoint& pos = aEvent.iPointerEvent.iPosition;
       
   903     
       
   904     TBool useDispRect = EFalse;
       
   905     // If it has children, offer to those first.
       
   906     for(TInt i = aVisual.Count() - 1; i >= 0; --i)
       
   907         {
       
   908         // set useDispRect, if scroll is enabled on a layout
       
   909         useDispRect = static_cast<CHuiLayout&>(aVisual).Scrolling();
       
   910         
       
   911         if(OfferPointerEventWithinTreeL(aVisual.Visual(i), aEvent, useDispRect))
       
   912             {
       
   913             return ETrue;
       
   914             }
       
   915         }
       
   916             
       
   917     TRect visualRect;
       
   918     if(aUseDispRect)
       
   919         {
       
   920         visualRect = TRect(aVisual.DisplayRect());
       
   921         }
       
   922     else
       
   923         {
       
   924         // use cashed display rect
       
   925         visualRect = TRect(aVisual.CachedDisplayRect());
       
   926         }
       
   927     
       
   928     // Offer to the visual itself.
       
   929     if(visualRect.Contains(pos))
       
   930         {
       
   931         HUI_DEBUG3(_L("CHuiRosterImpl::OfferPointerEventWithinTreeL: aVisual=%x pos=%i,%i"), 
       
   932             &aVisual, pos.iX, pos.iY);
       
   933 
       
   934         MHuiEventHandler* handler = aVisual.Owner().EventHandler();
       
   935         if(handler)
       
   936             {
       
   937             THuiEvent eventWithVisual = aEvent;
       
   938             eventWithVisual.SetVisual(&aVisual);
       
   939             HandleTactileFeedback( eventWithVisual );
       
   940             if(handler->OfferEventL(eventWithVisual))
       
   941                 {
       
   942                 return ETrue;
       
   943                 }
       
   944             }
       
   945         }
       
   946         
       
   947     // Not consumed.
       
   948     return EFalse;        
       
   949     }
       
   950     
       
   951     
       
   952 TBool CHuiRosterImpl::Changed() const
       
   953     {
       
   954     if(iChanged)
       
   955         {
       
   956         return ETrue;
       
   957         }
       
   958     
       
   959     TInt entryCount = iEntries.Count();
       
   960     for(TInt i = 0; i < entryCount; ++i)
       
   961         {
       
   962         if(iEntries[i]->ControlGroup().Changed())
       
   963             {
       
   964             return ETrue;
       
   965             }
       
   966         }
       
   967 
       
   968     if (iEffect && iEffect->Changed())
       
   969         {
       
   970         return ETrue;
       
   971         }
       
   972                         
       
   973     return EFalse;        
       
   974     }
       
   975     
       
   976     
       
   977 void CHuiRosterImpl::ScanDirty()
       
   978     {
       
   979     if(Changed())
       
   980         {
       
   981         // If the entire roster has changed, there is no need to query 
       
   982         // individual visuals.
       
   983         if(iDisplay)
       
   984             {
       
   985             iDisplay->AddDirtyRegion(iRect);
       
   986             }
       
   987         
       
   988         SetChanged(EFalse);
       
   989         return;
       
   990         }
       
   991     
       
   992     if (iDisplay && !iDisplay->IsDirtyScanNeeded())
       
   993         {
       
   994         // Dirty scan is not needed, we can return directly.
       
   995         return;    
       
   996         }
       
   997     
       
   998     TInt entryCount = iEntries.Count();
       
   999     for(TInt j = 0; j < entryCount; ++j)
       
  1000         {
       
  1001         CHuiRosterEntry& entry = *iEntries[j]; 
       
  1002         TInt count = entry.iRootVisuals.Count();
       
  1003         for(TInt i = 0; i < count; ++i)
       
  1004             {
       
  1005             //Ignore inactive visuals
       
  1006             if ( entry.iRootVisuals[i]->Flags()& EHuiVisualFlagInactive )
       
  1007            		{
       
  1008            		continue; 
       
  1009            		}
       
  1010             entry.iRootVisuals[i]->ReportChanged();
       
  1011             }
       
  1012         }
       
  1013     }
       
  1014 
       
  1015 
       
  1016 // This ScanDirty-method supports transformed dirty rects
       
  1017 void CHuiRosterImpl::ScanTransformedDirty(CHuiGc& aGc, CHuiDisplay* aDisplay)
       
  1018     {
       
  1019     CHuiDisplay* display = aDisplay ? aDisplay : iDisplay;
       
  1020 
       
  1021     // Init projection matrix
       
  1022     aGc.LoadIdentity(EHuiGcMatrixProjection);
       
  1023 
       
  1024     // Set up display-specifc window transformations e.g. scaling for tv out    	
       
  1025     aGc.SetWindowTransformation(&(display->WindowTransformation()));
       
  1026     aGc.UpdateProjection();                            
       
  1027 
       
  1028     if(Changed()) 
       
  1029         {
       
  1030         // If the entire roster has changed, there is no need to query 
       
  1031         // individual visuals.
       
  1032         if(display)
       
  1033             {
       
  1034             display->AddDirtyRegion(iRect);
       
  1035             }
       
  1036         
       
  1037         SetChanged(EFalse);
       
  1038         }
       
  1039     
       
  1040     for(TInt j = 0; j < iEntries.Count(); ++j)
       
  1041     	{
       
  1042         if (display && !display->IsDirtyScanNeeded())
       
  1043         	{
       
  1044             break;    
       
  1045             }
       
  1046 
       
  1047         CHuiRosterEntry& entry = *iEntries[j]; 
       
  1048         CHuiControlGroup& group = entry.ControlGroup();
       
  1049 
       
  1050         // Init model matrix always for every group
       
  1051         aGc.LoadIdentity(EHuiGcMatrixModel);        
       
  1052             
       
  1053         // Set up display-specifc transformations i.e. camera transformations    	
       
  1054         __ASSERT_DEBUG(display, USER_INVARIANT());
       
  1055         display->Transformation().Execute(EHuiGcMatrixModel, aGc);
       
  1056             
       
  1057         // Set up a group-specific transformation.
       
  1058         if(group.IsTransformed())
       
  1059             {
       
  1060             group.Transformation().Execute(EHuiGcMatrixModel, aGc);
       
  1061             }
       
  1062 
       
  1063         for(TInt i = 0; i < entry.iRootVisuals.Count(); ++i)
       
  1064             {
       
  1065             if (display && !display->IsDirtyScanNeeded())
       
  1066                 {
       
  1067                 break;    
       
  1068                 }
       
  1069             //Ignore inactive visuals     
       
  1070             if ( entry.iRootVisuals[i]->Flags()& EHuiVisualFlagInactive )
       
  1071            		{
       
  1072                 continue;
       
  1073            		}
       
  1074             entry.iRootVisuals[i]->ReportChanged();
       
  1075             }
       
  1076         }
       
  1077 
       
  1078     // Undo display-specifc window transformations                          
       
  1079     aGc.SetWindowTransformation(NULL);
       
  1080     aGc.UpdateProjection();            
       
  1081 
       
  1082     // Undo changes to model matrix
       
  1083     aGc.LoadIdentity(EHuiGcMatrixModel);
       
  1084     }
       
  1085 
       
  1086 
       
  1087 void CHuiRosterImpl::MoveVisualToFront(CHuiVisual* aRootVisual)
       
  1088     {
       
  1089     ASSERT( aRootVisual );
       
  1090     MoveVisualToFront(*aRootVisual);
       
  1091     }
       
  1092 
       
  1093 
       
  1094 void CHuiRosterImpl::MoveVisualToFront(const CHuiVisual& aRootVisual)
       
  1095     {
       
  1096     CHuiRosterEntry* entry = EntryForVisual(&aRootVisual);
       
  1097     __ASSERT_ALWAYS( entry != NULL, THuiPanic::Panic(THuiPanic::ERosterGroupNotFound) );
       
  1098     TInt index = entry->iRootVisuals.Find(&aRootVisual);
       
  1099     if(index == KErrNotFound)
       
  1100         {
       
  1101         /** @todo Panic? */
       
  1102         return;
       
  1103         }
       
  1104         
       
  1105     entry->iRootVisuals.Remove(index);
       
  1106     entry->iRootVisuals.Append(&aRootVisual);        
       
  1107     
       
  1108     UpdateLayout();
       
  1109     }
       
  1110     
       
  1111      
       
  1112 void CHuiRosterImpl::UpdateLayout()
       
  1113     {
       
  1114     SetChanged();
       
  1115     
       
  1116     TInt visualCount = 0;
       
  1117     TInt entryCount = iEntries.Count();
       
  1118     for(TInt i = 0; i < entryCount; ++i)
       
  1119         {
       
  1120         visualCount = iEntries[i]->iRootVisuals.Count();
       
  1121         for(TInt j = 0; j < visualCount; ++j)
       
  1122             {
       
  1123             //Ignore inactive visuals
       
  1124             if ( iEntries[i]->iRootVisuals[j]->Flags()& EHuiVisualFlagInactive )
       
  1125             	{
       
  1126             	continue;
       
  1127             	}
       
  1128             SetVisualToFullArea(iEntries[i]->iRootVisuals[j]);
       
  1129             }
       
  1130         }
       
  1131     }    
       
  1132 
       
  1133 
       
  1134 void CHuiRosterImpl::SetVisualToFullArea(CHuiVisual* aVisual)
       
  1135     {
       
  1136     ASSERT( aVisual );
       
  1137     
       
  1138     TInt globalTransitionTime = CHuiStatic::LayoutTransitionTime();
       
  1139     
       
  1140     // Root visuals are automatically full size.
       
  1141     /** @todo  Needs a better way to set the visual's display. */
       
  1142     if(iDisplay)
       
  1143         {
       
  1144         aVisual->SetDisplay(iDisplay);
       
  1145         iDisplay->Env().ContinueRefresh();
       
  1146         }
       
  1147     
       
  1148     if(!(aVisual->Flags() & EHuiVisualFlagManualPosition))
       
  1149         {
       
  1150         aVisual->SetPos(iRect.iTl, globalTransitionTime);
       
  1151         }
       
  1152 
       
  1153     if(!(aVisual->Flags() & EHuiVisualFlagManualSize))
       
  1154         {
       
  1155         aVisual->SetSize(iRect.Size(), globalTransitionTime);
       
  1156         }
       
  1157     else
       
  1158         {
       
  1159         aVisual->UpdateChildrenLayout(globalTransitionTime);
       
  1160         }
       
  1161         
       
  1162     aVisual->ReportLayoutUpdate();        
       
  1163     }
       
  1164 
       
  1165 
       
  1166 void CHuiRosterImpl::NotifySkinChangedL()
       
  1167     {
       
  1168     TInt visualCount = 0;
       
  1169     TInt entryCount = iEntries.Count();
       
  1170     for(TInt j = 0; j < entryCount; ++j)
       
  1171         {
       
  1172         CHuiRosterEntry& entry = *iEntries[j];
       
  1173         visualCount = entry.iRootVisuals.Count();
       
  1174         for(TInt i = 0; i < visualCount; ++i)
       
  1175             {
       
  1176             //Ignore inactive visuals
       
  1177             if ( entry.iRootVisuals[i]->Flags()& EHuiVisualFlagInactive )
       
  1178             	{
       
  1179             	continue;	
       
  1180             	}
       
  1181             entry.iRootVisuals[i]->NotifySkinChangedL();
       
  1182             }
       
  1183         }
       
  1184     }
       
  1185 
       
  1186 
       
  1187 void CHuiRosterImpl::DumpRootLevelTrees() const
       
  1188     {
       
  1189     TInt visualCount = 0;
       
  1190     TInt entryCount = iEntries.Count();
       
  1191     for(TInt j = 0; j < entryCount; ++j)
       
  1192         {
       
  1193         CHuiRosterEntry& entry = *iEntries[j];
       
  1194         visualCount = entry.iRootVisuals.Count();
       
  1195         for(TInt i = 0; i < visualCount; ++i)
       
  1196             {
       
  1197             CHuiVisual* visual = entry.iRootVisuals[i];
       
  1198             visual->DumpTree();
       
  1199             }
       
  1200         }
       
  1201     }
       
  1202 
       
  1203 
       
  1204 void CHuiRosterImpl::ClearChanged()
       
  1205     {
       
  1206     HUI_DEBUGF(_L("CHuiRosterImpl::ClearChanged() - Clearing all change flags."));
       
  1207     
       
  1208     TInt visualCount = 0;
       
  1209     TInt entryCount = iEntries.Count();
       
  1210     for(TInt j = 0; j < entryCount; ++j)
       
  1211         {
       
  1212         CHuiRosterEntry& entry = *iEntries[j];
       
  1213         visualCount = entry.iRootVisuals.Count();
       
  1214         for(TInt i = 0; i < visualCount; ++i)
       
  1215             {
       
  1216             // Ignore inactive visuals
       
  1217             if ( entry.iRootVisuals[i]->Flags()& EHuiVisualFlagInactive )
       
  1218                 {
       
  1219                 continue; 
       
  1220                 }
       
  1221             
       
  1222             // This will clear the change flags of the entire tree of visuals.
       
  1223             entry.iRootVisuals[i]->ClearChanged();
       
  1224             }
       
  1225         }
       
  1226     }
       
  1227 
       
  1228 
       
  1229 void CHuiRosterImpl::SetChanged(TBool aIsChanged)
       
  1230     {
       
  1231     if(aIsChanged && !iChanged)
       
  1232         {
       
  1233         HUI_DEBUG(_L("CHuiRosterImpl::SetChanged() - Roster flagged as changed."));
       
  1234         }
       
  1235     else if(!aIsChanged && iChanged)
       
  1236         {
       
  1237         HUI_DEBUG(_L("CHuiRosterImpl::SetChanged() - Roster change flag cleared."));
       
  1238         }
       
  1239     else
       
  1240         {
       
  1241         // for PC lint
       
  1242         }
       
  1243         
       
  1244     iChanged = aIsChanged;
       
  1245     }
       
  1246 
       
  1247 
       
  1248 RHuiObserverArray<MHuiEventHandler>& CHuiRosterImpl::Observers(THuiInputType aInputType)
       
  1249     {
       
  1250     switch(aInputType)
       
  1251         {
       
  1252         case EHuiInputPointerDrag:
       
  1253             return iPointerDragObservers;
       
  1254             
       
  1255         case EHuiInputPointerLongTap:
       
  1256             return iLongTapObservers;
       
  1257 
       
  1258         case EHuiInputPointerUnhandled:
       
  1259             return iUnhandledPointerObservers;
       
  1260             
       
  1261         default:
       
  1262             HUI_PANIC(THuiPanic::ERosterUnknownInputObserverType)
       
  1263             return iPointerDragObservers; // never reached
       
  1264         }
       
  1265     }
       
  1266     
       
  1267 void CHuiRosterImpl::HandleTactileFeedback( const THuiEvent& aEvent )
       
  1268     {
       
  1269     // If tactile feedback has been already deciede for this event....
       
  1270     if ( iTactileFeedbackHandled )
       
  1271         {
       
  1272         return;
       
  1273         }
       
  1274     
       
  1275     // The tactile feedback is defined on visual basis
       
  1276     if ( !aEvent.Visual() )
       
  1277         {
       
  1278         // no visual, no feedback
       
  1279         return;
       
  1280         }
       
  1281         
       
  1282     // Only pointer events
       
  1283     if ( !aEvent.IsPointerEvent() )
       
  1284         {
       
  1285         return;
       
  1286         }
       
  1287         
       
  1288     // Currently support only pointer down events
       
  1289     if ( !aEvent.PointerDown() )
       
  1290         {
       
  1291         return;
       
  1292         }
       
  1293         
       
  1294     const TInt eventType = 0; // = ETouchEventStylusDown
       
  1295     
       
  1296     // Check if the viusal has a tactile feedback specified
       
  1297     const TInt feedbackType = aEvent.Visual()->TactileFeedback( eventType );
       
  1298     
       
  1299     if ( feedbackType != KErrNotFound )
       
  1300         {
       
  1301         iTactileFeedbackHandled = ETrue; // Handling it now.
       
  1302         
       
  1303 #ifdef RD_TACTILE_FEEDBACK
       
  1304         MTouchFeedback* feedback = MTouchFeedback::Instance();
       
  1305         if ( feedback )
       
  1306             {
       
  1307             feedback->InstantFeedback( (TTouchLogicalFeedback)feedbackType );
       
  1308             }   
       
  1309 #else
       
  1310 
       
  1311 #ifdef _DEBUG
       
  1312         // for RnD
       
  1313         switch( feedbackType )
       
  1314             {
       
  1315             case 0: // none
       
  1316                 User::InfoPrint( _L("None") );
       
  1317                 break;
       
  1318             case 1: // basic
       
  1319                 User::InfoPrint( _L("Basic") );
       
  1320                 break;
       
  1321             case 2: // sensitive
       
  1322                 User::InfoPrint( _L("Sensitive") );
       
  1323                 break;
       
  1324             default:
       
  1325                 break;
       
  1326             }
       
  1327 #endif // _DEBUG
       
  1328 
       
  1329 #endif
       
  1330         }
       
  1331     }
       
  1332 
       
  1333 // Adds new detail entry to iPointerEventDetails
       
  1334 void CHuiRosterImpl::AddEventDetailsL(MHuiEventHandler* aEventHandler, const THuiXYMetric& aXYMetric, TBool aDisable)
       
  1335 	{
       
  1336 	THuiPointerEventDetails* newDetails = new (ELeave) THuiPointerEventDetails;
       
  1337 	newDetails->iEventHandler = aEventHandler;
       
  1338 	newDetails->iXYMetric = aXYMetric;
       
  1339 	newDetails->iDisableLongTapWhenDragging = aDisable;
       
  1340 	newDetails->iDragging = EFalse;	
       
  1341 	TInt err = iPointerEventDetails.Append(newDetails);
       
  1342 	if ( err != KErrNone )
       
  1343 	    {
       
  1344 	    delete newDetails;
       
  1345 	    User::Leave( err );
       
  1346 	    }
       
  1347 	}
       
  1348 	
       
  1349 // Cleans entries from iPointerEventDetails if there isn't observer for 
       
  1350 // that event handler
       
  1351 void CHuiRosterImpl::CleanEventDetails()
       
  1352 	{
       
  1353 	TInt i = 0;
       
  1354 	
       
  1355 	while(i < iPointerEventDetails.Count())
       
  1356 		{
       
  1357 		TBool used = EFalse;
       
  1358 		
       
  1359 		// Check in drag observers
       
  1360 		for(TInt j = 0; j < iPointerDragObservers.Count(); ++j)
       
  1361 			{
       
  1362 			if(iPointerEventDetails[i]->iEventHandler == &iPointerDragObservers[j])
       
  1363 				{
       
  1364 				used = ETrue;
       
  1365 				break;
       
  1366 				}
       
  1367 			}
       
  1368 
       
  1369 		// Check in long tap observers
       
  1370 		if(!used) 
       
  1371 			{
       
  1372 			for(TInt j = 0; j < iLongTapObservers.Count(); ++j)
       
  1373 				{
       
  1374 				if(iPointerEventDetails[i]->iEventHandler == &iLongTapObservers[j])
       
  1375 					{
       
  1376 					used = ETrue;
       
  1377 					break;
       
  1378 					}
       
  1379 				}			
       
  1380 			}
       
  1381 			
       
  1382 		// Check in unhandled observers
       
  1383 		if(!used) 
       
  1384 			{
       
  1385 			for(TInt j = 0; j < iUnhandledPointerObservers.Count(); ++j)
       
  1386 				{
       
  1387 				if(iPointerEventDetails[i]->iEventHandler == &iUnhandledPointerObservers[j])
       
  1388 					{
       
  1389 					used = ETrue;
       
  1390 					break;
       
  1391 					}
       
  1392 				}
       
  1393 			}
       
  1394 		
       
  1395 		// If event handler isn't found in observers, we remove details for that
       
  1396 		// event handler from iPointerEventDetails
       
  1397 		if(!used)
       
  1398 			{
       
  1399 			delete iPointerEventDetails[i];
       
  1400 			iPointerEventDetails.Remove(i);
       
  1401 			}
       
  1402 		else
       
  1403 			{
       
  1404 			i++;
       
  1405 			}
       
  1406 		}	
       
  1407 	}
       
  1408 
       
  1409 // Cleans dragging flags in iPointerEventDetails
       
  1410 void CHuiRosterImpl::CleanDraggingFlags()
       
  1411 	{
       
  1412 	for(TInt i = 0; i < iPointerEventDetails.Count(); ++i)
       
  1413 		{
       
  1414 		iPointerEventDetails[i]->iDragging = EFalse;
       
  1415 		}
       
  1416 	}
       
  1417 
       
  1418 // Sets treshold which pointer needs to be moved before starting to send drag events.
       
  1419 void CHuiRosterImpl::SetPointerDragThresholdL(const MHuiEventHandler& aEventHandler, const THuiXYMetric& aXYMetric)
       
  1420 	{		
       
  1421 	MHuiEventHandler *handler = (MHuiEventHandler*)&aEventHandler;
       
  1422 
       
  1423 	// Check if there is already detail entry in iPointerEventDetails where to update
       
  1424 	// details
       
  1425 	for(TInt i = 0; i < iPointerEventDetails.Count(); ++i)
       
  1426 		{
       
  1427 		if(iPointerEventDetails[i]->iEventHandler == handler)
       
  1428 			{
       
  1429 			iPointerEventDetails[i]->iXYMetric = aXYMetric;
       
  1430 			return;
       
  1431 			}					
       
  1432 		}
       
  1433 	
       
  1434 	// If event handler wasn't found, we add new detail entry
       
  1435 	AddEventDetailsL(handler, aXYMetric, EFalse);
       
  1436 	}
       
  1437 	
       
  1438 // Disables long tap events when dragging is going on. 
       
  1439 void  CHuiRosterImpl::DisableLongTapEventsWhenDraggingL(const MHuiEventHandler& aEventHandler, TBool aDisable)
       
  1440 	{
       
  1441 	MHuiEventHandler* handler = const_cast<MHuiEventHandler*>( &aEventHandler );
       
  1442 	
       
  1443 	// Check if there is already detail entry in iPointerEventDetails where to update
       
  1444 	// details
       
  1445 	for(TInt i = 0; i < iPointerEventDetails.Count(); ++i)
       
  1446 		{
       
  1447 		if(iPointerEventDetails[i]->iEventHandler == handler)
       
  1448 			{
       
  1449 			iPointerEventDetails[i]->iDisableLongTapWhenDragging = aDisable;
       
  1450 			return;
       
  1451 			}
       
  1452 		}	
       
  1453 
       
  1454 	// If event handler wasn't found, we add new detail entry
       
  1455 	AddEventDetailsL(handler, THuiXYMetric(KDefaultDragTresholdInPixelsX, KDefaultDragTresholdInPixelsY), aDisable);
       
  1456 	}
       
  1457 
       
  1458 // Checks if event handler is within threshold range.
       
  1459 TBool CHuiRosterImpl::DragEventOutOfRangeL(MHuiEventHandler* aEventHandler, const THuiEvent& aEvent)
       
  1460 	{	
       
  1461  	if ( aEvent.IsPointerEvent() && iInitialDownEvent.IsPointerEvent())
       
  1462         {
       
  1463 		TBool handlerFound = EFalse;
       
  1464 		
       
  1465 		// Find event handler from detail array
       
  1466 		for(TInt i = 0; i < iPointerEventDetails.Count(); ++i)
       
  1467 			{
       
  1468 			if(iPointerEventDetails[i]->iEventHandler == aEventHandler)
       
  1469 				{
       
  1470 				
       
  1471 				// If we are already sending dragging events to this handler
       
  1472 				// we can return immediately
       
  1473 				if(iPointerEventDetails[i]->iDragging) 
       
  1474 					{
       
  1475 					return ETrue;
       
  1476 					}
       
  1477 					
       
  1478 				handlerFound = ETrue;
       
  1479 				
       
  1480 				// calculate moved distance in pixels
       
  1481 				TPoint result = iInitialDownEvent.iPointerEvent.iPosition-aEvent.iPointerEvent.iPosition;
       
  1482 								
       
  1483 				// Do metric calculations
       
  1484 			    THuiRealPoint tresholdInPx(iPointerEventDetails[i]->iXYMetric.iX.iMagnitude, iPointerEventDetails[i]->iXYMetric.iY.iMagnitude);
       
  1485 			    if(iPointerEventDetails[i]->iXYMetric.iX.iUnit != EHuiUnitPixel) 
       
  1486 			    	{
       
  1487 			    	TReal32 reference = 0;
       
  1488 			    	if (iPointerEventDetails[i]->iXYMetric.iX.iUnit == EHuiUnitRelativeToDisplay && iDisplay ) 
       
  1489 			    		{
       
  1490 			    		reference = iDisplay->VisibleArea().Width();
       
  1491 			    		}
       
  1492 			    	if (iPointerEventDetails[i]->iXYMetric.iX.iUnit == EHuiUnitS60  && iDisplay ) 
       
  1493 			    		{
       
  1494 			    		reference = iDisplay->UnitValue();
       
  1495 			    		}			    		
       
  1496 			    	tresholdInPx.iX = tresholdInPx.iX * reference;
       
  1497 			    	}
       
  1498 			    if(iPointerEventDetails[i]->iXYMetric.iY.iUnit != EHuiUnitPixel) 
       
  1499 			    	{
       
  1500 			    	TReal32 reference = 0;
       
  1501 			    	if (iPointerEventDetails[i]->iXYMetric.iY.iUnit == EHuiUnitRelativeToDisplay && iDisplay ) 
       
  1502 			    		{
       
  1503 			    		reference = iDisplay->VisibleArea().Width();
       
  1504 			    		}
       
  1505 			    	if (iPointerEventDetails[i]->iXYMetric.iY.iUnit == EHuiUnitS60  && iDisplay ) 
       
  1506 			    		{
       
  1507 			    		reference = iDisplay->UnitValue();
       
  1508 			    		}			    		
       
  1509 			    	tresholdInPx.iY = tresholdInPx.iY * reference;
       
  1510 			    	}
       
  1511 			    
       
  1512 			    // Check if we are outside of the threshold
       
  1513 				if (result.iX < -tresholdInPx.iX || result.iX > tresholdInPx.iX||
       
  1514 					result.iY < -tresholdInPx.iY ||	result.iY > tresholdInPx.iY	) 
       
  1515 					{
       
  1516 					iPointerEventDetails[i]->iDragging = ETrue;					
       
  1517 					return ETrue;						
       
  1518 					}
       
  1519 				else
       
  1520 					{
       
  1521 					iPointerEventDetails[i]->iDragging = EFalse;
       
  1522 					}
       
  1523 				}
       
  1524 			}
       
  1525 			
       
  1526 		// If no event handler found in iPointerEventDetails array,
       
  1527 		// check with default threshold.
       
  1528 		if(!handlerFound) 
       
  1529 			{
       
  1530 			TPoint result = iInitialDownEvent.iPointerEvent.iPosition-aEvent.iPointerEvent.iPosition;
       
  1531 								
       
  1532 			if (result.iX < -KDefaultDragTresholdInPixelsX || result.iX > KDefaultDragTresholdInPixelsX||
       
  1533 				result.iY < -KDefaultDragTresholdInPixelsY || result.iY > KDefaultDragTresholdInPixelsY) 
       
  1534 				{
       
  1535 				// We need to add new event detail to store dragging flag
       
  1536 				AddEventDetailsL(aEventHandler, THuiXYMetric(KDefaultDragTresholdInPixelsX, KDefaultDragTresholdInPixelsY), EFalse);
       
  1537 				return DragEventOutOfRangeL(aEventHandler, aEvent);
       
  1538 				}			
       
  1539 			}		
       
  1540         }	
       
  1541 	return EFalse;
       
  1542 	}
       
  1543 
       
  1544 // Checks if long tap event is allowed to send.
       
  1545 TBool CHuiRosterImpl::IsLongTapEventAllowed(MHuiEventHandler* aEventHandler)
       
  1546 	{
       
  1547 	for(TInt i = 0; i < iPointerEventDetails.Count(); ++i)
       
  1548 		{
       
  1549 		if(iPointerEventDetails[i]->iEventHandler == aEventHandler)
       
  1550 			{
       
  1551 			if ( iPointerEventDetails[i]->iDragging ) 
       
  1552 				{
       
  1553 				return !(iPointerEventDetails[i]->iDisableLongTapWhenDragging);				
       
  1554 				}
       
  1555 			}	
       
  1556         }	
       
  1557 	return ETrue;
       
  1558 	}
       
  1559 
       
  1560 
       
  1561 void CHuiRosterImpl::SetDrawingExternalContent(TBool aEnable)
       
  1562 	{
       
  1563 	iDrawEvenIfDisabledDrawInRoster = aEnable;
       
  1564 	}
       
  1565 
       
  1566 	
       
  1567 TBool CHuiRosterImpl::IsDrawingExternalContent() const
       
  1568 	{
       
  1569 	return iDrawEvenIfDisabledDrawInRoster;
       
  1570 	}
       
  1571 
       
  1572 void CHuiRosterImpl::RemoveExternalContentVisualFromParentL(CHuiVisual* aExternalContentVisual)
       
  1573     {
       
  1574     // External content is only used with canvas visuals, and the layouts of canvas visuals are always in the roster.
       
  1575     // Browse all layouts in the roster and check if they have a canvas visual as a child visual.
       
  1576     // Note: this can be slow operation, so it should only be done rarely.
       
  1577    
       
  1578     TInt visualCount = 0;
       
  1579     TInt entryCount = iEntries.Count();    
       
  1580     for(TInt j = 0; j < entryCount; ++j)
       
  1581     	{
       
  1582     	CHuiRosterEntry& entry = *iEntries[j]; // control group
       
  1583     	visualCount = entry.iRootVisuals.Count();
       
  1584         for(TInt i = 0; i < visualCount; ++i)
       
  1585         	{
       
  1586         	CHuiLayout* layout = dynamic_cast<CHuiLayout*>(entry.iRootVisuals[i]); // layout
       
  1587         	
       
  1588         	if (layout)
       
  1589         		{
       
  1590         		RemoveExternalContentVisualFromParentL(aExternalContentVisual,layout);
       
  1591         		}
       
  1592         	} 	
       
  1593     	}
       
  1594     }
       
  1595 
       
  1596 void CHuiRosterImpl::RemoveExternalContentVisualFromParentL(CHuiVisual* aExternalContentVisual, CHuiLayout* aLayout)
       
  1597 	{
       
  1598 	for(TInt k = 0; aLayout && k < aLayout->Count(); ++k)
       
  1599 		{
       
  1600 		CHuiCanvasVisual* canvasVisual = dynamic_cast<CHuiCanvasVisual*>(&(aLayout->Visual(k)));
       
  1601 
       
  1602 		if (canvasVisual)
       
  1603 			{
       
  1604 			if (canvasVisual->ExternalContent() == aExternalContentVisual)
       
  1605 				{
       
  1606 				// Remove aExternalContentVisual from the parent visual
       
  1607 				canvasVisual->SetExternalContentL(NULL);
       
  1608 				}
       
  1609 			}
       
  1610 		else
       
  1611 			{
       
  1612 			CHuiLayout* layoutVisual = dynamic_cast<CHuiLayout*>(&(aLayout->Visual(k)));
       
  1613 			if ( layoutVisual)
       
  1614 				{
       
  1615 				RemoveExternalContentVisualFromParentL(aExternalContentVisual,layoutVisual);
       
  1616 				}
       
  1617 			}
       
  1618 		}
       
  1619 	}
       
  1620 
       
  1621 
       
  1622 void CHuiRosterImpl::FreezeVisibleContentL(TBool aEnable)
       
  1623     {
       
  1624     if (aEnable)
       
  1625         {    
       
  1626         if (!iCanvasGc)
       
  1627             {
       
  1628             CHuiRenderPlugin& renderplugin = CHuiStatic::Renderer();
       
  1629             iCanvasGc = renderplugin.CreateCanvasGcL();
       
  1630             }    
       
  1631         if (!iCanvasRenderBuffer)
       
  1632             {
       
  1633             iCanvasRenderBuffer = iCanvasGc->CreateRenderBufferL(TSize(0,0));
       
  1634             iCanvasRenderBuffer->InitializeL(CHuiStatic::Env().Display(0).VisibleArea().Size());
       
  1635             iCanvasRenderBuffer->Copy(TPoint(0,0));    
       
  1636             iCanvasRenderBufferOrientation = CHuiStatic::Env().Display(0).Orientation();
       
  1637             }
       
  1638         }
       
  1639     else
       
  1640         {
       
  1641         delete iCanvasGc;
       
  1642         iCanvasGc = NULL;        
       
  1643         delete iCanvasRenderBuffer;
       
  1644         iCanvasRenderBuffer = NULL;
       
  1645         SetChanged();
       
  1646         }    
       
  1647     }
       
  1648 
       
  1649 TBool CHuiRosterImpl::IsVisibleContentFrozen() const
       
  1650     {
       
  1651     return ((iCanvasRenderBuffer != NULL) && (iCanvasGc != NULL));
       
  1652     }
       
  1653     
       
  1654 void CHuiRosterImpl::EffectSetEffect(CHuiFxEffect* aEffect)
       
  1655     {
       
  1656     if (iEffect)
       
  1657         {
       
  1658         delete iEffect;
       
  1659         iEffect = NULL;
       
  1660         }
       
  1661     iEffect = aEffect;
       
  1662     SetChanged();
       
  1663     }
       
  1664 
       
  1665 TReal32 CHuiRosterImpl::EffectOpacityTarget() const
       
  1666     {
       
  1667     return iEffectOpacity; 
       
  1668     }
       
  1669 
       
  1670 void CHuiRosterImpl::EffectSetOpacity(TReal32 aOpacity)
       
  1671     {
       
  1672     iEffectOpacity = aOpacity;
       
  1673     }
       
  1674 
       
  1675 void CHuiRosterImpl::EffectDrawSelf( CHuiGc &aGc, const TRect & aDisplayRect) const
       
  1676     {
       
  1677     DrawSelf(aGc, iDisplay);
       
  1678     }
       
  1679 
       
  1680 THuiRealRect CHuiRosterImpl::EffectDisplayRect() const __SOFTFP
       
  1681     {
       
  1682     if (iDisplay)
       
  1683         {
       
  1684         return iDisplay->VisibleArea();
       
  1685         }
       
  1686     else
       
  1687         {
       
  1688         return THuiRealRect(TRect(0,0,0,0));
       
  1689         }    
       
  1690     }
       
  1691 
       
  1692 MHuiEffectable* CHuiRosterImpl::Effectable()
       
  1693     {
       
  1694     return this;
       
  1695     }
       
  1696 
       
  1697 void CHuiRosterImpl::SetLoadingEffect(TBool /*aLoading*/)
       
  1698     {
       
  1699     // not needed
       
  1700     }
       
  1701 void CHuiRosterImpl::EffectSetSource( TBool aIsInput1 )
       
  1702     {
       
  1703     iIsInput1 = aIsInput1;
       
  1704     }
       
  1705 
       
  1706 TBool CHuiRosterImpl::EffectGetSource() const
       
  1707     {
       
  1708     return iIsInput1;
       
  1709     }