diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiTimedValue.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiTimedValue.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,491 @@ +/* +* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of THuiTimedValue. THuiTimedValue is value +* that can change based on time. +* +*/ + + + +#include "uiacceltk/HuiTimedValue.h" // Class definition +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/huifixmath.h" + +#include + +EXPORT_C TBool MHuiMappingFunction::MappingFunctionChanged() const + { + return EFalse; + } + + +EXPORT_C void MHuiMappingFunction::MappingFunctionClearChanged() + { + } + + +EXPORT_C THuiTimedValue::THuiTimedValue(THuiInterpolationStyle aStyle) + : + iStyle(aStyle), + iInternalState(0), + iInterpolationStartValue(0), + iTargetValue(0), + iMapFunction(0), + iTimeRemainingWhenSuspended(0) + { + // Use current time. + iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart(); + iInterpolationEndTime = iInterpolationStartTime; + + SetStyle(aStyle); + } + + +EXPORT_C THuiTimedValue::THuiTimedValue(TReal32 aInitialValue, THuiInterpolationStyle aStyle) __SOFTFP + : iStyle(aStyle), + iInternalState(0), + iInterpolationStartValue(aInitialValue), + iTargetValue(aInitialValue), + iMapFunction(0), + iTimeRemainingWhenSuspended(0) + { + // Use current time. + iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart(); + iInterpolationEndTime = iInterpolationStartTime; + + SetStyle(aStyle); + } + + +EXPORT_C THuiInterpolationStyle THuiTimedValue::Style() const + { + return iStyle; + } + + +EXPORT_C void THuiTimedValue::SetStyle(THuiInterpolationStyle aStyle) + { + iStyle = aStyle; + + if(iStyle == EHuiTimedValueStyleAdaptive) + { + iInternalState |= EFlagAdaptive; + } + else + { + iInternalState &= ~EFlagAdaptive; + } + } + + +EXPORT_C void THuiTimedValue::SetFunction(MHuiMappingFunction* aFunction) + { + TReal32 oldMapped = 0; + + if(!aFunction) + { + // We are switching to identity mapping, store the current mapped + // value. + oldMapped = Now(); + } + + iMapFunction = aFunction; + + if(!aFunction) + { + // No jumping around. Use the previous mapped value. + Set(oldMapped); + } + } + + +TReal32 THuiTimedValue::SecondsFrom(TUint32 aStart, TUint32 aEnd) const + { + TUint32 diff; + + diff = aEnd - aStart; + + if (diff > 0x7FFFFFFF) + { + // Timer has wrapped, we need to account for overflow. + diff = (0xFFFFFFFF - aStart) + aEnd; + } + + return diff / 1000.0; + } + + +TReal32 THuiTimedValue::MapValue(TReal32 aValue) const + { + if(!iMapFunction) + { + // No change. + return aValue; + } + else + { + return iMapFunction->MapValue(aValue, + (iInternalState & EFlagMappingModeMask ? 1 : 0)); + } + } + + +EXPORT_C TReal32 THuiTimedValue::Now() const __SOFTFP + { + return MapValue(UnmappedNow()); + } + + // This macro is used for modifying the return value appropriately + // for the clock flag. +#define HUI_EVALUATED_VALUE(aValue) \ + ((aValue) + (iInternalState & EFlagAddSecondsSinceStart? CHuiStatic::SecondsSinceStart() : 0)) + +EXPORT_C TReal32 THuiTimedValue::UnmappedNow() const __SOFTFP + { + if(iInternalState & EFlagFrozen) + { + // Frozen values are not updated in any way. + return iInterpolationStartValue; + } + + /** @todo Wrapping of iInterpolationEndTime and iInterpolationStartTime is + not handled at the moment. If wrapping occurs during interpolation, + the interpolation is cut short and the value skips to the target. */ + + if((iInternalState & EFlagInterpolating) && iInterpolationEndTime > iInterpolationStartTime) + { + iInternalState |= EFlagChanged; + + TInt duration = HuiFixMath::FloatToFix(SecondsFrom(iInterpolationStartTime, iInterpolationEndTime)); + TInt elapsed = HuiFixMath::FloatToFix(SecondsFrom(iInterpolationStartTime, CHuiStatic::MilliSecondsSinceStart())); + + if(elapsed > duration) + { + // We have reached the destination. + iInterpolationStartValue = iTargetValue; + iInterpolationStartTime = iInterpolationEndTime; + iInternalState &= ~EFlagInterpolating; + return HUI_EVALUATED_VALUE(iInterpolationStartValue); + } + + TReal32 t = 0.0f; + const TInt fixt = HuiFixMath::FixDiv(elapsed,duration); + + switch(iStyle) + { + case EHuiTimedValueStyleLinear: + // Linear interpolation. + t = HuiFixMath::FixToFloat(fixt); + break; + + case EHuiTimedValueStyleSineWave: + { + TInt angle = HuiFixMath::FixMul(fixt,KFixPi); + TInt anglePos = HuiFixMath::FixCos(angle); + t = HuiFixMath::FixToFloat((65535-anglePos)/2); + break; + } + + case EHuiTimedValueStyleDecelerate: + { + // Decelerating quarter of a sine wave. + TInt angle = HuiFixMath::FixMul((fixt/2)+32768,KFixPi); + TInt anglePos = HuiFixMath::FixCos(angle); + t = HuiFixMath::FixToFloat((((65536 - anglePos) / 2) - 32768) * 2); + break; + } + + case EHuiTimedValueStyleAccelerate: + { + // Accelerating quarter of a sine wave. + TInt angle = HuiFixMath::FixMul(fixt/2,KFixPi); + TInt anglePos = HuiFixMath::FixCos(angle); + t = HuiFixMath::FixToFloat((65536 - anglePos)); + break; + } + + case EHuiTimedValueStyleImpulse: + { + // Sine wave curve. + TInt angle = HuiFixMath::FixMul(fixt,KFixPi); + TInt anglePos = HuiFixMath::FixCos(angle); + t = HuiFixMath::FixToFloat((65536 - anglePos) / 2); + break; + } + + default: + // No interpolation. + t = 0; + break; + } + + return HUI_EVALUATED_VALUE(iInterpolationStartValue * (1 - t) + iTargetValue * t); + } + else + { + if(iInternalState & EFlagInterpolating) + { + iInternalState |= EFlagChanged; + iInternalState &= ~EFlagInterpolating; + } + return HUI_EVALUATED_VALUE(iInterpolationStartValue); + } + } + + +EXPORT_C TReal32 THuiTimedValue::Target() const __SOFTFP + { + return MapValue(iTargetValue); + } + + +EXPORT_C void THuiTimedValue::Set(TReal32 aValue) __SOFTFP + { + iTargetValue = iInterpolationStartValue = aValue; + iInternalState &= ~EFlagInterpolating; + iInternalState |= EFlagChanged; + + CHuiStatic::ContinueRefresh(); + } + + +EXPORT_C void THuiTimedValue::Set(TReal32 aValue, TInt aMilliSeconds) __SOFTFP + { + if(Math::IsNaN(aValue)) + { + HUI_DEBUG(_L("THuiTimedValue::Set - Math::IsNaN(aValue)")); + return; + } + if(aMilliSeconds <= 0) + { + Set(aValue); + return; + } + + if(iInternalState & EFlagInterpolating) + { + iInterpolationStartValue = UnmappedNow(); + } + else + { + if( HuiUtil::RealCompare(iInterpolationStartValue, aValue ) ) + { + // This is the current value of the timed value, and it won't + // change, so we are already at the target. + return; + } + } + + // Adaptive style depends on whether a change is currently underway. + if(iInternalState & EFlagAdaptive) + { + if(iInternalState & EFlagInterpolating) + { + iStyle = EHuiTimedValueStyleDecelerate; + } + else + { + iStyle = EHuiTimedValueStyleSineWave; + } + } + + CHuiStatic::ContinueRefresh(); + + iTargetValue = aValue; + + // If the difference between the current value and the target value + // is insignificant, no interpolation is done (it would be subject + // to round-off problems). + const TReal32 KEpsilon = .0001; + TReal32 delta = aValue - iInterpolationStartValue; + if(delta > -KEpsilon && delta < KEpsilon) + { + iInterpolationStartValue = aValue; + iInternalState &= ~EFlagInterpolating; + iInternalState |= EFlagChanged; + return; + } + + iInterpolationStartTime = CHuiStatic::MilliSecondsSinceStart(); + + // Target time is an offset to the current time. + iInterpolationEndTime = iInterpolationStartTime + aMilliSeconds; + + iTargetValue = aValue; + + iInternalState |= EFlagChanged | EFlagInterpolating; + } + + +EXPORT_C void THuiTimedValue::SetWithSpeed(TReal32 aValue, + TReal32 aUnitsPerSecond) __SOFTFP + { + if( Math::IsNaN(aUnitsPerSecond) || Math::IsNaN(aValue) ) + { + HUI_DEBUG(_L("THuiTimedValue::SetWithSpeed - Math::IsNaN()")); + return; + } + TReal32 delta = UnmappedNow() - aValue; + + // don't divide by 0 + if( HuiUtil::RealCompare( delta, 0.f ) || HuiUtil::RealCompare( aUnitsPerSecond, 0.f ) ) + { + // Already there. + Set(aValue); + return; + } + + if(delta < 0.f) + { + delta = -delta; + } + + Set(aValue, (TInt)((delta / aUnitsPerSecond) * 1000.0)); + } + + +EXPORT_C TInt THuiTimedValue::RemainingTime() const + { + if(iInternalState & EFlagInterpolating) + { + TUint32 lastTime = iInterpolationStartTime; + if(!(iInternalState & EFlagFrozen)) + { + // If the value is not frozen, just compare against the current time. + lastTime = CHuiStatic::MilliSecondsSinceStart(); + } + + TReal32 remaining = SecondsFrom(lastTime, iInterpolationEndTime); + if(remaining < 0) + { + return 0; + } + return TInt(remaining * 1000); + } + else + { + // No interpolation occuring. + return 0; + } + } + + +EXPORT_C void THuiTimedValue::Finish() + { + iInterpolationStartTime = iInterpolationEndTime; + iInterpolationStartValue = iTargetValue; + } + + +EXPORT_C void THuiTimedValue::ClearChanged() + { + if(iMapFunction) + { + iMapFunction->MappingFunctionClearChanged(); + } + + if(!(iInternalState & EFlagInterpolating) && + !(iInternalState & EFlagAddSecondsSinceStart)) + { + iInternalState &= ~EFlagChanged; + } + } + + +EXPORT_C void THuiTimedValue::SetMappingMode(TInt aMode) + { + switch(aMode) + { + case 0: + iInternalState &= ~EFlagMappingModeMask; + break; + + case 1: + iInternalState |= EFlagMappingModeMask; + break; + + default: + break; + } + } + + +EXPORT_C void THuiTimedValue::EnableClock(TBool aEnable) + { + if(aEnable) + { + // EFlagChanged is always raised when the clock mode is enabled. + iInternalState |= EFlagAddSecondsSinceStart | EFlagChanged; + } + else + { + iInternalState &= ~EFlagAddSecondsSinceStart; + } + } + + +EXPORT_C void THuiTimedValue::Suspend(TBool aDoSuspend) + { + if(aDoSuspend && !(iInternalState & EFlagFrozen)) + { + iInterpolationStartValue = UnmappedNow(); // to report correct value + iInternalState |= EFlagFrozen; + iTimeRemainingWhenSuspended = RemainingTime(); + // UnmappedNow() will not update the state of the value any longer. + } + else if(!aDoSuspend && (iInternalState & EFlagFrozen)) + { + iInternalState &= ~EFlagFrozen; + + if (iTimeRemainingWhenSuspended) // move for real + { + iInternalState &= ~EFlagInterpolating; // force us to continue from paused position + // + to avoid interpolation mode change + Set(iTargetValue, iTimeRemainingWhenSuspended); + iTimeRemainingWhenSuspended = 0; + } + else // old functionality + { + // Temporal relocation. + TUint32 difference = CHuiStatic::MilliSecondsSinceStart() - iInterpolationStartTime; + iInterpolationStartTime += difference; + iInterpolationEndTime += difference; + } + } + else + { + // for PC lint + } + } + + +EXPORT_C THuiTimedValue& THuiTimedValue::operator=(const THuiTimedValue& aOtherValue) + { + if ( this == &aOtherValue ) + { + Suspend(EFalse); + return *this; + } + + iStyle = aOtherValue.iStyle; + iInternalState = aOtherValue.iInternalState; + iInterpolationStartTime = aOtherValue.iInterpolationStartTime; + iInterpolationEndTime = aOtherValue.iInterpolationEndTime; + iInterpolationStartValue = aOtherValue.iInterpolationStartValue; + iTargetValue = aOtherValue.iTargetValue; + iMapFunction = aOtherValue.iMapFunction; + Suspend(EFalse); + return *this; + }