X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fpublic-api%2Fobject%2Fproperty-value.cpp;h=6a46abbf85e842f973351e0b49a3d57da9dbe1e2;hb=baae72ecde3f942d91829d0b2a042097b0206967;hp=d03b012c150e8c0e937fab4072e23dc25b7d95b1;hpb=9e4ec586b0b85f22460f68a22413be4308457ecd;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp index d03b012..6a46abb 100644 --- a/dali/public-api/object/property-value.cpp +++ b/dali/public-api/object/property-value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2015 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,10 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES -#include #include #include #include @@ -29,316 +31,299 @@ #include #include #include +#include +#include #include #include namespace Dali { +namespace +{ +/** + * Helper to check if the property value can be read as int/unsigned int/bool + */ +inline bool IsIntegerType( Property::Type type ) +{ + return ( Property::BOOLEAN == type )||( Property::INTEGER == type )||(Property::UNSIGNED_INTEGER == type ); +} +} + struct Property::Value::Impl { Impl() - : mType( Property::NONE ) - { - } + : type( Property::NONE ), + integerValue( 0 ) + { } - Impl(bool boolValue) - : mType( PropertyTypes::Get() ), - mValue( boolValue ) - { - } + Impl( bool booleanValue ) + : type( Property::BOOLEAN ), + integerValue( booleanValue ) + { } - Impl(float floatValue) - : mType( PropertyTypes::Get() ), - mValue( floatValue ) - { - } + Impl( float floatValue ) + : type( Property::FLOAT ), + floatValue( floatValue ) + { } - Impl(int integerValue) - : mType( PropertyTypes::Get() ), - mValue( integerValue ) - { - } + Impl( int integerValue ) + : type( Property::INTEGER ), + integerValue( integerValue ) + { } - Impl(unsigned int unsignedIntegerValue) - : mType( PropertyTypes::Get() ), - mValue( unsignedIntegerValue ) - { - } + Impl( unsigned int unsignedIntegerValue ) + : type( Property::UNSIGNED_INTEGER ), + unsignedIntegerValue( unsignedIntegerValue ) + { } - Impl(const Vector2& vectorValue) - : mType( PropertyTypes::Get() ), - mValue( vectorValue ) - { - } + Impl( const Vector2& vectorValue ) + : type( Property::VECTOR2 ), + vector2Value( new Vector2( vectorValue ) ) + { } - Impl(const Vector3& vectorValue) - : mType( PropertyTypes::Get() ), - mValue( vectorValue ) - { - } + Impl( const Vector3& vectorValue ) + : type( Property::VECTOR3 ), + vector3Value( new Vector3( vectorValue ) ) + { } + + Impl( const Vector4& vectorValue ) + : type( Property::VECTOR4 ), + vector4Value( new Vector4( vectorValue ) ) + { } - Impl(const Vector4& vectorValue) - : mType( PropertyTypes::Get() ), - mValue( vectorValue ) + Impl( const Matrix3& matrixValue ) + : type( Property::MATRIX3 ), + matrix3Value( new Matrix3( matrixValue ) ) { } - Impl(const Matrix3& matrixValue) - : mType(PropertyTypes::Get()), - mValue(matrixValue) + Impl( const Matrix& matrixValue ) + : type( Property::MATRIX ), + matrixValue( new Matrix( matrixValue ) ) { } - Impl(const Matrix& matrixValue) - : mType(PropertyTypes::Get()), - mValue(matrixValue) + Impl( const AngleAxis& angleAxisValue ) + : type( Property::ROTATION ), + quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) ) { } - Impl(const AngleAxis& angleAxisValue) - : mType( PropertyTypes::Get() ), - mValue( angleAxisValue ) + Impl( const Quaternion& quaternionValue ) + : type( Property::ROTATION ), + quaternionValue( new Quaternion( quaternionValue ) ) { } - Impl(const Quaternion& quaternionValue) - : mType( PropertyTypes::Get() ), - mValue( quaternionValue ) + Impl(const std::string& stringValue) + : type( Property::STRING ), + stringValue( new std::string( stringValue ) ) { } - Impl(const std::string& stringValue) - : mType( PropertyTypes::Get() ), - mValue( stringValue ) + Impl( const Rect& rectValue ) + : type( Property::RECTANGLE ), + rectValue( new Rect( rectValue ) ) { } - Impl(const Rect& rect) - : mType( PropertyTypes::Get >() ), - mValue( rect ) + Impl( const Property::Array& arrayValue ) + : type( Property::ARRAY ), + arrayValue( new Property::Array( arrayValue ) ) { } - Impl(Property::Map container) - : mType( PropertyTypes::Get() ), - mValue( container ) + Impl( const Property::Map& mapValue ) + : type( Property::MAP ), + mapValue( new Property::Map( mapValue ) ) { } - Impl(Property::Array container) - : mType( PropertyTypes::Get() ), - mValue( container ) + /** + * Destructor, takes care of releasing the dynamically allocated types + */ + ~Impl() { + switch( type ) + { + case Property::NONE : // FALLTHROUGH + case Property::BOOLEAN : // FALLTHROUGH + case Property::FLOAT : // FALLTHROUGH + case Property::INTEGER : // FALLTHROUGH + case Property::UNSIGNED_INTEGER : + { + break; // nothing to do + } + case Property::VECTOR2 : + { + delete vector2Value; + break; + } + case Property::VECTOR3: + { + delete vector3Value; + break; + } + case Property::VECTOR4: + { + delete vector4Value; + break; + } + case Property::MATRIX3: + { + delete matrix3Value; + break; + } + case Property::MATRIX: + { + delete matrixValue; + break; + } + case Property::RECTANGLE: + { + delete rectValue; + break; + } + case Property::ROTATION: + { + delete quaternionValue; + break; + } + case Property::STRING: + { + delete stringValue; + break; + } + case Property::ARRAY: + { + delete arrayValue; + break; + } + case Property::MAP: + { + delete mapValue; + break; + } + } } - Type mType; +public: // Data - typedef Any AnyValue; - AnyValue mValue; + Type type; + union + { + int integerValue; + float floatValue; + unsigned int unsignedIntegerValue; + // must use pointers for any class value pre c++ 11 + Vector2* vector2Value; + Vector3* vector3Value; + Vector4* vector4Value; + Matrix3* matrix3Value; + Matrix* matrixValue; + Quaternion* quaternionValue; + std::string* stringValue; + Rect* rectValue; + Property::Array* arrayValue; + Property::Map* mapValue; + }; }; Property::Value::Value() : mImpl( NULL ) { - mImpl = new Impl(); -} - -Property::Value::Value(bool boolValue) -: mImpl( NULL ) -{ - mImpl = new Impl( boolValue ); -} - -Property::Value::Value(float floatValue) -: mImpl( NULL ) -{ - mImpl = new Impl( floatValue ); } -Property::Value::Value(int integerValue) -: mImpl( NULL ) +Property::Value::Value( bool booleanValue ) +: mImpl( new Impl( booleanValue ) ) { - mImpl = new Impl( integerValue ); } -Property::Value::Value(unsigned int unsignedIntegerValue) -: mImpl( NULL ) +Property::Value::Value( float floatValue ) +: mImpl( new Impl( floatValue ) ) { - mImpl = new Impl( unsignedIntegerValue ); } -Property::Value::Value(const Vector2& vectorValue) -: mImpl( NULL ) +Property::Value::Value( int integerValue ) +: mImpl( new Impl( integerValue ) ) { - mImpl = new Impl( vectorValue ); } -Property::Value::Value(const Vector3& vectorValue) -: mImpl( NULL ) +Property::Value::Value( unsigned int unsignedIntegerValue ) +: mImpl( new Impl( unsignedIntegerValue ) ) { - mImpl = new Impl( vectorValue ); } -Property::Value::Value(const Vector4& vectorValue) -: mImpl( NULL ) +Property::Value::Value( const Vector2& vectorValue ) +: mImpl( new Impl( vectorValue ) ) { - mImpl = new Impl( vectorValue ); } -Property::Value::Value(const Matrix3& matrixValue) -: mImpl( NULL ) +Property::Value::Value( const Vector3& vectorValue ) +: mImpl( new Impl( vectorValue ) ) { - mImpl = new Impl( matrixValue ); } -Property::Value::Value(const Matrix& matrixValue) -: mImpl( NULL ) +Property::Value::Value( const Vector4& vectorValue ) +: mImpl( new Impl( vectorValue ) ) { - mImpl = new Impl( matrixValue ); } -Property::Value::Value(const Rect& rect) -: mImpl( NULL ) +Property::Value::Value( const Matrix3& matrixValue ) +: mImpl( new Impl( matrixValue ) ) { - mImpl = new Impl( rect ); } -Property::Value::Value(const AngleAxis& angleAxisValue) -: mImpl( NULL ) +Property::Value::Value( const Matrix& matrixValue ) +: mImpl( new Impl( matrixValue ) ) { - mImpl = new Impl( angleAxisValue ); } -Property::Value::Value(const Quaternion& quaternionValue) +Property::Value::Value( const Rect& rectValue ) +: mImpl( new Impl( rectValue ) ) { - mImpl = new Impl( quaternionValue ); } -Property::Value::Value(const std::string& stringValue) +Property::Value::Value( const AngleAxis& angleAxisValue ) +: mImpl( new Impl( angleAxisValue ) ) { - mImpl = new Impl( stringValue ); } -Property::Value::Value(const char *stringValue) +Property::Value::Value( const Quaternion& quaternionValue ) +: mImpl( new Impl( quaternionValue ) ) { - mImpl = new Impl( std::string(stringValue) ); } -Property::Value::Value(Property::Array &arrayValue) +Property::Value::Value( const std::string& stringValue ) +: mImpl( new Impl( stringValue ) ) { - mImpl = new Impl( arrayValue ); } -Property::Value::Value(Property::Map &mapValue) +Property::Value::Value( const char* stringValue ) +: mImpl( NULL ) { - mImpl = new Impl( mapValue ); + if( stringValue ) // string constructor is undefined with NULL pointer + { + mImpl = new Impl( std::string(stringValue) ); + } + else + { + mImpl = new Impl( std::string() ); + } } - -Property::Value::~Value() +Property::Value::Value( Property::Array& arrayValue ) +: mImpl( new Impl( arrayValue ) ) { - delete mImpl; } -Property::Value::Value(const Value& value) +Property::Value::Value( Property::Map& mapValue ) +: mImpl( new Impl( mapValue ) ) { - switch (value.GetType()) - { - case Property::BOOLEAN: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::FLOAT: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::INTEGER: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::UNSIGNED_INTEGER: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::VECTOR2: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::VECTOR3: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::VECTOR4: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::RECTANGLE: - { - mImpl = new Impl( value.Get >() ); - break; - } - - case Property::ROTATION: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::MATRIX3: - { - mImpl = new Impl( value.Get()); - break; - } - - case Property::MATRIX: - { - mImpl = new Impl( value.Get()); - break; - } - - case Property::STRING: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::MAP: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::ARRAY: - { - mImpl = new Impl( value.Get() ); - break; - } - - case Property::NONE: // fall - default: - { - mImpl = new Impl(); - break; - } - } } -Property::Value::Value(Type type) +Property::Value::Value( Type type ) { switch (type) { @@ -347,676 +332,556 @@ Property::Value::Value(Type type) mImpl = new Impl( false ); break; } - case Property::FLOAT: { mImpl = new Impl( 0.f ); break; } - case Property::INTEGER: { mImpl = new Impl( 0 ); break; } - case Property::UNSIGNED_INTEGER: { mImpl = new Impl( 0U ); break; } - case Property::VECTOR2: { mImpl = new Impl( Vector2::ZERO ); break; } - case Property::VECTOR3: { mImpl = new Impl( Vector3::ZERO ); break; } - case Property::VECTOR4: { mImpl = new Impl( Vector4::ZERO ); break; } - case Property::RECTANGLE: { mImpl = new Impl( Rect(0,0,0,0) ); break; } - case Property::ROTATION: { - mImpl = new Impl( Quaternion(0.f, Vector4::YAXIS) ); + mImpl = new Impl( Quaternion() ); break; } - case Property::STRING: { mImpl = new Impl( std::string() ); break; } - - case Property::MAP: - { - mImpl = new Impl( Property::Map() ); - break; - } - case Property::MATRIX: { mImpl = new Impl( Matrix() ); break; } - case Property::MATRIX3: { mImpl = new Impl( Matrix3() ); break; } - case Property::ARRAY: { mImpl = new Impl( Property::Array() ); break; } - - case Property::NONE: // fall - default: + case Property::MAP: + { + mImpl = new Impl( Property::Map() ); + break; + } + case Property::NONE: { mImpl = new Impl(); break; } } } +Property::Value::Value( const Property::Value& value ) +: mImpl( NULL ) +{ + // reuse assignment operator + operator=( value ); +} -Property::Value& Property::Value::operator=(const Property::Value& value) +Property::Value& Property::Value::operator=( const Property::Value& value ) { - if (this == &value) + if ( this == &value ) { // skip self assignment return *this; } - - mImpl->mType = value.GetType(); - - switch (mImpl->mType) + // if we are assigned an empty value, just drop impl + if( !value.mImpl ) { - case Property::BOOLEAN: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::FLOAT: + delete mImpl; + mImpl = NULL; + return *this; + } + // first check if the type is the same, no need to change impl, just assign + if( mImpl && ( mImpl->type == value.mImpl->type ) ) + { + switch( mImpl->type ) { - mImpl->mValue = value.Get(); - break; + case Property::BOOLEAN: + { + mImpl->integerValue = value.mImpl->integerValue; + break; + } + case Property::FLOAT: + { + mImpl->floatValue = value.mImpl->floatValue; + break; + } + case Property::INTEGER: + { + mImpl->integerValue = value.mImpl->integerValue; + break; + } + case Property::UNSIGNED_INTEGER: + { + mImpl->unsignedIntegerValue = value.mImpl->unsignedIntegerValue; + break; + } + case Property::VECTOR2: + { + *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated + break; + } + case Property::VECTOR3: + { + *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated + break; + } + case Property::VECTOR4: + { + *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated + break; + } + case Property::RECTANGLE: + { + *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated + break; + } + case Property::ROTATION: + { + *mImpl->quaternionValue = *value.mImpl->quaternionValue; // type cannot change in mImpl so quaternion is allocated + break; + } + case Property::STRING: + { + *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated + break; + } + case Property::MATRIX: + { + *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated + break; + } + case Property::MATRIX3: + { + *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated + break; + } + case Property::ARRAY: + { + *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated + break; + } + case Property::MAP: + { + *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated + break; + } + case Property::NONE: + { // mImpl will be NULL, there's no way to get to this case + } } - - case Property::INTEGER: + } + else + { + // different type, release old impl and create new + Impl* newImpl( NULL ); + switch ( value.mImpl->type ) { - mImpl->mValue = value.Get(); - break; + case Property::BOOLEAN: + { + newImpl = new Impl( bool( value.mImpl->integerValue ) ); + break; + } + case Property::FLOAT: + { + newImpl = new Impl( value.mImpl->floatValue ); + break; + } + case Property::INTEGER: + { + newImpl = new Impl( value.mImpl->integerValue ); + break; + } + case Property::UNSIGNED_INTEGER: + { + newImpl = new Impl( value.mImpl->unsignedIntegerValue ); + break; + } + case Property::VECTOR2: + { + newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated + break; + } + case Property::VECTOR3: + { + newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated + break; + } + case Property::VECTOR4: + { + newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated + break; + } + case Property::RECTANGLE: + { + newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated + break; + } + case Property::ROTATION: + { + newImpl = new Impl( *value.mImpl->quaternionValue ); // type cannot change in mImpl so quaternion is allocated + break; + } + case Property::MATRIX3: + { + newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated + break; + } + case Property::MATRIX: + { + newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated + break; + } + case Property::STRING: + { + newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated + break; + } + case Property::ARRAY: + { + newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated + break; + } + case Property::MAP: + { + newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated + break; + } + case Property::NONE: + { // NULL value will be used for "empty" value + } } - - case Property::UNSIGNED_INTEGER: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::VECTOR2: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::VECTOR3: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::VECTOR4: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::RECTANGLE: - { - mImpl->mValue = value.Get >(); - break; - } - - case Property::ROTATION: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::STRING: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::MATRIX: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::MATRIX3: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::MAP: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::ARRAY: - { - mImpl->mValue = value.Get(); - break; - } - - case Property::NONE: // fall - default: - { - mImpl->mValue = Impl::AnyValue(0); - break; - } - } + delete mImpl; + mImpl = newImpl; + } return *this; } -Property::Type Property::Value::GetType() const -{ - return mImpl->mType; -} - -void Property::Value::Get(bool& boolValue) const -{ - DALI_ASSERT_DEBUG( Property::BOOLEAN == GetType() && "Property type invalid" ); // AnyCast does asserted type checking - - boolValue = AnyCast(mImpl->mValue); -} - -void Property::Value::Get(float& floatValue) const -{ - DALI_ASSERT_DEBUG( Property::FLOAT == GetType() && "Property type invalid" ); - - floatValue = AnyCast(mImpl->mValue); -} - -void Property::Value::Get(int& integerValue) const -{ - DALI_ASSERT_DEBUG( Property::INTEGER == GetType() && "Property type invalid" ); - - integerValue = AnyCast(mImpl->mValue); -} - -void Property::Value::Get(unsigned int& unsignedIntegerValue) const -{ - DALI_ASSERT_DEBUG( Property::UNSIGNED_INTEGER == GetType() && "Property type invalid" ); - - unsignedIntegerValue = AnyCast(mImpl->mValue); -} - -void Property::Value::Get(Vector2& vectorValue) const +Property::Value::~Value() { - DALI_ASSERT_DEBUG( Property::VECTOR2 == GetType() && "Property type invalid" ); - - vectorValue = AnyCast(mImpl->mValue); + delete mImpl; } -void Property::Value::Get(Vector3& vectorValue) const +Property::Type Property::Value::GetType() const { - DALI_ASSERT_DEBUG( Property::VECTOR3 == GetType() && "Property type invalid" ); - - vectorValue = AnyCast(mImpl->mValue); + Property::Type type( Property::NONE ); + if( mImpl ) + { + type = mImpl->type; + } + return type; } -void Property::Value::Get(Vector4& vectorValue) const +bool Property::Value::Get( bool& booleanValue ) const { - DALI_ASSERT_DEBUG( Property::VECTOR4 == GetType() && "Property type invalid" ); - - vectorValue = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && IsIntegerType( mImpl->type ) ) + { + booleanValue = mImpl->integerValue; + converted = true; + } + return converted; } -void Property::Value::Get(Matrix3& matrixValue) const +bool Property::Value::Get( float& floatValue ) const { - DALI_ASSERT_DEBUG( Property::MATRIX3 == GetType() && "Property type invalid" ); - matrixValue = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && mImpl->type == FLOAT ) + { + floatValue = mImpl->floatValue; + converted = true; + } + return converted; } -void Property::Value::Get(Matrix& matrixValue) const +bool Property::Value::Get( int& integerValue ) const { - DALI_ASSERT_DEBUG( Property::MATRIX == GetType() && "Property type invalid" ); - matrixValue = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && IsIntegerType( mImpl->type ) ) + { + integerValue = mImpl->integerValue; + converted = true; + } + return converted; } -void Property::Value::Get(Rect& rect) const +bool Property::Value::Get( unsigned int& unsignedIntegerValue ) const { - DALI_ASSERT_DEBUG( Property::RECTANGLE == GetType() && "Property type invalid" ); - - rect = AnyCast >(mImpl->mValue); + bool converted = false; + if( mImpl && IsIntegerType( mImpl->type ) ) + { + unsignedIntegerValue = mImpl->unsignedIntegerValue; + converted = true; + } + return converted; } -void Property::Value::Get(AngleAxis& angleAxisValue) const +bool Property::Value::Get( Vector2& vectorValue ) const { - DALI_ASSERT_ALWAYS( Property::ROTATION == GetType() && "Property type invalid" ); - - // Rotations have two representations - DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() || - typeid(AngleAxis) == mImpl->mValue.GetType() ); - - if ( typeid(Quaternion) == mImpl->mValue.GetType() ) - { - Quaternion quaternion = AnyCast(mImpl->mValue); - - Radian angleRadians(0.0f); - quaternion.ToAxisAngle( angleAxisValue.axis, angleRadians ); - angleAxisValue.angle = angleRadians; - } - else + bool converted = false; + if( mImpl && (mImpl->type == VECTOR2) ) // type cannot change in mImpl so vector is allocated { - angleAxisValue = AnyCast(mImpl->mValue); + vectorValue = *(mImpl->vector2Value); + converted = true; } + return converted; } -void Property::Value::Get(Quaternion& quaternionValue) const +bool Property::Value::Get( Vector3& vectorValue ) const { - DALI_ASSERT_DEBUG( Property::ROTATION == GetType() && "Property type invalid" ); - - // Rotations have two representations - DALI_ASSERT_DEBUG( typeid(Quaternion) == mImpl->mValue.GetType() || - typeid(AngleAxis) == mImpl->mValue.GetType() ); - - if ( typeid(Quaternion) == mImpl->mValue.GetType() ) + bool converted = false; + if( mImpl && (mImpl->type == VECTOR3) ) // type cannot change in mImpl so vector is allocated { - quaternionValue = AnyCast(mImpl->mValue); - } - else - { - AngleAxis angleAxis = AnyCast(mImpl->mValue); - - quaternionValue = Quaternion( Radian(angleAxis.angle), angleAxis.axis ); + vectorValue = *(mImpl->vector3Value); + converted = true; } + return converted; } -void Property::Value::Get(std::string &out) const +bool Property::Value::Get( Vector4& vectorValue ) const { - DALI_ASSERT_DEBUG(Property::STRING == GetType() && "Property type invalid"); - - out = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && (mImpl->type == VECTOR4) ) // type cannot change in mImpl so vector is allocated + { + vectorValue = *(mImpl->vector4Value); + converted = true; + } + return converted; } -void Property::Value::Get(Property::Array &out) const +bool Property::Value::Get( Matrix3& matrixValue ) const { - DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid"); - - out = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated + { + matrixValue = *(mImpl->matrix3Value); + converted = true; + } + return converted; } -void Property::Value::Get(Property::Map &out) const +bool Property::Value::Get( Matrix& matrixValue ) const { - DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid"); - - out = AnyCast(mImpl->mValue); + bool converted = false; + if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated + { + matrixValue = *(mImpl->matrixValue); + converted = true; + } + return converted; } -Property::Value& Property::Value::GetValue(const std::string& key) const +bool Property::Value::Get( Rect& rectValue ) const { - DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid"); - - Property::Map *container = AnyCast(&(mImpl->mValue)); - - DALI_ASSERT_DEBUG(container); - - if(container) + bool converted = false; + if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated { - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(iter->first == key) - { - return iter->second; - } - } + rectValue = *(mImpl->rectValue); + converted = true; } - - DALI_LOG_WARNING("Cannot find property map key %s", key.c_str()); - DALI_ASSERT_ALWAYS(!"Cannot find property map key"); - - // should never return this - static Property::Value null; - return null; + return converted; } -bool Property::Value::HasKey(const std::string& key) const +bool Property::Value::Get( AngleAxis& angleAxisValue ) const { - bool has = false; - - if( Property::MAP == GetType() ) + bool converted = false; + if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated { - Property::Map *container = AnyCast(&(mImpl->mValue)); - - DALI_ASSERT_DEBUG(container && "Property::Map has no container?"); - - if(container) - { - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(iter->first == key) - { - has = true; - } - } - } + mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle ); + converted = true; } - - return has; + return converted; } - -const std::string& Property::Value::GetKey(const int index) const +bool Property::Value::Get( Quaternion& quaternionValue ) const { - switch( GetType() ) + bool converted = false; + if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated { - case Property::MAP: - { - int i = 0; - Property::Map *container = AnyCast(&(mImpl->mValue)); - DALI_ASSERT_DEBUG(container && "Property::Map has no container?"); - if(container) - { - if(0 <= index && index < static_cast(container->size())) - { - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(i++ == index) - { - return iter->first; - } - } - } - } - } - break; - case Property::NONE: - case Property::ARRAY: - case Property::BOOLEAN: - case Property::FLOAT: - case Property::UNSIGNED_INTEGER: - case Property::INTEGER: - case Property::VECTOR2: - case Property::VECTOR3: - case Property::VECTOR4: - case Property::MATRIX: - case Property::MATRIX3: - case Property::RECTANGLE: - case Property::ROTATION: - case Property::STRING: - case Property::TYPE_COUNT: - { - break; - } + quaternionValue = *(mImpl->quaternionValue); + converted = true; } - - - // should never return this - static std::string null; - return null; + return converted; } - -void Property::Value::SetValue(const std::string& key, const Property::Value &value) +bool Property::Value::Get( std::string& stringValue ) const { - DALI_ASSERT_DEBUG(Property::MAP == GetType() && "Property type invalid"); - - Property::Map *container = AnyCast(&(mImpl->mValue)); - - if(container) + bool converted = false; + if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated { - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(iter->first == key) - { - iter->second = value; - return; - } - } - - // if we get here its a new key - container->push_back(Property::StringValuePair(key, value)); - + stringValue.assign( *(mImpl->stringValue) ); + converted = true; } + return converted; } -Property::Value& Property::Value::GetItem(const int index) const +bool Property::Value::Get( Property::Array& arrayValue ) const { - switch( GetType() ) + bool converted = false; + if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated { - case Property::MAP: - { - int i = 0; - Property::Map *container = AnyCast(&(mImpl->mValue)); - - DALI_ASSERT_DEBUG(container && "Property::Map has no container?"); - if(container) - { - DALI_ASSERT_ALWAYS(index < static_cast(container->size()) && "Property array index invalid"); - DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid"); - - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(i++ == index) - { - return iter->second; - } - } - } - } - break; - - case Property::ARRAY: - { - int i = 0; - Property::Array *container = AnyCast(&(mImpl->mValue)); - - DALI_ASSERT_DEBUG(container && "Property::Map has no container?"); - if(container) - { - DALI_ASSERT_ALWAYS(index < static_cast(container->size()) && "Property array index invalid"); - DALI_ASSERT_ALWAYS(index >= 0 && "Property array index invalid"); - - for(Property::Array::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(i++ == index) - { - return *iter; - } - } - } - } - break; - - case Property::NONE: - case Property::BOOLEAN: - case Property::FLOAT: - case Property::INTEGER: - case Property::UNSIGNED_INTEGER: - case Property::VECTOR2: - case Property::VECTOR3: - case Property::VECTOR4: - case Property::MATRIX3: - case Property::MATRIX: - case Property::RECTANGLE: - case Property::ROTATION: - case Property::STRING: - case Property::TYPE_COUNT: - { - DALI_ASSERT_ALWAYS(!"Cannot GetItem on property Type; not a container"); - break; - } - - } // switch GetType() - - - DALI_ASSERT_ALWAYS(!"Property value index not valid"); - - // should never return this - static Property::Value null; - return null; + arrayValue = *(mImpl->arrayValue); + converted = true; + } + return converted; } -Property::Value& Property::Value::GetItem(const int index, std::string& key) const +bool Property::Value::Get( Property::Map& mapValue ) const { - Property::Value& ret( GetItem(index) ); - - if( Property::MAP == GetType() ) + bool converted = false; + if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated { - Property::Map *container = AnyCast(&(mImpl->mValue)); - if( index < static_cast(container->size()) ) - { - - key = (*container)[ index ].first; - } + mapValue = *(mImpl->mapValue); + converted = true; } - - return ret; + return converted; } -void Property::Value::SetItem(const int index, const Property::Value &value) +Property::Array* Property::Value::GetArray() const { - switch( GetType() ) + Property::Array* array = NULL; + if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated { - case Property::MAP: - { - Property::Map *container = AnyCast(&(mImpl->mValue)); - if( container && index < static_cast(container->size()) ) - { - int i = 0; - for(Property::Map::iterator iter = container->begin(); iter != container->end(); ++iter) - { - if(i++ == index) - { - iter->second = value; - break; - } - } - } - } - break; - - case Property::ARRAY: - { - Property::Array *container = AnyCast(&(mImpl->mValue)); - if( container && index < static_cast(container->size()) ) - { - (*container)[index] = value; - } - } - break; - - case Property::NONE: - case Property::BOOLEAN: - case Property::FLOAT: - case Property::INTEGER: - case Property::UNSIGNED_INTEGER: - case Property::VECTOR2: - case Property::VECTOR3: - case Property::VECTOR4: - case Property::MATRIX3: - case Property::MATRIX: - case Property::RECTANGLE: - case Property::ROTATION: - case Property::STRING: - case Property::TYPE_COUNT: - { - DALI_ASSERT_ALWAYS(!"Cannot SetItem on property Type; not a container"); - break; - } + array = mImpl->arrayValue; } + return array; } -int Property::Value::AppendItem(const Property::Value &value) +Property::Map* Property::Value::GetMap() const { - DALI_ASSERT_DEBUG(Property::ARRAY == GetType() && "Property type invalid"); - - Property::Array *container = AnyCast(&(mImpl->mValue)); - - if(container) + Property::Map* map = NULL; + if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated { - container->push_back(value); - return container->size() - 1; + map = mImpl->mapValue; } - else - { - return -1; - } - + return map; } -int Property::Value::GetSize() const +std::ostream& operator<<( std::ostream& stream, const Property::Value& value ) { - int ret = 0; - - switch(GetType()) + if( value.mImpl ) { - case Property::MAP: + const Property::Value::Impl& impl( *value.mImpl ); + + switch( impl.type ) { - Property::Map *container = AnyCast(&(mImpl->mValue)); - if(container) + case Dali::Property::BOOLEAN: { - ret = container->size(); + stream << impl.integerValue; + break; } - } - break; - - case Property::ARRAY: - { - Property::Array *container = AnyCast(&(mImpl->mValue)); - if(container) + case Dali::Property::FLOAT: { - ret = container->size(); + stream << impl.floatValue; + break; + } + case Dali::Property::INTEGER: + { + stream << impl.integerValue; + break; + } + case Dali::Property::UNSIGNED_INTEGER: + { + stream << impl.unsignedIntegerValue; + break; + } + case Dali::Property::VECTOR2: + { + stream << *impl.vector2Value; + break; + } + case Dali::Property::VECTOR3: + { + stream << *impl.vector3Value; + break; + } + case Dali::Property::VECTOR4: + { + stream << *impl.vector4Value; + break; + } + case Dali::Property::MATRIX3: + { + stream << *impl.matrix3Value; + break; + } + case Dali::Property::MATRIX: + { + stream << *impl.matrixValue; + break; + } + case Dali::Property::RECTANGLE: + { + stream << *impl.rectValue; + break; + } + case Dali::Property::ROTATION: + { + stream << *impl.quaternionValue; + break; + } + case Dali::Property::STRING: + { + stream << *impl.stringValue; + break; + } + case Dali::Property::ARRAY: + { + stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array + break; + } + case Dali::Property::MAP: + { + stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map + break; + } + case Dali::Property::NONE: + { + stream << "undefined type"; + break; } } - break; - - case Property::NONE: - case Property::BOOLEAN: - case Property::FLOAT: - case Property::INTEGER: - case Property::UNSIGNED_INTEGER: - case Property::VECTOR2: - case Property::VECTOR3: - case Property::VECTOR4: - case Property::MATRIX3: - case Property::MATRIX: - case Property::RECTANGLE: - case Property::ROTATION: - case Property::STRING: - case Property::TYPE_COUNT: - { - break; - } - } - - return ret; + else + { + stream << "empty type"; + } + return stream; }