Added Property::Key type to properly represent keys in maps 52/88152/9
authorDavid Steele <david.steele@partner.samsung.com>
Tue, 13 Sep 2016 19:57:40 +0000 (20:57 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Fri, 16 Sep 2016 10:40:46 +0000 (11:40 +0100)
Currently, Property::Map can have either string or integer
keys. The two methods GetPair and GetKey only allow iteration
over string keys.

Have added a single Key type that enables the retrieval of all
keys of Property::Map via the two new methods GetKeyAt and GetKeyValue

Have un-deprecated GetValue, which is still valid.

Added a new method Handle::GetPropertyIndex( Property::Key ), which
allows a lookup of a property from a property map key.

This is useful to enable property maps to be used as a property
aggregator when setting values on objects.

Have updated Scripting and PropertyBuffer to use new Property::Map
interface rather than the deprecated interface.

Change-Id: Ie2db5355fd661ed73a6f92b720d92ca1e6ab8d76
Signed-off-by: David Steele <david.steele@samsung.com>
15 files changed:
automated-tests/src/dali/utc-Dali-Handle.cpp
automated-tests/src/dali/utc-Dali-PropertyMap.cpp
automated-tests/src/dali/utc-Dali-Scripting.cpp
dali/devel-api/scripting/scripting.cpp
dali/internal/event/common/object-impl.cpp
dali/internal/event/common/object-impl.h
dali/internal/event/common/property-buffer-impl.cpp
dali/public-api/file.list
dali/public-api/object/handle.cpp
dali/public-api/object/handle.h
dali/public-api/object/property-key.cpp [new file with mode: 0644]
dali/public-api/object/property-key.h [new file with mode: 0644]
dali/public-api/object/property-map.cpp
dali/public-api/object/property-map.h
dali/public-api/object/property.h

index 387676b..35e2784 100644 (file)
@@ -171,7 +171,7 @@ int UtcDaliHandleGetPropertyName(void)
   END_TEST;
 }
 
-int UtcDaliHandleGetPropertyIndex(void)
+int UtcDaliHandleGetPropertyIndex01(void)
 {
   tet_infoline("Positive Test Dali::Handle::GetPropertyIndex()");
   TestApplication application;
@@ -186,6 +186,81 @@ int UtcDaliHandleGetPropertyIndex(void)
   END_TEST;
 }
 
+int UtcDaliHandleGetPropertyIndex02(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyIndex() int key");
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  stage.Add( actor );
+
+  const unsigned int defaultPropertyCount = actor.GetPropertyCount();
+
+  application.SendNotification();
+  application.Render();
+
+  Property::Index key1 = CORE_PROPERTY_MAX_INDEX+1;
+  Property::Index key2 = CORE_PROPERTY_MAX_INDEX+2;
+
+  const Vector4 testColor(0.5f, 0.2f, 0.9f, 1.0f);
+  const float withFlake(99.f);
+
+  Property::Index index1 = actor.RegisterProperty( "MyPropertyOne", Vector3::ONE );
+  Property::Index index2 = actor.RegisterProperty( key1, "sideColor", testColor);
+  Property::Index index3 = actor.RegisterProperty( "MyPropertyTwo", Vector3::ONE );
+  Property::Index index4 = actor.RegisterProperty( key2, "iceCream", withFlake );
+  Property::Index index5 = actor.RegisterProperty( "MyPropertyThree", Vector3::ONE );
+
+  application.SendNotification();
+  application.Render();
+
+  // Test that we can get the property index from the integer key
+  Property::Index testIndex1 = actor.GetPropertyIndex( key1 );
+  Property::Index testIndex2 = actor.GetPropertyIndex( key2 );
+
+  DALI_TEST_EQUALS( index2, testIndex1, TEST_LOCATION );
+  DALI_TEST_EQUALS( index4, testIndex2, TEST_LOCATION );
+
+  // Test that we keep the same indices on the named properties
+  Property::Index testIndex = actor.GetPropertyIndex("MyPropertyOne");
+  DALI_TEST_EQUALS(testIndex, index1, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("MyPropertyTwo");
+  DALI_TEST_EQUALS(testIndex, index3, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("MyPropertyThree");
+  DALI_TEST_EQUALS(testIndex, index5, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("sideColor");
+  DALI_TEST_EQUALS(testIndex, index2, TEST_LOCATION);
+  testIndex = actor.GetPropertyIndex("iceCream");
+  DALI_TEST_EQUALS(testIndex, index4, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(defaultPropertyCount+5, actor.GetPropertyCount(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliHandleGetPropertyIndex03(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  std::string myName("croydon");
+  Property::Index intKey = CORE_PROPERTY_MAX_INDEX+1;
+  Property::Value value( Color::GREEN );
+  Property::Index myIndex = actor.RegisterProperty( intKey, myName, value );
+
+  DALI_TEST_EQUALS( myIndex, actor.GetPropertyIndex( intKey ), TEST_LOCATION );
+
+  Property::Key key1(myName);
+  Property::Key key2(intKey);
+
+  DALI_TEST_EQUALS( myIndex, actor.GetPropertyIndex( key1 ), TEST_LOCATION );
+  DALI_TEST_EQUALS( myIndex, actor.GetPropertyIndex( key2 ), TEST_LOCATION );
+  END_TEST;
+}
+
+
 int UtcDaliHandleIsPropertyWritable(void)
 {
   tet_infoline("Positive Test Dali::Handle::IsPropertyWritable()");
@@ -678,58 +753,6 @@ int UtcDaliHandleRegisterProperty02(void)
 }
 
 
-int UtcDaliHandleGetPropertyIndex02(void)
-{
-  tet_infoline("Positive Test Dali::Handle::GetPropertyIndex() int key");
-  TestApplication application;
-
-  Stage stage = Stage::GetCurrent();
-
-  Actor actor = Actor::New();
-  stage.Add( actor );
-
-  const unsigned int defaultPropertyCount = actor.GetPropertyCount();
-
-  application.SendNotification();
-  application.Render();
-
-  Property::Index key1 = CORE_PROPERTY_MAX_INDEX+1;
-  Property::Index key2 = CORE_PROPERTY_MAX_INDEX+2;
-
-  const Vector4 testColor(0.5f, 0.2f, 0.9f, 1.0f);
-  const float withFlake(99.f);
-
-  Property::Index index1 = actor.RegisterProperty( "MyPropertyOne", Vector3::ONE );
-  Property::Index index2 = actor.RegisterProperty( key1, "sideColor", testColor);
-  Property::Index index3 = actor.RegisterProperty( "MyPropertyTwo", Vector3::ONE );
-  Property::Index index4 = actor.RegisterProperty( key2, "iceCream", withFlake );
-  Property::Index index5 = actor.RegisterProperty( "MyPropertyThree", Vector3::ONE );
-
-  application.SendNotification();
-  application.Render();
-
-  // Test that we can get the property index from the integer key
-  Property::Index testIndex1 = actor.GetPropertyIndex( key1 );
-  Property::Index testIndex2 = actor.GetPropertyIndex( key2 );
-
-  DALI_TEST_EQUALS( index2, testIndex1, TEST_LOCATION );
-  DALI_TEST_EQUALS( index4, testIndex2, TEST_LOCATION );
-
-  // Test that we keep the same indices on the named properties
-  Property::Index testIndex = actor.GetPropertyIndex("MyPropertyOne");
-  DALI_TEST_EQUALS(testIndex, index1, TEST_LOCATION);
-  testIndex = actor.GetPropertyIndex("MyPropertyTwo");
-  DALI_TEST_EQUALS(testIndex, index3, TEST_LOCATION);
-  testIndex = actor.GetPropertyIndex("MyPropertyThree");
-  DALI_TEST_EQUALS(testIndex, index5, TEST_LOCATION);
-  testIndex = actor.GetPropertyIndex("sideColor");
-  DALI_TEST_EQUALS(testIndex, index2, TEST_LOCATION);
-  testIndex = actor.GetPropertyIndex("iceCream");
-  DALI_TEST_EQUALS(testIndex, index4, TEST_LOCATION);
-
-  DALI_TEST_EQUALS(defaultPropertyCount+5, actor.GetPropertyCount(), TEST_LOCATION);
-  END_TEST;
-}
 
 int UtcDaliHandleGetProperty(void)
 {
index 6fb550d..7283e1c 100644 (file)
@@ -109,22 +109,27 @@ int UtcDaliPropertyMapConstOperator(void)
   END_TEST;
 }
 
-// deprecated API, only retrieve the value from string-value pairs
 int UtcDaliPropertyMapGetValue(void)
 {
   Property::Map map;
   map[ "hello" ] = 1;
   map[ "world" ] = 2;
+  map[ Actor::Property::COLOR ] = Color::MAGENTA;
 
   Property::Value& value = map.GetValue( 0 );
   DALI_TEST_CHECK( value.Get<int>() == 1 );
   value = 10; // Allows the actual changing of the value as we have a ref
   DALI_TEST_CHECK( map[ "hello" ].Get<int>() == 10 );
 
+  Property::Value& value2 = map.GetValue( 2 );
+  DALI_TEST_CHECK( value2.Get<Vector4>() == Color::MAGENTA );
+  value2 = Color::CYAN;
+  DALI_TEST_EQUALS( map[ Actor::Property::COLOR].Get<Vector4>(), Color::CYAN, TEST_LOCATION);
+
   // Out of bounds
   try
   {
-    map.GetValue( 2 );
+    map.GetValue( 3 );
     tet_result( TET_FAIL );
   }
   catch ( DaliException& e )
@@ -141,11 +146,12 @@ int UtcDaliPropertyMapGetKey(void)
   Property::Map map;
   map[ "hello" ] = 1;
   map[ "world" ] = 2;
+  map[ Actor::Property::COLOR ] = Color::MAGENTA;
 
   DALI_TEST_CHECK( map.GetKey( 0 ) == "hello" );
   DALI_TEST_CHECK( map.GetKey( 1 ) == "world" );
 
-  // Out of bounds
+  // Wrong type
   try
   {
     map.GetKey( 2 );
@@ -156,22 +162,59 @@ int UtcDaliPropertyMapGetKey(void)
     DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
   }
 
+  // Out of bounds
+  try
+  {
+    map.GetKey( 3 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliPropertyMapGetKeyAt(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+  map[ Actor::Property::COLOR ] = Color::MAGENTA;
+
+  DALI_TEST_CHECK( map.GetKeyAt( 0 ) == "hello" );
+  DALI_TEST_CHECK( map.GetKeyAt( 1 ) == "world" );
+  DALI_TEST_CHECK( map.GetKeyAt( 2 ) == Actor::Property::COLOR );
+
+  // Out of bounds
+  try
+  {
+    map.GetKey( 3 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
   END_TEST;
 }
 
-// deprecated API, only retrieve the string-value pairs
 int UtcDaliPropertyMapGetPair(void)
 {
   Property::Map map;
   map[ "hello" ] = 1;
   map[ "world" ] = 2;
+  map[ Actor::Property::COLOR ] = Color::MAGENTA;
 
   DALI_TEST_CHECK( map.GetPair( 0 ).first == "hello" );
   DALI_TEST_CHECK( map.GetPair( 0 ).second.Get< int >() == 1 );
   DALI_TEST_CHECK( map.GetPair( 1 ).first == "world" );
   DALI_TEST_CHECK( map.GetPair( 1 ).second.Get< int >() == 2 );
 
-  // Out of bounds
+  // Wrong Type
   try
   {
     map.GetPair( 2 );
@@ -182,6 +225,45 @@ int UtcDaliPropertyMapGetPair(void)
     DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
   }
 
+  // Out of bounds
+  try
+  {
+    map.GetPair( 3 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapGetKeyValue(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+  map[ Actor::Property::COLOR ] = Color::MAGENTA;
+
+  DALI_TEST_CHECK( map.GetKeyValue( 0 ).first == "hello" );
+  DALI_TEST_CHECK( map.GetKeyValue( 0 ).second.Get< int >() == 1 );
+  DALI_TEST_CHECK( map.GetKeyValue( 1 ).first == "world" );
+  DALI_TEST_CHECK( map.GetKeyValue( 1 ).second.Get< int >() == 2 );
+  DALI_TEST_CHECK( map.GetKeyValue( 2 ).first == Actor::Property::COLOR );
+  DALI_TEST_CHECK( map.GetKeyValue( 2 ).second.Get< Vector4 >() == Color::MAGENTA );
+
+  // Out of bounds
+  try
+  {
+    map.GetPair( 3 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
   END_TEST;
 }
 
@@ -533,3 +615,74 @@ int UtcDaliPropertyMapOstream02(void)
 
   END_TEST;
 }
+
+int UtcDaliPropertyKeyConstructorP(void)
+{
+  Property::Key key1( "aKey" );
+  DALI_TEST_EQUALS( key1.type, Property::Key::STRING, TEST_LOCATION );
+  DALI_TEST_EQUALS( key1.stringKey, "aKey", TEST_LOCATION );
+  DALI_TEST_EQUALS( key1.indexKey, Property::INVALID_INDEX, TEST_LOCATION );
+
+  Property::Key key2( Actor::Property::COLOR );
+  DALI_TEST_EQUALS( key2.type, Property::Key::INDEX, TEST_LOCATION );
+  DALI_TEST_EQUALS( key2.indexKey, (Dali::Property::Index)Actor::Property::COLOR, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyKeyEqualityOperatorP(void)
+{
+  Property::Key key1( "aKey" );
+  Property::Key key2( 113 );
+
+  DALI_TEST_CHECK( key1 == "aKey" );
+  DALI_TEST_CHECK( ! (key1 == "notTheKey") );
+  DALI_TEST_CHECK( ! (key1 == 1) );
+
+  DALI_TEST_CHECK( key2 == 113 );
+  DALI_TEST_CHECK( ! (key2 == 0) );
+  DALI_TEST_CHECK( ! (key2 == "One hundred and thirteen" ) );
+
+  DALI_TEST_CHECK( ! (key1 == key2) );
+  DALI_TEST_CHECK( key1 != key2 );
+
+  Property::Key key1B( "aKey" );
+  Property::Key key2B( 113 );
+
+  DALI_TEST_CHECK( key1 == key1B );
+  DALI_TEST_CHECK( key2 == key2B );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyKeyInequalityOperatorP(void)
+{
+  Property::Key key1( "aKey" );
+  Property::Key key2( 113 );
+
+  DALI_TEST_CHECK( key1 != "notTheKey" );
+  DALI_TEST_CHECK( key1 != 1 );
+
+  DALI_TEST_CHECK( key2 != 0 );
+  DALI_TEST_CHECK( key2 != "One hundred and thirteen" );
+
+  DALI_TEST_CHECK( key1 != key2 );
+
+  END_TEST;
+}
+
+
+int UtcDaliPropertyKeyOutputStream(void)
+{
+  Property::Key key1( "aKey" );
+  Property::Key key2( 113 );
+
+  std::ostringstream oss;
+  oss << key1;
+  DALI_TEST_EQUALS( oss.str(), "aKey", TEST_LOCATION );
+
+  std::ostringstream oss2;
+  oss2 << key2;
+  DALI_TEST_EQUALS( oss2.str(), "113", TEST_LOCATION );
+
+  END_TEST;
+}
index 151b770..756176a 100644 (file)
@@ -549,6 +549,46 @@ int UtcDaliScriptingNewActorProperties(void)
   END_TEST;
 }
 
+int UtcDaliScriptingNewAnimation(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map["actor"] = "Actor1";
+  map["property"] = "color";
+  map["value"] = Color::MAGENTA;
+  map["alphaFunction"] = "EASE_IN_OUT";
+
+  Property::Map timePeriod;
+  timePeriod["delay"] = 0.5f;
+  timePeriod["duration"] = 1.0f;
+  map["timePeriod"] = timePeriod;
+
+  Dali::AnimationData data;
+  Scripting::NewAnimation( map, data );
+
+  Actor actor = Actor::New();
+  actor.SetName("Actor1");
+  actor.SetColor(Color::CYAN);
+  Stage::GetCurrent().Add(actor);
+
+  Animation anim = data.CreateAnimation( actor, 0.5f );
+  anim.Play();
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render(500); // Start animation
+  application.Render(500); // Halfway thru anim
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), (Color::MAGENTA+Color::CYAN)*0.5f, TEST_LOCATION);
+
+  application.Render(500); // Halfway thru anim
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::MAGENTA, TEST_LOCATION );
+
+  END_TEST;
+}
+
 int UtcDaliScriptingNewActorChildren(void)
 {
   TestApplication application;
index 57c1ede..4a91adf 100644 (file)
@@ -342,8 +342,12 @@ Actor NewActor( const Property::Map& map )
     // Now set the properties, or create children
     for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
     {
-      const StringValuePair& pair( map.GetPair( i ) );
-      const std::string& key( pair.first );
+      const KeyValuePair pair( map.GetKeyValue( i ) );
+      if( pair.first.type == Property::Key::INDEX )
+      {
+        continue;
+      }
+      const std::string& key( pair.first.stringKey );
       if ( key == "type" )
       {
         continue;
@@ -459,8 +463,13 @@ void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimatio
   // Now set the properties, or create children
   for( unsigned int i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i )
   {
-    const StringValuePair& pair( map.GetPair( i ) );
-    const std::string& key( pair.first );
+    const KeyValuePair pair( map.GetKeyValue( i ) );
+    if( pair.first.type == Property::Key::INDEX )
+    {
+      continue; // We don't consider index keys.
+    }
+    const std::string& key( pair.first.stringKey );
+
     const Property::Value& value( pair.second );
 
     if( key == "actor" )
@@ -537,12 +546,18 @@ void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimatio
       Property::Map timeMap = value.Get< Property::Map >();
       for( unsigned int i = 0; i < timeMap.Count(); ++i )
       {
-        const StringValuePair& pair( timeMap.GetPair( i ) );
-        if( pair.first == "delay" )
+        const KeyValuePair pair( timeMap.GetKeyValue( i ) );
+        if( pair.first.type == Property::Key::INDEX )
+        {
+          continue;
+        }
+        const std::string& key( pair.first.stringKey );
+
+        if( key == "delay" )
         {
           element->timePeriodDelay = pair.second.Get< float >();
         }
-        else if( pair.first == "duration" )
+        else if( key == "duration" )
         {
           element->timePeriodDuration = pair.second.Get< float >();
         }
@@ -556,7 +571,3 @@ void NewAnimation( const Property::Map& map, Dali::AnimationData& outputAnimatio
 } // namespace scripting
 
 } // namespace Dali
-
-
-
-
index 14a5008..f150c35 100644 (file)
@@ -273,6 +273,20 @@ Property::Index Object::GetPropertyIndex( Property::Index key ) const
   return index;
 }
 
+Property::Index Object::GetPropertyIndex( Property::Key key ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+  if( key.type == Property::Key::INDEX )
+  {
+    index = GetPropertyIndex( key.indexKey );
+  }
+  else
+  {
+    index = GetPropertyIndex( key.stringKey );
+  }
+  return index;
+}
+
 bool Object::IsPropertyWritable( Property::Index index ) const
 {
   DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
index b4fbc53..25547a9 100644 (file)
@@ -156,6 +156,11 @@ public:
   virtual Property::Index GetPropertyIndex( Property::Index key ) const;
 
   /**
+   * @copydoc Dali::Handle::GetPropertyIndex()
+   */
+  virtual Property::Index GetPropertyIndex( Property::Key key ) const;
+
+  /**
    * @copydoc Dali::Handle::IsPropertyWritable()
    */
   virtual bool IsPropertyWritable( Property::Index index ) const;
index 7b00e9e..70c5edc 100644 (file)
@@ -195,10 +195,14 @@ void PropertyBuffer::Initialize( Dali::Property::Map& formatMap )
 
   for( size_t i = 0u; i < numComponents; ++i )
   {
-    StringValuePair component = mFormat.GetPair( i );
+    KeyValuePair component = mFormat.GetKeyValue( i );
 
     // Get the name
-    format->components[i].name = component.first;
+    if(component.first.type == Property::Key::INDEX)
+    {
+      continue;
+    }
+    format->components[i].name = component.first.stringKey;
 
     // enums are stored in the map as int
     Property::Type type = Property::Type( component.second.Get<int>() );
index c24cbea..e23504d 100644 (file)
@@ -61,6 +61,7 @@ public_api_src_files = \
   $(public_api_src_dir)/object/property-array.cpp \
   $(public_api_src_dir)/object/property-conditions.cpp \
   $(public_api_src_dir)/object/property-input.cpp \
+  $(public_api_src_dir)/object/property-key.cpp \
   $(public_api_src_dir)/object/property-map.cpp \
   $(public_api_src_dir)/object/property-notification.cpp \
   $(public_api_src_dir)/object/property-types.cpp \
@@ -187,6 +188,7 @@ public_api_core_object_header_files = \
   $(public_api_src_dir)/object/property-conditions.h \
   $(public_api_src_dir)/object/property-index-ranges.h \
   $(public_api_src_dir)/object/property-input.h \
+  $(public_api_src_dir)/object/property-key.h \
   $(public_api_src_dir)/object/property-map.h \
   $(public_api_src_dir)/object/property-notification-declarations.h \
   $(public_api_src_dir)/object/property-notification.h \
index ea5ddd9..aa6147d 100644 (file)
@@ -95,6 +95,11 @@ Property::Index Handle::GetPropertyIndex( Property::Index key ) const
   return GetImplementation(*this).GetPropertyIndex( key );
 }
 
+Property::Index Handle::GetPropertyIndex( Property::Key key ) const
+{
+  return GetImplementation(*this).GetPropertyIndex( key );
+}
+
 bool Handle::IsPropertyWritable( Property::Index index ) const
 {
   return GetImplementation(*this).IsPropertyWritable( index );
index b0f7f6b..b5a7f0e 100644 (file)
@@ -195,6 +195,19 @@ public:
   Property::Index GetPropertyIndex( Property::Index key ) const;
 
   /**
+   * @brief Query the index of a property using the given key from a Property::Map
+   * @SINCE_1_2.7
+   *
+   * @param[in] key The key of the property to search for.
+   * @return the matching property index of either the string key or the matching
+   * custom property index of the index key, or Property::INVALID_INDEX if no
+   * property matches the given key.
+   *
+   * @note See also, GetPropertyIndex(Property::Index) and GetPropertyIndex(const std::string&)
+   */
+  Property::Index GetPropertyIndex( Property::Key key ) const;
+
+  /**
    * @brief Query whether a property can be set using SetProperty().
    *
    * @SINCE_1_0.0
diff --git a/dali/public-api/object/property-key.cpp b/dali/public-api/object/property-key.cpp
new file mode 100644 (file)
index 0000000..78e42bf
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-key.h>
+
+
+namespace Dali
+{
+
+Property::Key::Key( const std::string& key )
+: type(Key::STRING),
+  indexKey( Property::INVALID_INDEX ),
+  stringKey( key )
+{
+}
+
+Property::Key::Key( Property::Index key )
+: type(Key::INDEX),
+  indexKey( key )
+{
+}
+
+bool Property::Key::operator== (const std::string& rhs)
+{
+  bool result=false;
+  if(type == Key::STRING)
+  {
+    result = (stringKey == rhs);
+  }
+  return result;
+}
+
+bool Property::Key::operator== (Property::Index rhs)
+{
+  bool result=false;
+  if(type == Key::INDEX)
+  {
+    result = (indexKey == rhs);
+  }
+  return result;
+}
+
+bool Property::Key::operator== (const Key& rhs)
+{
+  bool result=false;
+  if(type == Key::STRING && rhs.type == Key::STRING )
+  {
+    result = (stringKey == rhs.stringKey);
+  }
+  else if( type == Key::INDEX && rhs.type == Key::INDEX )
+  {
+    result = (indexKey == rhs.indexKey);
+  }
+  return result;
+}
+
+bool Property::Key::operator!= (const std::string& rhs)
+{
+  return !operator==(rhs);
+}
+
+bool Property::Key::operator!= (Property::Index rhs)
+{
+  return !operator==(rhs);
+}
+
+bool Property::Key::operator!= (const Key& rhs)
+{
+  return !operator==(rhs);
+}
+
+std::ostream& operator<<( std::ostream& stream, const Property::Key& key )
+{
+  if( key.type == Property::Key::INDEX )
+  {
+    stream << key.indexKey;
+  }
+  else
+  {
+    stream << key.stringKey;
+  }
+  return stream;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-key.h b/dali/public-api/object/property-key.h
new file mode 100644 (file)
index 0000000..bd9a921
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __DALI_PROPERTY_KEY_H__
+#define __DALI_PROPERTY_KEY_H__
+
+/*
+ * Copyright (c) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief A key type which can be either a std::string or a Property::Index
+ * @SINCE_1_2.7
+ */
+struct DALI_IMPORT_API Property::Key
+{
+  /**
+   * @brief The type of key
+   * @SINCE_1_2.7
+   */
+  enum Type
+  {
+    INDEX, ///< The key is a Property::Index
+    STRING ///< The key is a string
+  } type; ///< The type of the key
+
+  Property::Index indexKey; ///< The index key.
+  std::string stringKey; ///< The string key.
+
+  /**
+   * @brief Constructor
+   * @SINCE_1_2.7
+   *
+   * @param[in] key The string key
+   */
+  explicit Key( const std::string& key );
+
+  /**
+   * @brief Constructor
+   * @SINCE_1_2.7
+   *
+   * @param[in] key The index key
+   */
+  explicit Key( Property::Index key );
+
+  /**
+   * @brief The equality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs A string key to compare against.
+   * @return true if the key compares, or false if it isn't equal or of the wrong type
+   */
+  bool operator== (const std::string& rhs);
+
+  /**
+   * @brief The equality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs An index key to compare against.
+   * @return true if the key compares, or false if it isn't equal or of the wrong type
+   */
+  bool operator== (Property::Index rhs);
+
+  /**
+   * @brief The equality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs A key  to compare against.
+   * @return true if the keys are of the same type and have the same value
+   */
+  bool operator== (const Key& rhs);
+
+  /**
+   * @brief The inequality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs A string key to compare against.
+   * @return true if the key is not equal or not a string key
+   */
+  bool operator!= (const std::string& rhs);
+
+  /**
+   * @brief The inequality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs An index key to compare against.
+   * @return true if the key is not equal, or not an index key
+   */
+  bool operator!= (Property::Index rhs);
+
+  /**
+   * @brief The inequality operator
+   * @SINCE_1_2.7
+   *
+   * @param[in] rhs A key to compare against.
+   * @return true if the keys are not of the same type or are not equal
+   */
+  bool operator!= (const Key& rhs);
+};
+
+/**
+ * @brief Convert the key into a string and append to an output stream.
+ *
+ * @SINCE_1_2.7
+ * @param [in] stream The output stream operator.
+ * @param [in] key the key to convert
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<<( std::ostream& stream, const Property::Key& key );
+
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_KEY_H__
index f6d7775..fddcaa4 100644 (file)
@@ -33,6 +33,7 @@ typedef std::vector< IndexValuePair > IndexValueContainer;
 
 }; // unnamed namespace
 
+
 struct Property::Map::Impl
 {
   StringValueContainer mStringValueContainer;
@@ -83,25 +84,76 @@ void Property::Map::Insert( Property::Index key, const Value& value )
 
 Property::Value& Property::Map::GetValue( SizeType position ) const
 {
-  DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
+  SizeType numStringKeys = mImpl->mStringValueContainer.size();
+  SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
+  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
 
-  return mImpl->mStringValueContainer[ position ].second;
+  if( position < numStringKeys )
+  {
+    return mImpl->mStringValueContainer[ position ].second;
+  }
+  else
+  {
+    return mImpl->mIndexValueContainer[ position-numStringKeys ].second;
+  }
 }
 
 const std::string& Property::Map::GetKey( SizeType position ) const
 {
-  DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
+  SizeType numStringKeys = mImpl->mStringValueContainer.size();
+  DALI_ASSERT_ALWAYS( position < numStringKeys && "position out-of-bounds" );
 
   return mImpl->mStringValueContainer[ position ].first;
 }
 
+Property::Key Property::Map::GetKeyAt( SizeType position ) const
+{
+  SizeType numStringKeys = mImpl->mStringValueContainer.size();
+  SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
+  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
+
+  if( position < numStringKeys )
+  {
+    Key key(mImpl->mStringValueContainer[ position ].first);
+    return key;
+  }
+  else
+  {
+    Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
+    return key;
+  }
+}
+
 StringValuePair& Property::Map::GetPair( SizeType position ) const
 {
-  DALI_ASSERT_ALWAYS( position < mImpl->mStringValueContainer.size() && "position out-of-bounds" );
+  SizeType numStringKeys = mImpl->mStringValueContainer.size();
+
+  DALI_ASSERT_ALWAYS( position < ( numStringKeys ) && "position out-of-bounds" );
 
   return mImpl->mStringValueContainer[ position ];
 }
 
+KeyValuePair Property::Map::GetKeyValue( SizeType position ) const
+{
+  SizeType numStringKeys = mImpl->mStringValueContainer.size();
+  SizeType numIndexKeys  = mImpl->mIndexValueContainer.size();
+
+  DALI_ASSERT_ALWAYS( position < ( numStringKeys + numIndexKeys ) && "position out-of-bounds" );
+
+  if( position < numStringKeys )
+  {
+    Key key(mImpl->mStringValueContainer[ position ].first);
+    KeyValuePair keyValue(key, mImpl->mStringValueContainer[ position ].second );
+    return keyValue;
+  }
+  else
+  {
+    Key key( mImpl->mIndexValueContainer[ position-numStringKeys ].first );
+    KeyValuePair keyValue(key, mImpl->mIndexValueContainer[ position-numStringKeys ].second );
+    return keyValue;
+  }
+}
+
 Property::Value* Property::Map::Find( const char* key ) const
 {
   for ( StringValueContainer::iterator iter = mImpl->mStringValueContainer.begin(), endIter = mImpl->mStringValueContainer.end(); iter != endIter; ++iter )
index 2f26c1b..255693e 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <string>
+#include <sstream>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/object/property-value.h>
 #include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-key.h>
+#include <dali/public-api/object/property-value.h>
 
 namespace Dali
 {
@@ -33,6 +35,7 @@ namespace Dali
  * @{
  */
 
+typedef std::pair< Property::Key, Property::Value > KeyValuePair;
 typedef std::pair<std::string, Property::Value> StringValuePair;
 
 /**
@@ -159,9 +162,7 @@ public:
   }
 
   /**
-   * DEPRECATED_1_1.39. Retrieve the value with key instead of position, Use Find( key ) instead.
-   *
-   * @brief Retrieve the value of the string-value pair at the specified position.
+   * @brief Retrieve the value at the specified position.
    *
    * @SINCE_1_0.0
    * @return A reference to the value at the specified position.
@@ -183,6 +184,16 @@ public:
   const std::string& GetKey( SizeType position ) const;
 
   /**
+   * @brief Retrieve the key at the specified position.
+   *
+   * @SINCE_1_2.7
+   * @return A copy of the key at the specified position.
+   *
+   * @note Will assert if position >= Count()
+   */
+  Key GetKeyAt( SizeType position ) const;
+
+  /**
    * DEPRECATED_1_1.39 Position based retrieval is no longer supported after extending the key type to both Index and String.
    *
    * @brief Retrieve the key & the value at the specified position.
@@ -190,11 +201,21 @@ public:
    * @SINCE_1_0.0
    * @return A reference to the pair of key and value at the specified position.
    *
-   * @note Will assert if position >= Count()
+   * @note Will assert if position >= Count() or key at position is an index key.
    */
   StringValuePair& GetPair( SizeType position ) const;
 
   /**
+   * @brief Retrieve the key & the value at the specified position.
+   *
+   * @SINCE_1_2.7
+   * @return A copy of the pair of key and value at the specified position.
+   *
+   * @note Will assert if position >= Count()
+   */
+  KeyValuePair GetKeyValue( SizeType position ) const;
+
+  /**
    * @brief Finds the value for the specified key if it exists.
    *
    * @SINCE_1_0.0
@@ -354,7 +375,6 @@ private:
  */
 DALI_IMPORT_API std::ostream& operator<<( std::ostream& stream, const Property::Map& map );
 
-
 /**
  * @}
  */
index b280269..00c45c9 100644 (file)
@@ -59,6 +59,11 @@ struct DALI_IMPORT_API Property
   class Value;
 
   /**
+   * @brief A Key used by Map
+   */
+  struct Key;
+
+  /**
    * @brief A Map of property values.
    */
   class Map;