diff -r 000000000000 -r f72a12da539e idlehomescreen/xmluicontroller/src/policyevaluator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/idlehomescreen/xmluicontroller/src/policyevaluator.cpp Thu Dec 17 08:40:49 2009 +0200 @@ -0,0 +1,514 @@ +/* +* Copyright (c) 2005-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: Policy evaluator +* +*/ + + +#include "xnnodeappif.h" +#include "xnproperty.h" +#include "xnuiengineappif.h" +#include "policyevaluator.h" +#include "aipolicyelement.h" +#include "aixmluiutils.h" +#include "aistrcnv.h" +#include "aixmluiconstants.h" + +namespace + { + + void ReplaceCharacters( TDes8& aDes, + TChar aOriginal, + TChar aNew ) + { + if ( aDes.Length() == 0 ) + { + return; + } + + TPtr8 des = aDes.MidTPtr(0); + TInt pos = des.Locate( aOriginal ); + + while ( pos != KErrNotFound ) + { + des[ pos++ ] = aNew; + + if ( pos == des.Length() ) + { + break; + } + + des.Set( des.MidTPtr( pos ) ); + pos = des.Locate( aOriginal ); + } + } + + } + +using namespace AiXmlUiController; + +enum EAI2Policies + { + KAI2PolUnset = 0, + KAI2PolShow, + KAI2PolHide, + }; + +// ======== MEMBER FUNCTIONS ======== + +CPolicyEvaluator::CPolicyEvaluator() + { + } + + +void CPolicyEvaluator::ConstructL() + { + } + + +CPolicyEvaluator* CPolicyEvaluator::NewL() + { + CPolicyEvaluator* self = new( ELeave ) CPolicyEvaluator; + return self; + } + + +CPolicyEvaluator::~CPolicyEvaluator() + { + } + +void CPolicyEvaluator::EvaluateContentPolicyL( CXnNodeAppIf& aTarget, + RAiPolicyElementArray& aPolicyArray ) + { + EvaluatePolicyL( aTarget, + aPolicyArray, + AiUiDef::xml::policy::KContent ); + } + +void CPolicyEvaluator::EvaluateEmptyContentPolicyL( CXnNodeAppIf& aTarget, + RAiPolicyElementArray& aPolicyArray ) + { + EvaluatePolicyL( aTarget, + aPolicyArray, + AiUiDef::xml::policy::KEmptyContent ); + } + +void CPolicyEvaluator::EvaluateVisibilityPolicyL( CXnNodeAppIf& aTarget, + RAiPolicyElementArray& aPolicyArray ) + { + EvaluatePolicyL( aTarget, + aPolicyArray, + AiUiDef::xml::policy::KVisibilityPolicy ); + } + +void CPolicyEvaluator::EvaluateContentChangedPolicyL( CXnNodeAppIf& aTarget, + RAiPolicyElementArray& aPolicyArray ) + { + EvaluatePolicyL( aTarget, + aPolicyArray, + AiUiDef::xml::policy::KContentChanged ); + } + +void CPolicyEvaluator::EvaluateResourcePolicyL( CXnNodeAppIf& aTarget, + CXnNodeAppIf& aResource, + RAiPolicyElementArray& aPolicyArray ) + { + RPointerArray< CXnNodeAppIf > policyArray = + FindPropertyElementL( aTarget, + AiUiDef::xml::policy::KResource ); + + CleanupClosePushL( policyArray ); + + aPolicyArray.ReserveL( aPolicyArray.Count() + policyArray.Count() ); + + for ( TInt i = 0; i < policyArray.Count(); ++i ) + { + CXnNodeAppIf* property = policyArray[ i ]; + + // Get name property to lookup target ui element + const TDesC8* name = PropertyValue( *property, + AiUiDef::xml::property::KName ); + + CXnNodeAppIf* target = NULL; + if( name ) + { + // Lookup target ui element + target = property->UiEngineL()->FindNodeByIdL( *name, property->Namespace() ); + } + + if ( !target ) + { + // No target found. Continue with next property + continue; + } + + const TDesC8* value = PropertyValue( *property, + AiUiDef::xml::property::KValue ); + + if ( !value ) + { + // No value found. Continue with next property + continue; + } + + // Check if resource matches condition + const TDesC8* id = PropertyValue( aResource, + XnPropertyNames::common::KId ); + + if ( !id ) + { + continue; + } + + TInt conditionEnd = value->Locate( KRightParenthesis ); + + if ( conditionEnd++ < 0 ) + { + continue; + } + + TPtrC8 condition( value->Left( conditionEnd ) ); + TPtrC8 cssValue( value->Mid( conditionEnd ) ); + + HBufC8* condBuffer = condition.AllocL(); + TPtr8 condPtr = condBuffer->Des(); + ReplaceCharacters( condPtr, KLeftParenthesis, KWhiteSpace ); + ReplaceCharacters( condPtr, KComma, KWhiteSpace ); + ReplaceCharacters( condPtr, KRightParenthesis, KWhiteSpace ); + + if ( MatchCondition( *id, condPtr ) ) + { + // Append target and value. + // This cannot fail because space has been reserved. + aPolicyArray.Append( TAiPolicyElement( *target, cssValue ) ); + } + + delete condBuffer; + } + + CleanupStack::PopAndDestroy( &policyArray ); + } + +void CPolicyEvaluator::EvaluatePolicyL( CXnNodeAppIf& aTarget, + RAiPolicyElementArray& aPolicyArray, + const TDesC8& aPolicyClass ) + { + RPointerArray< CXnNodeAppIf > policyArray = + FindPropertyElementL( aTarget, + aPolicyClass ); + + CleanupClosePushL( policyArray ); + + aPolicyArray.ReserveL( aPolicyArray.Count() + policyArray.Count() ); + + for ( TInt i = 0; i < policyArray.Count(); ++i ) + { + CXnNodeAppIf* property = policyArray[ i ]; + + // Get name property to lookup target ui element + const TDesC8* name = PropertyValue( *property, + AiUiDef::xml::property::KName ); + + CXnNodeAppIf* target = NULL; + if( name ) + { + // Lookup target ui element + target = property->UiEngineL()->FindNodeByIdL( *name, property->Namespace() ); + } + + if ( !target ) + { + // No target found. Continue with next property + continue; + } + + const TDesC8* value = PropertyValue( *property, + AiUiDef::xml::property::KValue ); + + if ( !value ) + { + // No value found. Continue with next property + continue; + } + + if( aPolicyClass == AiUiDef::xml::policy::KVisibilityPolicy ) + { + TInt conditionEnd = value->Locate( KRightParenthesis ); + + if ( conditionEnd++ < 0 ) + { + continue; + } + + TPtrC8 condition( value->Left( conditionEnd ) ); + TPtrC8 cssValue( value->Mid( conditionEnd ) ); + + HBufC8* condBuffer = condition.AllocLC(); + TPtr8 condPtr = condBuffer->Des(); + ReplaceCharacters( condPtr, KLeftParenthesis, KWhiteSpace ); + ReplaceCharacters( condPtr, KComma, KWhiteSpace ); + ReplaceCharacters( condPtr, KRightParenthesis, KWhiteSpace ); + + if ( MatchVisibilityConditionL( condPtr, *property, aPolicyArray ) ) + { + // Append target and value. + // This cannot fail because space has been reserved. + aPolicyArray.Append( TAiPolicyElement( *target, cssValue ) ); + } + + CleanupStack::PopAndDestroy( condBuffer ); + } + else + { + // Append target and value. + // This cannot fail because space has been reserved. + aPolicyArray.Append( TAiPolicyElement( *target, *value ) ); + } + } + + CleanupStack::PopAndDestroy( &policyArray ); + } + +TBool CPolicyEvaluator::MatchCondition( const TDesC8& aId, + const TDesC8& aCondition ) + { + TBool negation = EFalse; + + TLex8 parser( aCondition ); + + if ( parser.NextToken() == AiUiDef::xml::policy::KCondition ) + { + // Condition found + parser.SkipSpace(); + + // check negation + if ( parser.Get() == KNotOperator ) + { + negation = ETrue; + } + else + { + parser.UnGet(); + } + + parser.SkipSpace(); + + TBool found = EFalse; + + // Find id from the list. Stop when found or in the end of string. + while ( !parser.Eos() ) + { + if ( parser.NextToken() == aId ) + { + found = ETrue; + break; + } + } + + // Test if id matches the given condition + return ( ( found && !negation ) || ( !found && negation ) ); // found XOR negation + } + else + { + return EFalse; + } + + } + +TBool CPolicyEvaluator::MatchVisibilityConditionL( const TDesC8& aCondition, + CXnNodeAppIf& aProperty, + RAiPolicyElementArray& aPolicyArray ) + { + TBool negation = EFalse; + TBool andOperation = EFalse; + TInt nodesVisible = 0; // for managing the end of 'or' op. + + TLex8 parser( aCondition ); + + if ( parser.NextToken() == AiUiDef::xml::policy::KCondition ) + { + // Condition found + parser.SkipSpace(); + + // check negation + if ( parser.Get() == KNotOperator ) + { + negation = ETrue; + } + else + { + parser.UnGet(); + } + + if ( parser.Get() == KAndOperator ) + { + andOperation = ETrue; + } + else + { + parser.UnGet(); + } + + parser.SkipSpace(); + + // Determine aCondition lists visibilities. Stop when: + // - Eos reached + // - First 'false' in 'and' op + // - First 'true' in 'or' op + while ( !parser.Eos() ) + { + TPtrC8 id( parser.NextToken() ); + CXnNodeAppIf* target = NULL; + TBool nodeVisible = EFalse; + + TBool displayBlockSet = KAI2PolUnset; + TBool visibilityVisibleSet = KAI2PolUnset; + + // Lookup target ui element + target = aProperty.UiEngineL()->FindNodeByIdL( id, aProperty.Namespace() ); + + if( target ) + { + // first try to first the display or visibility property updates from policy array + for( TInt i = 0; i < aPolicyArray.Count(); ++i ) + { + if( &(aPolicyArray[i].Target()) == target ) + { + if( aPolicyArray[i].Name() == XnPropertyNames::style::common::KDisplay ) + { + if( aPolicyArray[i].Value() == + XnPropertyNames::style::common::display::KBlock ) + { + displayBlockSet = KAI2PolShow; + } + else if( aPolicyArray[i].Value() == + XnPropertyNames::style::common::display::KNone ) + { + displayBlockSet = KAI2PolHide; + } + } + if( aPolicyArray[i].Name() == XnPropertyNames::style::common::KVisibility ) + { + if( aPolicyArray[i].Value() == + XnPropertyNames::style::common::visibility::KVisible ) + { + visibilityVisibleSet = KAI2PolShow; + } + else if( aPolicyArray[i].Value() == + XnPropertyNames::style::common::visibility::KHidden ) + { + visibilityVisibleSet = KAI2PolHide; + } + } + } + } + + HBufC* displayPropertyValue = NULL; + if( !displayBlockSet ) + { + // Only check CSS if policy array did not set the value + displayPropertyValue = PropertyValueL( + *target, + XnPropertyNames::style::common::KDisplay ); + CleanupStack::PushL( displayPropertyValue ); + + if( displayPropertyValue ) + { + HBufC8* buf8 = NULL; + buf8 = AiUtility::CopyToBufferL( buf8, *displayPropertyValue ); + if( buf8 ) + { + if( *buf8 == XnPropertyNames::style::common::display::KBlock ) + { + displayBlockSet = KAI2PolShow; + } + else + { + displayBlockSet = KAI2PolHide; + } + delete buf8; + } + } + CleanupStack::PopAndDestroy( displayPropertyValue ); + } + + if( !visibilityVisibleSet ) + { + displayPropertyValue = PropertyValueL( + *target, + XnPropertyNames::style::common::KVisibility ); + CleanupStack::PushL( displayPropertyValue ); + + if( displayPropertyValue ) + { + // only if visiblity property is set we affect nodeVisible variable + HBufC8* buf8 = NULL; + buf8 = AiUtility::CopyToBufferL( buf8, *displayPropertyValue ); + if( buf8 ) + { + if( *buf8 == XnPropertyNames::style::common::visibility::KVisible ) + { + visibilityVisibleSet = KAI2PolShow; + } + else + { + visibilityVisibleSet = KAI2PolHide; + } + delete buf8; + } + } + CleanupStack::PopAndDestroy( displayPropertyValue ); + } + } + + // At least one value has to be 'not unset' + // and neither can be 'hide' + if( ( displayBlockSet || visibilityVisibleSet ) && + ( ( displayBlockSet != KAI2PolHide ) && + ( visibilityVisibleSet != KAI2PolHide ) ) ) + { + nodeVisible = ETrue; + } + + if( nodeVisible ) + { + ++nodesVisible; + if( !andOperation && !negation ) + { + // 'Or' ends to first true + // 'Not and' ends to first true + return ETrue; + } + } + else if( !nodeVisible && andOperation && !negation ) + { + // 'And' ends to first false + return EFalse; + } + + parser.SkipSpace(); + } + if( nodesVisible > 0 && !negation ) + { + return ETrue; + } + if( nodesVisible == 0 && negation ) + { + return ETrue; + } + } + return EFalse; + } + +// End of file.