[dali_1.0.45] Merge branch 'devel/master' 63/41863/1
authorXiangyin Ma <x1.ma@samsung.com>
Thu, 18 Jun 2015 11:14:55 +0000 (12:14 +0100)
committerXiangyin Ma <x1.ma@samsung.com>
Thu, 18 Jun 2015 11:14:55 +0000 (12:14 +0100)
Change-Id: Icbe86eb9cdf905e76d17e33fdf57e0a0e939db80

62 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-CharacterSetConversion.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-BloomView.cpp
automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp
automated-tests/src/dali-toolkit/utc-Dali-Control.cpp
automated-tests/src/dali-toolkit/utc-Dali-EffectsView.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-ItemView.cpp
automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
build/tizen/configure.ac
build/tizen/dali-toolkit/Makefile.am
dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h
dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.cpp [new file with mode: 0644]
dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h [new file with mode: 0644]
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/shader-effects/distance-field-effect.cpp
dali-toolkit/images/selection-popup-bg#.png [new file with mode: 0755]
dali-toolkit/internal/builder/builder-actor.cpp
dali-toolkit/internal/builder/builder-animations.cpp
dali-toolkit/internal/builder/builder-impl.cpp
dali-toolkit/internal/builder/builder-set-property.cpp
dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp
dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp
dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp
dali-toolkit/internal/controls/slider/slider-impl.cpp
dali-toolkit/internal/controls/table-view/table-view-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h
dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h [new file with mode: 0644]
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/accessibility-focus-manager-impl.cpp
dali-toolkit/internal/text/character-set-conversion.cpp
dali-toolkit/internal/text/character-set-conversion.h
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/line-run.h
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp
dali-toolkit/public-api/controls/scroll-bar/scroll-bar.h
dali-toolkit/public-api/controls/scrollable/item-view/item-view.cpp
dali-toolkit/public-api/controls/scrollable/item-view/item-view.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/styles/dali-toolkit-default-theme.json
dali-toolkit/styles/mobile/dali-toolkit-default-theme.json
packaging/dali-toolkit.spec
plugins/dali-script-v8/src/object/property-value-wrapper.cpp

index 8011f6a..c3b14ab 100644 (file)
@@ -8,6 +8,8 @@ SET(CAPI_LIB "dali-toolkit-internal")
 # List of test case sources (Only these get parsed for test cases)
 SET(TC_SOURCES
  utc-Dali-PushButton.cpp
+ utc-Dali-Text-CharacterSetConversion.cpp
+ utc-Dali-Text-Segmentation.cpp
 )
 
 # Append list of test harness files (Won't get parsed for test cases)
index 7d1ef18..e23dbe3 100644 (file)
@@ -689,53 +689,5 @@ int UtcDaliPushButtonProperties(void)
   DALI_TEST_CHECK( button.IsSelected() ) ;
   DALI_TEST_CHECK( button.GetProperty< bool >( Button::Property::SELECTED ) );
 
-  //  Button::PROPERTY_NORMAL_STATE_ACTOR
-  {
-    button.SetButtonImage( ResourceImage::New( "IMAGE_PATH_1") );
-    DALI_TEST_EQUALS( "IMAGE_PATH_1", button.GetProperty( Button::Property::NORMAL_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
-    Property::Map map;
-    map[ "type" ] = "ImageActor";
-
-    button.SetProperty( Button::Property::NORMAL_STATE_ACTOR, map );
-    DALI_TEST_EQUALS( "ImageActor", button.GetProperty( Button::Property::NORMAL_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-  }
-
-  //  Button::PROPERTY_SELECTED_STATE_ACTOR
-  {
-    button.SetSelectedImage( ResourceImage::New( "IMAGE_PATH_2") );
-    DALI_TEST_EQUALS( "IMAGE_PATH_2", button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
-    Property::Map map;
-    map[ "type" ] = "Actor";
-
-    button.SetProperty( Button::Property::SELECTED_STATE_ACTOR, map );
-    DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-    DALI_TEST_CHECK( "ImageActor" != button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >() );
-  }
-
-  //  Button::PROPERTY_DISABLED_STATE_ACTOR
-  {
-    button.SetDisabledImage( ResourceImage::New( "IMAGE_PATH_3") );
-    DALI_TEST_EQUALS( "IMAGE_PATH_3", button.GetProperty( Button::Property::DISABLED_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
-    Property::Map map;
-    map[ "type" ] = "Actor";
-
-    button.SetProperty( Button::Property::DISABLED_STATE_ACTOR, map );
-    DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::DISABLED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-  }
-
-  //  Button::PROPERTY_LABEL_ACTOR
-  {
-    button.SetLabel( "LABEL_TEXT_CUSTOM" );
-    DALI_TEST_EQUALS( "TextLabel", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-
-    Property::Map map;
-    map[ "type" ] = "Actor";
-
-    button.SetProperty( Button::Property::LABEL_ACTOR, map );
-    DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-  }
   END_TEST;
 }
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-CharacterSetConversion.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-CharacterSetConversion.cpp
new file mode 100644 (file)
index 0000000..9f816ef
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions for scripts with different number of bytes per character.
+// Latin 1 byte per character, Arabic 2 bytes per character, Devanagari 3 bytes per character and emojis 4 bytes per character.
+//
+// uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length );
+// uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters );
+// uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 );
+// uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 );
+//     void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 );
+//
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct GetNumberOfUtf8CharactersData
+{
+  std::string  description;        ///< Description of the test.
+  std::string  text;               ///< input text.
+  unsigned int numberOfCharacters; ///< The expected number of characters.
+};
+
+bool GetNumberOfUtf8CharactersTest( const GetNumberOfUtf8CharactersData& data )
+{
+  return GetNumberOfUtf8Characters( reinterpret_cast<const uint8_t*>( data.text.c_str() ), data.text.size() ) == data.numberOfCharacters;
+}
+
+//////////////////////////////////////////////////////////
+
+struct GetNumberOfUtf8BytesData
+{
+  std::string   description;        ///< Description of the test.
+  unsigned int* utf32;              ///< input text in utf32.
+  unsigned int  numberOfCharacters; ///< The number of characters.
+  unsigned int  numberOfBytes;      ///< The expected number of bytes in utf8.
+};
+
+bool GetNumberOfUtf8BytesTest( const GetNumberOfUtf8BytesData& data )
+{
+  return GetNumberOfUtf8Bytes( data.utf32, data.numberOfCharacters ) == data.numberOfBytes;
+}
+
+//////////////////////////////////////////////////////////
+
+struct Utf8ToUtf32Data
+{
+  std::string   description; ///< Description of the test.
+  std::string   text;        ///< input text.
+  unsigned int* utf32;       ///< The expected text (array of bytes with text encoded in utf32).
+};
+
+
+bool Utf8ToUtf32Test( const Utf8ToUtf32Data& data )
+{
+  Vector<uint32_t> utf32;
+  utf32.Resize( data.text.size() );
+
+  const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+                                                   data.text.size(),
+                                                   utf32.Begin() );
+
+  for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+  {
+    if( data.utf32[index] != utf32[index] )
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+struct Utf32ToUtf8Data
+{
+  std::string   description;        ///< Description of the test.
+  unsigned int* utf32;              ///< The input text (array of bytes with text encoded in utf32).
+  unsigned int  numberOfCharacters; ///< The number of characters.
+  std::string   text;               ///< The expected text.
+};
+
+bool Utf32ToUtf8Test( const Utf32ToUtf8Data& data )
+{
+  std::string text;
+
+  Utf32ToUtf8( data.utf32, data.numberOfCharacters, text );
+
+  return text == data.text;
+}
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextCharacterSetConversionGetNumberOfUtf8Characters(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Characters");
+
+  const GetNumberOfUtf8CharactersData data[] =
+  {
+    {
+      "Latin script",
+      "Hello World",
+      11u,
+    },
+    {
+      "Arabic script",
+      "مرحبا بالعالم",
+      13u,
+    },
+    {
+      "Devanagari script",
+      "हैलो वर्ल्ड",
+      11u,
+    },
+    {
+      "Emojis",
+      "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+      7u,
+    },
+  };
+  const unsigned int numberOfTests = 4u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !GetNumberOfUtf8CharactersTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes");
+
+  unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+  unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+  unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+  unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+  const GetNumberOfUtf8BytesData data[] =
+  {
+    {
+      "Latin script",
+      utf32_01,
+      11u,
+      11u,
+    },
+    {
+      "Arabic script",
+      utf32_02,
+      13u,
+      25u,
+    },
+    {
+      "Devanagari script",
+      utf32_03,
+      11u,
+      31u,
+    },
+    {
+      "Emojis",
+      utf32_04,
+      7u,
+      19u,
+    },
+  };
+  const unsigned int numberOfTests = 4u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !GetNumberOfUtf8BytesTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionUtf8ToUtf32(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes");
+
+  unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+  unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+  unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+  unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+  const Utf8ToUtf32Data data[] =
+  {
+    {
+      "Latin script",
+      "Hello World",
+      utf32_01,
+    },
+    {
+      "Arabic script",
+      "مرحبا بالعالم",
+      utf32_02,
+    },
+    {
+      "Devanagari script",
+      "हैलो वर्ल्ड",
+      utf32_03,
+    },
+    {
+      "Emojis",
+      "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+      utf32_04,
+    },
+  };
+  const unsigned int numberOfTests = 4u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !Utf8ToUtf32Test( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionUtf32ToUtf8(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextCharacterSetConversionUtf32ToUtf8");
+
+  unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+  unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+  unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+  unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+  struct Utf32ToUtf8Data data[] =
+  {
+    {
+      "Latin script",
+      utf32_01,
+      11u,
+      "Hello World",
+    },
+    {
+      "Arabic script",
+      utf32_02,
+      13u,
+      "مرحبا بالعالم",
+    },
+    {
+      "Devanagari script",
+      utf32_03,
+      11u,
+      "हैलो वर्ल्ड",
+    },
+    {
+      "Emojis",
+      utf32_04,
+      7u,
+      "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+    },
+  };
+
+  const unsigned int numberOfTests = 4u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !Utf32ToUtf8Test( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Segmentation.cpp
new file mode 100644 (file)
index 0000000..2e60ee5
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions with different scripts.
+// void SetLineBreakInfo( const Vector<Character>& text, Vector<LineBreakInfo>& lineBreakInfo );
+// void SetWordBreakInfo( const Vector<Character>& text, Vector<WordBreakInfo>& wordBreakInfo );
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct BreakInfoData
+{
+  std::string description; ///< Description of the test.
+  std::string text;        ///< input text.
+  std::string breakInfo;   ///< The expected break info.
+};
+
+bool LineBreakInfoTest( const BreakInfoData& data )
+{
+  // 1) Convert to utf32
+  Vector<Character> utf32;
+  utf32.Resize( data.text.size() );
+
+  const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+                                                   data.text.size(),
+                                                   &utf32[0u] );
+  utf32.Resize( numberOfCharacters );
+
+  // 2) Set the line break info.
+  Vector<LineBreakInfo> lineBreakInfo;
+  lineBreakInfo.Resize( numberOfCharacters );
+
+  SetLineBreakInfo( utf32, lineBreakInfo );
+
+  // 3) compare the results
+  std::ostringstream breakInfo;
+
+  for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+  {
+    breakInfo << static_cast<unsigned int>( lineBreakInfo[index] );
+  }
+
+  return data.breakInfo == breakInfo.str();
+}
+
+bool WordBreakInfoTest( const BreakInfoData& data )
+{
+  // 1) Convert to utf32
+  Vector<Character> utf32;
+  utf32.Resize( data.text.size() );
+
+  const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+                                                   data.text.size(),
+                                                   &utf32[0u] );
+  utf32.Resize( numberOfCharacters );
+
+  // 2) Set the word break info.
+  Vector<WordBreakInfo> wordBreakInfo;
+  wordBreakInfo.Resize( numberOfCharacters );
+
+  SetWordBreakInfo( utf32, wordBreakInfo );
+
+  // 3) compare the results
+  std::ostringstream breakInfo;
+
+  for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+  {
+    breakInfo << static_cast<unsigned int>( wordBreakInfo[index] );
+  }
+
+  return data.breakInfo == breakInfo.str();
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextSegnemtationSetLineBreakInfo(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextSegnemtationSetLineBreakInfo");
+
+  struct BreakInfoData data[] =
+  {
+    {
+      "Zero characters",
+      "",
+      "",
+    },
+    {
+      "Latin script",
+      "Hello world",
+      "22222122220",
+    },
+    {
+      "Latin script with \n",
+      "Hello\nworld",
+      "22222022220",
+    },
+    {
+      "Japanese script",
+      "こんにちは世界",
+      "1111110",
+    },
+    {
+      "Japanese script with \n",
+      "こんにちは\n世界",
+      "11112010",
+    },
+    {
+      "Chinese script",
+      "你好世界",
+      "1110",
+    },
+    {
+      "Chinese script with \n",
+      "你好\n世界",
+      "12010",
+    }
+  };
+  const unsigned int numberOfTests = 7u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !LineBreakInfoTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextSegnemtationSetWordBreakInfo(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextSegnemtationSetWordBreakInfo");
+
+  struct BreakInfoData data[] =
+  {
+    {
+      "Zero characters",
+      "",
+      "",
+    },
+    {
+      "Latin script",
+      "Hello world",
+      "11110011110",
+    },
+    {
+      "Latin script with \n",
+      "Hello\nworld",
+      "11110011110",
+    },
+    {
+      "Japanese script",
+      "こんにちは世界",
+      "0000000",
+    },
+    {
+      "Japanese script with \n",
+      "こんにちは\n世界",
+      "00000000",
+    },
+    {
+      "Chinese script",
+      "你好世界",
+      "0000",
+    },
+    {
+      "Chinese script with \n",
+      "你好\n世界",
+      "00000",
+    }
+  };
+  const unsigned int numberOfTests = 7u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    if( !WordBreakInfoTest( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index 523b97a..bc2bfb0 100644 (file)
@@ -18,6 +18,7 @@ SET(TC_SOURCES
    utc-Dali-CubeTransitionEffect.cpp
    utc-Dali-DisplacementEffect.cpp
    utc-Dali-DistanceFieldEffect.cpp
+   utc-Dali-EffectsView.cpp
    utc-Dali-GaussianBlurView.cpp
    utc-Dali-JsonParser.cpp
    utc-Dali-KeyInputFocusManager.cpp
index c35269a..fa3f10c 100644 (file)
@@ -164,3 +164,63 @@ int UtcDaliBloomActivateDeactivate(void)
   DALI_TEST_CHECK( 1u == taskList3.GetTaskCount() );
   END_TEST;
 }
+
+int UtcDaliBloomCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  BloomView view = Toolkit::BloomView::New();
+  DALI_TEST_CHECK( view );
+
+  BloomView copy( view );
+  DALI_TEST_CHECK( view == copy );
+
+  BloomView assign;
+  DALI_TEST_CHECK( ! assign );
+
+  assign = copy;
+  DALI_TEST_CHECK( assign == view );
+
+  END_TEST;
+}
+
+int UtcDaliBloomTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK( typeRegistry );
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "BloomView" );
+  DALI_TEST_CHECK( typeInfo );
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  BloomView view = BloomView::DownCast( handle );
+  DALI_TEST_CHECK( view );
+
+  END_TEST;
+}
+
+int UtcDaliBloomOnSizeSet(void)
+{
+  ToolkitTestApplication application;
+
+  BloomView view = Toolkit::BloomView::New();
+
+  Stage::GetCurrent().Add( view );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector3 size( 200.0f, 300.0f, 200.0f );
+  view.SetSize( size );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( view.GetCurrentSize(), size, TEST_LOCATION );
+
+  END_TEST;
+}
index 5fa3d17..6d8ddff 100644 (file)
@@ -21,6 +21,8 @@
 #include <dali-toolkit/devel-api/builder/builder.h>
 #include <dali/integration-api/events/touch-event-integ.h>
 
+#define STRINGIFY(A)#A
+
 using namespace Dali;
 using namespace Toolkit;
 
@@ -104,3 +106,629 @@ int UtcDaliBuilderQuitSignal(void)
 
   END_TEST;
 }
+
+
+int UtcDaliBuilderAnimationP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+        "{"
+        "   \"paths\":"
+        "   {"
+        "     \"path0\":"
+        "     {"
+        "       \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],"
+        "       \"curvature\":0.35"
+        "     }"
+        "   },"
+        "  \"animations\": {"
+        "    \"animate\": {"
+        "      \"loop\": true,"
+        "      \"end-action\": \"BAKE\","
+        "      \"disconnect-action\": \"BAKE\","
+        "      \"properties\":"
+        "      [{"
+        "        \"actor\": \"greeting\","
+        "        \"property\": \"position\","
+        "        \"value\": [300, 300, -1000],"
+        "        \"alpha-function\": \"EASE_IN_OUT\","
+        "        \"relative\": true,"
+        "        \"time-period\": {"
+        "          \"delay\": 0,"
+        "          \"duration\": 3"
+        "        }"
+        "      },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"visible\","
+        "         \"alpha-function\": \"LINEAR\","
+        "         \"value\": true"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"size-width\","
+        "         \"alpha-function\": \"REVERSE\","
+        "         \"value\": 10.0"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_IN\","
+        "         \"value\": [10.0,20.0,30.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_OUT\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_IN_OUT\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_IN_SINE\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_OUT_SINE\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_IN_OUT_SINE\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"BOUNCE\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"SIN\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       },"
+        "       {"
+        "         \"actor\": \"greeting\","
+        "         \"property\": \"orientation\","
+        "         \"alpha-function\": \"EASE_OUT_BACK\","
+        "         \"value\": [0.0, 0.0, 0.0, 1.0]"
+        "       }"
+        "      ]"
+        "    },"
+        "    \"path-animation\": {"
+        "      \"duration\": 3.0,"
+        "      \"end-action\": \"DISCARD\","
+        "      \"disconnect-action\": \"BAKE_FINAL\","
+        "      \"properties\": [{"
+        "        \"actor\": \"greeting\","
+        "        \"path\":\"path0\","
+        "        \"forward\":[1,0,0],"
+        "        \"alpha-function\": \"EASE_IN_OUT\","
+        "        \"time-period\": {"
+        "          \"delay\": 0,"
+        "          \"duration\": 3"
+        "        }"
+        "      }]"
+        "    }"
+        "  },"
+        "  \"stage\": [{"
+        "    \"name\": \"greeting\","
+        "    \"type\": \"TextLabel\","
+        "    \"text\": \"Touch me\","
+        "    \"styles\": [\"basic-text\"],"
+        "    \"position\": [0, -120, 0],"
+        "    \"size\": [200, 200, 1],"
+        "    \"orientation\": [0, 0, 30],"
+        "    \"signals\": [{"
+        "      \"name\": \"touched\","
+        "      \"action\": \"play\","
+        "      \"animation\": \"animate\""
+        "    }]"
+        "  }]"
+        "}");
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors( Stage::GetCurrent().GetRootLayer() );
+
+  Animation anim = builder.CreateAnimation("animate");
+
+  DALI_TEST_CHECK( anim );
+
+  anim = builder.CreateAnimation("path-animation");
+
+  DALI_TEST_CHECK( anim );
+
+  // trigger play
+  // Emit touch event and check that our quit method is called
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+  application.ProcessEvent( touchEvent );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+
+  END_TEST;
+}
+
+int UtcDaliBuilderAnimationN(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+        "{"
+        "   \"paths\":"
+        "   {"
+        "     \"path0\":"
+        "     {"
+        "       \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],"
+        "       \"curvature\":0.35"
+        "     }"
+        "   },"
+        "  \"animations\": {"
+        "    \"animate\": {"
+        "      \"loop\": true,"
+        "      \"end-action\": \"BAKE\","
+        "      \"disconnect-action\": \"BAKE\","
+        "      \"properties\":"
+        "      [{"
+        "        \"actor\": \"greeting\","
+        "        \"property\": \"positioninvalid\","
+        "        \"value\": [300, 300, -1000],"
+        "        \"alpha-function\": \"EASE_IN_OUT\","
+        "        \"relative\": true,"
+        "        \"time-period\": {"
+        "          \"delay\": 0,"
+        "          \"duration\": 3"
+        "        }"
+        "      }"
+        "      ]"
+        "    },"
+        "    \"animate2\": {"
+        "      \"loop\": true,"
+        "      \"end-action\": \"BAKE\","
+        "      \"disconnect-action\": \"BAKE\","
+        "      \"properties\":"
+        "      [{"
+        "        \"actor\": \"greeting\","
+        "        \"property\": \"positioninvalid\","
+        "        \"value\": [300, 300, -1000],"
+        "        \"alpha-function\": \"EGGS_OVER_EASY\","
+        "        \"relative\": true,"
+        "        \"time-period\": {"
+        "          \"delay\": 0,"
+        "          \"duration\": 3"
+        "        }"
+        "      }"
+        "      ]"
+        "    },"
+        "    \"path-animation\": {"
+        "      \"duration\": 3.0,"
+        "      \"end-action\": \"DISCARD\","
+        "      \"disconnect-action\": \"BAKE_FINAL\","
+        "      \"properties\": [{"
+        "        \"actor\": \"greeting\","
+        "        \"path\":\"pathDoesntExist\","
+        "        \"forward\":[1,0,0],"
+        "        \"alpha-function\": \"EASE_IN_OUT\","
+        "        \"time-period\": {"
+        "          \"delay\": 0,"
+        "          \"duration\": 3"
+        "        }"
+        "      }]"
+        "    }"
+        "  },"
+        "  \"stage\": [{"
+        "    \"name\": \"greeting\","
+        "    \"type\": \"TextLabel\","
+        "    \"text\": \"Touch me\","
+        "    \"styles\": [\"basic-text\"],"
+        "    \"position\": [0, -120, 0],"
+        "    \"size\": [200, 200, 1],"
+        "    \"orientation\": [0, 0, 30],"
+        "    \"signals\": [{"
+        "      \"name\": \"touched\","
+        "      \"action\": \"play\","
+        "      \"animation\": \"animate\""
+        "    }]"
+        "  }]"
+        "}");
+
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors( Stage::GetCurrent().GetRootLayer() );
+
+  Animation anim = builder.CreateAnimation("animate");
+
+  // log warning line coverage
+  anim = builder.CreateAnimation("path-animation");
+
+  anim = builder.CreateAnimation("animate");
+
+  anim = builder.CreateAnimation("animate2");
+
+  DALI_TEST_CHECK(true);
+
+  END_TEST;
+
+}
+
+int UtcDaliBuilderConstantsP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{"
+      "\"constants\":"
+      "{"
+      "  \"IMAGE_PATH\": \"apath\","
+      "  \"WIDTH\": 22.3,"
+      "  \"ANCHOR\": \"TOP_LEFT\","
+      "  \"PADDING\": [1,2,3,4]"
+      "},"
+      "\"stage\":"
+      "[{"
+      "  \"type\": \"ImageActor\","
+      "  \"size\": [100,100,1],"
+      "  \"parent-origin\": \"TOP_LEFT\","
+      "  \"anchor-point\": \"{ANCHOR}\","
+      "  \"padding\": \"{PADDING}\","
+      "  \"image\": { \"filename\": \"dir/{IMAGE_PATH}\" },"
+      "  \"size-width\": \"{WIDTH}\","
+      "  \"signals\": [{"
+      "    \"name\": \"touched\","
+      "    \"action\": \"quit\""
+      "  }]"
+      "}]"
+      "}"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+  DALI_TEST_CHECK( builder );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderTemplatesAndStylesP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "\"styles\":\n"
+      "{\n"
+      "  \"image-style\": \n"
+      "  {\n"
+      "    \"color\": [1,0,0,1],\n"
+      "    \"actors\": {\n"
+      "      \"child-image\": {\n"
+      "        \"color\": [0,1,0,1]\n"
+      "      }\n"
+      "    }\n"
+      "  }\n"
+      "},\n"
+      "\"templates\":\n"
+      "{\n"
+      "  \"image-tree\": { \n"
+      "    \"type\": \"ImageActor\",\n"
+      "    \"styles\": [\"image-style\"],\n"
+      "    \"name\": \"image\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"quit\"\n"
+      "    }],\n"
+      "    \"actors\": [\n"
+      "      {\n"
+      "        \"type\":\"ImageActor\",\n"
+      "        \"name\":\"child-image\" \n"
+      "      }\n"
+      "    ]\n"
+      "  }\n"
+      "}\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+
+  ImageActor actor = ImageActor::DownCast( builder.Create( "image-tree" ) );
+  DALI_TEST_CHECK( actor );
+
+  // NB: already applied in create
+  DALI_TEST_CHECK( builder.ApplyStyle( "image-style", actor ) );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderRenderTasksP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "\"render-tasks\":\n"
+      "{\n"
+      "  \"task0\": {\n"
+      "    \"source-actor\": \"image\",\n"
+      "    \"camera-actor\": \"camera\" \n"
+      "  }\n"
+      "},\n"
+      "\"stage\":\n"
+      "[\n"
+      "  { \n"
+      "    \"type\": \"CameraActor\",\n"
+      "    \"name\": \"image\"\n"
+      "  }, \n"
+      "  { \n"
+      "    \"type\": \"ImageActor\",\n"
+      "    \"name\": \"image\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"quit\"\n"
+      "    }],\n"
+      "    \"actors\": [\n"
+      "      {\n"
+      "        \"type\":\"ImageActor\",\n"
+      "        \"name\":\"child-image\" \n"
+      "      }\n"
+      "    ]\n"
+      "  }\n"
+      "]\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+
+  unsigned int count = Stage::GetCurrent().GetRenderTaskList().GetTaskCount();
+
+  // coverage
+  builder.CreateRenderTask( "task0" );
+
+  DALI_TEST_CHECK( count <
+                   Stage::GetCurrent().GetRenderTaskList().GetTaskCount() );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderChildActionP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "  \"stage\":\n"
+      "  [{\n"
+      "    \"type\": \"Actor\",\n"
+      "    \"name\": \"actor\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"parent-origin\": \"TOP_LEFT\",\n"
+      "    \"anchor-point\": \"TOP_LEFT\",\n"
+      "    \"actors\": [{\n"
+      "      \"type\": \"Actor\",\n"
+      "      \"name\": \"sub-actor\"\n"
+      "    }],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"hide\",\n"
+      "      \"actor\": \"actor\",\n"
+      "      \"child-actor\": \"sub-actor\"\n"
+      "    }]\n"
+      "  }]\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit touch event and check that our quit method is called
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+  application.ProcessEvent( touchEvent );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+  DALI_TEST_CHECK( actor );
+
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderSetPropertyActionP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "  \"stage\":\n"
+      "  [{\n"
+      "    \"type\": \"Actor\",\n"
+      "    \"name\": \"actor\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"parent-origin\": \"TOP_LEFT\",\n"
+      "    \"anchor-point\": \"TOP_LEFT\",\n"
+      "    \"actors\": [{\n"
+      "      \"type\": \"Actor\",\n"
+      "      \"name\": \"sub-actor\"\n"
+      "    }],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"set\",\n"
+      "      \"actor\": \"sub-actor\",\n"
+      "      \"property\": \"visible\",\n"
+      "      \"value\": false\n"
+      "    }]\n"
+      "  }]\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit touch event and check that our quit method is called
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+  application.ProcessEvent( touchEvent );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+  DALI_TEST_CHECK( actor );
+
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderGenericActionP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "  \"stage\":\n"
+      "  [{\n"
+      "    \"type\": \"Actor\",\n"
+      "    \"name\": \"actor\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"parent-origin\": \"TOP_LEFT\",\n"
+      "    \"anchor-point\": \"TOP_LEFT\",\n"
+      "    \"actors\": [{\n"
+      "      \"type\": \"Actor\",\n"
+      "      \"name\": \"sub-actor\"\n"
+      "    }],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"hide\"\n"
+      "    }]\n"
+      "  }]\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit touch event and check that our quit method is called
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+  application.ProcessEvent( touchEvent );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("actor");
+  DALI_TEST_CHECK( actor );
+
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  END_TEST;
+}
+
+int UtcDaliBuilderPropertyNotificationP(void)
+{
+  ToolkitTestApplication application;
+
+  // JSON with a quit event when the actor is touched
+  std::string json(
+      "{\n"
+      "  \"stage\":\n"
+      "  [{\n"
+      "    \"type\": \"Actor\",\n"
+      "    \"name\": \"actor\",\n"
+      "    \"size\": [100,100,1],\n"
+      "    \"parent-origin\": \"TOP_LEFT\",\n"
+      "    \"anchor-point\": \"TOP_LEFT\",\n"
+      "    \"actors\": [{\n"
+      "      \"type\": \"Actor\",\n"
+      "      \"name\": \"sub-actor\"\n"
+      "    }],\n"
+      "    \"signals\": [{\n"
+      "      \"name\": \"touched\",\n"
+      "      \"action\": \"hide\"\n"
+      "    }],\n"
+      "    \"notifications\": [{\n"
+      "      \"property\": \"visible\",\n"
+      "      \"condition\": \"False\",\n"
+      "      \"action\": \"show\"\n"
+      "    }]\n"
+      "  }]\n"
+      "}\n"
+  );
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+  builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit touch event and check that our quit method is called
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+  application.ProcessEvent( touchEvent );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("actor");
+  DALI_TEST_CHECK( actor );
+
+  DALI_TEST_CHECK( actor.IsVisible() );
+
+  END_TEST;
+}
index 3223daa..722f0a8 100644 (file)
@@ -428,17 +428,15 @@ int UtcDaliControlBackgroundProperties(void)
 
   Property::Map imageMap;
   imageMap[ "filename" ] = "TestImage";
-  Property::Map map;
-  map[ "image" ] = imageMap;
-  control.SetProperty( Control::Property::BACKGROUND_IMAGE, map );
+  control.SetProperty( Control::Property::BACKGROUND_IMAGE, imageMap );
   DALI_TEST_CHECK( control.GetChildCount() > 0 );
   DALI_TEST_EQUALS( control.GetBackgroundColor(), Color::RED, TEST_LOCATION );
   DALI_TEST_EQUALS( control.GetProperty( Control::Property::BACKGROUND_COLOR ).Get< Vector4 >(), Color::RED, TEST_LOCATION );
 
   Property::Value propValue = control.GetProperty( Control::Property::BACKGROUND_IMAGE );
-  DALI_TEST_CHECK( propValue.HasKey( "image" ) );
-  DALI_TEST_CHECK( propValue.GetValue( "image" ).HasKey( "filename" ) );
-  DALI_TEST_CHECK( propValue.GetValue( "image" ).GetValue( "filename" ).Get< std::string>() == "TestImage" );
+  Property::Map* resultMap = propValue.GetMap();
+  DALI_TEST_CHECK( resultMap->Find( "filename" ) );
+  DALI_TEST_CHECK( resultMap->Find( "filename" )->Get< std::string>() == "TestImage" );
 
   Property::Map emptyMap;
   control.SetProperty( Control::Property::BACKGROUND_IMAGE, emptyMap );
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-EffectsView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-EffectsView.cpp
new file mode 100644 (file)
index 0000000..dc1e25a
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <sstream>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/effects-view/effects-view.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void dali_effectsview_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void dali_effectsview_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliEffectsViewNew(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  DALI_TEST_CHECK( !view );
+
+  view = EffectsView::New();
+  DALI_TEST_CHECK( view );
+
+  Stage::GetCurrent().Add( view );
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewCopyAndAssignment(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( view );
+
+  EffectsView copy( view );
+  DALI_TEST_CHECK( copy == view );
+
+  EffectsView assign;
+  DALI_TEST_CHECK( !assign );
+  assign = view;
+  DALI_TEST_CHECK( assign == view );
+
+  // Self assignment
+  assign = assign;
+  DALI_TEST_CHECK( assign );
+  DALI_TEST_CHECK( assign == view );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewDownCast(void)
+{
+  ToolkitTestApplication application;
+
+  BaseHandle view = EffectsView::New();
+  DALI_TEST_CHECK( EffectsView::DownCast( view ) );
+
+  BaseHandle empty;
+  DALI_TEST_CHECK( ! EffectsView::DownCast( empty ) );
+
+  BaseHandle another = Actor::New();
+  DALI_TEST_CHECK( ! EffectsView::DownCast( another ) );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetGetTypeP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( view.GetType() == EffectsView::INVALID_TYPE );
+
+  view.SetType( EffectsView::DROP_SHADOW );
+  DALI_TEST_CHECK( view.GetType() == EffectsView::DROP_SHADOW );
+
+  view.SetType( EffectsView::EMBOSS );
+  DALI_TEST_CHECK( view.GetType() == EffectsView::EMBOSS );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetTypeN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.SetType( EffectsView::DROP_SHADOW );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetTypeN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    EffectsView::EffectType type = view.GetType();
+    (void) type;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewEnableP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  Stage stage = Stage::GetCurrent();
+  DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+  view.Enable();
+  DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewEnableN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.Enable();
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewDisableP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  Stage stage = Stage::GetCurrent();
+  DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+  view.Enable();
+  DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
+
+  view.Disable();
+  DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewDisableN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.Disable();
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewRefreshP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  try
+  {
+    view.Refresh();
+    DALI_TEST_CHECK( true );
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( false ); // Should not get here!
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewRefreshN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.Refresh();
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetPixelFormatP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  try
+  {
+    view.SetPixelFormat( Pixel::RGBA8888 );
+    DALI_TEST_CHECK( true );
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( false ); // Should not get here!
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetPixelFormatN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.SetPixelFormat( Pixel::RGBA8888 );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetGetOutputImage(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  FrameBufferImage image = FrameBufferImage::New();
+  DALI_TEST_CHECK( image );
+
+  view.SetOutputImage( image );
+  DALI_TEST_CHECK( view.GetOutputImage() == image );
+
+  // Replace with another image
+  FrameBufferImage image2 = FrameBufferImage::New();
+  DALI_TEST_CHECK( image2 );
+  view.SetOutputImage( image2 );
+  DALI_TEST_CHECK( view.GetOutputImage() == image2 );
+
+  // Remove output image
+  view.SetOutputImage( FrameBufferImage() );
+  DALI_TEST_CHECK( ! view.GetOutputImage() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetOutputImageN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.SetOutputImage( FrameBufferImage::New() );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetOutputImageN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    FrameBufferImage image = view.GetOutputImage();
+    (void)image;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectSizePropertyIndexP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectSizePropertyIndex() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectSizePropertyIndexN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    Property::Index index = view.GetEffectSizePropertyIndex();
+    (void)index;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectStrengthPropertyIndexP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectStrengthPropertyIndex() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectStrengthPropertyIndexN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    Property::Index index = view.GetEffectStrengthPropertyIndex();
+    (void)index;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectOffsetPropertyIndexP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectOffsetPropertyIndex() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectOffsetPropertyIndexN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    Property::Index index = view.GetEffectOffsetPropertyIndex();
+    (void)index;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectColorPropertyIndexP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectColorPropertyIndex() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectColorPropertyIndexN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    Property::Index index = view.GetEffectColorPropertyIndex();
+    (void)index;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetSetBackgroundColor(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  view.SetBackgroundColor( Color::RED );
+  DALI_TEST_CHECK( Color::RED == view.GetBackgroundColor() );
+
+  view.SetBackgroundColor( Color::YELLOW );
+  DALI_TEST_CHECK( Color::YELLOW == view.GetBackgroundColor() );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetBackgroundColorN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.SetBackgroundColor( Color::RED );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewGetBackgroundColorN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    Vector4 color = view.GetBackgroundColor();
+    (void)color;
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetRefreshOnDemandP(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view = EffectsView::New();
+  FrameBufferImage image = FrameBufferImage::New();
+  view.SetOutputImage( image );
+  view.Enable();
+
+  Stage stage = Stage::GetCurrent();
+  stage.Add( view );
+
+  RenderTaskList renderTaskList = stage.GetRenderTaskList();
+  DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+  DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+
+  view.SetRefreshOnDemand( true );
+  DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
+  DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
+
+  view.SetRefreshOnDemand( false );
+  DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+  DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSetRefreshOnDemandN(void)
+{
+  ToolkitTestApplication application;
+
+  EffectsView view;
+  try
+  {
+    view.SetRefreshOnDemand( false );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewSizeSet(void)
+{
+  ToolkitTestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  {
+    EffectsView view = EffectsView::New();
+    view.SetSize( 200.0f, 200.0f, 200.0f );
+    stage.Add( view );
+    view.Enable();
+    application.SendNotification();
+    application.Render();
+    view.Disable();
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+  }
+
+  {
+    EffectsView view = EffectsView::New();
+    view.SetOutputImage( FrameBufferImage::New( 200, 200 ) );
+    view.SetType( EffectsView::EMBOSS );
+    view.SetSize( 200.0f, 200.0f, 200.0f );
+    stage.Add( view );
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+  }
+
+  {
+    EffectsView view = EffectsView::New();
+    view.SetType( EffectsView::DROP_SHADOW );
+    view.SetSize( 200.0f, 200.0f, 200.0f );
+    stage.Add( view );
+    application.SendNotification();
+    application.Render();
+
+    stage.Remove( view );
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliEffectsViewTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK( typeRegistry );
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "EffectsView" );
+  DALI_TEST_CHECK( typeInfo );
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  EffectsView view = EffectsView::DownCast( handle );
+  DALI_TEST_CHECK( view );
+
+  END_TEST;
+}
index 82527f4..b85524d 100644 (file)
@@ -40,16 +40,47 @@ void utc_dali_toolkit_item_view_cleanup(void)
 
 namespace
 {
+
 const unsigned int TOTAL_ITEM_NUMBER = 100;
 const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg";
 
+const int RENDER_FRAME_INTERVAL = 16;                     ///< Duration of each frame in ms. (at approx 60FPS)
+
 static bool gObjectCreatedCallBackCalled;
+static bool gOnLayoutActivatedCalled;                     ///< Whether the LayoutActivated signal was invoked.
 
 static void TestCallback(BaseHandle handle)
 {
   gObjectCreatedCallBackCalled = true;
 }
 
+static void OnLayoutActivated()
+{
+  gOnLayoutActivatedCalled = true;
+}
+
+/*
+ * Simulate time passed by.
+ *
+ * @note this will always process at least 1 frame (1/60 sec)
+ *
+ * @param application Test application instance
+ * @param duration Time to pass in milliseconds.
+ * @return The actual time passed in milliseconds
+ */
+int Wait(ToolkitTestApplication& application, int duration = 0)
+{
+  int time = 0;
+
+  for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++)
+  {
+    application.SendNotification();
+    application.Render(RENDER_FRAME_INTERVAL);
+    time += RENDER_FRAME_INTERVAL;
+  }
+
+  return time;
+}
 
 // Implementation of ItemFactory for providing actors to ItemView
 class TestItemFactory : public ItemFactory
@@ -771,3 +802,38 @@ int UtcDaliItemFactoryGetExtention(void)
   DALI_TEST_CHECK( factory.GetExtension() == NULL );
   END_TEST;
 }
+
+int UtcDaliItemViewLayoutActivatedSignalP(void)
+{
+  ToolkitTestApplication application;
+
+  // Create the ItemView actor
+  TestItemFactory factory;
+  ItemView view = ItemView::New(factory);
+
+  // Create a grid layout and add it to ItemView
+  ItemLayoutPtr gridLayout = DefaultItemLayout::New( DefaultItemLayout::GRID );
+  view.AddLayout(*gridLayout);
+
+  Stage::GetCurrent().Add( view );
+
+  // Connect the layout activated signal
+  view.LayoutActivatedSignal().Connect( &OnLayoutActivated );
+
+  gOnLayoutActivatedCalled = false;
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Activate the grid layout so that the items will be created and added to ItemView
+  Vector3 stageSize(Dali::Stage::GetCurrent().GetSize());
+  view.ActivateLayout(0, stageSize, 0.1f);
+
+  // Wait for 0.1 second
+  Wait(application, 100);
+
+  DALI_TEST_EQUALS( gOnLayoutActivatedCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
index 8e6bffa..6254e7a 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <iostream>
 #include <stdlib.h>
+#include <sstream>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 
@@ -645,12 +646,14 @@ int UtcDaliTableViewSetGetProperty(void)
   Property::Map layoutRowsGet = tableView.GetProperty(TableView::Property::LAYOUT_ROWS).Get<Property::Map>();
 
   DALI_TEST_EQUALS( layoutRowsGet.GetKey(1).compare(layoutRows.GetKey(0)), 0, TEST_LOCATION );
-  DALI_TEST_CHECK( layoutRowsGet.GetValue(1).GetValue( "policy" ).Get<std::string>().compare(layoutRows.GetValue(0).GetValue( "policy" ).Get<std::string>()) == 0 );
-  DALI_TEST_EQUALS( layoutRowsGet.GetValue(1).GetValue( "value" ).Get<float>(), layoutRows.GetValue(0).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+  Property::Map* childMap =layoutRowsGet.GetValue(1).GetMap();
+  DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("fixed") == 0 );
+  DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 30.f, TEST_LOCATION );
 
+  childMap =layoutRowsGet.GetValue(3).GetMap();
   DALI_TEST_CHECK( layoutRowsGet.GetKey(3).compare(layoutRows.GetKey(1)) == 0 );
-  DALI_TEST_CHECK( layoutRowsGet.GetValue(3).GetValue( "policy" ).Get<std::string>().compare(layoutRows.GetValue(1).GetValue( "policy" ).Get<std::string>()) == 0 );
-  DALI_TEST_EQUALS( layoutRowsGet.GetValue(3).GetValue( "value" ).Get<float>(), layoutRows.GetValue(1).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+  DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("relative") == 0 );
+  DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 0.2f, TEST_LOCATION );
 
   // Test "layout-columns" property
   DALI_TEST_CHECK( tableView.GetPropertyIndex( PROPERTY_NAME_LAYOUT_COLUMNS ) == TableView::Property::LAYOUT_COLUMNS );
@@ -672,12 +675,13 @@ int UtcDaliTableViewSetGetProperty(void)
 
   Property::Map layoutColumnsGet = tableView.GetProperty(TableView::Property::LAYOUT_COLUMNS).Get<Property::Map>();
   DALI_TEST_CHECK( layoutColumnsGet.GetKey(2).compare(layoutColumns.GetKey(0)) == 0 );
-  DALI_TEST_CHECK( layoutColumnsGet.GetValue(2).GetValue( "policy" ).Get<std::string>().compare(layoutColumns.GetValue(0).GetValue( "policy" ).Get<std::string>()) == 0 );
-  DALI_TEST_EQUALS( layoutColumnsGet.GetValue(2).GetValue( "value" ).Get<float>(),layoutColumns.GetValue(0).GetValue( "value" ).Get<float>(), TEST_LOCATION );
-
+  childMap =layoutColumnsGet.GetValue(2).GetMap();
+  DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("relative") == 0 );
+  DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 0.2f, TEST_LOCATION );
+  childMap =layoutColumnsGet.GetValue(3).GetMap();
   DALI_TEST_CHECK( layoutColumnsGet.GetKey(3).compare(layoutColumns.GetKey(1)) == 0 );
-  DALI_TEST_CHECK( layoutColumnsGet.GetValue(3).GetValue( "policy" ).Get<std::string>().compare(layoutColumns.GetValue(1).GetValue( "policy" ).Get<std::string>()) == 0 );
-  DALI_TEST_EQUALS( layoutColumnsGet.GetValue(3).GetValue( "value" ).Get<float>(),layoutColumns.GetValue(1).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+  DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("fixed") == 0 );
+  DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(),30.f, TEST_LOCATION );
 
   END_TEST;
 }
@@ -719,3 +723,178 @@ int UtcDaliTableViewCustomProperties(void)
 
   END_TEST;
 }
+
+int UtcDaliTableViewGetChildAtN(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+
+  Actor actor = tableView.GetChildAt( TableView::CellPosition( 200, 200 ) );
+  DALI_TEST_CHECK( !actor );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewAddChildN(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+  DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 ) ) );
+  DALI_TEST_CHECK( ! tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 ) ) );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewInsertRowAtZero(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+  DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+  tableView.InsertRow(0);
+
+  DALI_TEST_CHECK( tableView.GetRows() == 11 );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewDeleteRowAtZero(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+  DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+  tableView.DeleteRow(0);
+
+  DALI_TEST_CHECK( tableView.GetRows() == 9 );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewInsertColumnAtZero(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+  DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+  tableView.InsertColumn(0);
+
+  DALI_TEST_CHECK( tableView.GetColumns() == 11 );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewDeleteColumnAtZero(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(10,10);
+  DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+  tableView.DeleteColumn(0);
+
+  DALI_TEST_CHECK( tableView.GetColumns() == 9 );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewTypeRegistry(void)
+{
+  ToolkitTestApplication application;
+
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  DALI_TEST_CHECK( typeRegistry );
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "TableView" );
+  DALI_TEST_CHECK( typeInfo );
+
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  TableView view = TableView::DownCast( handle );
+  DALI_TEST_CHECK( view );
+
+  END_TEST;
+}
+
+int UtcDaliTableViewKeyboardFocus(void)
+{
+  ToolkitTestApplication application;
+
+  TableView tableView = TableView::New(4,4);
+  tableView.SetKeyboardFocusable( true );
+  tableView.SetName( "TableView");
+
+  for ( int row = 0; row < 4; ++row )
+  {
+    for ( int col = 0; col < 4; ++col )
+    {
+      Control control = Control::New();
+      std::ostringstream str;
+      str << row << "-" << col;
+      control.SetName( str.str() );
+      control.SetKeyboardFocusable( true );
+      tableView.AddChild( control, TableView::CellPosition( row, col ) );
+    }
+  }
+
+  Stage::GetCurrent().Add( tableView );
+
+  application.SendNotification();
+  application.Render();
+
+  Actor firstFocusActor = Toolkit::Internal::GetImplementation( tableView ).GetNextKeyboardFocusableActor( Actor(), Control::KeyboardFocus::RIGHT, true );
+  DALI_TEST_CHECK( firstFocusActor );
+  DALI_TEST_CHECK( firstFocusActor.GetName() == "0-0" );
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  manager.SetFocusGroupLoop( true );
+  manager.SetCurrentFocusActor( firstFocusActor );
+
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-3" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-0" );
+
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-3" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::LEFT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-3" );
+
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+  manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-1" );
+  manager.MoveFocus( Control::KeyboardFocus::DOWN );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-1" );
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1" );
+  manager.MoveFocus( Control::KeyboardFocus::UP );
+  DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+  END_TEST;
+}
index d19b3a1..21d7a3a 100644 (file)
@@ -155,33 +155,6 @@ int UtcDaliTextFieldNewP(void)
   END_TEST;
 }
 
-int UtcDaliTextFieldGetPropertyN(void)
-{
-  ToolkitTestApplication application;
-  tet_infoline(" UtcDaliToolkitTextFieldGetPropertyN");
-  TextField field = TextField::New();
-  DALI_TEST_CHECK( field );
-
-  bool assert = false;
-  try
-  {
-    Property::Value value = field.GetProperty<bool>( 0 );
-  }
-  catch ( ... )
-  {
-    assert = true;
-  }
-  if ( assert )
-  {
-    tet_result(TET_PASS);
-  }
-  else
-  {
-    tet_result(TET_FAIL);
-  }
-  END_TEST;
-}
-
 // Positive test case for a method
 int UtcDaliTextFieldGetPropertyP(void)
 {
@@ -263,34 +236,6 @@ int UtcDaliTextFieldSetPropertyP(void)
   END_TEST;
 }
 
-// Negative test case for a method
-int UtcDaliTextFieldSetPropertyN(void)
-{
-  ToolkitTestApplication application;
-  tet_infoline(" UtcDaliToolkitTextFieldSetPropertyN");
-  TextField field = TextField::New();
-  DALI_TEST_CHECK( field );
-
-  bool assert = false;
-  try
-  {
-    field.SetProperty( 0, true );
-  }
-  catch ( ... )
-  {
-    assert = true;
-  }
-  if ( assert )
-  {
-    tet_result(TET_PASS);
-  }
-  else
-  {
-    tet_result(TET_FAIL);
-  }
-  END_TEST;
-}
-
 // Positive Basic Text Renderer test
 int utcDaliTextFieldBasicRenderP(void)
 {
index c0e4bec..8f59dd7 100644 (file)
@@ -125,33 +125,6 @@ int UtcDaliToolkitTextLabelAssignmentOperatorP(void)
   END_TEST;
 }
 
-int UtcDaliToolkitTextLabelGetPropertyN(void)
-{
-  ToolkitTestApplication application;
-  tet_infoline(" UtcDaliToolkitTextLabelGetPropertyN");
-  TextLabel label = TextLabel::New("Test Text");
-  DALI_TEST_CHECK( label );
-
-  bool assert = false;
-  try
-  {
-    Property::Value value = label.GetProperty<bool>( 0 );
-  }
-  catch ( ... )
-  {
-    assert = true;
-  }
-  if ( assert )
-  {
-    tet_result(TET_PASS);
-  }
-  else
-  {
-    tet_result(TET_FAIL);
-  }
-  END_TEST;
-}
-
 // Positive test case for a method
 int UtcDaliToolkitTextLabelGetPropertyP(void)
 {
@@ -186,33 +159,6 @@ int UtcDaliToolkitTextLabelGetPropertyP(void)
   END_TEST;
 }
 
-int UtcDaliToolkitTextLabelSetPropertyN(void)
-{
-  ToolkitTestApplication application;
-  tet_infoline(" UtcDaliToolkitTextLabelSetPropertyN");
-  TextLabel label = TextLabel::New("Test Text");
-  DALI_TEST_CHECK( label );
-
-  bool assert = false;
-  try
-  {
-    label.SetProperty( 0, true );
-  }
-  catch ( ... )
-  {
-    assert = true;
-  }
-  if ( assert )
-  {
-    tet_result(TET_PASS);
-  }
-  else
-  {
-    tet_result(TET_FAIL);
-  }
-  END_TEST;
-}
-
 int UtcDaliToolkitTextLabelSetPropertyP(void)
 {
   ToolkitTestApplication application;
index 006e192..6fb8b47 100644 (file)
@@ -45,6 +45,12 @@ AC_ARG_ENABLE([debug],
               [enable_debug=$enableval],
               [enable_debug=no])
 
+AC_ARG_ENABLE([i18n],
+              [AC_HELP_STRING([--enable-i18n],
+                              [Turns on internationalisation])],
+              [enable_i18n=$enableval],
+              [enable_i18n=no])
+
 # option to build JavaScript plugin
 # configure settings and output
 # --enable-javascript        // enable_javascript = yes
@@ -67,8 +73,9 @@ if test "x$enable_debug" = "xno" -a "x$enable_exportall" = "xno"; then
   DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -fvisibility=hidden -DHIDE_DALI_INTERNALS"
 fi
 
-
-
+if test "x$enable_i18n" = "xyes"; then
+  DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDGETTEXT_ENABLED "
+fi
 
 # Tizen Profile options
 AC_ARG_ENABLE([profile],
index b1d8989..0319ac1 100644 (file)
@@ -101,6 +101,7 @@ develapishadereffectsdir =      $(develapidir)/shader-effects
 develapitransitioneffectsdir =  $(develapidir)/transition-effects
 develapistylingdir =            $(develapidir)/styling
 develapitoolbardir =            $(develapicontrolsdir)/tool-bar
+develapitextselectionpopupdir = $(develapicontrolsdir)/text-controls
 
 # devel headers
 develapibloomview_HEADERS =         $(devel_api_bloom_view_header_files)
@@ -120,6 +121,7 @@ develapistyling_HEADERS =           $(devel_api_styling_header_files)
 develapisuperblurview_HEADERS =     $(devel_api_super_blur_view_header_files)
 develapitoolbar_HEADERS =           $(devel_api_tool_bar_header_files)
 develapitransitioneffects_HEADERS = $(devel_api_transition_effects_header_files)
+develapitextselectionpopup_HEADERS = $(devel_api_text_selection_popup_header_files)
 
 # public api source
 publicapidir =                  $(topleveldir)/public-api
index 2243f2d..69df315 100644 (file)
@@ -56,15 +56,18 @@ public:
   };
 
   /**
-   * @brief An enumeration of properties belonging to the TextLabel class.
+   * @brief An enumeration of properties belonging to the TextSelectionPopup class.
    */
   struct Property
   {
     enum
     {
 
-      POPUP_MAX_SIZE,                           ///< name "popup-max-size",                The max size the Popup can be,                  type VECTOR2
-      POPUP_BACKGROUND_IMAGE,                   ///< name "popup-background-image",        The image to display for popup background       type STRING
+      POPUP_MAX_SIZE =  PROPERTY_START_INDEX,   ///< name "popup-max-size",                The maximum size the Popup can be,              type VECTOR2
+      POPUP_MIN_SIZE,                           ///< name "popup-min-size",                The minimum size the Popup can be,              type VECTOR2
+      OPTION_MAX_SIZE,                          ///< name "option-max-size",               The maximum size an option can be,              type VECTOR2
+      OPTION_MIN_SIZE,                          ///< name "option-min-size",               The minimum size an option can be,              type VECTOR2
+      OPTION_DIVIDER_SIZE,                      ///< name "option-divider-size",           The size of the divider between options         type VECTOR2
       POPUP_CLIPBOARD_BUTTON_ICON_IMAGE,        ///< name "popup-clipboard-button-image",  The image to use as the popup clipboard icon,   type STRING
       POPUP_CUT_BUTTON_ICON_IMAGE,              ///< name "popup-cut-button-image",        The image to use as the popup cut icon,         type STRING
       POPUP_COPY_BUTTON_ICON_IMAGE,             ///< name "popup-copy-button-image",       The image to use as the popup copy icon,        type STRING
@@ -138,6 +141,6 @@ public: // Not intended for application developers
 
 } // namespace Toolkit
 
-} // namepsace Dali
+} // namespace Dali
 
 #endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__
diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.cpp b/dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.cpp
new file mode 100644 (file)
index 0000000..453b12d
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ * 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-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
+
+using namespace Dali;
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+TextSelectionToolbar TextSelectionToolbar::New()
+{
+  return Internal::TextSelectionToolbar::New();
+}
+
+TextSelectionToolbar::TextSelectionToolbar()
+{
+}
+
+TextSelectionToolbar::TextSelectionToolbar( const TextSelectionToolbar& handle )
+: Control( handle )
+{
+}
+
+TextSelectionToolbar& TextSelectionToolbar::operator=( const TextSelectionToolbar& handle )
+{
+  if( &handle != this )
+  {
+    Control::operator=( handle );
+  }
+  return *this;
+}
+
+TextSelectionToolbar::~TextSelectionToolbar()
+{
+}
+
+void TextSelectionToolbar::AddOption( Actor& option )
+{
+  GetImpl(*this).AddOption(option);
+}
+
+
+void TextSelectionToolbar::AddDivider( Actor& divider )
+{
+  GetImpl(*this).AddDivider( divider );
+}
+
+void TextSelectionToolbar::ResizeDividers( Size& size )
+{
+  GetImpl(*this).ResizeDividers( size );
+}
+
+TextSelectionToolbar TextSelectionToolbar::DownCast( BaseHandle handle )
+{
+  return Control::DownCast<TextSelectionToolbar, Internal::TextSelectionToolbar>(handle);
+}
+
+TextSelectionToolbar::TextSelectionToolbar( Internal::TextSelectionToolbar& implementation )
+: Control(implementation)
+{
+}
+
+TextSelectionToolbar::TextSelectionToolbar( Dali::Internal::CustomActor* internal )
+: Control( internal )
+{
+  VerifyCustomActorPointer<Internal::TextSelectionToolbar>( internal );
+}
+
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h b/dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h
new file mode 100644 (file)
index 0000000..31fca5c
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
+#define __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
+
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class TextSelectionToolbar;
+}
+
+/**
+ * @brief A control which provides a Popup with a number of buttons
+ *
+ * The style of the pop can be set through style sheets, this includes the images for the buttons
+ * A Show and Hide API is provided.
+ *
+ * If the buttons exceed the size constraints of the popup then it will offer scrolling.
+ *
+ *
+ */
+class DALI_IMPORT_API TextSelectionToolbar : public Control
+{
+public:
+
+  /**
+   * @brief The start and end property ranges for this control.
+   */
+  enum PropertyRange
+  {
+    PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1,
+    PROPERTY_END_INDEX =   PROPERTY_START_INDEX + 1000              ///< Reserve property indices
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the TextSelectionToolbar class.
+   */
+  struct Property
+  {
+    enum
+    {
+      MAX_SIZE =  PROPERTY_START_INDEX   ///< name "popup-max-size",                The maximum size the Popup can be,              type VECTOR2
+    };
+  };
+
+  /**
+   * Create the TextSelectionToolbar control.
+   * @return A handle to the TextSelectionToolbar control.
+   */
+  static TextSelectionToolbar New();
+
+  /**
+   * @brief Creates an empty handle.
+   */
+  TextSelectionToolbar();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @param[in] handle The handle to copy from.
+   */
+  TextSelectionToolbar( const TextSelectionToolbar& handle );
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @param[in] handle The handle to copy from.
+   * @return A reference to this.
+   */
+  TextSelectionToolbar& operator=( const TextSelectionToolbar& handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~TextSelectionToolbar();
+
+
+  /**
+   * @brief Add a option to the the Tool bar
+   * @param[in] option Option actor to add
+   */
+  void AddOption( Actor& option );
+
+  /**
+   * @brief Add a divider to the the Tool bar
+   * @param[in] divider Actor to be used as divider
+   */
+  void AddDivider( Actor& divider );
+
+  /**
+   *  @brief ResizeDividers
+   *  @param[in] size New size of dividers, provide 0 for height to automatically set height
+   */
+  void ResizeDividers( Size& size );
+
+  /**
+   * @brief Downcast a handle to TextSelectionToolbar.
+   *
+   * If the BaseHandle points is a TextSelectionToolbar the downcast returns a valid handle.
+   * If not the returned handle is left empty.
+   *
+   * @param[in] handle Handle to an object
+   * @return handle to a TextSelectionToolbar or an empty handle
+   */
+  static TextSelectionToolbar DownCast( BaseHandle handle );
+
+public: // Not intended for application developers
+
+  /**
+   * @brief Creates a handle using the Toolkit::Internal implementation.
+   *
+   * @param[in] implementation The Control implementation.
+   */
+  DALI_INTERNAL TextSelectionToolbar( Internal::TextSelectionToolbar& implementation );
+
+  /**
+   * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
+   *
+   * @param[in]  internal  A pointer to the internal CustomActor.
+   */
+  explicit DALI_INTERNAL TextSelectionToolbar( Dali::Internal::CustomActor* internal );
+
+}; // Class TextSelectionToolbar
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
index ae50ba3..d669daf 100755 (executable)
@@ -17,6 +17,7 @@ devel_api_src_files = \
   $(devel_api_src_dir)/controls/slider/slider.cpp \
   $(devel_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \
   $(devel_api_src_dir)/controls/text-controls/text-selection-popup.cpp \
+  $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.cpp \
   $(devel_api_src_dir)/controls/tool-bar/tool-bar.cpp \
   $(devel_api_src_dir)/focus-manager/keyinput-focus-manager.cpp \
   $(devel_api_src_dir)/styling/style-manager.cpp \
@@ -137,8 +138,9 @@ devel_api_shader_effects_header_files = \
 devel_api_super_blur_view_header_files = \
   $(devel_api_src_dir)/controls/super-blur-view/super-blur-view.h
 
-devel_api_text_selection_popup_header_files = \
-  $(devel_api_src_dir)/controls/text-controls/text-selection-popup.h
+devel_api_text_controls_header_files = \
+  $(devel_api_src_dir)/controls/text-controls/text-selection-popup.h \
+  $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.h
 
 devel_api_tool_bar_header_files = \
   $(devel_api_src_dir)/controls/tool-bar/tool-bar.h
index aedd849..988eabb 100644 (file)
@@ -17,8 +17,6 @@
 
 #include <dali-toolkit/devel-api/shader-effects/distance-field-effect.h>
 
-#define STRINGIFY(...) #__VA_ARGS__
-
 namespace Dali
 {
 
diff --git a/dali-toolkit/images/selection-popup-bg#.png b/dali-toolkit/images/selection-popup-bg#.png
new file mode 100755 (executable)
index 0000000..3eac19f
Binary files /dev/null and b/dali-toolkit/images/selection-popup-bg#.png differ
index 287663c..6ef44c0 100644 (file)
@@ -49,11 +49,11 @@ Actor SetupActor( const TreeNode& child, Actor& actor, const Replacement& consta
   // this has already been set as a generic property.
   if( !IsVector3( child, "parent-origin") )
   {
-    if( OptionalVector3 v = IsVector3(child, "parent-origin") )
+    if( OptionalVector3 v = constant.IsVector3( IsChild(child, "parent-origin") ) )
     {
       actor.SetParentOrigin( *v );
     }
-    else if( OptionalString origin = IsString(child, "parent-origin") )
+    else if( OptionalString origin = constant.IsString( IsChild(child, "parent-origin") ) )
     {
       actor.SetParentOrigin( GetAnchorConstant(*origin) );
     }
@@ -61,11 +61,11 @@ Actor SetupActor( const TreeNode& child, Actor& actor, const Replacement& consta
 
   if( !IsVector3(child, "anchor-point") )
   {
-    if( OptionalVector3 v = IsVector3(child, "anchor-point") )
+    if( OptionalVector3 v = constant.IsVector3( IsChild(child, "anchor-point") ) )
     {
       actor.SetAnchorPoint( *v );
     }
-    else if( OptionalString anchor = IsString(child, "anchor-point") )
+    else if( OptionalString anchor = constant.IsString( IsChild(child, "anchor-point") ) )
     {
       actor.SetAnchorPoint( GetAnchorConstant(*anchor) );
     }
index 6caf392..93f3623 100644 (file)
@@ -134,7 +134,7 @@ AlphaFunction GetAlphaFunction( const std::string& alphaFunction )
   }
   else
   {
-    DALI_ASSERT_ALWAYS( iter != alphaFunctionLut.end() && "Unknown Anchor Constant" );
+    DALI_ASSERT_ALWAYS( iter != alphaFunctionLut.end() && "Unknown Alpha Constant" );
     return Dali::AlphaFunction::DEFAULT;
   }
 }
index 6046ddd..ea0b15a 100644 (file)
@@ -176,11 +176,6 @@ std::string PropertyValueToString( const Property::Value& value )
       ret = std::string("Map Size=") + ToString( value.Get<Property::Map>().Count() );
       break;
     }
-    case Property::TYPE_COUNT:
-    {
-      ret = "";
-      break;
-    }
   }
 
   return ret;
@@ -721,11 +716,12 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re
     {
       if( OptionalChild image = IsChild( *images, name ) )
       {
-        Dali::Property::Value propertyMap(Property::MAP);
-        if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) )
+        Dali::Property::Value property(Property::MAP);
+        if( SetPropertyFromNode( *image, Property::MAP, property, constant ) )
         {
-          propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage")));
-          ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( propertyMap ) );
+          Property::Map* map = property.GetMap();
+          (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
+          ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
           mFrameBufferImageLut[ name ] = ret;
         }
       }
index cd90217..a1ed104 100644 (file)
@@ -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.
@@ -17,6 +17,8 @@
 
 // EXTERNAL INCLUDES
 #include <sstream>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/devel-api/adaptor-framework/color-controller.h>
 
 // INTERNAL INCLUDES
@@ -210,11 +212,8 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::V
     {
       if( OptionalUnsignedInt v = replacer.IsUnsignedInteger( node) )
       {
-        if( *v >= 0 ) // with a loss of resolution....
-        {
-          value = *v;
-          done = true;
-        }
+        value = *v;
+        done = true;
       }
       break;
     }
@@ -352,18 +351,19 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::V
       else if(node.Size())
       {
         value = Property::Value(Property::ARRAY);
+        Property::Array* array = value.GetArray();
         unsigned int i = 0;
         TreeNode::ConstIterator iter(node.CBegin());
         for( ; i < node.Size(); ++i, ++iter)
         {
-          Property::Value v;
-          if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+          Property::Value childValue;
+          if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
           {
-            value.AppendItem(v);
+            array->PushBack( childValue );
           }
         }
 
-        if( value.GetSize() == static_cast<int>(node.Size()) )
+        if( array->Count() == node.Size() )
         {
           done = true;
         }
@@ -383,18 +383,19 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::V
       else if(node.Size())
       {
         value = Property::Value(Property::MAP);
+        Property::Map* map = value.GetMap();
         unsigned int i = 0;
         TreeNode::ConstIterator iter(node.CBegin());
         for( ; i < node.Size(); ++i, ++iter)
         {
-          Property::Value v;
-          if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+          Property::Value childValue;
+          if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
           {
-            value.SetValue( (*iter).first, v );
+            map->Insert( (*iter).first, childValue );
           }
         }
 
-        if( value.GetSize() == static_cast<int>(node.Size()) )
+        if( map->Count() == node.Size() )
         {
           done = true;
         }
@@ -405,7 +406,6 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::V
       }
       break;
     }
-    case Property::TYPE_COUNT:
     case Property::NONE:
     {
       break;
@@ -490,13 +490,14 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
         else
         {
           value = Property::Value(Property::ARRAY);
-          Property::Value v;
+          Property::Array* array = value.GetArray();
 
           for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
           {
-            if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+            Property::Value childValue;
+            if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
             {
-              value.AppendItem(v);
+              array->PushBack( childValue );
               done = true;
             }
           }
@@ -514,12 +515,13 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
         if( ((*iter).first) == 0 )
         {
           value = Property::Value(Property::ARRAY);
-          Property::Value v;
+          Property::Array* array = value.GetArray();
           for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
           {
-            if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+            Property::Value childValue;
+            if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
             {
-              value.AppendItem(v);
+              array->PushBack( childValue );
               done = true;
             }
           }
@@ -527,12 +529,13 @@ bool SetPropertyFromNode( const TreeNode& node, Property::Value& value,
         else
         {
           value = Property::Value(Property::MAP);
-          Property::Value v;
+          Property::Map* map = value.GetMap();
           for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
           {
-            if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+            Property::Value childValue;
+            if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
             {
-              value.SetValue((*iter).first, v);
+              map->Insert( (*iter).first, childValue );
               done = true;
             }
           }
index f65e77e..998289b 100755 (executable)
 
 // EXTERNAL INCLUDES
 #include <cstring> // for strcmp
-#include <dali/integration-api/debug.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/images/resource-image.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/property-array.h>
 #include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/public-api/images/resource-image.h>
+#include <dali/integration-api/debug.h>
+
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h>
@@ -600,16 +602,19 @@ void ScrollBar::SetProperty( BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
       {
-        Dali::Vector<float> positions;
-        size_t positionCount = value.GetSize();
-        positions.Resize( positionCount );
-
-        for( size_t i = 0; i != positionCount; ++i )
+        Property::Array* array = value.GetArray();
+        if( array )
         {
-          value.GetItem(i).Get( positions[i] );
+          Dali::Vector<float> positions;
+          size_t positionCount = array->Count();
+          positions.Resize( positionCount );
+          for( size_t i = 0; i != positionCount; ++i )
+          {
+            array->GetElementAt( i ).Get( positions[i] );
+          }
+
+          scrollBarImpl.SetScrollPositionIntervals(positions);
         }
-
-        scrollBarImpl.SetScrollPositionIntervals(positions);
         break;
       }
     }
@@ -654,12 +659,13 @@ Property::Value ScrollBar::GetProperty( BaseObject* object, Property::Index inde
       }
       case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
       {
-        Property::Value value;
+        Property::Value value( Property::ARRAY );
+        Property::Array* array = value.GetArray();
         Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
-        size_t positionCount( positions.Size() );
+        size_t positionCount( array->Count() );
         for( size_t i( 0 ); i != positionCount; ++i )
         {
-          value.AppendItem( positions[i] );
+          array->PushBack( positions[i] );
         }
         break;
       }
index e56760f..38e6216 100644 (file)
@@ -53,6 +53,8 @@ DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-direction",
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layout-orientation",  INTEGER,  LAYOUT_ORIENTATION)
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-content-size", FLOAT,    SCROLL_CONTENT_SIZE)
 
+DALI_SIGNAL_REGISTRATION(              Toolkit, ItemView, "layout-activated",    LAYOUT_ACTIVATED_SIGNAL )
+
 DALI_TYPE_REGISTRATION_END()
 
 const float DEFAULT_MINIMUM_SWIPE_SPEED = 1.0f;
@@ -422,6 +424,11 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz
     mScrollAnimation.FinishedSignal().Connect(this, &ItemView::OnLayoutActivationScrollFinished);
     mScrollAnimation.Play();
   }
+  else
+  {
+    // Emit the layout activated signal
+    mLayoutActivatedSignal.Emit();
+  }
 
   AnimateScrollOvershoot(0.0f);
   mScrollOvershoot = 0.0f;
@@ -1298,6 +1305,9 @@ void ItemView::OnLayoutActivationScrollFinished(Animation& source)
   RemoveAnimation(mScrollAnimation);
   mRefreshEnabled = true;
   DoRefresh(GetCurrentLayoutPosition(0), true);
+
+  // Emit the layout activated signal
+  mLayoutActivatedSignal.Emit();
 }
 
 void ItemView::OnOvershootOnFinished(Animation& animation)
@@ -1625,6 +1635,26 @@ void ItemView::OnScrollPositionChanged( float position )
   DoRefresh(position, false); // No need to cache extra items.
 }
 
+bool ItemView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  Dali::BaseHandle handle( object );
+
+  bool connected( true );
+  Toolkit::ItemView itemView = Toolkit::ItemView::DownCast( handle );
+
+  if( 0 == strcmp( signalName.c_str(), LAYOUT_ACTIVATED_SIGNAL ) )
+  {
+    itemView.LayoutActivatedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 16f0b0a..b6a2d96 100644 (file)
@@ -53,6 +53,11 @@ class ItemView : public Scrollable
 {
 public:
 
+  // Signals
+  typedef Toolkit::ItemView::LayoutActivatedSignalType LayoutActivatedSignalType;
+
+public:
+
   /**
    * Create a new ItemView.
    * @param[in] factory The factory which provides ItemView with items.
@@ -284,6 +289,25 @@ public:
    */
   void GetItemsRange(ItemRange& range);
 
+  /**
+   * @copydoc Toolkit::ItemView::LayoutActivatedSignal()
+   */
+  LayoutActivatedSignalType& LayoutActivatedSignal()
+  {
+    return mLayoutActivatedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
 private:
 
   /**
@@ -593,6 +617,8 @@ private:
 
   Vector3 mItemsParentOrigin;
   Vector3 mItemsAnchorPoint;
+
+  LayoutActivatedSignalType mLayoutActivatedSignal;
 };
 
 } // namespace Internal
index 439dd8f..f12b873 100644 (file)
 // CLASS HEADER
 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.h>
 
-//INTERNAL INCLUDES
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/property-array.h>
+
+// INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
 
 namespace Dali
@@ -47,9 +50,10 @@ ScrollViewPagePathEffect::ScrollViewPagePathEffect(Path path, const Vector3& for
 
   //Create linear constrainer
   pointsProperty = Property::Value(Property::ARRAY);
-  pointsProperty.AppendItem(0.0f);
-  pointsProperty.AppendItem(1.0f);
-  pointsProperty.AppendItem(0.0f);
+  Property::Array* array = pointsProperty.GetArray();
+  array->PushBack(0.0f);
+  array->PushBack(1.0f);
+  array->PushBack(0.0f);
   mLinearConstrainer = Dali::LinearConstrainer::New();
   mLinearConstrainer.SetProperty( LinearConstrainer::Property::VALUE, pointsProperty );
 }
index 8ff89c3..a037767 100755 (executable)
@@ -725,7 +725,7 @@ float Slider::MarkFilter( float value )
   const float MARK_TOLERANCE = GetMarkTolerance();
 
   float mark;
-  for( std::size_t i = 0; i < mMarks.Size(); ++i)
+  for( MarkList::SizeType i = 0; i < mMarks.Count(); ++i)
   {
     const Property::Value& propertyValue = mMarks[i];
     propertyValue.Get( mark );
@@ -747,7 +747,7 @@ float Slider::SnapToMark( float value )
   float closestDist = std::numeric_limits<float>::max();
 
   float mark;
-  for( std::size_t i = 0; i < mMarks.Size(); ++i)
+  for( MarkList::SizeType  i = 0; i < mMarks.Count(); ++i)
   {
     const Property::Value& propertyValue = mMarks[i];
     propertyValue.Get( mark );
index bd96f77..742ef5e 100644 (file)
@@ -49,7 +49,9 @@ bool FitToChild( Actor actor, Dimension::Type dimension )
 
 #define TABLEVIEW_TAG "DALI Toolkit::TableView "
 #define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
+//#define TABLEVIEW_DEBUG 1
 
+#if defined(TABLEVIEW_DEBUG)
 void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
 {
   TV_LOG( "Array2d<CellData> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
@@ -101,6 +103,7 @@ void PrintVector( std::vector<float>& array )
   }
   TV_LOG( "\n" );
 }
+#endif // defined(TABLEVIEW_DEBUG)
 #endif // defined(DEBUG_ENABLED)
 
 } // namespace
@@ -134,7 +137,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP,
 
 DALI_TYPE_REGISTRATION_END()
 
-const Scripting::StringEnum< Toolkit::TableView::LayoutPolicy > LAYOUT_POLICY_STRING_TABLE[] =
+const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
 {
  { "fixed",    Toolkit::TableView::FIXED    },
  { "relative", Toolkit::TableView::RELATIVE },
@@ -1047,27 +1050,38 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
                                          void(TableView::*funcRelative)(unsigned int, float),
                                          const Property::Value& value )
 {
-  if( Property::MAP == value.GetType() )
+  Property::Map* map = value.GetMap();
+  if( map )
   {
-    Property::Map map = value.Get<Property::Map>();
     unsigned int rowIndex(0);
-    for ( unsigned int i = 0, count = map.Count(); i < count; ++i )
+    for ( unsigned int i = 0, count = map->Count(); i < count; ++i )
     {
-      Property::Value& item = map.GetValue(i);
+      Property::Value& item = map->GetValue(i);
+      Property::Map* childMap = item.GetMap();
 
-      if( std::istringstream(map.GetKey(i)) >> rowIndex  // the key is a number
-          && Property::MAP == item.GetType())
+      std::istringstream( map->GetKey(i) ) >> rowIndex;
+      if( childMap )
       {
-        if( item.HasKey( "policy" ) && item.HasKey( "value" ) )
+        Property::Value* policy = childMap->Find( "policy" );
+        Property::Value* value = childMap->Find( "value" );
+        if( policy && value )
         {
-          Toolkit::TableView::LayoutPolicy policy = Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( item.GetValue("policy").Get<std::string>().c_str(), LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT );
-          if( policy == Toolkit::TableView::FIXED )
+          std::string policyValue;
+          policy->Get( policyValue );
+          Toolkit::TableView::LayoutPolicy policy;
+          if( Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( policyValue.c_str(),
+                                                                             LAYOUT_POLICY_STRING_TABLE,
+                                                                             LAYOUT_POLICY_STRING_TABLE_COUNT,
+                                                                             policy ) )
           {
-            (tableViewImpl.*funcFixed)( rowIndex, item.GetValue("value").Get<float>() );
-          }
-          else if( policy == Toolkit::TableView::RELATIVE )
-          {
-            (tableViewImpl.*funcRelative)( rowIndex, item.GetValue("value").Get<float>() );
+            if( policy == Toolkit::TableView::FIXED )
+            {
+              (tableViewImpl.*funcFixed)( rowIndex, value->Get<float>() );
+            }
+            else if( policy == Toolkit::TableView::RELATIVE )
+            {
+              (tableViewImpl.*funcRelative)( rowIndex, value->Get<float>() );
+            }
           }
         }
       }
@@ -1091,8 +1105,22 @@ Property::Value TableView::GetColumnWidthsPropertyValue()
 
 void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
 {
-  std::string fixedPolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
-  std::string relativePolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
+  const char* name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED,
+                                                                                        LAYOUT_POLICY_STRING_TABLE,
+                                                                                        LAYOUT_POLICY_STRING_TABLE_COUNT );
+  std::string fixedPolicy;
+  if( name )
+  {
+    fixedPolicy = name;
+  }
+  name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE,
+                                                                            LAYOUT_POLICY_STRING_TABLE,
+                                                                            LAYOUT_POLICY_STRING_TABLE_COUNT );
+  std::string relativePolicy;
+  if( name )
+  {
+    relativePolicy = name;
+  }
 
   const RowColumnArray::SizeType count = data.Size();
   for( RowColumnArray::SizeType i = 0; i < count; i++ )
index 43de0d9..6f868e6 100644 (file)
@@ -62,7 +62,7 @@ namespace // unnamed namespace
 namespace
 {
 
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
 {
   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
@@ -70,7 +70,7 @@ const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment >
 };
 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
 
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
 {
   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
@@ -251,11 +251,14 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
           const std::string alignStr = value.Get< std::string >();
           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
 
-          const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
-                                                                                                                        HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                        HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-          impl.mController->SetHorizontalAlignment( alignment );
+          LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
+          if( Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
+                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                                              alignment ) )
+          {
+            impl.mController->SetHorizontalAlignment( alignment );
+          }
         }
         break;
       }
@@ -266,11 +269,14 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
           const std::string alignStr = value.Get< std::string >();
           DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
 
-          LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
-                                                                                                                    VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                    VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-          impl.mController->SetVerticalAlignment( alignment );
+          LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
+          if( Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
+                                                                            VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                                            VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                                            alignment ) )
+          {
+            impl.mController->SetVerticalAlignment( alignment );
+          }
         }
         break;
       }
@@ -612,9 +618,13 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mController )
         {
-          value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
-                                                                                                                  HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                  HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+          const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
+                                                                                                                HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                                                                                HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
+          if( name )
+          {
+            value = std::string( name );
+          }
         }
         break;
       }
@@ -622,9 +632,13 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mController )
         {
-          value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
-                                                                                                                  VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                  VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+          const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
+                                                                                                              VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                                                                              VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
+          if( name )
+          {
+            value = std::string( name );
+          }
         }
         break;
       }
index 854ddbf..de713ac 100644 (file)
@@ -50,7 +50,7 @@ namespace
 namespace
 {
 
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
 {
   { "BEGIN",  Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN  },
   { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
@@ -58,7 +58,7 @@ const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment >
 };
 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
 
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
 {
   { "TOP",    Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP    },
   { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
@@ -189,11 +189,14 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
-                                                                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-          impl.mController->SetHorizontalAlignment( alignment );
+          LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
+          if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
+                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                                                             HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                                                             alignment ) )
+          {
+            impl.mController->SetHorizontalAlignment( alignment );
+          }
         }
         break;
       }
@@ -201,11 +204,14 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
       {
         if( impl.mController )
         {
-          const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
-                                                                                                                                         VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                                         VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
-
-          impl.mController->SetVerticalAlignment( alignment );
+          LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
+          if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
+                                                                                           VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                                                           VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                                                           alignment ) )
+          {
+            impl.mController->SetVerticalAlignment( alignment );
+          }
         }
         break;
       }
@@ -356,9 +362,13 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mController )
         {
-          value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
-                                                                                                                  HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                  HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+          const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
+                                                                                                                HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                                                                                HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
+          if( name )
+          {
+            value = std::string( name );
+          }
         }
         break;
       }
@@ -366,9 +376,13 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
       {
         if( impl.mController )
         {
-          value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
-                                                                                                                VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                                                                                VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+          const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
+                                                                                                              VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                                                                              VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
+          if( name )
+          {
+            value = std::string( name );
+          }
         }
         break;
       }
index d66a70a..be7834a 100644 (file)
 #include <dali/public-api/images/resource-image.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/object/type-registry-helper.h>
 #include <libintl.h>
 #include <cfloat>
 
-// todo Move this to adaptor??
-#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
-
 namespace Dali
 {
 
@@ -45,15 +43,14 @@ namespace Internal
 
 namespace
 {
-const Dali::Vector4 DEFAULT_POPUP_BACKGROUND( Dali::Vector4( .20f, 0.29f, 0.44f, 1.0f ) );
-const Dali::Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Dali::Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) );
-const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) );
+// todo Move this to adaptor??
+#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
+
+const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.69f, 0.93f, 0.93f, 1.0f ) );
 const Dali::Vector4 DEFAULT_OPTION_ICON( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
 const Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 0.5f, 1.0f, 1.0f, 1.0f ) );
-const Dali::Vector4 DEFAULT_OPTION_TEXT( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
-const Dali::Vector4 DEFAULT_OPTION_TEXT_PRESSED( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
 
-const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "popup_bubble_bg.#.png" );
+const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "selection-popup-bg#.png" );
 const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
 const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
 const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" );
@@ -61,20 +58,27 @@ const std::string OPTION_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png"
 const std::string OPTION_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" );
 const std::string OPTION_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" );
 
-const Dali::Vector2 DEFAULT_POPUP_MAX_SIZE( 450.0f, 100.0f ); ///< The maximum size of the popup.
-
-const Dali::Vector2 OPTION_ICON_SIZE( 65.0f, 65.0f );       ///< The size of the icon.
 const float OPTION_MARGIN_WIDTH( 10.f );          ///< The margin between the right or lefts edge and the text or icon.
-const float OPTION_MAX_WIDTH( 110.0f );          ///< The maximum width of the option   //todo Make Property
-const float OPTION_MIN_WIDTH( 86.0f );           ///< The minimum width of the option. //todo Make Property
-const float POPUP_DIVIDER_WIDTH( 3.f );        ///< The size of the divider.
 
-const Dali::Vector2 POPUP_TAIL_SIZE( 20.0f, 16.0f ); ///< The size of the tail.
-const float POPUP_TAIL_Y_OFFSET( 5.f );        ///< The y offset of the tail (when its position is on the bottom).
-const float POPUP_TAIL_TOP_Y_OFFSET( 3.f );    ///< The y offset of the tail (when its position is on the top).
+#ifdef DGETTEXT_ENABLED
 
-const float HIDE_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup hide animation in seconds.
-const float SHOW_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup show animation in seconds.
+#define POPUP_CUT_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CUT")
+#define POPUP_COPY_STRING GET_LOCALE_TEXT("IDS_COM_BODY_COPY")
+#define POPUP_PASTE_STRING GET_LOCALE_TEXT("IDS_COM_BODY_PASTE")
+#define POPUP_SELECT_STRING GET_LOCALE_TEXT("IDS_COM_SK_SELECT")
+#define POPUP_SELECT_ALL_STRING GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL")
+#define POPUP_CLIPBOARD_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD")
+
+#else
+
+#define POPUP_CUT_STRING  "Cut"
+#define POPUP_COPY_STRING  "Copy"
+#define POPUP_PASTE_STRING  "Paste"
+#define POPUP_SELECT_STRING  "Select"
+#define POPUP_SELECT_ALL_STRING  "Select All"
+#define POPUP_CLIPBOARD_STRING  "Clipboard"
+
+#endif
 
 const char* const OPTION_SELECT_WORD = "option-select_word";                       // "Select Word" popup option.
 const char* const OPTION_SELECT_ALL("option-select_all");                          // "Select All" popup option.
@@ -83,14 +87,30 @@ const char* const OPTION_COPY("option-copy");
 const char* const OPTION_PASTE("option-paste");                                    // "Paste" popup option.
 const char* const OPTION_CLIPBOARD("option-clipboard");                            // "Clipboard" popup option.
 
-} // namespace
+BaseHandle Create()
+{
+  return Toolkit::TextSelectionPopup::New();
+}
 
-//// Comparison function for ButtonRequirement Priority
-//bool TextSelectionPopup::PriorityCompare( ButtonRequirement const& a, ButtonRequirement const& b )
-//{
-//  return a.priority < b.priority;
-//}
+// Setup properties, signals and actions using the type-registry.
 
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextSelectionPopup, Toolkit::Control, Create );
+
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-max-size", VECTOR2,   POPUP_MAX_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-min-size", VECTOR2,   POPUP_MIN_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-max-size", VECTOR2,   OPTION_MAX_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-min-size", VECTOR2,   OPTION_MIN_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-divider-size", VECTOR2,   OPTION_DIVIDER_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-clipboard-button-image", STRING, POPUP_CLIPBOARD_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-cut-button-image", STRING, POPUP_CUT_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-copy-button-image", STRING, POPUP_COPY_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-paste-button-image", STRING, POPUP_PASTE_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-select-button-image", STRING, POPUP_SELECT_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-select-all-button-image", STRING, POPUP_SELECT_ALL_BUTTON_ICON_IMAGE )
+
+DALI_TYPE_REGISTRATION_END()
+
+} // namespace
 
 Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New()
 {
@@ -119,49 +139,63 @@ void TextSelectionPopup::SetProperty( BaseObject* object, Property::Index index,
     {
       case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
       {
-       impl.SetPopupMaxSize( value.Get< Vector2 >() );
+       impl.SetDimensionToCustomise( POPUP_MAXIMUM_SIZE, value.Get< Vector2 >() );
        break;
       }
-      case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE:
+      case Toolkit::TextSelectionPopup::Property::POPUP_MIN_SIZE:
       {
-        ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_BACKGROUND, image );
+        impl.SetDimensionToCustomise( POPUP_MINIMUM_SIZE, value.Get< Vector2 >() );
+        break;
+      }
+      case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
+      {
+        impl.SetDimensionToCustomise( OPTION_MAXIMUM_SIZE, value.Get< Vector2 >() );
+        break;
+      }
+      case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
+      {
+        impl.SetDimensionToCustomise( OPTION_MINIMUM_SIZE, value.Get< Vector2>() );
+        break;
+      }
+      case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
+      {
+        impl.SetDimensionToCustomise( OPTION_DIVIDER_SIZE, value.Get< Vector2>() );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_CLIPBOARD_BUTTON, image );
+        impl.SetButtonImage( CLIPBOARD, image );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_CUT_BUTTON_ICON, image );
+        impl.SetButtonImage( CUT, image );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_COPY_BUTTON_ICON, image );
+        impl.SetButtonImage( COPY, image );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_PASTE_BUTTON_ICON, image );
+        impl.SetButtonImage( PASTE, image );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_SELECT_BUTTON_ICON, image );
+        impl.SetButtonImage( SELECT, image );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE:
       {
         ResourceImage image = ResourceImage::New( value.Get< std::string >() );
-        impl.SetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON, image );
+        impl.SetButtonImage( SELECT_ALL, image );
         break;
       }
     } // switch
@@ -182,21 +216,27 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
     {
       case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
       {
-        value = impl.GetPopupMaxSize();
+        value = impl.GetDimensionToCustomise( POPUP_MAXIMUM_SIZE );
         break;
       }
-      case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE:
+      case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_BACKGROUND ) );
-        if( image )
-        {
-          value = image.GetUrl();
-        }
+        value = impl.GetDimensionToCustomise( OPTION_MAXIMUM_SIZE );
+        break;
+      }
+      case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
+      {
+        value = impl.GetDimensionToCustomise( OPTION_MINIMUM_SIZE );
+        break;
+      }
+      case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
+      {
+        value = impl.GetDimensionToCustomise( OPTION_DIVIDER_SIZE );
         break;
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CLIPBOARD_BUTTON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( CLIPBOARD ) );
         if( image )
         {
           value = image.GetUrl();
@@ -205,7 +245,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CUT_BUTTON_ICON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( CUT ) );
         if( image )
         {
           value = image.GetUrl();
@@ -214,7 +254,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_COPY_BUTTON_ICON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( COPY ) );
         if( image )
         {
           value = image.GetUrl();
@@ -223,7 +263,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_PASTE_BUTTON_ICON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( PASTE ) );
         if( image )
         {
           value = image.GetUrl();
@@ -232,7 +272,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_BUTTON_ICON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( SELECT ) );
         if( image )
         {
           value = image.GetUrl();
@@ -241,7 +281,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I
       }
       case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE:
       {
-        ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON ) );
+        ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( SELECT_ALL ) );
         if( image )
         {
           value = image.GetUrl();
@@ -258,106 +298,160 @@ void TextSelectionPopup::OnInitialize()
   CreatePopup();
 }
 
-void TextSelectionPopup::OnRelayout( const Vector2& size, RelayoutContainer& container )
+void TextSelectionPopup::SetDimensionToCustomise( const PopupCustomisations& settingToCustomise, const Size& dimension )
 {
+  switch( settingToCustomise )
+  {
+    case POPUP_MAXIMUM_SIZE :
+    {
+      Actor self = Self();
+      mMaxSize = dimension;
+      if ( mToolbar )
+      {
+        mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, mMaxSize );
+      }
+      break;
+    }
+    case POPUP_MINIMUM_SIZE :
+    {
+      Actor self = Self();
+      mMinSize = dimension;
+      // Option can not be smaller than this if only one.
+      break;
+    }
+    case OPTION_MAXIMUM_SIZE :
+    {
+      mOptionMaxSize = dimension;
+      // Option max size not currently currently supported
 
+      break;
+    }
+    case OPTION_MINIMUM_SIZE :
+    {
+      mOptionMinSize = dimension;
+      // Option min size not currently currently supported
+      break;
+    }
+    case OPTION_DIVIDER_SIZE :
+    {
+      mOptionDividerSize = dimension;
+      if ( mToolbar )
+      {
+        // Resize Dividers not currently supported
+      }
+      break;
+    }
+  } // switch
 }
 
-void TextSelectionPopup::SetPopupMaxSize( const Size& maxSize )
+Size TextSelectionPopup::GetDimensionToCustomise( const PopupCustomisations& settingToCustomise )
 {
-  mMaxSize = maxSize;
-}
+  switch( settingToCustomise )
+  {
+    case POPUP_MAXIMUM_SIZE :
+    {
+      return mMaxSize;
+    }
+    case POPUP_MINIMUM_SIZE :
+    {
+      return mMinSize;
+    }
+    case OPTION_MAXIMUM_SIZE :
+    {
+      return mOptionMaxSize;
+    }
+    case OPTION_MINIMUM_SIZE :
+    {
+      return mOptionMinSize;
+    }
+    case OPTION_DIVIDER_SIZE :
+    {
+      return mOptionDividerSize;
+    }
+  } // switch
 
-const Dali::Vector2& TextSelectionPopup::GetPopupMaxSize() const
-{
-  return mMaxSize;
+  return Size::ZERO;
 }
 
-void TextSelectionPopup::SetPopupImage( PopupParts part, Dali::Image image )
+void TextSelectionPopup::SetButtonImage( Buttons button, Dali::Image image )
 {
-   switch ( part )
-   {
-   case POPUP_BACKGROUND :
+   switch ( button )
    {
-     mBackgroundImage = image;
-   }
    break;
-   case POPUP_CLIPBOARD_BUTTON :
+   case CLIPBOARD:
    {
      mClipboardIconImage  = image;
    }
    break;
-   case POPUP_CUT_BUTTON_ICON :
+   case CUT :
    {
      mCutIconImage = image;
    }
    break;
-   case POPUP_COPY_BUTTON_ICON :
+   case COPY :
    {
      mCopyIconImage = image;
    }
    break;
-   case POPUP_PASTE_BUTTON_ICON :
+   case PASTE :
    {
      mPasteIconImage = image;
    }
    break;
-   case POPUP_SELECT_BUTTON_ICON :
+   case SELECT :
    {
      mSelectIconImage = image;
    }
    break;
-   case POPUP_SELECT_ALL_BUTTON_ICON :
+   case SELECT_ALL :
    {
      mSelectAllIconImage = image;
    }
    break;
-
+   default :
+   {
+     DALI_ASSERT_DEBUG( "TextSelectionPopup SetPopupImage Unknown Button" );
+   }
    } // switch
 }
 
-Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part )
+Dali::Image TextSelectionPopup::GetButtonImage( Buttons button )
 {
-  switch ( part )
+  switch ( button )
   {
-  case POPUP_BACKGROUND :
-  {
-    return mBackgroundImage;
-  }
-  break;
-  case POPUP_CLIPBOARD_BUTTON :
+  case CLIPBOARD :
   {
     return mClipboardIconImage;
   }
   break;
-  case POPUP_CUT_BUTTON_ICON :
+  case CUT :
   {
     return mCutIconImage;
   }
   break;
-  case POPUP_COPY_BUTTON_ICON :
+  case COPY :
   {
     return mCopyIconImage;
   }
   break;
-  case POPUP_PASTE_BUTTON_ICON :
+  case PASTE :
   {
     return mPasteIconImage;
   }
   break;
-  case POPUP_SELECT_BUTTON_ICON :
+  case SELECT :
   {
     return mSelectIconImage;
   }
   break;
-  case POPUP_SELECT_ALL_BUTTON_ICON :
+  case SELECT_ALL :
   {
     return mSelectAllIconImage;
   }
   break;
   default :
   {
-    DALI_ASSERT_DEBUG( "Unknown Popup Part" );
+    DALI_ASSERT_DEBUG( "TextSelectionPopup GetPopupImage Unknown Button" );
   }
   } // switch
 
@@ -373,66 +467,56 @@ Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part )
    {
      mCutIconImage = ResourceImage::New( OPTION_ICON_CUT );
    }
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), mCutIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( CUT, mCutOptionPriority, OPTION_CUT, POPUP_CUT_STRING , mCutIconImage, false ) );
 
    if ( !mCopyIconImage )
    {
      mCopyIconImage = ResourceImage::New( OPTION_ICON_COPY );
    }
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), mCopyIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( COPY, mCopyOptionPriority, OPTION_COPY, POPUP_COPY_STRING, mCopyIconImage, false ) );
 
    if ( !mPasteIconImage )
    {
      mPasteIconImage = ResourceImage::New( OPTION_ICON_PASTE );
    }
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), mPasteIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( PASTE, mPasteOptionPriority, OPTION_PASTE, POPUP_PASTE_STRING, mPasteIconImage, false ) );
 
    if ( !mSelectIconImage )
    mSelectIconImage = ResourceImage::New( OPTION_ICON_SELECT );
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), mSelectIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( SELECT, mSelectOptionPriority, OPTION_SELECT_WORD, POPUP_SELECT_STRING, mSelectIconImage, true ) );
 
    if ( !mSelectAllIconImage )
    {
     mSelectAllIconImage = ResourceImage::New( OPTION_ICON_SELECT_ALL );
    }
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), mSelectAllIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( SELECT_ALL, mSelectAllOptionPriority, OPTION_SELECT_ALL, POPUP_SELECT_ALL_STRING, mSelectAllIconImage, true ) );
 
    if ( !mClipboardIconImage )
    {
      mClipboardIconImage = ResourceImage::New( OPTION_ICON_CLIPBOARD );
    }
-   mOrderListOfButtons.push_back( ButtonRequirement( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), mClipboardIconImage, true ) );
+   mOrderListOfButtons.push_back( ButtonRequirement( CLIPBOARD, mClipboardOptionPriority, OPTION_CLIPBOARD, POPUP_CLIPBOARD_STRING, mClipboardIconImage, false ) );
 
    // Sort the buttons according their priorities.
    std::sort( mOrderListOfButtons.begin(), mOrderListOfButtons.end(), TextSelectionPopup::ButtonPriorityCompare() );
  }
 
- void TextSelectionPopup::CreateBackground()
- {
-   if ( mBackgroundImage )
-   {
-     SetBackgroundImage (  mBackgroundImage );
-   }
-
-   SetBackgroundColor( mBackgroundColor );
- }
-
- void TextSelectionPopup::AddOption( Dali::Toolkit::TableView& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons, bool showCaption, std::size_t& indexInTable )
+ void TextSelectionPopup::AddOption( const std::string& name, const std::string& caption, const Image iconImage, bool showDivider, bool showIcons, bool showCaption  )
  {
    // 1. Create the backgrounds for the popup option both normal and pressed.
    // Both containers will be added to a button.
 
-   Toolkit::TableView optionContainer = Toolkit::TableView::New( (showIcons)?2:1 , 1 );
+   Toolkit::TableView optionContainer = Toolkit::TableView::New( (showIcons&showCaption)?2:1 , 1 );
    optionContainer.SetDrawMode( DrawMode::OVERLAY );
-   optionContainer.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
-   optionContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) );
+   optionContainer.SetFitHeight( 0 );
    optionContainer.SetFitWidth( 0 );
 
-   Toolkit::TableView  optionPressedContainer = Toolkit::TableView::New( (showIcons)?2:1 , 1 );
+   Toolkit::TableView  optionPressedContainer = Toolkit::TableView::New( (showIcons&showCaption)?2:1 , 1 );
    optionPressedContainer.SetDrawMode( DrawMode::OVERLAY );
-   optionPressedContainer.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
-   optionPressedContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) );
+   optionPressedContainer.SetFitHeight( 0 );
    optionPressedContainer.SetFitWidth( 0 );
+   optionPressedContainer.SetBackgroundColor(Color::RED); //todo member variable
+
 #ifdef DECORATOR_DEBUG
    optionContainer.SetName("optionContainer");
    optionPressedContainer.SetName("optionPressedContainer");
@@ -441,112 +525,83 @@ Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part )
 
    if ( showCaption )
    {
-   Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New();
-   captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
-   optionContainer.SetFitHeight( 0 );
-
-   Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New();
-   pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
-   optionPressedContainer.SetFitHeight( 0 );
-
-   captionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
-   captionTextLabel.SetMaximumSize( Vector2( OPTION_MAX_WIDTH - 2.f * OPTION_MARGIN_WIDTH , FLT_MAX ) ); //todo FLT_MAX Size negotiation feature needed
-
-   pressedCaptionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH );
-   pressedCaptionTextLabel.SetMaximumSize( Vector2( OPTION_MAX_WIDTH - 2.f * OPTION_MARGIN_WIDTH , FLT_MAX) ); //todo FLT_MAX Size negotiation feature needed
-
-   optionContainer.AddChild( captionTextLabel, Toolkit::TableView::CellPosition( 1, 0 )  ); // todo Labels need ellipsis or similar
-   optionPressedContainer.AddChild( pressedCaptionTextLabel, Toolkit::TableView::CellPosition( 1, 0 )  ); // todo Labels need ellipsis or similar
+     Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New();
+     captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+     captionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+
+     Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New();
+     pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+     pressedCaptionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+
+     Padding padding;
+     padding.left = 24.0f;
+     padding.right = 24.0f;
+     padding.top = 13.0f;
+     padding.bottom = 14.0f;
+     captionTextLabel.SetPadding( padding );
+     pressedCaptionTextLabel.SetPadding( padding );
+
+     optionContainer.AddChild( captionTextLabel, Toolkit::TableView::CellPosition(( showIcons&showCaption)?1:0, 0 )  );
+     optionPressedContainer.AddChild( pressedCaptionTextLabel, Toolkit::TableView::CellPosition(( showIcons&showCaption)?1:0, 0 ) );
    }
 
+   // 3. Create the icons
    if ( showIcons )
    {
-     // 3. Create the icons
      ImageActor pressedIcon = ImageActor::New(  iconImage );
      ImageActor icon = ImageActor::New(  iconImage );
-     icon.SetName("image-icon-2014");
+
      icon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
      pressedIcon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+     icon.SetColor( mIconColor );
      pressedIcon.SetColor( mIconPressedColor );
-     optionContainer.SetFitHeight( 0 );
-     optionPressedContainer.SetFitHeight( 0 );
+
+     if ( showCaption & showIcons )
+     {
+       optionContainer.SetFitHeight( 1 );
+       optionContainer.SetFitWidth( 1 );
+       optionPressedContainer.SetFitHeight( 1 );
+       optionPressedContainer.SetFitWidth( 1 );
+     }
+
      optionContainer.AddChild( icon, Toolkit::TableView::CellPosition( 0, 0 )  );
      optionPressedContainer.AddChild( pressedIcon, Toolkit::TableView::CellPosition( 0, 0 )  );
+
      icon.SetPadding( Padding( 10.0f, 10.0f, 10.0f, 10.0f ) );
      pressedIcon.SetPadding( Padding( 10.0f, 10.0f, 10.0f, 10.0f ) );
    }
 
-   // 5. Create a option.
+   // 4. Create a option.
    Toolkit::PushButton option = Toolkit::PushButton::New();
    option.SetName( name );
    option.SetAnimationTime( 0.0f );
-   option.SetSize( OPTION_ICON_SIZE );
+   option.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
    //option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
 
-   // 6. Set the normal option image.
+   // 5. Set the normal option image.
    option.SetButtonImage( optionContainer );
 
-   // 7. Set the pressed option image
+   // 6. Set the pressed option image
    option.SetSelectedImage( optionPressedContainer );
 
-   // 9 Add option to table view
-   parent.SetFitWidth( indexInTable );
-   parent.AddChild( option, Toolkit::TableView::CellPosition( 0, indexInTable )  );
-   indexInTable++;
+   // 7 Add option to tool bar
+   mToolbar.AddOption( option );
 
-   // 10. Add the divider
-   if( !finalOption )
+   // 8. Add the divider
+   if( showDivider )
    {
-     const Size size( POPUP_DIVIDER_WIDTH, 0.0f ); // Height FILL_TO_PARENT
+     const Size size( mOptionDividerSize.width, 0.0f ); // Height FILL_TO_PARENT
 
      ImageActor divider = Toolkit::CreateSolidColorActor( Color::WHITE );
-
      divider.SetSize( size );
      divider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
-     parent.SetFitWidth( indexInTable );
-     parent.AddChild( divider, Toolkit::TableView::CellPosition( 0, indexInTable )  );
-     indexInTable++;
+     divider.SetColor( mLineColor );
+     mToolbar.AddDivider( divider );
    }
  }
 
- void TextSelectionPopup::SetUpPopup()
- {
-   Actor self = Self();
-   self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
-
-   // Create Layer and Stencil.
-   mStencilLayer = Layer::New();
-   mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
-   mStencilLayer.SetParentOrigin( ParentOrigin::CENTER );
-
-   ImageActor stencil = CreateSolidColorActor( Color::RED );
-   stencil.SetDrawMode( DrawMode::STENCIL );
-   stencil.SetVisible( true );
-   stencil.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
-   stencil.SetParentOrigin( ParentOrigin::CENTER );
-
-   Actor scrollview = Actor::New(); //todo make a scrollview
-   scrollview.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
-   scrollview.SetParentOrigin( ParentOrigin::CENTER );
-
-   mTableOfButtons.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
-   mTableOfButtons.SetFitHeight( 0 );
-   mTableOfButtons.SetParentOrigin( ParentOrigin::CENTER );
-
-   mStencilLayer.Add( stencil );
-   mStencilLayer.Add( scrollview );
-   scrollview.Add( mTableOfButtons );
-   self.Add( mStencilLayer );
-   //self.Add ( mTableOfButtons );
- }
-
- void TextSelectionPopup::AddPopupOptions( bool createTail, bool showIcons, bool showCaptions )
+ std::size_t TextSelectionPopup::GetNumberOfEnabledOptions()
  {
-   mContentSize = Vector2::ZERO;
-
-   // Add the options into the buttons container.
-
-   // 1. Determine how many buttons are active and should be added to container.
    std::size_t numberOfOptions = 0u;
    for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
    {
@@ -557,56 +612,59 @@ Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part )
      }
    }
 
-   // 2. Iterate list of buttons and add active ones.
-   std::size_t optionsAdded = 0u;
-
-   numberOfOptions = ( numberOfOptions*2 ) - 1 ; // Last Option does not get a divider so -1 or if only one option then also no divider
-
-   mTableOfButtons = Dali::Toolkit::TableView::New( 1, numberOfOptions );
+   return numberOfOptions;
+ }
 
+ void TextSelectionPopup::AddPopupOptionsToToolbar( bool showIcons, bool showCaptions )
+ {
+   // Iterate list of buttons and add active ones to Toolbar
+   std::size_t numberOfOptionsRequired =  GetNumberOfEnabledOptions();
+   std::size_t numberOfOptionsAdded = 0u;
    for( std::vector<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
    {
      const ButtonRequirement& button( *it );
      if ( button.enabled )
      {
-       AddOption( mTableOfButtons, button.name, button.caption, button.icon, optionsAdded == numberOfOptions - 1, showIcons, showCaptions, optionsAdded ); // -1 to ignore the last divider
+       numberOfOptionsAdded++;
+       AddOption(  button.name, button.caption, button.icon, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions );
      }
    }
  }
 
  void TextSelectionPopup::CreatePopup()
  {
-   if ( !mStencilLayer )
+   Actor self = Self();
+   CreateOrderedListOfPopupOptions();  //todo Currently causes all options to be shown
+   self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+   SetBackgroundImage( NinePatchImage::New( DEFAULT_POPUP_BACKGROUND_IMAGE ) );
+
+   if ( !mToolbar )
    {
-     CreateOrderedListOfPopupOptions();  //todo Currently causes all options to be shown
-     CreateBackground();
-     AddPopupOptions( true, true, false );  // todo false so not to show Labels until ellipses or similar possible.
-     SetUpPopup();
+     mToolbar = Toolkit::TextSelectionToolbar::New();
+     mToolbar.SetParentOrigin( ParentOrigin::CENTER );
+     mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, mMaxSize );
+     self.Add( mToolbar );
+     AddPopupOptionsToToolbar( mShowIcons, mShowCaptions );
    }
-
-   mStencilLayer.RaiseToTop();
  }
 
 TextSelectionPopup::TextSelectionPopup()
-: Control( ControlBehaviour( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ) ),
-  mMaxSize ( DEFAULT_POPUP_MAX_SIZE ),
-  mVisiblePopUpSize( DEFAULT_POPUP_MAX_SIZE ),
-  mRequiredPopUpSize( DEFAULT_POPUP_MAX_SIZE ),
-  mBackgroundColor( DEFAULT_POPUP_BACKGROUND ),
-  mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ),
+: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
+  mToolbar(),
+  mMaxSize(),
+  mMinSize(),
+  mOptionDividerSize( Size( 2.0f, 0.0f) ),
   mLineColor( DEFAULT_POPUP_LINE_COLOR ),
   mIconColor( DEFAULT_OPTION_ICON ),
   mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ),
-  mTextColor( DEFAULT_OPTION_TEXT ),
-  mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ),
   mSelectOptionPriority( 1 ),
   mSelectAllOptionPriority ( 2 ),
   mCutOptionPriority ( 3 ),
   mCopyOptionPriority ( 4 ),
   mPasteOptionPriority ( 5 ),
   mClipboardOptionPriority( 6 ),
-  mShowIcons( true ),
-  mShowCaptions( false )
+  mShowIcons( false ),
+  mShowCaptions( true )
 {
 }
 
@@ -620,3 +678,5 @@ TextSelectionPopup::~TextSelectionPopup()
 } // namespace Toolkit
 
 } // namespace Dali
+
+
index 892c563..34c2235 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/table-view/table-view.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/actors/image-actor.h>
@@ -38,15 +39,14 @@ namespace Internal
 
 namespace
 {
-enum PopupParts
+
+enum PopupCustomisations
 {
-  POPUP_BACKGROUND,
-  POPUP_CLIPBOARD_BUTTON,
-  POPUP_CUT_BUTTON_ICON,
-  POPUP_COPY_BUTTON_ICON,
-  POPUP_PASTE_BUTTON_ICON,
-  POPUP_SELECT_BUTTON_ICON,
-  POPUP_SELECT_ALL_BUTTON_ICON,
+  POPUP_MAXIMUM_SIZE,
+  POPUP_MINIMUM_SIZE,
+  OPTION_MAXIMUM_SIZE,
+  OPTION_MINIMUM_SIZE,
+  OPTION_DIVIDER_SIZE
 };
 
 } // namespace
@@ -57,19 +57,19 @@ public:
 
   enum Buttons
   {
-    ButtonsCut,
-    ButtonsCopy,
-    ButtonsPaste,
-    ButtonsSelect,
-    ButtonsSelectAll,
-    ButtonsClipboard,
-    ButtonsEnumEnd
+    CUT,
+    COPY,
+    PASTE,
+    SELECT,
+    SELECT_ALL,
+    CLIPBOARD,
+    ENUM_END
   };
 
   struct ButtonRequirement
   {
     ButtonRequirement()
-    : id( ButtonsEnumEnd ),
+    : id( ENUM_END ),
       priority( 0u ),
       name(),
       caption(),
@@ -106,11 +106,6 @@ public:
       }
   };
 
-//  static inline bool ButtonPriorityCompare( ButtonRequirement a, ButtonRequirement b )
-//  {
-//    return a.priority < b.priority ? true : false;
-//  }
-
   /**
    * @copydoc Dali::Toollkit::TextSelectionPopup::New()
    */
@@ -135,81 +130,55 @@ public:
    */
   static Property::Value GetProperty( BaseObject* object, Property::Index index );
 
-  void CreatePopup();
-
-  void DestroyPopup();
-
 private: // From Control
 
   /**
    * @copydoc Control::OnInitialize()
    */
- virtual void OnInitialize();
-
-//  /**
-//   * @copydoc Control::GetNaturalSize()
-//   */
-//  virtual Vector3 GetNaturalSize();
-//
-//  /**
-//   * @copydoc Control::GetHeightForWidth()
-//   */
-//  virtual float GetHeightForWidth( float width );
+  virtual void OnInitialize();
 
-  /**
-   * @copydoc Control::OnInitialize()
-   */
-  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container );
-//
-//  /**
-//   * Received for single & double taps
-//   */
-//  virtual void OnTap( const TapGesture& tap );
-//
-//  /**
-//   * @copydoc Text::ControlInterface::RequestTextRelayout()
-//   */
-//  virtual void RequestTextRelayout();
+private: // Implementation
 
   /**
-   * Set max size of Popup
-   * @param[in] maxSize Size (Vector2)
+   * @brief Method to set the dimension or dimension constraint on certain aspects of the Popup.
+   *
+   * @param[in] settingToCustomise The setting for the PopupCustomisations enum that can be customised
+   * @param[in] dimension The size to customise with
    */
-  void SetPopupMaxSize( const Size& maxSize );
+  void SetDimensionToCustomise( const PopupCustomisations& settingToCustomise, const Size& dimension );
 
   /**
-   * Get Max size of Popup
-   * @return Vector2 the max size of the Popup
+   * @brief Method to get the dimension or dimension constraint on certain aspects of the Popup that was previously customised
+   *
+   * @param[in] setting The setting from the PopupCustomisations enum
    */
-  const Dali::Vector2& GetPopupMaxSize() const;
+  Size GetDimensionToCustomise( const PopupCustomisations& setting );
 
   /**
-   * @brief Sets the image for the given part of the Popup.
+   * @brief Sets the image for the given button of the Popup.
    *
-   * @param[in] part  The part of the pop from the Enum PopupParts
+   * @param[in] button  The button the image should be used for from the Buttons Enum.
    * @param[in] image The image to use.
    */
- void SetPopupImage( PopupParts part, Dali::Image image );
+ void SetButtonImage( Buttons button, Dali::Image image );
 
   /**
-   * @brief Retrieves the image of the given part used by the popup
+   * @brief Retrieves the image of the given button used by the popup
    *
-   * @param[in] part The part of the popup
-   * @return The image used for that part.
+   * @param[in] button The button to get the image from
+   * @return The image used for that button.
    */
-  Dali::Image GetPopupImage( PopupParts part );
+  Dali::Image GetButtonImage( Buttons button );
 
   void CreateOrderedListOfPopupOptions();
 
-  void CreateBackground();
-
-  void AddOption( Dali::Toolkit::TableView& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons, bool showCaption, std::size_t& indexInTable  );
+  void AddOption( const std::string& name, const std::string& caption, const Image iconImage, bool showDivider, bool showIcons, bool showCaption );
 
-  void SetUpPopup();
+  std::size_t GetNumberOfEnabledOptions();
 
-  void AddPopupOptions( bool createTail, bool showIcons, bool showCaptions );
+  void AddPopupOptionsToToolbar(  bool showIcons, bool showCaptions );
 
-private: // Implementation
+  void CreatePopup();
 
   /**
    * Construct a new TextField.
@@ -229,11 +198,12 @@ private:
 
 private: // Data
 
-  Dali::Toolkit::TableView mTableOfButtons;                          // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
-  Layer mStencilLayer;                                // Layer to enable clipping when buttons exceed popup
 
-  // Images to be used by the Popup
-  Image mBackgroundImage;
+  Dali::Toolkit::TextSelectionToolbar mToolbar;
+
+  Dali::Toolkit::TableView mTableOfButtons;           // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
+
+  // Images to be used by the Popup buttons
   Image mCutIconImage;
   Image mCopyIconImage;
   Image mPasteIconImage;
@@ -241,29 +211,18 @@ private: // Data
   Image mSelectIconImage;
   Image mSelectAllIconImage;
 
-  ImageActor mBackground;                             // The background popup panel
-  ImageActor mTail;                                   // The tail for the popup
-  ImageActor mTailEffect;   //todo remove                          // the tail effect
-  ImageActor mTailLine;     //todo remove                          // The border/outline around the tail
-
-  Size mMaxSize;                                      // Max size of the Popup
-  Size mVisiblePopUpSize;                             // Visible Size of popup excluding content that needs scrolling.
-  Size mRequiredPopUpSize;                            // Total size of popup including any invisible margin
+  Size mMaxSize;                       // Maximum size of the Popup
+  Size mMinSize;                       // Minimum size of the Popup
 
-  Vector4 mNinePatchMargins;                          // Margins between the edge of the cropped image and the nine patch rect (left, right, top, bottom).
-
-  Size mContentSize;                                  // Size of Content (i.e. Buttons)
-  //Animation mAnimation;                               // Popup Hide/Show animation.
+  Size mOptionMaxSize;                 // Maximum size of an Option button
+  Size mOptionMinSize;                 // Minimum size of an Option button
+  Size mOptionDividerSize;             // Size of divider line
 
   std::vector<ButtonRequirement> mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed.
 
-  Vector4 mBackgroundColor;             // Color of the background of the text input popup
-  Vector4 mBackgroundPressedColor;      // Color of the option background.
   Vector4 mLineColor;                   // Color of the line around the text input popup
   Vector4 mIconColor;                   // Color of the popup icon.
   Vector4 mIconPressedColor;            // Color of the popup icon when pressed.
-  Vector4 mTextColor;                   // Color of the popup text.
-  Vector4 mTextPressedColor;            // Color of the popup text when pressed.
 
   // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right.
   std::size_t mSelectOptionPriority;    // Position of Select Button
@@ -305,3 +264,4 @@ inline const Toolkit::Internal::TextSelectionPopup& GetImpl( const Toolkit::Text
 } // namespace Dali
 
 #endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__
+
diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp
new file mode 100644 (file)
index 0000000..4b25f77
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ * 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-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+#include <iostream>
+#include <libintl.h>
+#include <cfloat>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+const Dali::Vector2 DEFAULT_MAX_SIZE( 400.0f, 65.0f ); ///< The maximum size of the Toolbar.
+
+} // namespace
+
+BaseHandle Create()
+{
+  return Toolkit::TextSelectionToolbar::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextSelectionToolbar, Toolkit::Control, Create );
+
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionToolbar, "max-size", VECTOR2, MAX_SIZE )
+
+DALI_TYPE_REGISTRATION_END()
+
+Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New()
+{
+  // Create the implementation, temporarily owned by this handle on stack
+  IntrusivePtr< TextSelectionToolbar > impl = new TextSelectionToolbar();
+
+  // Pass ownership to CustomActor handle
+  Dali::Toolkit::TextSelectionToolbar handle( *impl );
+
+  // Second-phase init of the implementation
+  // This can only be done after the CustomActor connection has been made...
+  impl->Initialize();
+
+  return handle;
+}
+
+void TextSelectionToolbar::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+  Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast( Dali::BaseHandle( object ) );
+
+  if( selectionPopup )
+  {
+    TextSelectionToolbar& impl( GetImpl( selectionPopup ) );
+
+    switch( index )
+    {
+      case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
+      {
+       impl.SetPopupMaxSize( value.Get< Vector2 >() );
+       break;
+      }
+
+    } // switch
+  } // TextSelectionToolbar
+}
+
+Property::Value TextSelectionToolbar::GetProperty( BaseObject* object, Property::Index index )
+{
+  Property::Value value;
+
+  Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast( Dali::BaseHandle( object ) );
+
+  if( selectionPopup )
+  {
+    TextSelectionToolbar& impl( GetImpl( selectionPopup ) );
+
+    switch( index )
+    {
+      case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
+      {
+        value = impl.GetPopupMaxSize();
+        break;
+      }
+    } // switch
+  }
+  return value;
+}
+
+void TextSelectionToolbar::OnInitialize()
+{
+  SetUp();
+}
+
+void TextSelectionToolbar::SetPopupMaxSize( const Size& maxSize )
+{
+  mMaxSize = maxSize;
+}
+
+const Dali::Vector2& TextSelectionToolbar::GetPopupMaxSize() const
+{
+  return mMaxSize;
+}
+
+void TextSelectionToolbar::SetUp()
+{
+  Actor self = Self();
+  self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+
+  // Create Layer and Stencil.
+  mStencilLayer = Layer::New();
+  mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+  mStencilLayer.SetParentOrigin( ParentOrigin::CENTER );
+  mStencilLayer.SetMaximumSize( mMaxSize );
+
+  ImageActor stencil = CreateSolidColorActor( Color::RED );
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stencil.SetVisible( true );
+  stencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+  stencil.SetParentOrigin( ParentOrigin::CENTER );
+
+  Actor scrollview = Actor::New(); //todo make a scrollview
+  scrollview.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+  scrollview.SetParentOrigin( ParentOrigin::CENTER );
+
+  // Toolbar needs at least one option, adding further options with increase it's size
+  mTableOfButtons = Dali::Toolkit::TableView::New( 1, 1 );
+  mTableOfButtons.SetFitHeight( 0 );
+  mTableOfButtons.SetParentOrigin( ParentOrigin::CENTER );
+
+  mStencilLayer.Add( stencil );
+  mStencilLayer.Add( scrollview );
+  scrollview.Add( mTableOfButtons );
+  self.Add( mStencilLayer );
+
+  mStencilLayer.RaiseToTop();
+}
+
+void TextSelectionToolbar::AddOption( Actor& option )
+{
+  mTableOfButtons.AddChild( option, Toolkit::TableView::CellPosition( 0, mIndexInTable )  );
+  mTableOfButtons.SetFitWidth( mIndexInTable );
+  mIndexInTable++;
+}
+
+void TextSelectionToolbar::AddDivider( Actor& divider )
+{
+  AddOption( divider );
+  mDividerIndexes.PushBack( mIndexInTable );
+}
+
+void TextSelectionToolbar::ResizeDividers( Size& size )
+{
+  for( unsigned int i = 0; i < mDividerIndexes.Count(); ++i )
+  {
+    Actor divider = mTableOfButtons.GetChildAt( Toolkit::TableView::CellPosition( 0, mDividerIndexes[ i ] ) );
+    divider.SetSize( size );
+  }
+  RelayoutRequest();
+}
+
+TextSelectionToolbar::TextSelectionToolbar()
+: Control( ControlBehaviour( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ) ),
+  mMaxSize ( DEFAULT_MAX_SIZE ),
+  mIndexInTable( 0 ),
+  mDividerIndexes()
+{
+}
+
+TextSelectionToolbar::~TextSelectionToolbar()
+{
+}
+
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h
new file mode 100644 (file)
index 0000000..fb85e95
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_H__
+
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/table-view/table-view.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+} // namespace
+
+class TextSelectionToolbar : public Control
+{
+public:
+
+  /**
+   * @copydoc Dali::Toollkit::TextSelectionToolbar::New()
+   */
+  static Toolkit::TextSelectionToolbar New();
+
+  // Properties
+
+  /**
+   * @brief Called when a property of an object of this type is set.
+   * @param[in] object The object whose property is set.
+   * @param[in] index The property index.
+   * @param[in] value The new property value.
+   */
+  static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value );
+
+  /**
+   * @brief Called to retrieve a property of an object of this type.
+   *
+   * @param[in] object The object whose property is to be retrieved.
+   * @param[in] index The property index.
+   * @return The current value of the property.
+   */
+  static Property::Value GetProperty( BaseObject* object, Property::Index index );
+
+  /**
+   *  @copydoc TextSelectionToolbar::AddOption
+   */
+  void AddOption( Actor& option );
+
+  /**
+   *  @copydoc TextSelectionToolbar::AddDivider
+   */
+  void AddDivider( Actor& divider );
+
+  /**
+   * @copydoc ResizeDividers
+   */
+  void ResizeDividers( Size& size );
+
+private: // From Control
+
+  /**
+   * @copydoc Control::OnInitialize()
+   */
+ virtual void OnInitialize();
+
+  /**
+   * @brief Set max size of Popup
+   * @param[in] maxSize Size (Vector2)
+   */
+  void SetPopupMaxSize( const Size& maxSize );
+
+  /**
+   * @brief Get Max size of Popup
+   * @return Vector2 the max size of the Popup
+   */
+  const Dali::Vector2& GetPopupMaxSize() const;
+
+  /**
+   * @brief Set up the parts that make the Toolbar
+   */
+  void SetUp();
+
+private: // Implementation
+
+  /**
+   * Construct a new TextField.
+   */
+  TextSelectionToolbar();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~TextSelectionToolbar();
+
+private:
+
+  // Undefined copy constructor and assignment operators
+  TextSelectionToolbar(const TextSelectionToolbar&);
+  TextSelectionToolbar& operator=(const TextSelectionToolbar& rhs);
+
+private: // Data
+
+  Dali::Toolkit::TableView mTableOfButtons;           // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
+  Layer mStencilLayer;                                // Layer to enable clipping when buttons exceed popup
+
+  Size mMaxSize;                                      // Max size of the Toolbar
+  unsigned int mIndexInTable;                         // Index in table to add option
+  Dali::Vector< unsigned int > mDividerIndexes;       // Vector of indexes in the Toolbar that contain dividers.
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Toolkit::Internal::TextSelectionToolbar& GetImpl( Toolkit::TextSelectionToolbar& textSelectionToolbar )
+{
+  DALI_ASSERT_ALWAYS( textSelectionToolbar );
+
+  Dali::RefObject& handle = textSelectionToolbar.GetImplementation();
+
+  return static_cast<Toolkit::Internal::TextSelectionToolbar&>(handle);
+}
+
+inline const Toolkit::Internal::TextSelectionToolbar& GetImpl( const Toolkit::TextSelectionToolbar& textSelectionToolbar )
+{
+  DALI_ASSERT_ALWAYS( textSelectionToolbar );
+
+  const Dali::RefObject& handle = textSelectionToolbar.GetImplementation();
+
+  return static_cast<const Toolkit::Internal::TextSelectionToolbar&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_H__
index c1536f0..f5a9b35 100644 (file)
@@ -46,6 +46,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/controls/text-controls/text-field-impl.cpp \
    $(toolkit_src_dir)/controls/text-controls/text-label-impl.cpp \
    $(toolkit_src_dir)/controls/text-controls/text-selection-popup-impl.cpp \
+   $(toolkit_src_dir)/controls/text-controls/text-selection-toolbar-impl.cpp \
    $(toolkit_src_dir)/controls/tool-bar/tool-bar-impl.cpp \
    $(toolkit_src_dir)/focus-manager/accessibility-focus-manager-impl.cpp \
    $(toolkit_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \
index 0be65d3..447a73b 100644 (file)
@@ -23,7 +23,7 @@
 #include <dali/public-api/actors/layer.h>
 #include <dali/devel-api/adaptor-framework/accessibility-manager.h>
 #include <dali/devel-api/adaptor-framework/sound-player.h>
-#include <dali/devel-api/adaptor-framework/tts-player.h>
+#include <dali/public-api/adaptor-framework/tts-player.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/devel-api/events/hit-test-algorithm.h>
 #include <dali/public-api/images/resource-image.h>
index b1b9993..67c294b 100644 (file)
@@ -24,6 +24,9 @@ namespace Dali
 namespace Toolkit
 {
 
+namespace Text
+{
+
 namespace
 {
   const static uint8_t U1 = 1u;
@@ -222,6 +225,8 @@ void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std:
   Utf32ToUtf8( utf32, numberOfCharacters, reinterpret_cast<uint8_t*>(&utf8[0]) );
 }
 
+} // namespace Text
+
 } // namespace Toolkit
 
 } // namespace Dali
index 19784fb..720114b 100644 (file)
@@ -31,6 +31,9 @@ namespace Dali
 namespace Toolkit
 {
 
+namespace Text
+{
+
 /**
  * @brief Retrieves the number of characters of the text array encoded in UTF8
  *
@@ -86,6 +89,8 @@ uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters,
  */
 void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 );
 
+} // namespace Text
+
 } // namespace Toolkit
 
 } // namespace Dali
index d1c38e2..e75009d 100644 (file)
@@ -60,7 +60,8 @@ struct LineLayout
     numberOfGlyphs( 0u ),
     numberOfCharacters( 0u ),
     length( 0.f ),
-    widthAdvanceDiff( 0.f ),
+    extraBearing( 0.f ),
+    extraWidth( 0.f ),
     wsLengthEndOfLine( 0.f ),
     ascender( 0.f ),
     descender( MAX_FLOAT )
@@ -76,7 +77,8 @@ struct LineLayout
     numberOfGlyphs = 0u;
     numberOfCharacters = 0u;
     length = 0.f;
-    widthAdvanceDiff = 0.f;
+    extraBearing = 0.f;
+    extraWidth = 0.f;
     wsLengthEndOfLine = 0.f;
     ascender = 0.f;
     descender = MAX_FLOAT;
@@ -86,8 +88,9 @@ struct LineLayout
   CharacterIndex characterIndex;     ///< Index of the first character to be laid-out.
   Length         numberOfGlyphs;     ///< The number of glyph which fit in one line.
   Length         numberOfCharacters; ///< The number of characters which fit in one line.
-  float          length;             ///< The length of the glyphs which fit in one line.
-  float          widthAdvanceDiff;   ///< The difference between the xBearing + width and the advance of the last glyph.
+  float          length;             ///< The addition of the advance metric of all the glyphs which fit in one line.
+  float          extraBearing;       ///< The extra width to be added to the line's length when the bearing of the first glyph is negative.
+  float          extraWidth;         ///< The extra width to be added to the line's length when the bearing + width of the last glyph is greater than the advance.
   float          wsLengthEndOfLine;  ///< The length of the white spaces at the end of the line.
   float          ascender;           ///< The maximum ascender of all fonts in the line.
   float          descender;          ///< The minimum descender of all fonts in the line.
@@ -146,7 +149,6 @@ struct LayoutEngine::Impl
       lineLayout.length += lineLayout.wsLengthEndOfLine;
 
       lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
-      lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
     }
     else
     {
@@ -167,12 +169,23 @@ struct LayoutEngine::Impl
   /**
    * Retrieves the line layout for a given box width.
    *
+   * @note This method lais out text as it were left to right. At this point is not possible to reorder the line
+   *       because the number of characters of the line is not known (one of the responsabilities of this method
+   *       is calculate that). Due to glyph's 'x' bearing, width and advance, when right to left or mixed right to left
+   *       and left to right text is laid out, it can be small differences in the line length. One solution is to
+   *       reorder and re-lay out the text after this method and add or remove one extra glyph if needed. However,
+   *       this method calculates which are the first and last glyphs of the line (the ones that causes the
+   *       differences). This is a good point to check if there is problems with the text exceeding the boundaries
+   *       of the control when there is right to left text.
+   *
    * @param[in] parameters The layout parameters.
    * @param[out] lineLayout The line layout.
+   * @param[in,out] paragraphDirection in: the current paragraph's direction, out: the next paragraph's direction. Is set after a must break.
    * @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
    */
   void GetLineLayoutForBox( const LayoutParameters& parameters,
                             LineLayout& lineLayout,
+                            CharacterDirection& paragraphDirection,
                             bool completelyFill )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n" );
@@ -184,38 +197,26 @@ struct LayoutEngine::Impl
     const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
 
     // If the first glyph has a negative bearing its absolute value needs to be added to the line length.
-    // In the case the line starts with a right to left character the bearing needs to be substracted to the line length.
+    // In the case the line starts with a right to left character, if the width is longer than the advance,
+    // the difference needs to be added to the line length.
     const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + lineLayout.glyphIndex );
-    float initialHorizontalBearing = glyphInfo.xBearing;
 
+    // Set the direction of the first character of the line.
     lineLayout.characterIndex = *( parameters.glyphsToCharactersBuffer + lineLayout.glyphIndex );
     const CharacterDirection firstCharacterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + lineLayout.characterIndex );
+    CharacterDirection previousCharacterDirection = firstCharacterDirection;
 
-    if( RTL == firstCharacterDirection )
-    {
-      initialHorizontalBearing = -initialHorizontalBearing;
+    const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+    float tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
 
-      if( 0.f < glyphInfo.xBearing )
-      {
-        tmpLineLayout.length = glyphInfo.xBearing;
-        initialHorizontalBearing = 0.f;
-      }
-    }
-    else
-    {
-      if( 0.f > glyphInfo.xBearing )
-      {
-        tmpLineLayout.length = -glyphInfo.xBearing;
-        initialHorizontalBearing = 0.f;
-      }
-    }
+    float tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+
+    tmpLineLayout.length += 1.f; // Added one unit to give some space to the cursor.
 
     // Calculate the line height if there is no characters.
     FontId lastFontId = glyphInfo.fontId;
     UpdateLineHeight( lastFontId, tmpLineLayout );
 
-    const float boundingBoxWidth = parameters.boundingBox.width - initialHorizontalBearing;
-
     bool oneWordLaidOut = false;
 
     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
@@ -253,7 +254,11 @@ struct LayoutEngine::Impl
 
       // Used to restore the temporal line layout when a single word does not fit in the control's width and is split by character.
       const float previousTmpLineLength = tmpLineLayout.length;
-      const float previousTmpWidthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
+      const float previousTmpExtraBearing = tmpExtraBearing;
+      const float previousTmpExtraWidth = tmpExtraWidth;
+
+      // Get the character's direction.
+      const CharacterDirection characterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + characterFirstIndex );
 
       // Increase the accumulated length.
       if( isWhiteSpace )
@@ -265,13 +270,82 @@ struct LayoutEngine::Impl
       {
         // Add as well any previous white space length.
         tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance;
-        if( RTL == firstCharacterDirection )
+
+        // An extra space may be added to the line for the first and last glyph of the line.
+        // If the bearing of the first glyph is negative, its positive value needs to be added.
+        // If the bearing plus the width of the last glyph is greater than the advance, the difference
+        // needs to be added.
+
+        if( characterDirection == paragraphDirection )
         {
-          tmpLineLayout.widthAdvanceDiff = -glyphInfo.xBearing;
+          if( RTL == characterDirection )
+          {
+            //       <--
+            // |   Rrrrr|
+            // or
+            // |  Rllrrr|
+            // or
+            // |lllrrrrr|
+            // |     Rll|
+            //
+
+            tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+          }
+          else // LTR
+          {
+            //  -->
+            // |lllL    |
+            // or
+            // |llrrL   |
+            // or
+            // |lllllrrr|
+            // |rrL     |
+            //
+
+            const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+            tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+          }
         }
         else
         {
-          tmpLineLayout.widthAdvanceDiff = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+          if( characterDirection != previousCharacterDirection )
+          {
+            if( RTL == characterDirection )
+            {
+              //  -->
+              // |lllR    |
+
+              const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+              tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+            }
+            else // LTR
+            {
+              //       <--
+              // |   Lrrrr|
+
+              tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+            }
+          }
+          else if( characterDirection == firstCharacterDirection )
+          {
+            if( RTL == characterDirection )
+            {
+              //  -->
+              // |llllllrr|
+              // |Rr      |
+
+              tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+            }
+            else // LTR
+            {
+              //       <--
+              // |llllrrrr|
+              // |     llL|
+
+              const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+              tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+            }
+          }
         }
 
         // Clear the white space length at the end of the line.
@@ -280,7 +354,7 @@ struct LayoutEngine::Impl
 
       // Check if the accumulated length fits in the width of the box.
       if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
-          ( lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff > boundingBoxWidth ) )
+          ( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
       {
         // Current word does not fit in the box's width.
         if( !oneWordLaidOut || completelyFill )
@@ -293,7 +367,8 @@ struct LayoutEngine::Impl
             tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
             --tmpLineLayout.numberOfGlyphs;
             tmpLineLayout.length = previousTmpLineLength;
-            tmpLineLayout.widthAdvanceDiff = previousTmpWidthAdvanceDiff;
+            tmpExtraBearing = previousTmpExtraBearing;
+            tmpExtraWidth = previousTmpExtraWidth;
           }
 
           // Add part of the word to the line layout.
@@ -303,7 +378,12 @@ struct LayoutEngine::Impl
         {
           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  Current word does not fit.\n" );
         }
-        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
+
+        lineLayout.extraBearing = tmpExtraBearing;
+        lineLayout.extraWidth = tmpExtraWidth;
+
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox.\n" );
+
         return;
       }
 
@@ -313,6 +393,16 @@ struct LayoutEngine::Impl
         // Must break the line. Update the line layout and return.
         MergeLineLayout( lineLayout, tmpLineLayout );
 
+        // Set the next paragraph's direction.
+        if( !isLastGlyph &&
+            ( NULL != parameters.characterDirectionBuffer ) )
+        {
+          paragraphDirection = *( parameters.characterDirectionBuffer + 1u + characterLastIndex );
+        }
+
+        lineLayout.extraBearing = tmpExtraBearing;
+        lineLayout.extraWidth = tmpExtraWidth;
+
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  Must break\n" );
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
         return;
@@ -338,7 +428,13 @@ struct LayoutEngine::Impl
         UpdateLineHeight( glyphInfo.fontId, tmpLineLayout );
         lastFontId = glyphInfo.fontId;
       }
+
+      previousCharacterDirection = characterDirection;
     }
+
+    lineLayout.extraBearing = tmpExtraBearing;
+    lineLayout.extraWidth = tmpExtraWidth;
+
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
   }
 
@@ -352,13 +448,10 @@ struct LayoutEngine::Impl
     // Check if the x bearing of the first character is negative.
     // If it has a negative x bearing, it will exceed the boundaries of the actor,
     // so the penX position needs to be moved to the right.
-    float penX = 0.f;
 
     const GlyphInfo& glyph = *glyphsBuffer;
-    if( 0.f > glyph.xBearing )
-    {
-      penX = -glyph.xBearing;
-    }
+    float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+    penX += 1.f; // Added one unit to give some space to the cursor.
 
     for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
     {
@@ -380,14 +473,20 @@ struct LayoutEngine::Impl
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" );
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height );
 
+    // Set the first paragraph's direction.
+    CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL;
+
     float penY = 0.f;
     for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
     {
+      CharacterDirection currentParagraphDirection = paragraphDirection;
+
       // Get the layout for the line.
       LineLayout layout;
       layout.glyphIndex = index;
       GetLineLayoutForBox( layoutParameters,
                            layout,
+                           paragraphDirection,
                            false );
 
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "           glyph index %d\n", layout.glyphIndex );
@@ -411,7 +510,7 @@ struct LayoutEngine::Impl
       if( mEllipsisEnabled &&
           ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
             ( ( mLayout == SINGLE_LINE_BOX ) &&
-              ( layout.length + layout.widthAdvanceDiff > layoutParameters.boundingBox.width ) ) ) )
+              ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) ) )
       {
         // Do not layout more lines if ellipsis is enabled.
 
@@ -439,15 +538,16 @@ struct LayoutEngine::Impl
 
         GetLineLayoutForBox( layoutParameters,
                              ellipsisLayout,
+                             currentParagraphDirection,
                              true );
 
         lineRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
         lineRun.characterRun.characterIndex = ellipsisLayout.characterIndex;
         lineRun.characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
-        lineRun.width = layoutParameters.boundingBox.width;
+        lineRun.width = ellipsisLayout.length;
+        lineRun.extraLength =  ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f;
         lineRun.ascender = ellipsisLayout.ascender;
         lineRun.descender = ellipsisLayout.descender;
-        lineRun.extraLength = ellipsisLayout.wsLengthEndOfLine > 0.f ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.widthAdvanceDiff : 0.f;
         lineRun.ellipsis = true;
 
         actualSize.width = layoutParameters.boundingBox.width;
@@ -473,15 +573,34 @@ struct LayoutEngine::Impl
       }
       else
       {
+        const bool isLastLine = index + layout.numberOfGlyphs == layoutParameters.totalNumberOfGlyphs;
+
         LineRun lineRun;
         lineRun.glyphIndex = index;
         lineRun.numberOfGlyphs = layout.numberOfGlyphs;
         lineRun.characterRun.characterIndex = layout.characterIndex;
         lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
-        lineRun.width = layout.length + layout.widthAdvanceDiff;
+        if( isLastLine )
+        {
+          const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
+          if( MULTI_LINE_BOX == mLayout )
+          {
+            lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
+          }
+          else
+          {
+            lineRun.width = width;
+          }
+
+          lineRun.extraLength = 0.f;
+        }
+        else
+        {
+          lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
+          lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+        }
         lineRun.ascender = layout.ascender;
         lineRun.descender = layout.descender;
-        lineRun.extraLength = layout.wsLengthEndOfLine > 0.f ? layout.wsLengthEndOfLine - layout.widthAdvanceDiff : 0.f;
         lineRun.direction = false;
         lineRun.ellipsis = false;
 
@@ -508,6 +627,7 @@ struct LayoutEngine::Impl
     }
 
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
+
     return true;
   }
 
@@ -519,12 +639,11 @@ struct LayoutEngine::Impl
     {
       const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer + lineIndex );
 
-      float penX = 0.f;
-
       const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap;
       const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) );
 
-      penX = -glyph.xBearing;
+      float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+      penX += 1.f; // Added one unit to give some space to the cursor.
 
       Vector2* glyphPositionsBuffer = glyphPositions.Begin();
 
@@ -556,76 +675,36 @@ struct LayoutEngine::Impl
     }
   }
 
-  void Align( const LayoutParameters& layoutParameters,
-              const Size& layoutSize,
-              const Vector<LineRun>& lines,
-              Vector<Vector2>& glyphPositions )
+  void Align( const Size& layoutSize,
+              Vector<LineRun>& lines )
   {
-    Vector2* glyphPositionsBuffer = glyphPositions.Begin();
-
     // Traverse all lines and align the glyphs.
-    // LayoutParameters contains bidirectional info for those lines with
-    // right to left text, this info includes the paragraph's direction.
 
-    LineIndex bidiLineIndex = 0u;
-    for( Vector<LineRun>::ConstIterator it = lines.Begin(), endIt = lines.End();
+    for( Vector<LineRun>::Iterator it = lines.Begin(), endIt = lines.End();
          it != endIt;
          ++it )
     {
-      const LineRun& line = *it;
-
-      // 1) Get the paragrap's direction.
-      bool paragraphDirection = false;
-
-      // Check if there is any right to left line.
-      if( ( NULL != layoutParameters.lineBidirectionalInfoRunsBuffer ) &&
-          ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) )
-      {
-        const BidirectionalLineInfoRun* bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex;
-
-        // Get the right to left line that match with current line.
-        while( ( line.characterRun.characterIndex > bidiLine->characterRun.characterIndex ) &&
-               ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) )
-        {
-          ++bidiLineIndex;
-          bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex;
-        }
-
-        if( line.characterRun.characterIndex == bidiLine->characterRun.characterIndex )
-        {
-          paragraphDirection = bidiLine->direction;
-        }
-      }
-
-      // 2) Calculate the alignment offset accordingly with the align option,
-      //    the box width, line length, and the paragraphs direction.
-      float alignOffset = CalculateHorizontalAlignment( layoutSize.width,
-                                                        line.width,
-                                                        line.extraLength,
-                                                        paragraphDirection );
-
-      // 3) Traverse all glyphs and update the 'x' position.
-      for( GlyphIndex index = line.glyphIndex,
-             endIndex = line.glyphIndex + line.numberOfGlyphs;
-           index < endIndex;
-           ++index )
-      {
-        Vector2& position = *( glyphPositionsBuffer + index );
-
-        position.x += alignOffset;
-      }
+      LineRun& line = *it;
+      const bool isLastLine = lines.End() == it + 1u;
+
+      // Calculate the alignment offset accordingly with the align option,
+      // the box width, line length, and the paragraphs direction.
+      CalculateHorizontalAlignment( layoutSize.width,
+                                    line,
+                                    isLastLine );
     }
   }
 
-  float CalculateHorizontalAlignment( float boxWidth,
-                                      float lineLength,
-                                      float extraLength,
-                                      bool paragraphDirection )
+  void CalculateHorizontalAlignment( float boxWidth,
+                                     LineRun& line,
+                                     bool isLastLine )
   {
-    float offset = 0.f;
+    line.alignmentOffset = 0.f;
+    const bool isRTL = RTL == line.direction;
+    float lineLength = line.width;
 
     HorizontalAlignment alignment = mHorizontalAlignment;
-    if( paragraphDirection &&
+    if( isRTL &&
         ( HORIZONTAL_ALIGN_CENTER != alignment ) )
     {
       if( HORIZONTAL_ALIGN_BEGIN == alignment )
@@ -642,29 +721,69 @@ struct LayoutEngine::Impl
     {
       case HORIZONTAL_ALIGN_BEGIN:
       {
-        offset = 0.f;
+        line.alignmentOffset = 0.f;
+
+        if( isRTL )
+        {
+          // 'Remove' the white spaces at the end of the line (which are at the beginning in visual order)
+          line.alignmentOffset -= line.extraLength;
+
+          if( isLastLine )
+          {
+            line.alignmentOffset += std::min( line.extraLength, boxWidth - lineLength );
+          }
+        }
         break;
       }
       case HORIZONTAL_ALIGN_CENTER:
       {
-        offset = 0.5f * ( boxWidth - lineLength );
-        const int intOffset = static_cast<int>( offset ); // try to avoid pixel alignment.
-        offset = static_cast<float>( intOffset );
+        if( isLastLine && !isRTL )
+        {
+          lineLength += line.extraLength;
+          if( lineLength > boxWidth )
+          {
+            lineLength = boxWidth;
+            line.alignmentOffset = 0.f;
+            break;
+          }
+        }
+
+        line.alignmentOffset = 0.5f * ( boxWidth - lineLength );
+
+        if( isRTL )
+        {
+          line.alignmentOffset -= line.extraLength;
+
+          if( isLastLine )
+          {
+            line.alignmentOffset += 0.5f * std::min( line.extraLength, boxWidth - lineLength );
+          }
+        }
+
+        line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
         break;
       }
       case HORIZONTAL_ALIGN_END:
       {
-        offset = boxWidth - lineLength;
+        if( isLastLine && !isRTL )
+        {
+          lineLength += line.extraLength;
+          if( lineLength > boxWidth )
+          {
+            line.alignmentOffset = 0.f;
+            break;
+          }
+        }
+
+        if( isRTL )
+        {
+          lineLength += line.extraLength;
+        }
+
+        line.alignmentOffset = boxWidth - lineLength;
         break;
       }
     }
-
-    if( paragraphDirection )
-    {
-      offset -= extraLength;
-    }
-
-    return offset;
   }
 
   LayoutEngine::Layout mLayout;
@@ -745,15 +864,11 @@ void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParam
                                    glyphPositions );
 }
 
-void LayoutEngine::Align( const LayoutParameters& layoutParameters,
-                          const Size& layoutSize,
-                          const Vector<LineRun>& lines,
-                          Vector<Vector2>& glyphPositions )
+void LayoutEngine::Align( const Size& layoutSize,
+                          Vector<LineRun>& lines )
 {
-  mImpl->Align( layoutParameters,
-                layoutSize,
-                lines,
-                glyphPositions );
+  mImpl->Align( layoutSize,
+                lines );
 }
 
 } // namespace Text
index 42ff1aa..e48de90 100644 (file)
@@ -158,15 +158,11 @@ public:
   /**
    * @brief Aligns the laid out lines.
    *
-   * @param[in] layoutParameters The parameters needed to layout the text.
    * @param[in] layoutSize The size of the laid out the text.
-   * @param[in] lines The laid-out lines.
-   * @param[in,out] glyphPositions The positions of all the glyphs.
+   * @param[in,out] lines The laid-out lines.
    */
-  void Align( const LayoutParameters& layoutParameters,
-              const Size& layoutSize,
-              const Vector<LineRun>& lines,
-              Vector<Vector2>& glyphPositions );
+  void Align( const Size& layoutSize,
+              Vector<LineRun>& lines );
 
 private:
 
index 5668669..584d758 100644 (file)
@@ -38,15 +38,16 @@ namespace Text
  */
 struct LineRun
 {
-  GlyphIndex         glyphIndex;     ///< The initial glyph index.
-  Length             numberOfGlyphs; ///< The number of glyphs of the run.
-  CharacterRun       characterRun;   ///< The initial character and the number of characters.
-  float              width;          ///< The line's width.
-  float              ascender;       ///< The line's ascender.
-  float              descender;      ///< The line's descender.
-  float              extraLength;    ///< The length of the white spaces at the end of the line.
-  CharacterDirection direction : 1;  ///< Direction of the first character of the paragraph.
-  bool               ellipsis  : 1;  ///< Wheter ellipsis is added to the line.
+  GlyphIndex         glyphIndex;      ///< The initial glyph index.
+  Length             numberOfGlyphs;  ///< The number of glyphs of the run.
+  CharacterRun       characterRun;    ///< The initial character and the number of characters.
+  float              width;           ///< The line's width.
+  float              ascender;        ///< The line's ascender.
+  float              descender;       ///< The line's descender.
+  float              extraLength;     ///< The length of the white spaces at the end of the line.
+  float              alignmentOffset; ///< The horizontal alignment offset.
+  CharacterDirection direction : 1;   ///< Direction of the first character of the paragraph.
+  bool               ellipsis  : 1;   ///< Wheter ellipsis is added to the line.
 };
 
 } // namespace Text
index 47db1e2..2d2352e 100644 (file)
@@ -126,24 +126,6 @@ Script GetScript( Length index,
   return script;
 }
 
-/**
- * @brief Whether the character is valid for all scripts. i.e. the white space.
- *
- * @param[in] character The character.
- *
- * @return @e true if the character is valid for all scripts.
- */
-bool IsValidForAllScripts( Character character )
-{
-  return ( TextAbstraction::IsWhiteSpace( character )         ||
-           TextAbstraction::IsZeroWidthNonJoiner( character ) ||
-           TextAbstraction::IsZeroWidthJoiner( character )    ||
-           TextAbstraction::IsZeroWidthSpace( character )     ||
-           TextAbstraction::IsLeftToRightMark( character )    ||
-           TextAbstraction::IsRightToLeftMark( character )    ||
-           TextAbstraction::IsThinSpace( character ) );
-}
-
 bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const
 {
   for( Vector<FontId>::ConstIterator it = mValidFonts.Begin(),
@@ -262,7 +244,7 @@ void MultilanguageSupport::SetScripts( const Vector<Character>& text,
     // Skip those characters valid for many scripts like white spaces or '\n'.
     bool endOfText = index == numberOfCharacters;
     while( !endOfText &&
-           IsValidForAllScripts( character ) )
+           TextAbstraction::IsCommonScript( character ) )
     {
       // Count all these characters to be added into a script.
       ++numberOfAllScriptCharacters;
@@ -374,10 +356,12 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
                                           const Vector<ScriptRun>& scripts,
                                           Vector<FontRun>& fonts )
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->MultilanguageSupport::ValidateFonts\n" );
   const Length numberOfCharacters = text.Count();
 
   if( 0u == numberOfCharacters )
   {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
     // Nothing to do if there are no characters.
     return;
   }
@@ -427,6 +411,20 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
                                scriptRunIt,
                                scriptRunEndIt );
 
+#ifdef DEBUG_ENABLED
+    {
+      Dali::TextAbstraction::FontDescription description;
+      fontClient.GetDescription( fontId, description );
+
+      DALI_LOG_INFO( gLogFilter,
+                     Debug::Verbose,
+                     "  Initial font set\n  Character : %x, Script : %s, Font : %s \n",
+                     character,
+                     Dali::TextAbstraction::ScriptName[script],
+                     description.path.c_str() );
+    }
+#endif
+
     if( TextAbstraction::UNKNOWN == script )
     {
       DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" );
@@ -436,6 +434,11 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     // Whether the font being validated is a default one not set by the user.
     const bool isDefault = ( 0u == fontId );
 
+    DALI_LOG_INFO( gLogFilter,
+                   Debug::Verbose,
+                   "  Is a default font : %s\n",
+                   ( isDefault ? "true" : "false" ) );
+
     // The default font point size.
     PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
 
@@ -488,6 +491,26 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
             else
             {
               // Add the font to the valid font cache.
+
+              //   At this point the validated font supports the given character. However, characters
+              // common for all scripts, like white spaces or new paragraph characters, need to be
+              // processed differently.
+              //
+              //   i.e. A white space can have assigned a DEVANAGARI script but the font assigned may not
+              // support none of the DEVANAGARI glyphs. This font can't be added to the cache as a valid
+              // font for the DEVANAGARI script but the COMMON one.
+              if( TextAbstraction::IsCommonScript( character ) )
+              {
+                validateFontsPerScript = *( validFontsPerScriptCacheBuffer + TextAbstraction::COMMON );
+
+                if( NULL == validateFontsPerScript )
+                {
+                  validateFontsPerScript = new ValidateFontsPerScript();
+
+                  *( validFontsPerScriptCacheBuffer + TextAbstraction::COMMON ) = validateFontsPerScript;
+                }
+              }
+
               validateFontsPerScript->mValidFonts.PushBack( fontId );
             }
           }
@@ -520,16 +543,24 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
           fontId = fontClient.FindDefaultFont( UTF32_A, pointSize );
         }
 
-#ifdef DEBUG_ENABLED
-        Dali::TextAbstraction::FontDescription description;
-        fontClient.GetDescription( fontId, description );
-        DALI_LOG_INFO( gLogFilter, Debug::Concise, "Script: %s; Selected font: %s\n", Dali::TextAbstraction::ScriptName[script], description.path.c_str() );
-#endif
         // Cache the font.
         *( defaultFontPerScriptCacheBuffer + script ) = fontId;
       }
     }
 
+#ifdef DEBUG_ENABLED
+    {
+      Dali::TextAbstraction::FontDescription description;
+      fontClient.GetDescription( fontId, description );
+      DALI_LOG_INFO( gLogFilter,
+                     Debug::Verbose,
+                     "  Validated font set\n  Character : %x, Script : %s, Font : %s \n",
+                     character,
+                     Dali::TextAbstraction::ScriptName[script],
+                     description.path.c_str() );
+    }
+#endif
+
     // The font is now validated.
 
     if( ( fontId != currentFontRun.fontId ) ||
@@ -559,6 +590,7 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     // Store the last run.
     fonts.PushBack( currentFontRun );
   }
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
 }
 
 void MultilanguageSupport::ValidateFonts( LogicalModel& model,
index 35c43b0..2d84c2d 100644 (file)
@@ -128,14 +128,15 @@ EventData::EventData( DecoratorPtr decorator )
   mDecoratorUpdated( false ),
   mCursorBlinkEnabled( true ),
   mGrabHandleEnabled( true ),
-  mGrabHandlePopupEnabled( false ),
+  mGrabHandlePopupEnabled( true ),
   mSelectionEnabled( false ),
   mHorizontalScrollingEnabled( true ),
   mVerticalScrollingEnabled( false ),
   mUpdateCursorPosition( false ),
   mUpdateLeftSelectionPosition( false ),
   mUpdateRightSelectionPosition( false ),
-  mScrollAfterUpdateCursorPosition( false )
+  mScrollAfterUpdateCursorPosition( false ),
+  mScrollAfterDelete( false )
 {}
 
 EventData::~EventData()
@@ -201,6 +202,12 @@ bool Controller::Impl::ProcessInputEvents()
     mEventData->mDecoratorUpdated = true;
     mEventData->mUpdateCursorPosition = false;
   }
+  else if( mEventData->mScrollAfterDelete )
+  {
+    ScrollTextToMatchCursor();
+    mEventData->mDecoratorUpdated = true;
+    mEventData->mScrollAfterDelete = false;
+  }
   else if( mEventData->mUpdateLeftSelectionPosition )
   {
     UpdateSelectionHandle( LEFT_SELECTION_HANDLE );
@@ -525,7 +532,7 @@ void Controller::Impl::OnHandleEvent( const Event& event )
 
     if( Event::GRAB_HANDLE_EVENT == event.type )
     {
-      ChangeState ( EventData::EDITING );
+      ChangeState ( EventData::GRAB_HANDLE_PANNING );
 
       if( handleNewPosition != mEventData->mPrimaryCursorPosition )
       {
@@ -535,6 +542,8 @@ void Controller::Impl::OnHandleEvent( const Event& event )
     }
     else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
     {
+      ChangeState ( EventData::SELECTION_HANDLE_PANNING );
+
       if( handleNewPosition != mEventData->mLeftSelectionPosition )
       {
         mEventData->mLeftSelectionPosition = handleNewPosition;
@@ -543,6 +552,8 @@ void Controller::Impl::OnHandleEvent( const Event& event )
     }
     else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
     {
+      ChangeState ( EventData::SELECTION_HANDLE_PANNING );
+
       if( handleNewPosition != mEventData->mRightSelectionPosition )
       {
         mEventData->mRightSelectionPosition = handleNewPosition;
@@ -553,14 +564,12 @@ void Controller::Impl::OnHandleEvent( const Event& event )
   else if( ( HANDLE_RELEASED == state ) ||
            ( HANDLE_STOP_SCROLLING == state ) )
   {
-    if( mEventData->mGrabHandlePopupEnabled )
-    {
-      ChangeState( EventData::EDITING_WITH_POPUP );
-    }
     if( Event::GRAB_HANDLE_EVENT == event.type )
     {
       mEventData->mUpdateCursorPosition = true;
 
+      ChangeState( EventData::EDITING_WITH_POPUP );
+
       if( HANDLE_STOP_SCROLLING == state )
       {
         // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
@@ -572,6 +581,10 @@ void Controller::Impl::OnHandleEvent( const Event& event )
         mEventData->mScrollAfterUpdateCursorPosition = true;
       }
     }
+    else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type || Event::RIGHT_SELECTION_HANDLE_EVENT )
+    {
+      ChangeState( EventData::SELECTING );
+    }
     mEventData->mDecoratorUpdated = true;
   }
   else if( HANDLE_SCROLLING == state )
@@ -583,7 +596,16 @@ void Controller::Impl::OnHandleEvent( const Event& event )
 
     ClampHorizontalScroll( actualSize );
 
-   mEventData->mDecoratorUpdated = true;
+    if( Event::GRAB_HANDLE_EVENT == event.type )
+    {
+      ChangeState( EventData::GRAB_HANDLE_PANNING );
+    }
+    else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type || Event::RIGHT_SELECTION_HANDLE_EVENT )
+    {
+      ChangeState( EventData::SELECTION_HANDLE_PANNING );
+    }
+
+    mEventData->mDecoratorUpdated = true;
   }
 }
 
@@ -652,6 +674,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
       mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
       mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
       mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+      if( mEventData->mGrabHandlePopupEnabled )
+      {
+        mEventData->mDecorator->SetPopupActive( true );
+      }
       mEventData->mDecoratorUpdated = true;
     }
     else if( EventData::EDITING == mEventData->mState )
@@ -665,6 +691,10 @@ void Controller::Impl::ChangeState( EventData::State newState )
       mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
       mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
       mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+      if( mEventData->mGrabHandlePopupEnabled )
+      {
+        mEventData->mDecorator->SetPopupActive( false );
+      }
       mEventData->mDecoratorUpdated = true;
     }
     else if( EventData::EDITING_WITH_POPUP == mEventData->mState )
@@ -674,11 +704,14 @@ void Controller::Impl::ChangeState( EventData::State newState )
       {
         mEventData->mDecorator->StartCursorBlink();
       }
-      mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
       if( mEventData->mSelectionEnabled )
       {
-        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
-        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+        mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+        mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+      }
+      else
+      {
+        mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
       }
       if( mEventData->mGrabHandlePopupEnabled )
       {
@@ -686,6 +719,35 @@ void Controller::Impl::ChangeState( EventData::State newState )
       }
       mEventData->mDecoratorUpdated = true;
     }
+    else if ( EventData::SELECTION_HANDLE_PANNING == mEventData->mState )
+    {
+      mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
+      mEventData->mDecorator->StopCursorBlink();
+      mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
+      mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+      mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+      if( mEventData->mGrabHandlePopupEnabled )
+      {
+        mEventData->mDecorator->SetPopupActive( false );
+      }
+      mEventData->mDecoratorUpdated = true;
+    }
+    else if ( EventData::GRAB_HANDLE_PANNING == mEventData->mState )
+    {
+      mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
+      if( mEventData->mCursorBlinkEnabled )
+      {
+        mEventData->mDecorator->StartCursorBlink();
+      }
+      mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+      mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+      mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+      if( mEventData->mGrabHandlePopupEnabled )
+      {
+        mEventData->mDecorator->SetPopupActive( false );
+      }
+      mEventData->mDecoratorUpdated = true;
+    }
   }
 }
 
@@ -707,6 +769,11 @@ LineIndex Controller::Impl::GetClosestLine( float y ) const
     }
   }
 
+  if( lineIndex == 0 )
+  {
+    return 0;
+  }
+
   return lineIndex-1;
 }
 
@@ -1247,6 +1314,57 @@ void Controller::Impl::ScrollToMakeCursorVisible()
   // TODO : calculate the vertical scroll.
 }
 
+void Controller::Impl::ScrollTextToMatchCursor()
+{
+  // Get the current cursor position in decorator coords.
+  const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+  // Calculate the new cursor position.
+  CursorInfo cursorInfo;
+  GetCursorPosition( mEventData->mPrimaryCursorPosition,
+                     cursorInfo );
+
+  // Calculate the offset to match the cursor position before the character was deleted.
+  mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x;
+
+  ClampHorizontalScroll( mVisualModel->GetActualSize() );
+  bool updateCursorPosition = true;
+
+  const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
+  const Vector2 cursorPosition = cursorInfo.primaryPosition + offset;
+
+  if( updateCursorPosition )
+  {
+    // Sets the cursor position.
+    mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
+                                         cursorPosition.x,
+                                         cursorPosition.y,
+                                         cursorInfo.primaryCursorHeight,
+                                         cursorInfo.lineHeight );
+
+    // Sets the grab handle position.
+    mEventData->mDecorator->SetPosition( GRAB_HANDLE,
+                                         cursorPosition.x,
+                                         cursorPosition.y,
+                                         cursorInfo.lineHeight );
+
+    if( cursorInfo.isSecondaryCursor )
+    {
+      mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH );
+      mEventData->mDecorator->SetPosition( SECONDARY_CURSOR,
+                                           cursorInfo.secondaryPosition.x + offset.x,
+                                           cursorInfo.secondaryPosition.y + offset.y,
+                                           cursorInfo.secondaryCursorHeight,
+                                           cursorInfo.lineHeight );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y );
+    }
+    else
+    {
+      mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
+    }
+  }
+}
+
 void Controller::Impl::RequestRelayout()
 {
   mControlInterface.RequestTextRelayout();
index ab2764c..1a797b3 100644 (file)
@@ -100,7 +100,9 @@ struct EventData
     INACTIVE,
     SELECTING,
     EDITING,
-    EDITING_WITH_POPUP
+    EDITING_WITH_POPUP,
+    GRAB_HANDLE_PANNING,
+    SELECTION_HANDLE_PANNING
   };
 
   EventData( DecoratorPtr decorator );
@@ -146,6 +148,7 @@ struct EventData
   bool mUpdateLeftSelectionPosition        : 1;   ///< True if the visual position of the left selection handle must be recalculated.
   bool mUpdateRightSelectionPosition       : 1;   ///< True if the visual position of the right selection handle must be recalculated.
   bool mScrollAfterUpdateCursorPosition    : 1;   ///< Whether to scroll after the cursor position is updated.
+  bool mScrollAfterDelete                  : 1;   ///< Whether to scroll after delete characters.
 };
 
 struct ModifyEvent
@@ -394,10 +397,17 @@ struct Controller::Impl
   /**
    * @brief Scrolls the text to make the cursor visible.
    *
-   * This method is called after inserting, deleting or moving the cursor with the keypad.
+   * This method is called after inserting text or moving the cursor with the keypad.
    */
   void ScrollToMakeCursorVisible();
 
+  /**
+   * @brief Scrolls the text to make the cursor visible.
+   *
+   * This method is called after deleting text.
+   */
+  void ScrollTextToMatchCursor();
+
   ControlInterface& mControlInterface;     ///< Reference to the text controller.
   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
   VisualModelPtr  mVisualModel;            ///< Pointer to the visual model.
index 36b566b..26d7ef0 100644 (file)
@@ -337,8 +337,7 @@ bool Controller::RemoveText( int cursorOffset, int numberOfChars )
       numberOfChars = currentText.Count() - cursorIndex;
     }
 
-    if( cursorIndex >= 0 &&
-        (cursorIndex + numberOfChars) <= currentText.Count() )
+    if( (cursorIndex + numberOfChars) <= currentText.Count() )
     {
       Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
       Vector<Character>::Iterator last  = first + numberOfChars;
@@ -772,8 +771,7 @@ void Controller::TextDeletedEvent()
                                                            REORDER );
 
   // Queue a cursor reposition event; this must wait until after DoRelayout()
-  mImpl->mEventData->mUpdateCursorPosition = true;
-  mImpl->mEventData->mScrollAfterUpdateCursorPosition = true;
+  mImpl->mEventData->mScrollAfterDelete = true;
 }
 
 bool Controller::DoRelayout( const Size& size,
@@ -893,17 +891,6 @@ bool Controller::DoRelayout( const Size& size,
         }
       } // REORDER
 
-      // TODO: I'm working on a patch that changes the LayoutEngine::Align() method.
-      //       The layoutParameters is not needed and this call can be moved outside the if().
-      //       Then there is no need to do the layout again to change the alignment.
-      if( ALIGN & operations )
-      {
-        mImpl->mLayoutEngine.Align( layoutParameters,
-                                    layoutSize,
-                                    lines,
-                                    glyphPositions );
-      }
-
       // Sets the actual size.
       if( UPDATE_ACTUAL_SIZE & operations )
       {
@@ -916,6 +903,17 @@ bool Controller::DoRelayout( const Size& size,
     layoutSize = mImpl->mVisualModel->GetActualSize();
   }
 
+  if( ALIGN & operations )
+  {
+    // The laid-out lines.
+    Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+
+    mImpl->mLayoutEngine.Align( layoutSize,
+                                lines );
+
+    viewUpdated = true;
+  }
+
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) );
   return viewUpdated;
 }
@@ -954,15 +952,7 @@ void Controller::SetHorizontalAlignment( LayoutEngine::HorizontalAlignment align
     mImpl->mLayoutEngine.SetHorizontalAlignment( alignment );
 
     // Set the flag to redo the alignment operation.
-    // TODO : Is not needed re-layout and reorder again but with the current implementation it is.
-    //        Im working on a different patch to fix an issue with the alignment. When that patch
-    //        is in, this issue can be fixed.
-    const OperationsMask layoutOperations =  static_cast<OperationsMask>( LAYOUT             |
-                                                                          UPDATE_ACTUAL_SIZE |
-                                                                          ALIGN              |
-                                                                          REORDER );
-
-    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | layoutOperations );
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | ALIGN );
 
     mImpl->RequestRelayout();
   }
@@ -1122,6 +1112,9 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
     int keyCode = keyEvent.keyCode;
     const std::string& keyString = keyEvent.keyPressed;
 
+    // Hide the grab handle.
+    mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
+
     // Pre-process to separate modifying events from non-modifying input events.
     if( Dali::DALI_KEY_ESCAPE == keyCode )
     {
@@ -1149,14 +1142,15 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent )
 
       if( removed )
       {
-        if( 0u == mImpl->mLogicalModel->mText.Count() )
+        if( 0u != mImpl->mLogicalModel->mText.Count() ||
+            !mImpl->IsPlaceholderAvailable() )
         {
-          ShowPlaceholderText();
-          mImpl->mEventData->mUpdateCursorPosition = true;
+          mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
         }
         else
         {
-          mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
+          ShowPlaceholderText();
+          mImpl->mEventData->mUpdateCursorPosition = true;
         }
 
         textChanged = true;
index 47a2028..91ecadf 100644 (file)
@@ -92,6 +92,48 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
                                               glyphIndex,
                                               numberOfLaidOutGlyphs );
 
+      // Get the lines for the given range of glyphs.
+      // The lines contain the alignment offset which needs to be added to the glyph's position.
+      LineIndex firstLine = 0u;
+      Length numberOfLines = 0u;
+      mImpl->mVisualModel->GetNumberOfLines( glyphIndex,
+                                             numberOfLaidOutGlyphs,
+                                             firstLine,
+                                             numberOfLines );
+
+      Vector<LineRun> lines;
+      lines.Resize( numberOfLines );
+      LineRun* lineBuffer = lines.Begin();
+
+      mImpl->mVisualModel->GetLinesOfGlyphRange( lineBuffer,
+                                                 glyphIndex,
+                                                 numberOfLaidOutGlyphs );
+
+      // Get the first line for the given glyph range.
+      LineIndex lineIndex = firstLine;
+      LineRun* line = lineBuffer + lineIndex;
+
+      // Index of the last glyph of the line.
+      GlyphIndex lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+
+      // Add the alignment offset to the glyph's position.
+      for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
+      {
+        ( *( glyphPositions + index ) ).x += line->alignmentOffset;
+
+        if( lastGlyphIndexOfLine == index )
+        {
+          // Get the next line.
+          ++lineIndex;
+
+          if( lineIndex < numberOfLines )
+          {
+            line = lineBuffer + lineIndex;
+            lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+          }
+        }
+      }
+
       if( 1u == numberOfLaidOutGlyphs )
       {
         // not a point try to do ellipsis with only one laid out character.
@@ -151,7 +193,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
             {
               GlyphInfo& glyphInfo = *( glyphs + index );
               Vector2& position = *( glyphPositions + index );
-              position.x -= glyphInfo.xBearing;
+              position.x -= ( 0.f > glyphInfo.xBearing ) ? glyphInfo.xBearing : 0.f;
 
               // Replace the glyph by the ellipsis glyph.
               glyphInfo = ellipsisGlyph;
index 5f36226..beeb08b 100644 (file)
@@ -36,9 +36,9 @@ VisualModelPtr VisualModel::New()
   return VisualModelPtr( new VisualModel() );
 }
 
-void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
-                             const CharacterIndex* characterIndices,
-                             const Length* charactersPerGlyph,
+void VisualModel::SetGlyphs( const GlyphInfo* const glyphs,
+                             const CharacterIndex* const characterIndices,
+                             const Length* const charactersPerGlyph,
                              Length numberOfGlyphs )
 {
   if( 0u == numberOfGlyphs )
@@ -225,7 +225,7 @@ void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
   memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
 }
 
-void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
+void VisualModel::SetGlyphPositions( const Vector2* const glyphPositions,
                                      Length numberOfGlyphs )
 {
   if( 0u == numberOfGlyphs )
index fb9f7bc..227019f 100644 (file)
@@ -73,9 +73,9 @@ public:
    * @param[in] charactersPerGlyph An array containing the number of characters per glyph.
    * @param[in] numberOfGlyphs The number of glyphs.
    */
-  void SetGlyphs( const GlyphInfo* glyphs,
-                  const CharacterIndex* characterIndices,
-                  const Length* charactersPerGlyph,
+  void SetGlyphs( const GlyphInfo* const glyphs,
+                  const CharacterIndex* const characterIndices,
+                  const Length* const charactersPerGlyph,
                   Length numberOfGlyphs );
 
   /**
@@ -228,7 +228,7 @@ public:
    * @param[in] glyphPositions An array of visual positions for each glyph.
    * @param[in] numberOfGlyphs The number of positions.
    */
-  void SetGlyphPositions( const Vector2* glyphPositions,
+  void SetGlyphPositions( const Vector2* const glyphPositions,
                           Length numberOfGlyphs );
 
   /**
index 0d7a2f0..ee5d0fd 100644 (file)
@@ -348,17 +348,12 @@ public:
 
         case Toolkit::Control::Property::BACKGROUND_IMAGE:
         {
-          if ( value.HasKey( "image" ) )
+          Image image = Scripting::NewImage( value );
+          if ( image )
           {
-            Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
-            Image image = Scripting::NewImage( imageMap );
-
-            if ( image )
-            {
-              controlImpl.SetBackgroundImage( image );
-            }
+            controlImpl.SetBackgroundImage( image );
           }
-          else if ( value.Get< Property::Map >().Empty() )
+          else
           {
             // An empty map means the background is no longer required
             controlImpl.ClearBackground();
@@ -423,9 +418,7 @@ public:
             if ( imageActor )
             {
               Image image = imageActor.GetImage();
-              Property::Map imageMap;
-              Scripting::CreatePropertyMap( image, imageMap );
-              map[ "image" ] = imageMap;
+              Scripting::CreatePropertyMap( image, map );
             }
           }
 
index 1c396c0..63ea4e9 100644 (file)
@@ -597,7 +597,7 @@ private:
  * @param handle
  * @return implementation
  */
-Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
+DALI_IMPORT_API Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
 
 /**
  * @brief Get implementation from the handle
@@ -606,7 +606,7 @@ Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
  * @param handle
  * @return implementation
  */
-const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
+DALI_IMPORT_API const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
 
 } // namespace Internal
 
index a43c874..5bf8561 100644 (file)
@@ -46,6 +46,11 @@ ImageActor CreateSolidColorActor( const Vector4& color, bool border, const Vecto
 
   // Create the image
   PixelBuffer* pixbuf = imageData.GetBuffer();
+  if( !pixbuf )
+  {
+    return image;
+  }
+
   Vector4 outerColor = color;
   if ( border )
   {
index d30f809..5da66a5 100755 (executable)
@@ -66,12 +66,12 @@ public:
   {
     enum
     {
-      SCROLL_DIRECTION = PROPERTY_START_INDEX,        ///< name "scroll-direction",        @see SetScrollDirection(),       type std::string
-      INDICATOR_HEIGHT_POLICY,                        ///< name "indicator-height-policy", @see SetIndicatorHeightPolicy(), type std::string
-      INDICATOR_FIXED_HEIGHT,                         ///< name "indicator-fixed-height",  @see SetIndicatorFixedHeight(),  type float
-      INDICATOR_SHOW_DURATION,                        ///< name "indicator-show-duration", @see SetIndicatorShowDuration(), type float
-      INDICATOR_HIDE_DURATION,                        ///< name "indicator-hide-duration", @see SetIndicatorHideDuration(), type float
-      SCROLL_POSITION_INTERVALS                       ///< name "scroll-position-intervals",                                type float
+      SCROLL_DIRECTION = PROPERTY_START_INDEX, ///< name "scroll-direction",         @see SetScrollDirection(),        type std::string
+      INDICATOR_HEIGHT_POLICY,                 ///< name "indicator-height-policy",  @see SetIndicatorHeightPolicy(),  type std::string
+      INDICATOR_FIXED_HEIGHT,                  ///< name "indicator-fixed-height",   @see SetIndicatorFixedHeight(),   type float
+      INDICATOR_SHOW_DURATION,                 ///< name "indicator-show-duration",  @see SetIndicatorShowDuration(),  type float
+      INDICATOR_HIDE_DURATION,                 ///< name "indicator-hide-duration",  @see SetIndicatorHideDuration(),  type float
+      SCROLL_POSITION_INTERVALS                ///< name "scroll-position-intervals",@see SetScrollPositionIntervals() type Property::Array
     };
   };
 
index 6daa933..12a6baf 100644 (file)
@@ -243,6 +243,11 @@ void ItemView::GetItemsRange(ItemRange& range)
   GetImpl(*this).GetItemsRange(range);
 }
 
+ItemView::LayoutActivatedSignalType& ItemView::LayoutActivatedSignal()
+{
+  return GetImpl(*this).LayoutActivatedSignal();
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index ca51a44..cb0859d 100644 (file)
@@ -46,7 +46,13 @@ typedef IntrusivePtr<ItemLayout> ItemLayoutPtr;
  *
  * Multiple ItemLayouts may be provided, to determine the logical position of each item a layout.
  * Actors are provided from an external ItemFactory, to display the currently visible items.
+ *
+ * Signals
+ * | %Signal Name                     | Method                                     |
+ * |----------------------------------|--------------------------------------------|
+ * | layout-activated                 | @ref LayoutActivatedSignal()               |
  */
+
 class DALI_IMPORT_API ItemView : public Scrollable
 {
 public:
@@ -73,6 +79,10 @@ public:
     };
   };
 
+  // Signals
+
+  typedef Signal< void () > LayoutActivatedSignalType;
+
 public:
 
   /**
@@ -421,6 +431,20 @@ public:
    */
   void GetItemsRange(ItemRange& range);
 
+public: // Signals
+
+  /**
+   * @brief Signal emitted when layout activation is finished.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName();
+   * @endcode
+   * @pre The Object has been initialized.
+   * @return The signal to connect to.
+   */
+  ItemView::LayoutActivatedSignalType& LayoutActivatedSignal();
+
 public: // Not intended for application developers
 
   /**
index c7121dc..38e9672 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 44;
+const unsigned int TOOLKIT_MICRO_VERSION = 45;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index f850715..fcfae07 100644 (file)
@@ -37,6 +37,12 @@ distributing this software or its derivatives.
       "font-style":"Regular",
       "point-size":18
     },
+    "textselectionpopup":
+    {
+      "popup-max-size":[400,100],
+      "popup-min-size":[100,65],
+      "background-color":[0.0,0.0,0.0,1.0]
+    },
     "textfield":
     {
       "font-family":"HelveticaNeue",
index 8deaa50..7c4099e 100644 (file)
@@ -84,7 +84,12 @@ distributing this software or its derivatives.
     {
       "point-size":10
     },
-
+    "textselectionpopup":
+    {
+      "popup-max-size":[400,100],
+      "popup-min-size":[100,65],
+      "background-color":[0.0,0.0,0.0,1.0]
+    },
     "scrollview":
     {
       "overshoot-effect-color":"B018"
index 13bff90..6ba1b7f 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    The OpenGLES Canvas Core Library Toolkit
-Version:    1.0.44
+Version:    1.0.45
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0
index b5595f8..c58d991 100644 (file)
@@ -769,7 +769,6 @@ Dali::Property::Value PropertyValueWrapper::ExtractPropertyValue( v8::Isolate* i
       break;
     }
     case Dali::Property::NONE:
-    case Dali::Property::TYPE_COUNT:
     default:
     {
       break;