uiacceltk/hitchcock/coretoolkit/src/HuiTimedValue.cpp
changeset 0 15bf7259bb7c
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 THuiTimedValue. THuiTimedValue is value 
       
    15 *                that can change based on time.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "uiacceltk/HuiTimedValue.h"  // Class definition
       
    22 #include "uiacceltk/HuiStatic.h"
       
    23 #include "uiacceltk/HuiUtil.h"
       
    24 #include "uiacceltk/huifixmath.h"
       
    25 
       
    26 #include <e32math.h>
       
    27 
       
    28 EXPORT_C TBool MHuiMappingFunction::MappingFunctionChanged() const
       
    29     {
       
    30     return EFalse;
       
    31     }
       
    32 
       
    33 
       
    34 EXPORT_C void MHuiMappingFunction::MappingFunctionClearChanged()
       
    35     {
       
    36     }
       
    37 
       
    38 
       
    39 EXPORT_C THuiTimedValue::THuiTimedValue(THuiInterpolationStyle aStyle)
       
    40         :
       
    41           iStyle(aStyle),
       
    42           iInternalState(0),
       
    43           iInterpolationStartValue(0),
       
    44           iTargetValue(0),
       
    45           iMapFunction(0),
       
    46           iTimeRemainingWhenSuspended(0)
       
    47     {
       
    48     // Use current time.
       
    49     iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart();
       
    50     iInterpolationEndTime = iInterpolationStartTime;
       
    51 
       
    52     SetStyle(aStyle);
       
    53     }
       
    54 
       
    55 
       
    56 EXPORT_C THuiTimedValue::THuiTimedValue(TReal32 aInitialValue, THuiInterpolationStyle aStyle) __SOFTFP
       
    57         : iStyle(aStyle),
       
    58           iInternalState(0),
       
    59           iInterpolationStartValue(aInitialValue),
       
    60           iTargetValue(aInitialValue),
       
    61           iMapFunction(0),
       
    62           iTimeRemainingWhenSuspended(0)
       
    63     {
       
    64     // Use current time.
       
    65     iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart();
       
    66     iInterpolationEndTime = iInterpolationStartTime;
       
    67 
       
    68     SetStyle(aStyle);
       
    69     }
       
    70 
       
    71 
       
    72 EXPORT_C THuiInterpolationStyle THuiTimedValue::Style() const
       
    73     {
       
    74     return iStyle;
       
    75     }
       
    76 
       
    77 
       
    78 EXPORT_C void THuiTimedValue::SetStyle(THuiInterpolationStyle aStyle)
       
    79     {
       
    80     iStyle = aStyle;
       
    81 
       
    82     if(iStyle == EHuiTimedValueStyleAdaptive)
       
    83         {
       
    84         iInternalState |= EFlagAdaptive;
       
    85         }
       
    86     else
       
    87         {
       
    88         iInternalState &= ~EFlagAdaptive;
       
    89         }
       
    90     }
       
    91 
       
    92 
       
    93 EXPORT_C void THuiTimedValue::SetFunction(MHuiMappingFunction* aFunction)
       
    94     {
       
    95     TReal32 oldMapped = 0;
       
    96 
       
    97     if(!aFunction)
       
    98         {
       
    99         // We are switching to identity mapping, store the current mapped
       
   100         // value.
       
   101         oldMapped = Now();
       
   102         }
       
   103 
       
   104     iMapFunction = aFunction;
       
   105 
       
   106     if(!aFunction)
       
   107         {
       
   108         // No jumping around. Use the previous mapped value.
       
   109         Set(oldMapped);
       
   110         }
       
   111     }
       
   112 
       
   113 
       
   114 TReal32 THuiTimedValue::SecondsFrom(TUint32 aStart, TUint32 aEnd) const
       
   115     {
       
   116     TUint32 diff;
       
   117 
       
   118     diff = aEnd - aStart;
       
   119     
       
   120     if (diff > 0x7FFFFFFF)
       
   121         {
       
   122         // Timer has wrapped, we need to account for overflow.
       
   123         diff = (0xFFFFFFFF - aStart) + aEnd;
       
   124         }
       
   125 
       
   126     return diff / 1000.0;
       
   127     }
       
   128 
       
   129 
       
   130 TReal32 THuiTimedValue::MapValue(TReal32 aValue) const
       
   131     {
       
   132     if(!iMapFunction)
       
   133         {
       
   134         // No change.
       
   135         return aValue;
       
   136         }
       
   137     else
       
   138         {
       
   139         return iMapFunction->MapValue(aValue,
       
   140             (iInternalState & EFlagMappingModeMask ? 1 : 0));
       
   141         }
       
   142     }
       
   143 
       
   144 
       
   145 EXPORT_C TReal32 THuiTimedValue::Now() const __SOFTFP
       
   146     {
       
   147     return MapValue(UnmappedNow());
       
   148     }
       
   149 
       
   150     // This macro is used for modifying the return value appropriately
       
   151     // for the clock flag.
       
   152 #define HUI_EVALUATED_VALUE(aValue)  \
       
   153     ((aValue) + (iInternalState & EFlagAddSecondsSinceStart? CHuiStatic::SecondsSinceStart() : 0))
       
   154 
       
   155 EXPORT_C TReal32 THuiTimedValue::UnmappedNow() const __SOFTFP
       
   156     {
       
   157     if(iInternalState & EFlagFrozen)
       
   158         {
       
   159         // Frozen values are not updated in any way.
       
   160         return iInterpolationStartValue;
       
   161         }
       
   162 
       
   163     /** @todo  Wrapping of iInterpolationEndTime and iInterpolationStartTime is 
       
   164                not handled at the moment. If wrapping occurs during interpolation, 
       
   165                the interpolation is cut short and the value skips to the target. */
       
   166 
       
   167     if((iInternalState & EFlagInterpolating) && iInterpolationEndTime > iInterpolationStartTime)
       
   168         {
       
   169         iInternalState |= EFlagChanged;
       
   170 
       
   171         TInt duration = HuiFixMath::FloatToFix(SecondsFrom(iInterpolationStartTime, iInterpolationEndTime));
       
   172         TInt elapsed = HuiFixMath::FloatToFix(SecondsFrom(iInterpolationStartTime, CHuiStatic::MilliSecondsSinceStart()));
       
   173 
       
   174         if(elapsed > duration)
       
   175             {
       
   176             // We have reached the destination.
       
   177             iInterpolationStartValue = iTargetValue;
       
   178             iInterpolationStartTime = iInterpolationEndTime;
       
   179             iInternalState &= ~EFlagInterpolating;
       
   180             return HUI_EVALUATED_VALUE(iInterpolationStartValue);
       
   181             }
       
   182 
       
   183         TReal32 t = 0.0f;
       
   184         const TInt fixt = HuiFixMath::FixDiv(elapsed,duration);
       
   185 
       
   186         switch(iStyle)
       
   187             {
       
   188             case EHuiTimedValueStyleLinear:
       
   189                 // Linear interpolation.
       
   190                 t = HuiFixMath::FixToFloat(fixt);
       
   191                 break;
       
   192 
       
   193             case EHuiTimedValueStyleSineWave:
       
   194                 {
       
   195                 TInt angle = HuiFixMath::FixMul(fixt,KFixPi);
       
   196                 TInt anglePos = HuiFixMath::FixCos(angle);
       
   197                 t = HuiFixMath::FixToFloat((65535-anglePos)/2);
       
   198                 break;
       
   199                 }
       
   200 
       
   201             case EHuiTimedValueStyleDecelerate:
       
   202                 {
       
   203                 // Decelerating quarter of a sine wave.
       
   204                 TInt angle = HuiFixMath::FixMul((fixt/2)+32768,KFixPi);
       
   205                 TInt anglePos = HuiFixMath::FixCos(angle);
       
   206                 t = HuiFixMath::FixToFloat((((65536 - anglePos) / 2) - 32768) * 2);
       
   207                 break;
       
   208                 }
       
   209 
       
   210             case EHuiTimedValueStyleAccelerate:
       
   211                 {
       
   212                 // Accelerating quarter of a sine wave.
       
   213                 TInt angle = HuiFixMath::FixMul(fixt/2,KFixPi);
       
   214                 TInt anglePos = HuiFixMath::FixCos(angle);
       
   215                 t = HuiFixMath::FixToFloat((65536 - anglePos));
       
   216                 break;
       
   217                 }
       
   218 
       
   219             case EHuiTimedValueStyleImpulse:
       
   220                 {
       
   221                 // Sine wave curve.
       
   222                 TInt angle = HuiFixMath::FixMul(fixt,KFixPi);
       
   223                 TInt anglePos = HuiFixMath::FixCos(angle);
       
   224                 t = HuiFixMath::FixToFloat((65536 - anglePos) / 2);
       
   225                 break;
       
   226                 }
       
   227 
       
   228             default:
       
   229                 // No interpolation.
       
   230                 t = 0;
       
   231                 break;
       
   232             }
       
   233 
       
   234         return HUI_EVALUATED_VALUE(iInterpolationStartValue * (1 - t) + iTargetValue * t);
       
   235         }
       
   236     else
       
   237         {
       
   238         if(iInternalState & EFlagInterpolating)
       
   239             {
       
   240             iInternalState |= EFlagChanged;
       
   241             iInternalState &= ~EFlagInterpolating;
       
   242             }
       
   243         return HUI_EVALUATED_VALUE(iInterpolationStartValue);
       
   244         }
       
   245     }
       
   246 
       
   247 
       
   248 EXPORT_C TReal32 THuiTimedValue::Target() const __SOFTFP
       
   249     {
       
   250     return MapValue(iTargetValue);
       
   251     }
       
   252 
       
   253 
       
   254 EXPORT_C void THuiTimedValue::Set(TReal32 aValue) __SOFTFP
       
   255     {
       
   256     iTargetValue = iInterpolationStartValue = aValue;
       
   257     iInternalState &= ~EFlagInterpolating;
       
   258     iInternalState |= EFlagChanged;
       
   259 
       
   260     CHuiStatic::ContinueRefresh();
       
   261     }
       
   262 
       
   263 
       
   264 EXPORT_C void THuiTimedValue::Set(TReal32 aValue, TInt aMilliSeconds) __SOFTFP
       
   265     {
       
   266     if(Math::IsNaN(aValue))
       
   267         {
       
   268         HUI_DEBUG(_L("THuiTimedValue::Set - Math::IsNaN(aValue)"));
       
   269         return;
       
   270         }
       
   271     if(aMilliSeconds <= 0)
       
   272         {
       
   273         Set(aValue);
       
   274         return;
       
   275         }
       
   276 
       
   277     if(iInternalState & EFlagInterpolating)
       
   278         {
       
   279         iInterpolationStartValue = UnmappedNow();
       
   280         }
       
   281     else
       
   282         {
       
   283         if( HuiUtil::RealCompare(iInterpolationStartValue, aValue ) )
       
   284             {
       
   285             // This is the current value of the timed value, and it won't
       
   286             // change, so we are already at the target.
       
   287             return;
       
   288             }
       
   289         }
       
   290 
       
   291     // Adaptive style depends on whether a change is currently underway.
       
   292     if(iInternalState & EFlagAdaptive)
       
   293         {
       
   294         if(iInternalState & EFlagInterpolating)
       
   295             {
       
   296             iStyle = EHuiTimedValueStyleDecelerate;
       
   297             }
       
   298         else
       
   299             {
       
   300             iStyle = EHuiTimedValueStyleSineWave;
       
   301             }
       
   302         }
       
   303 
       
   304     CHuiStatic::ContinueRefresh();
       
   305 
       
   306     iTargetValue = aValue;
       
   307 
       
   308     // If the difference between the current value and the target value
       
   309     // is insignificant, no interpolation is done (it would be subject
       
   310     // to round-off problems).
       
   311     const TReal32 KEpsilon = .0001;
       
   312     TReal32 delta = aValue - iInterpolationStartValue;
       
   313     if(delta > -KEpsilon && delta < KEpsilon)
       
   314         {
       
   315         iInterpolationStartValue = aValue;
       
   316         iInternalState &= ~EFlagInterpolating;
       
   317         iInternalState |= EFlagChanged;
       
   318         return;
       
   319         }
       
   320 
       
   321     iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart();
       
   322 
       
   323     // Target time is an offset to the current time.
       
   324     iInterpolationEndTime = iInterpolationStartTime + aMilliSeconds;
       
   325 
       
   326     iTargetValue = aValue;
       
   327 
       
   328     iInternalState |= EFlagChanged | EFlagInterpolating;
       
   329     }
       
   330 
       
   331 
       
   332 EXPORT_C void THuiTimedValue::SetWithSpeed(TReal32 aValue,
       
   333                                            TReal32 aUnitsPerSecond) __SOFTFP
       
   334     {
       
   335     if( Math::IsNaN(aUnitsPerSecond) || Math::IsNaN(aValue) )
       
   336         {
       
   337         HUI_DEBUG(_L("THuiTimedValue::SetWithSpeed - Math::IsNaN()"));
       
   338         return;
       
   339         }
       
   340     TReal32 delta = UnmappedNow() - aValue;
       
   341 
       
   342     // don't divide by 0
       
   343     if( HuiUtil::RealCompare( delta, 0.f ) || HuiUtil::RealCompare( aUnitsPerSecond, 0.f ) )
       
   344         {
       
   345         // Already there.
       
   346         Set(aValue);
       
   347         return;
       
   348         }
       
   349 
       
   350     if(delta < 0.f)
       
   351         {
       
   352         delta = -delta;
       
   353         }
       
   354 
       
   355     Set(aValue, (TInt)((delta / aUnitsPerSecond) * 1000.0));
       
   356     }
       
   357 
       
   358 
       
   359 EXPORT_C TInt THuiTimedValue::RemainingTime() const
       
   360     {
       
   361     if(iInternalState & EFlagInterpolating)
       
   362         {
       
   363         TUint32 lastTime = iInterpolationStartTime;
       
   364         if(!(iInternalState & EFlagFrozen))
       
   365             {
       
   366             // If the value is not frozen, just compare against the current time.
       
   367             lastTime = CHuiStatic::MilliSecondsSinceStart();
       
   368             }
       
   369 
       
   370         TReal32 remaining = SecondsFrom(lastTime, iInterpolationEndTime);
       
   371         if(remaining < 0)
       
   372             {
       
   373             return 0;
       
   374             }
       
   375         return TInt(remaining * 1000);
       
   376         }
       
   377     else
       
   378         {
       
   379         // No interpolation occuring.
       
   380         return 0;
       
   381         }
       
   382     }
       
   383 
       
   384 
       
   385 EXPORT_C void THuiTimedValue::Finish()
       
   386     {
       
   387     iInterpolationStartTime = iInterpolationEndTime;
       
   388     iInterpolationStartValue = iTargetValue;
       
   389     }
       
   390 
       
   391 
       
   392 EXPORT_C void THuiTimedValue::ClearChanged()
       
   393     {
       
   394     if(iMapFunction)
       
   395         {
       
   396         iMapFunction->MappingFunctionClearChanged();
       
   397         }
       
   398     
       
   399     if(!(iInternalState & EFlagInterpolating) &&
       
   400        !(iInternalState & EFlagAddSecondsSinceStart))
       
   401         {
       
   402         iInternalState &= ~EFlagChanged;
       
   403         }
       
   404     }
       
   405 
       
   406 
       
   407 EXPORT_C void THuiTimedValue::SetMappingMode(TInt aMode)
       
   408     {
       
   409     switch(aMode)
       
   410         {
       
   411         case 0:
       
   412             iInternalState &= ~EFlagMappingModeMask;
       
   413             break;
       
   414 
       
   415         case 1:
       
   416             iInternalState |= EFlagMappingModeMask;
       
   417             break;
       
   418             
       
   419         default:
       
   420             break;
       
   421         }
       
   422     }
       
   423 
       
   424 
       
   425 EXPORT_C void THuiTimedValue::EnableClock(TBool aEnable)
       
   426     {
       
   427     if(aEnable)
       
   428         {
       
   429         // EFlagChanged is always raised when the clock mode is enabled.
       
   430         iInternalState |= EFlagAddSecondsSinceStart | EFlagChanged;
       
   431         }
       
   432     else
       
   433         {
       
   434         iInternalState &= ~EFlagAddSecondsSinceStart;
       
   435         }
       
   436     }
       
   437 
       
   438 
       
   439 EXPORT_C void THuiTimedValue::Suspend(TBool aDoSuspend)
       
   440     {
       
   441     if(aDoSuspend && !(iInternalState & EFlagFrozen))
       
   442         {
       
   443         iInterpolationStartValue = UnmappedNow(); // to report correct value
       
   444         iInternalState |= EFlagFrozen;
       
   445         iTimeRemainingWhenSuspended = RemainingTime();
       
   446         // UnmappedNow() will not update the state of the value any longer.
       
   447         }
       
   448     else if(!aDoSuspend && (iInternalState & EFlagFrozen))
       
   449         {
       
   450         iInternalState &= ~EFlagFrozen;
       
   451 
       
   452         if (iTimeRemainingWhenSuspended) // move for real
       
   453             {
       
   454             iInternalState &= ~EFlagInterpolating; // force us to continue from paused position 
       
   455                                                    // + to avoid interpolation mode change 
       
   456             Set(iTargetValue, iTimeRemainingWhenSuspended);
       
   457             iTimeRemainingWhenSuspended = 0;
       
   458             }
       
   459         else // old functionality
       
   460             {
       
   461             // Temporal relocation.
       
   462             TUint32 difference = CHuiStatic::MilliSecondsSinceStart() - iInterpolationStartTime;
       
   463             iInterpolationStartTime += difference;
       
   464             iInterpolationEndTime += difference;
       
   465             }
       
   466         }
       
   467     else
       
   468         {
       
   469         // for PC lint
       
   470         }
       
   471     }
       
   472 
       
   473 
       
   474 EXPORT_C THuiTimedValue& THuiTimedValue::operator=(const THuiTimedValue& aOtherValue)
       
   475     {
       
   476     if ( this == &aOtherValue )
       
   477         {
       
   478         Suspend(EFalse);
       
   479         return *this;
       
   480         }
       
   481     
       
   482     iStyle = aOtherValue.iStyle;
       
   483     iInternalState = aOtherValue.iInternalState;
       
   484     iInterpolationStartTime = aOtherValue.iInterpolationStartTime;
       
   485     iInterpolationEndTime = aOtherValue.iInterpolationEndTime;
       
   486     iInterpolationStartValue = aOtherValue.iInterpolationStartValue;
       
   487     iTargetValue = aOtherValue.iTargetValue;
       
   488     iMapFunction = aOtherValue.iMapFunction;
       
   489     Suspend(EFalse);
       
   490     return *this;
       
   491     }