Merge "Add ApplyCustomFragmentPrefix" into devel/master
authorSeungho BAEK <sbsh.baek@samsung.com>
Wed, 21 Jul 2021 06:30:00 +0000 (06:30 +0000)
committerGerrit Code Review <gerrit@review>
Wed, 21 Jul 2021 06:30:00 +0000 (06:30 +0000)
177 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Text.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Ellipsis.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Hyphen-Wrapping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-ViewModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualUrl.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gesture-generator.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gesture-generator.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-vector-animation-renderer.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-web-engine.cpp
automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-Image.cpp
automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Transition.cpp
automated-tests/src/dali-toolkit/utc-Dali-WebView.cpp
dali-toolkit/dali-toolkit.h
dali-toolkit/devel-api/controls/accessible-impl.cpp
dali-toolkit/devel-api/controls/accessible-impl.h
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-field-devel.h
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h
dali-toolkit/devel-api/controls/web-view/web-context.cpp
dali-toolkit/devel-api/controls/web-view/web-context.h
dali-toolkit/devel-api/controls/web-view/web-view.cpp
dali-toolkit/devel-api/controls/web-view/web-view.h
dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.cpp
dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.h
dali-toolkit/devel-api/text/text-enumerations-devel.h
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/controls/buttons/button-impl.cpp
dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp
dali-toolkit/internal/controls/buttons/push-button-impl.cpp
dali-toolkit/internal/controls/buttons/radio-button-impl.cpp
dali-toolkit/internal/controls/buttons/toggle-button-impl.cpp
dali-toolkit/internal/controls/canvas-view/canvas-view-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/progress-bar/progress-bar-impl.cpp
dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp
dali-toolkit/internal/controls/slider/slider-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/controls/web-view/web-view-impl.cpp
dali-toolkit/internal/controls/web-view/web-view-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/image-loader/image-url-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/image-loader/image-url-impl.h [new file with mode: 0644]
dali-toolkit/internal/text/bidirectional-line-info-run.h
dali-toolkit/internal/text/bidirectional-support.cpp
dali-toolkit/internal/text/bidirectional-support.h
dali-toolkit/internal/text/input-filter.cpp [new file with mode: 0644]
dali-toolkit/internal/text/input-filter.h [new file with mode: 0644]
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/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/text-typesetter.h
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/text-controller-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller-relayouter.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-editable-control-interface.h
dali-toolkit/internal/text/text-enumerations-impl.cpp
dali-toolkit/internal/text/text-enumerations-impl.h
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/internal/transition/fade-impl.cpp
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/internal/visuals/texture-manager-impl.h
dali-toolkit/internal/visuals/visual-url.cpp
dali-toolkit/internal/visuals/visual-url.h
dali-toolkit/po/ar.po
dali-toolkit/po/az.po
dali-toolkit/po/bg.po
dali-toolkit/po/bn_BD.po
dali-toolkit/po/ca.po
dali-toolkit/po/cs.po
dali-toolkit/po/da.po
dali-toolkit/po/de.po
dali-toolkit/po/el_GR.po
dali-toolkit/po/en.po
dali-toolkit/po/en_US.po
dali-toolkit/po/es_ES.po
dali-toolkit/po/es_US.po
dali-toolkit/po/et.po
dali-toolkit/po/eu.po
dali-toolkit/po/fa.po
dali-toolkit/po/fi.po
dali-toolkit/po/fr.po
dali-toolkit/po/fr_CA.po
dali-toolkit/po/gl.po
dali-toolkit/po/hr.po
dali-toolkit/po/hu.po
dali-toolkit/po/hy.po
dali-toolkit/po/is.po
dali-toolkit/po/it_IT.po
dali-toolkit/po/ka.po
dali-toolkit/po/kk.po
dali-toolkit/po/ko_KR.po
dali-toolkit/po/lt.po
dali-toolkit/po/lv.po
dali-toolkit/po/mn_MN.po
dali-toolkit/po/nb.po
dali-toolkit/po/nl.po
dali-toolkit/po/pl.po
dali-toolkit/po/pt_BR.po
dali-toolkit/po/pt_PT.po
dali-toolkit/po/ro.po
dali-toolkit/po/ru_RU.po
dali-toolkit/po/sk.po
dali-toolkit/po/sl.po
dali-toolkit/po/sr.po
dali-toolkit/po/sv.po
dali-toolkit/po/tr_TR.po
dali-toolkit/po/uk.po
dali-toolkit/po/ur.po
dali-toolkit/po/uz.po
dali-toolkit/po/vi.po
dali-toolkit/po/zh_CN.po
dali-toolkit/public-api/controls/text-controls/input-filter-properties.h [new file with mode: 0644]
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/file.list
dali-toolkit/public-api/image-loader/image-url.cpp [new file with mode: 0644]
dali-toolkit/public-api/image-loader/image-url.h [new file with mode: 0644]
dali-toolkit/public-api/image-loader/image.cpp
dali-toolkit/public-api/image-loader/image.h
packaging/dali-toolkit.spec

index 0a65397..d50921c 100755 (executable)
@@ -37,6 +37,7 @@ SET(TC_SOURCES
  utc-Dali-VisualModel.cpp
  utc-Dali-VisualUrl.cpp
  utc-Dali-Text-Hyphen-Wrapping.cpp
+ utc-Dali-Text-Ellipsis.cpp
 )
 
 IF(ELDBUS_AVAILABLE)
index d59df19..9011f2f 100644 (file)
@@ -666,9 +666,11 @@ struct DefaultDBusWrapper : public DBusWrapper {
       DBUS_DEBUG( "registering interface %p (%d)", v, fallback ? 1 : 0 );
       destructors.push_back([=]() {
         DBUS_DEBUG( "unregistering interface %p", v );
+        {
+          std::lock_guard< std::mutex > lock( globalEntriesMutex );
+          globalEntries.erase( v );
+        }
         eldbus_service_interface_unregister( v );
-        std::lock_guard< std::mutex > lock( globalEntriesMutex );
-        globalEntries.erase( v );
       });
     }
   }
index 6028e02..64a8473 100755 (executable)
@@ -102,7 +102,9 @@ void CreateTextModel( const std::string& text,
                       ModelPtr& textModel,
                       MetricsPtr& metrics,
                       bool markupProcessorEnabled,
-                      LineWrap::Mode wrapMode )
+                      LineWrap::Mode wrapMode,
+                      bool ellipsisEnabled,
+                      DevelText::EllipsisPosition::Type ellipsisPosition)
 {
   textModel = Model::New(); ///< Pointer to the text's model.
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
@@ -133,6 +135,12 @@ void CreateTextModel( const std::string& text,
     utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
   }
 
+  //Ellipsis
+  textModel-> mElideEnabled = ellipsisEnabled;
+  textModel-> mVisualModel->SetTextElideEnabled(ellipsisEnabled);
+  textModel-> mEllipsisPosition = ellipsisPosition;
+  textModel-> mVisualModel->SetEllipsisPosition(ellipsisPosition);
+
   // 1) Convert to utf32
   Vector<Character>& utf32Characters = logicalModel->mText;
   utf32Characters.Resize( textSize );
@@ -323,7 +331,6 @@ void CreateTextModel( const std::string& text,
   // Set the layout parameters.
   textModel->mHorizontalAlignment = Text::HorizontalAlignment::BEGIN;
   textModel->mIgnoreSpacesAfterText = true;
-  textModel->mMatchSystemLanguageDirection = false;
   Layout::Parameters layoutParameters( textArea,
                                        textModel );
 
@@ -344,7 +351,8 @@ void CreateTextModel( const std::string& text,
   layoutEngine.LayoutText( layoutParameters,
                            layoutSize,
                            false,
-                           isAutoScroll );
+                           isAutoScroll,
+                           ellipsisPosition);
 
   if( options.align )
   {
@@ -385,7 +393,7 @@ void ConfigureTextLabel( ControllerPtr controller )
   controller->SetTextElideEnabled( true );
 
   // Disable match system language direction
-  controller->SetMatchSystemLanguageDirection(false);
+  controller->SetMatchLayoutDirection(DevelText::MatchLayoutDirection::CONTENTS);
 }
 
 void ConfigureTextField( ControllerPtr controller )
@@ -417,7 +425,7 @@ void ConfigureTextField( ControllerPtr controller )
   controller->SetTextElideEnabled( false );
 
   // Disable match system language direction
-  controller->SetMatchSystemLanguageDirection(false);
+  controller->SetMatchLayoutDirection(DevelText::MatchLayoutDirection::CONTENTS);
 }
 
 void ConfigureTextEditor( ControllerPtr controller )
@@ -449,7 +457,7 @@ void ConfigureTextEditor( ControllerPtr controller )
   controller->SetTextElideEnabled( false );
 
   // Disable match system language direction
-  controller->SetMatchSystemLanguageDirection(false);
+  controller->SetMatchLayoutDirection(DevelText::MatchLayoutDirection::CONTENTS);
 }
 
 } // namespace Text
index 6e30bbb..ccfbe98 100644 (file)
@@ -56,6 +56,9 @@ struct LayoutOptions
  * @param[out] textModel Pointer to a text model instance.
  * @param[out] metrics Pointer to a wrapper around FontClient used to get metrics.
  * @param[in] markupProcessorEnabled Enable markup processor to use markup text.
+ * @param[in] wrapMode Line wrap mode.
+ * @param[in] ellipsisEnabled Whether the ellipsis layout option is enabled.
+ * @param[in] ellipsisPosition Where is the location the text elide.
  */
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
@@ -65,7 +68,9 @@ void CreateTextModel( const std::string& text,
                       ModelPtr& textModel,
                       MetricsPtr& metrics,
                       bool markupProcessorEnabled,
-                      LineWrap::Mode wrapMode );
+                      LineWrap::Mode wrapMode,
+                      bool ellipsisEnabled,
+                      DevelText::EllipsisPosition::Type ellipsisPosition);
 
 /**
  * @brief Configures the text @p controller similarly to the one configured by the text-label.
index 808cc7a..a6b682e 100644 (file)
@@ -712,7 +712,7 @@ int UtcDaliAccessibilityGetExtents(void)
   auto a = Dali::Accessibility::Accessible::Get( control );
   auto a_component = dynamic_cast<Dali::Accessibility::Component*>( a );
 
-  auto extents = a_component->GetExtents(Dali::Accessibility::CoordType::SCREEN);
+  auto extents = a_component->GetExtents(Dali::Accessibility::CoordinateType::SCREEN);
   DALI_TEST_EQUALS( extents.x, 5.0f, TEST_LOCATION );
   DALI_TEST_EQUALS( extents.y, 5.0f, TEST_LOCATION );
   DALI_TEST_EQUALS( extents.height, 10.0f, TEST_LOCATION );
@@ -728,7 +728,7 @@ int UtcDaliAccessibilityGetExtents(void)
   application.SendNotification();
   application.Render( 1 );
 
-  extents = a_component->GetExtents(Dali::Accessibility::CoordType::SCREEN);
+  extents = a_component->GetExtents(Dali::Accessibility::CoordinateType::SCREEN);
   DALI_TEST_EQUALS( extents.x, 10.0f, TEST_LOCATION );
   DALI_TEST_EQUALS( extents.y, 10.0f, TEST_LOCATION );
   DALI_TEST_EQUALS( extents.height, 10.0f, TEST_LOCATION );
@@ -1050,4 +1050,4 @@ int UtcDaliAccessibilityScrollToChildNonScrollable(void)
 
   Dali::Accessibility::TestEnableSC( false );
   END_TEST;
-}
\ No newline at end of file
+}
index dabd012..9243a0b 100644 (file)
@@ -540,9 +540,9 @@ int UtcDaliAccessibilityTextField(void)
   auto text = dynamic_cast< Dali::Accessibility::Text* >( accessible );
   DALI_TEST_CHECK( text );
   DALI_TEST_EQUALS( text->GetText( 0, 10 ), "", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetCaretOffset(100), false, TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetCaretOffset(2), true, TEST_LOCATION );
-  DALI_TEST_EQUALS( text->GetCaretOffset(), 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetCursorOffset(100), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetCursorOffset(2), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->GetCursorOffset(), 2, TEST_LOCATION );
 
   auto editabletext = dynamic_cast< Dali::Accessibility::EditableText* >( accessible );
   DALI_TEST_CHECK( editabletext );
@@ -552,11 +552,11 @@ int UtcDaliAccessibilityTextField(void)
   DALI_TEST_EQUALS( editabletext->CutText( 1, 3 ), true, TEST_LOCATION );
   DALI_TEST_EQUALS( text->GetText( 0, 1 ), "t", TEST_LOCATION );
 
-  auto range = text->GetSelection( 1 );
+  auto range = text->GetRangeOfSelection( 1 );
   DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.content, "", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetSelection( 1, 0, 1 ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
   DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
 
   DALI_TEST_EQUALS(editabletext->SetTextContents("adef"), true, TEST_LOCATION);
@@ -596,9 +596,9 @@ int UtcDaliAccessibilityTextEditor(void)
   auto text = dynamic_cast< Dali::Accessibility::Text* >( accessible );
   DALI_TEST_CHECK( text );
   DALI_TEST_EQUALS( text->GetText( 0, 10 ), "", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetCaretOffset(100), false, TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetCaretOffset(2), true, TEST_LOCATION );
-  DALI_TEST_EQUALS( text->GetCaretOffset(), 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetCursorOffset(100), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetCursorOffset(2), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->GetCursorOffset(), 2, TEST_LOCATION );
 
   auto editabletext = dynamic_cast< Dali::Accessibility::EditableText* >( accessible );
   DALI_TEST_CHECK( editabletext );
@@ -608,11 +608,11 @@ int UtcDaliAccessibilityTextEditor(void)
   DALI_TEST_EQUALS( editabletext->CutText( 1, 3 ), true, TEST_LOCATION );
   DALI_TEST_EQUALS( text->GetText( 0, 1 ), "t", TEST_LOCATION );
 
-  auto range = text->GetSelection( 1 );
+  auto range = text->GetRangeOfSelection( 1 );
   DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.content, "", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetSelection( 1, 0, 1 ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
   DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
 
   DALI_TEST_EQUALS(editabletext->SetTextContents("adef"), true, TEST_LOCATION);
@@ -650,14 +650,14 @@ int UtcDaliAccessibilityTextLabel(void)
   DALI_TEST_CHECK( text );
   DALI_TEST_EQUALS( text->GetText( 0, 10 ), "", TEST_LOCATION );
   DALI_TEST_EQUALS( text->GetText( 0, 4 ), "test", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetCaretOffset(0), false, TEST_LOCATION );
-  DALI_TEST_EQUALS( text->GetCaretOffset(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetCursorOffset(0), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->GetCursorOffset(), 0, TEST_LOCATION );
 
-  auto range = text->GetSelection( 1 );
+  auto range = text->GetRangeOfSelection( 1 );
   DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( range.content, "", TEST_LOCATION );
-  DALI_TEST_EQUALS( text->SetSelection( 1, 0, 1 ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( text->SetRangeOfSelection( 1, 0, 1 ), false, TEST_LOCATION );
   DALI_TEST_EQUALS( text->RemoveSelection( 1 ), false, TEST_LOCATION );
 
   Dali::Accessibility::TestEnableSC( false );
index 7bc4fe1..6b77f00 100644 (file)
@@ -141,7 +141,7 @@ int utcDaliAccessibilityTextEditorGetTextAtOffset(void)
   END_TEST;
 }
 
-int utcDaliAccessibilityTextEditorGetSetSelection(void)
+int utcDaliAccessibilityTextEditorGetSetRangeOfSelection(void)
 {
   ToolkitTestApplication application;
 
@@ -151,14 +151,14 @@ int utcDaliAccessibilityTextEditorGetSetSelection(void)
   DALI_TEST_CHECK( x );
   if( x )
   {
-    auto range = x->GetSelection( 0 );
+    auto range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.content, "", TEST_LOCATION );
 
-    x->SetSelection( 0, 4, 9 );
+    x->SetRangeOfSelection( 0, 4, 9 );
     editor.SetProperty( Toolkit::TextEditor::Property::TEXT, "exemplary_text" );
-    range = x->GetSelection( 0 );
+    range = x->GetRangeOfSelection( 0 );
 
     DALI_TEST_EQUALS( range.startOffset, 4, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 9, TEST_LOCATION );
@@ -178,17 +178,17 @@ int utcDaliAccessibilityTextEditorRemoveSelection(void)
   DALI_TEST_CHECK( x );
   if( x )
   {
-    auto range = x->GetSelection( 0 );
+    auto range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
 
-    x->SetSelection( 0, 4, 9 );
-    range = x->GetSelection( 0 );
+    x->SetRangeOfSelection( 0, 4, 9 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 4, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 9, TEST_LOCATION );
 
     x->RemoveSelection( 0 );
-    range = x->GetSelection( 0 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   }
@@ -299,7 +299,7 @@ int utcDaliAccessibilityTextFieldGetTextAtOffset(void)
   END_TEST;
 }
 
-int utcDaliAccessibilityTextFieldGetSetSelection(void)
+int utcDaliAccessibilityTextFieldGetSetRangeOfSelection(void)
 {
   ToolkitTestApplication application;
 
@@ -309,14 +309,14 @@ int utcDaliAccessibilityTextFieldGetSetSelection(void)
   DALI_TEST_CHECK( x );
   if( x )
   {
-    auto range = x->GetSelection( 0 );
+    auto range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.content, "", TEST_LOCATION );
 
-    x->SetSelection( 0, 4, 9 );
+    x->SetRangeOfSelection( 0, 4, 9 );
     field.SetProperty( Toolkit::TextEditor::Property::TEXT, "exemplary_text" );
-    range = x->GetSelection( 0 );
+    range = x->GetRangeOfSelection( 0 );
 
     DALI_TEST_EQUALS( range.startOffset, 4, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 9, TEST_LOCATION );
@@ -336,17 +336,17 @@ int utcDaliAccessibilityTextFieldRemoveSelection(void)
   DALI_TEST_CHECK( x );
   if( x )
   {
-    auto range = x->GetSelection( 0 );
+    auto range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
 
-    x->SetSelection( 0, 4, 9 );
-    range = x->GetSelection( 0 );
+    x->SetRangeOfSelection( 0, 4, 9 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 4, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 9, TEST_LOCATION );
 
     x->RemoveSelection( 0 );
-    range = x->GetSelection( 0 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   }
@@ -467,17 +467,17 @@ int utcDaliAccessibilityTextLabelRemoveSelection( void )
   DALI_TEST_CHECK( x );
   if( x )
   {
-    auto range = x->GetSelection( 0 );
+    auto range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
 
-    x->SetSelection( 0, 4, 9 );
-    range = x->GetSelection( 0 );
+    x->SetRangeOfSelection( 0, 4, 9 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 4, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 9, TEST_LOCATION );
 
     x->RemoveSelection( 0 );
-    range = x->GetSelection( 0 );
+    range = x->GetRangeOfSelection( 0 );
     DALI_TEST_EQUALS( range.startOffset, 0, TEST_LOCATION );
     DALI_TEST_EQUALS( range.endOffset, 0, TEST_LOCATION );
   }
index de772f3..84ecd2d 100644 (file)
@@ -112,7 +112,9 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -198,7 +200,9 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -275,7 +279,9 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
                    textModel,
                    metrics,
                    data.markupProcessorEnabled,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 8515172..a95b707 100755 (executable)
@@ -119,7 +119,9 @@ bool CreateParagraphTest( const CreateParagraphData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -182,7 +184,9 @@ bool FindParagraphTest( const FindParagraphData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -234,7 +238,9 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -281,7 +287,9 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -345,7 +353,9 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 1d394e6..bb3ed33 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -386,6 +386,50 @@ int UtcDaliTextControllerImfPreeditStyle(void)
   END_TEST;
 }
 
+int UtcDaliTextControllerImfPreeditStyleReverse(void)
+{
+  tet_infoline(" UtcDaliTextControllerImfPreeditStyleReverse");
+  ToolkitTestApplication application;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  std::string text;
+  InputMethodContext::EventData imfEvent;
+
+  DALI_TEST_CHECK(controller);
+
+  // Configures the text controller similarly to the text-field.
+  ConfigureTextField(controller);
+
+  InputMethodContext inputMethodContext = InputMethodContext::New();
+
+  // Send PRE_EDIT event
+  imfEvent = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "Reverse", 0, 7);
+  controller->OnInputMethodContextEvent(inputMethodContext, imfEvent);
+
+  // For coverage, mEditableControlInterface is required.
+  // Creates a temporary text-field to use mEditableControlInterface.
+  TextField field = TextField::New();
+  Toolkit::Internal::TextField& fieldImpl = GetImpl(field);
+  ControllerPtr fieldController = fieldImpl.GetTextController();
+  Controller::Impl& fieldControllerImpl = Controller::Impl::GetImplementation(*fieldController.Get());
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // For coverage, mEditableControlInterface is required.
+  controllerImpl.mEditableControlInterface = fieldControllerImpl.mEditableControlInterface;
+
+  // Set the preedit style as REVERSE
+  inputMethodContext.SetPreeditStyle(InputMethodContext::PreeditStyle::REVERSE);
+  controller->GetNaturalSize();
+
+  controller->GetText(text);
+  DALI_TEST_EQUALS("Reverse", text, TEST_LOCATION);
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
 int UtcDaliTextControllerTextPopupButtonTouched(void)
 {
   tet_infoline(" UtcDaliTextControllerTextPopupButtonTouched");
index 78d7cf8..377f976 100755 (executable)
@@ -112,7 +112,9 @@ bool GetClosestLineTest( const GetClosestLineData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -159,7 +161,9 @@ bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -210,7 +214,9 @@ bool GetCursorPositionTest( const GetCursorPositionData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -264,7 +270,9 @@ bool FindSelectionIndicesTest( const FindSelectionIndicesData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Ellipsis.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Ellipsis.cpp
new file mode 100755 (executable)
index 0000000..e5b8a88
--- /dev/null
@@ -0,0 +1,1848 @@
+/*
+ * Copyright (c) 2021 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 <unistd.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-utils.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
+#include <dali-toolkit/internal/text/rendering/view-model.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-view.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+
+namespace
+{
+
+  const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+
+  struct ElideData
+  {
+    std::string                                                description;
+    std::string                                                text;
+    bool                                                       isMultiLines;
+    DevelText::LineWrap::Mode                                  lineWrapMode;
+    DevelText::EllipsisPosition::Type                          ellipsisPosition;
+    bool                                                       isMarkup;
+    Vector2                                                    size;
+    unsigned int                                               numberOfLines;
+    unsigned int                                               numberOfGlyphs;
+    float*                                                     positions;
+  };
+
+
+  bool ElideTestViewModel( const ElideData& data )
+  {
+    std::cout << "  testing : " << data.description << std::endl;
+
+    // Load some fonts.
+    TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+    fontClient.SetDpi( 93u, 93u );
+
+    char* pathNamePtr = get_current_dir_name();
+    const std::string pathName( pathNamePtr );
+    free( pathNamePtr );
+
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+
+    // Creates a text controller.
+    ControllerPtr controller = Controller::New();
+
+    // Tests the rendering controller has been created.
+    TypesetterPtr typesetter = Typesetter::New( controller->GetTextModel() );
+    DALI_TEST_CHECK(typesetter);
+
+    // Tests the view model has been created.
+    ViewModel* model = typesetter->GetViewModel();
+    DALI_TEST_CHECK(model);
+
+    // Configures the text controller similarly to the text-label.
+    ConfigureTextLabel( controller );
+
+    // Sets a text and relais-out.
+    controller->SetMarkupProcessorEnabled( data.isMarkup );
+
+    controller->SetMultiLineEnabled( data.isMultiLines );
+    controller->SetLineWrapMode( (Text::LineWrap::Mode)(data.lineWrapMode) );
+    controller->SetEllipsisPosition( data.ellipsisPosition );
+
+    controller->SetText( data.text );
+    controller->Relayout( data.size );
+
+    // Elide the glyphs.
+    model->ElideGlyphs();
+
+    if( data.numberOfLines != model->GetNumberOfLines() )
+    {
+      std::cout << "  different number of lines : " << model->GetNumberOfLines() << ", expected : " << data.numberOfLines << std::endl;
+      return false;
+    }
+
+    Length numberOfGlyphs = model->GetNumberOfGlyphs();
+
+    if( data.numberOfGlyphs != numberOfGlyphs )
+    {
+      std::cout << "  different number of glyphs : " << numberOfGlyphs << ", expected : " << data.numberOfGlyphs << std::endl;
+      return false;
+    }
+
+    const Vector2* const layoutBuffer              = model->GetLayout();
+    const Length         numberOfLines             = model->GetNumberOfLines();
+    const GlyphIndex     startIndexOfGlyphs        = model->GetStartIndexOfElidedGlyphs();
+    const GlyphIndex     endIndexOfGlyphs          = model->GetEndIndexOfElidedGlyphs();
+    const GlyphIndex     firstMiddleIndexOfGlyphs  = model->GetFirstMiddleIndexOfElidedGlyphs();
+
+
+    if( numberOfLines != 0u )
+    {
+      Length   elidedLineIndex    = 0u;
+      for(Length lineIndex=0u; lineIndex < numberOfLines; lineIndex++)
+      {
+          const LineRun& tempLine         = *( model->GetLines() + elidedLineIndex);
+          if(tempLine.ellipsis)
+          {
+            elidedLineIndex = lineIndex;
+            break;
+          }
+      }
+      const LineRun& elidedLine                   = *( model->GetLines() + elidedLineIndex);
+      Length         numberOfLineGlyphs           = 0u;
+      Length         numberOfLineGlyphsSecondHalf = 0u;
+
+      switch(data.ellipsisPosition)
+      {
+        case DevelText::EllipsisPosition::START:
+        {
+          numberOfLineGlyphs = elidedLine.glyphRun.numberOfGlyphs - ( startIndexOfGlyphs - elidedLine.glyphRun.glyphIndex);
+          break;
+        }
+        case DevelText::EllipsisPosition::MIDDLE:
+        {
+          numberOfLineGlyphs = firstMiddleIndexOfGlyphs - elidedLine.glyphRun.glyphIndex +1u ;
+          break;
+        }
+        case DevelText::EllipsisPosition::END:
+        default:
+        {
+          numberOfLineGlyphs = endIndexOfGlyphs - elidedLine.glyphRun.glyphIndex + 1u;
+          break;
+        }
+      }
+
+      unsigned int index = 0u;
+      for( ; index < numberOfLineGlyphs; ++index )
+      {
+        if( *( data.positions + index ) != floor(elidedLine.alignmentOffset + ( *( layoutBuffer + index ) ).x ) )
+        {
+          std::cout << "  different layout :";
+          for( unsigned int i = 0; i < numberOfLineGlyphs; ++i )
+          {
+            std::cout << " " << floor( elidedLine.alignmentOffset + ( *( layoutBuffer + i ) ).x );
+          }
+          std::cout << std::endl;
+          std::cout << "          expected :";
+          for( unsigned int i = 0; i < numberOfLineGlyphs; ++i )
+          {
+            std::cout << " " << *( data.positions + i );
+          }
+          std::cout << std::endl;
+          return false;
+        }
+      }
+
+
+      for( ; index < numberOfLineGlyphsSecondHalf; ++index )
+      {
+        if( *( data.positions + index ) != floor(elidedLine.alignmentOffset + ( *( layoutBuffer + index ) ).x ) )
+        {
+          std::cout << "  different layout :";
+          for( unsigned int i = 0; i < numberOfLineGlyphsSecondHalf; ++i )
+          {
+            std::cout << " " << floor( elidedLine.alignmentOffset + ( *( layoutBuffer + i ) ).x );
+          }
+          std::cout << std::endl;
+          std::cout << "          expected :";
+          for( unsigned int i = 0; i < numberOfLineGlyphsSecondHalf; ++i )
+          {
+            std::cout << " " << *( data.positions + i );
+          }
+          std::cout << std::endl;
+          return false;
+        }
+      }
+
+    }
+
+    return true;
+  }
+
+  bool ElideTestTextView( const ElideData& data )
+  {
+    std::cout << "  testing : " << data.description << std::endl;
+
+    // Load some fonts.
+    TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+    fontClient.SetDpi( 93u, 93u );
+
+    char* pathNamePtr = get_current_dir_name();
+    const std::string pathName( pathNamePtr );
+    free( pathNamePtr );
+
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+    fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+
+    // Creates a text controller.
+    ControllerPtr controller = Controller::New();
+
+    if(data.isMultiLines)
+    {
+       // Configures the text controller similarly to the text-editor.
+       ConfigureTextEditor( controller );
+       controller->SetVerticalScrollEnabled( false );
+    }
+    else
+    {
+      // Configures the text controller similarly to the text-field.
+      ConfigureTextField( controller );
+    }
+
+    controller->SetDefaultFontFamily("TizenSansRegular");
+    controller->SetDefaultFontSize(12.0f, Text::Controller::POINT_SIZE);
+
+    controller->SetMultiLineEnabled( data.isMultiLines );
+    controller->SetLineWrapMode( (Text::LineWrap::Mode)(data.lineWrapMode) );
+
+    // Sets a text and relais-out.
+    controller->SetMarkupProcessorEnabled( data.isMarkup );
+
+    controller->SetTextElideEnabled( true );
+    controller->SetEllipsisPosition( data.ellipsisPosition );
+
+    controller->SetText( data.text );
+    controller->Relayout( data.size );
+
+    // Get view to elide the glyphs.
+    Text::ViewInterface& view = controller->GetView();
+
+    Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+    if(numberOfGlyphs == 0u)
+    {
+      return data.numberOfGlyphs == 0u;
+    }
+
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize(numberOfGlyphs);
+
+    Vector<Vector2> positions;
+    positions.Resize(numberOfGlyphs);
+
+    float alignmentOffset = 0u;
+    numberOfGlyphs = view.GetGlyphs(glyphs.Begin(),
+                                    positions.Begin(),
+                                    alignmentOffset,
+                                    0u,
+                                    numberOfGlyphs);
+
+    glyphs.Resize(numberOfGlyphs);
+    positions.Resize(numberOfGlyphs);
+
+
+    if( data.numberOfGlyphs != numberOfGlyphs )
+    {
+      std::cout << "  different number of glyphs : " << numberOfGlyphs << ", expected : " << data.numberOfGlyphs << std::endl;
+      return false;
+    }
+
+    // Tests the text model has been created.
+    const ModelInterface* textModel  = controller->GetTextModel();
+    DALI_TEST_CHECK(textModel);
+
+    if( data.numberOfLines != textModel->GetNumberOfLines() )
+    {
+      std::cout << "  different number of lines : " << textModel->GetNumberOfLines() << ", expected : " << data.numberOfLines << std::endl;
+      return false;
+    }
+
+    const Length     numberOfLines             = textModel->GetNumberOfLines();
+    const GlyphIndex startIndexOfGlyphs        = textModel->GetStartIndexOfElidedGlyphs();
+    const GlyphIndex endIndexOfGlyphs          = textModel->GetEndIndexOfElidedGlyphs();
+    const GlyphIndex firstMiddleIndexOfGlyphs  = textModel->GetFirstMiddleIndexOfElidedGlyphs();
+    const GlyphIndex secondMiddleIndexOfGlyphs = textModel->GetSecondMiddleIndexOfElidedGlyphs();
+
+    if( numberOfLines != 0u )
+    {
+      Length   elidedLineIndex    = 0u;
+      for(Length lineIndex=0u; lineIndex < numberOfLines; lineIndex++)
+      {
+          const LineRun& tempLine         = *( textModel->GetLines() + lineIndex);
+          if(tempLine.ellipsis)
+          {
+            elidedLineIndex = lineIndex;
+            break;
+          }
+      }
+      const LineRun& elidedLine         = *( textModel->GetLines() + elidedLineIndex);
+
+      Length         numberOfLineGlyphs           = 0u;
+      Length         numberOfLineGlyphsSecondHalf = 0u;
+
+      switch(data.ellipsisPosition)
+      {
+        case DevelText::EllipsisPosition::START:
+        {
+          numberOfLineGlyphs = elidedLine.glyphRun.numberOfGlyphs - ( startIndexOfGlyphs - elidedLine.glyphRun.glyphIndex);
+          break;
+        }
+        case DevelText::EllipsisPosition::MIDDLE:
+        {
+          numberOfLineGlyphs = firstMiddleIndexOfGlyphs == elidedLine.glyphRun.glyphIndex ? 0u : (firstMiddleIndexOfGlyphs - elidedLine.glyphRun.glyphIndex +1u);
+
+          if(elidedLine.isSplitToTwoHalves)
+          {
+            numberOfLineGlyphsSecondHalf = (elidedLine.glyphRunSecondHalf.glyphIndex + elidedLine.glyphRunSecondHalf.numberOfGlyphs) - secondMiddleIndexOfGlyphs ;
+
+          }
+          break;
+        }
+        case DevelText::EllipsisPosition::END:
+        default:
+        {
+          numberOfLineGlyphs = endIndexOfGlyphs - elidedLine.glyphRun.glyphIndex + 1u;
+          break;
+        }
+      }
+
+
+      unsigned int index = 0u;
+      for(  ; index < numberOfLineGlyphs; ++index )
+      {
+
+        if( *( data.positions + index ) != floor( elidedLine.alignmentOffset + positions[index].x ))
+        {
+          std::cout << "  different layout :";
+          for( unsigned int i = 0; i < numberOfLineGlyphs; ++i )
+          {
+            std::cout << " " << floor( elidedLine.alignmentOffset + positions[i].x );
+          }
+          std::cout << std::endl;
+          std::cout << "          expected :";
+          for( unsigned int i = 0; i < numberOfLineGlyphs; ++i )
+          {
+            std::cout << " " << *( data.positions + i );
+          }
+          std::cout << std::endl;
+          return false;
+        }
+      }
+
+      for( ; index < numberOfLineGlyphsSecondHalf; ++index )
+      {
+        if( *( data.positions + index ) != floor( elidedLine.alignmentOffset + positions[index].x ))
+        {
+          std::cout << "  different layout :";
+          for( unsigned int i = 0; i < numberOfLineGlyphsSecondHalf; ++i )
+          {
+            std::cout << " " << floor( elidedLine.alignmentOffset + positions[i].x );
+          }
+          std::cout << std::endl;
+          std::cout << "          expected :";
+          for( unsigned int i = 0; i < numberOfLineGlyphsSecondHalf; ++i )
+          {
+            std::cout << " " << *( data.positions + i );
+          }
+          std::cout << std::endl;
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+}
+
+int UtcDaliTextLabelElideTextLocation(void)
+{
+  tet_infoline(" UtcDaliTextLabelElideTextLocation ");
+
+  Size textSize00( 100.f, 100.f );
+
+  Size  textSize01( 120.0f, 50.0f );
+  float positions01[] = { 0.f, 11.f, 23.f, 32.f, 42.f, 52.f, 62.f, 73.f, 83.f, 95.f };
+
+  Size  textSize02( 120.0f, 50.0f );
+  float positions02[] = { 0.f, 11.f, 23.f, 32.f, 42.f, 52.f, 62.f, 73.f, 83.f, 93.f, 103.f, 112.f, 0.f, 10.f, 22.f, 31.f, 41.f, 51.f, 61.f, 72.f, 82.f, 94.f };
+
+  Size  textSize03( 120.0f, 60.0f );
+  float positions03[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 0.f, 10.f, 19.f, 29.f, 39.f, 46.f, 50.f, 66.f, 76.f, 85.f, 0.f, 15.f, 25.f, 30.f, 38.f, 48.f, 64.f, 73.f, 79.f, 93.f };
+
+  Size  textSize04( 120.0f, 60.0f );
+  float positions04[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f, 86.f, 96.f, 106.f, 113.f, 0.f, 15.f, 25.f, 34.f, 39.f, 55.f, 65.f, 69.f, 78.f, 88.f, 104.f, 112.f, 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f, 86.f, 98.f };
+
+  Size  textSize05( 110.0f, 60.0f );
+  float positions05[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f, 0.f, 10.f, 20.f, 26.f, 31.f, 46.f, 56.f, 65.f, 70.f, 86.f, 96.f, 0.f, 8.f, 18.f, 34.f, 43.f, 49.f, 61.f, 71.f, 75.f, 81.f };
+
+  Size  textSize06( 110.0f, 60.0f );
+  float positions06[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 0.f, 10.f, 19.f, 29.f, 39.f, 46.f, 50.f, 66.f, 76.f, 85.f, 0.f, 15.f, 25.f, 30.f, 38.f, 48.f, 64.f, 73.f, 81.f };
+
+  Size  textSize07( 120.0f, 50.0f );
+  float positions07[] = { 6.0f, 23.0f, 32.0f, 42.0f, 53.0f, 63.0f, 73.0f, 83.0f, 93.0f, 104.0f, 113.0f } ;
+
+  Size  textSize08( 120.0f, 50.0f );
+  float positions08[] = { 5.0f, 22.0f, 31.0f, 41.0f, 51.0f, 62.0f, 72.0f, 82.0f, 92.0f, 102.0f, 112.0f };
+
+  Size  textSize09( 120.0f, 60.0f );
+  float positions09[] = { 9.0f, 25.0f, 30.0f, 38.0f, 48.0f, 64.0f, 73.0f, 79.0f, 91.0f, 101.0f, 105.0f, 110.0f, 118.0f };
+
+  Size  textSize10( 120.0f, 60.0f );
+  float positions10[] = { 8.0f, 25.0f, 34.0f, 39.0f, 55.0f, 65.0f, 69.0f, 78.0f, 88.0f, 104.0f, 112.0f };
+
+  Size  textSize11( 100.0f, 60.0f );
+  float positions11[] = { 5.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f };
+
+  Size  textSize12( 100.0f, 60.0f );
+  float positions12[] = { 5.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f };
+
+  Size  textSize13( 120.0f, 60.0f );
+  float positions13[] = { 118.0f, 111.0f, 96.0f, 88.0f, 79.0f, 73.0f, 62.0f, 57.0f, 52.0f, 43.0f, 35.0f, 29.0f, 19.0f, 6.0f };
+
+  Size  textSize14( 120.0f, 60.0f );
+  float positions14[] = { 114.0f, 108.0f, 93.0f, 85.0f, 76.0f, 70.0f, 59.0f, 54.0f, 49.0f, 40.0f, 32.0f, 27.0f, 112.0f, 103.0f, 93.0f, 88.0f, 86.0f, 79.0f, 76.0f, 66.0f, 57.0f, 52.0f, 42.0f, 35.0f, 32.0f, 27.0f, 140.0f, 128.0f, 123.0f, 119.0f, 116.0f, 106.0f, 102.0f, 87.0f, 79.0f, 70.0f, 67.0f, 61.0f, 55.0f, 50.0f, 38.0f };
+
+  Size  textSize15( 110.0f, 60.0f );
+  float positions15[] = { 107.0f, 100.0f, 86.0f, 77.0f, 68.0f, 62.0f, 52.0f, 46.0f, 42.0f, 33.0f, 24.0f, 18.0f, 8.0f, 0.0f, 95.0f, 90.0f, 87.0f, 81.0f, 78.0f, 67.0f, 59.0f, 54.0f, 44.0f, 37.0f, 33.0f, 27.0f, 24.0f, 12.0f, 7.0f, 2.0f, 0.0f, 93.0f, 89.0f, 75.0f, 66.0f, 57.0f, 55.0f, 49.0f, 43.0f, 37.0f, 28.0f, 15.0f };
+
+  Size  textSize16( 110.0f, 60.0f );
+  float positions16[] = { 104.0f, 98.0f, 83.0f, 75.0f, 66.0f, 60.0f, 49.0f, 44.0f, 39.0f, 30.0f, 22.0f, 17.0f, 102.0f, 93.0f, 83.0f, 78.0f, 76.0f, 69.0f, 66.0f, 56.0f, 47.0f, 42.0f, 32.0f, 25.0f, 22.0f, 17.0f, 116.0f, 104.0f, 99.0f, 94.0f, 91.0f, 82.0f, 78.0f, 63.0f, 54.0f, 45.0f, 43.0f, 37.0f, 23.0f };
+
+  Size  textSize17( 110.0f, 60.0f );
+  float positions17[] = { 104.0f, 98.0f, 83.0f, 75.0f, 66.0f, 60.0f, 49.0f, 44.0f, 39.0f, 30.0f, 22.0f, 17.0f, 102.0f, 93.0f, 83.0f, 78.0f, 76.0f, 69.0f, 66.0f, 56.0f, 47.0f, 42.0f, 32.0f, 25.0f, 22.0f, 17.0f, 116.0f, 104.0f, 99.0f, 94.0f, 91.0f, 82.0f, 78.0f, 63.0f, 54.0f, 45.0f, 43.0f, 37.0f, 23.0f };
+
+  Size  textSize18( 120.0f, 60.0f );
+  float positions18[] = { 96.0f, 84.0f, 75.0f, 73.0f, 66.0f, 61.0f, 55.0f, 46.0f, 32.0f, 29.0f, 17.0f, 10.0f, 3.0f };
+
+  Size  textSize19( 120.0f, 60.0f );
+  float positions19[] = { 102.0f, 89.0f, 84.0f, 82.0f, 75.0f, 72.0f, 62.0f, 53.0f, 48.0f, 38.0f, 31.0f, 28.0f, 23.0f, };
+
+  Size  textSize20( 110.0f, 60.0f );
+  float positions20[] = { 89.0f, 81.0f, 78.0f, 67.0f, 59.0f, 54.0f, 44.0f, 37.0f, 33.0f, 27.0f, 24.0f, 12.0f, 7.0f, 2.0f, 0.0f };
+
+  Size  textSize21( 110.0f, 60.0f );
+  float positions21[] = { 92.0f, 79.0f, 74.0f, 72.0f, 65.0f, 62.0f, 52.0f, 43.0f, 38.0f, 28.0f, 21.0f, 18.0f, 13.0f };
+
+  Size  textSize22( 110.0f, 60.0f );
+  float positions22[] = {  92.0f, 79.0f, 74.0f, 72.0f, 65.0f, 62.0f, 52.0f, 43.0f, 38.0f, 28.0f, 21.0f, 18.0f, 13.0f };
+
+  Size  textSize23( 120.0f, 50.0f );
+  float positions23[] = { 0.0f, 11.0f, 22.0f, 33.0f, 46.0f };
+
+  Size  textSize24( 120.0f, 50.0f );
+  float positions24[] = { 0.0f, 11.0f, 23.0f, 32.0f, 42.0f, 52.0f, 62.0f, 73.0f, 83.0f, 95.0f };
+
+  Size  textSize25( 120.0f, 60.0f );
+  float positions25[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 0.0f, 10.0f, 19.0f, 29.0f, 39.0f, 46.0f, 50.0f, 68.0f };
+
+  Size  textSize26( 120.0f, 60.0f );
+  float positions26[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 96.0f, 106.0f, 113.0f, 0.0f, 15.0f, 25.0f, 34.0f, 39.0f, 55.0f, 65.0f, 69.0f, 78.0f, 90.0f };
+
+  Size  textSize27( 110.0f, 60.0f );
+  float positions27[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 0.0f, 10.0f, 20.0f, 26.0f, 31.0f, 46.0f, 56.0f, 65.0f, 72.0f };
+
+  Size  textSize28( 110.0f, 60.0f );
+  float positions28[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 0.0f, 10.0f, 19.0f, 29.0f, 39.0f, 46.0f, 50.0f, 68.0f };
+
+  Size  textSize29( 120.0f, 60.0f );
+  float positions29[] = { 116.0f, 109.0f, 94.0f, 86.0f, 77.0f, 71.0f, 60.0f };
+
+  Size  textSize30( 120.0f, 60.0f );
+  float positions30[] = { 114.0f, 108.0f, 93.0f, 85.0f, 76.0f, 70.0f, 59.0f, 54.0f, 49.0f, 40.0f, 32.0f, 27.0f, 112.0f, 103.0f, 93.0f, 88.0f, 86.0f, 79.0f, 76.0f, 66.0f, 57.0f, 52.0f, 33.0f };
+
+  Size  textSize31( 110.0f, 60.0f );
+  float positions31[] = { 107.0f, 100.0f, 86.0f, 77.0f, 68.0f, 62.0f, 52.0f, 46.0f, 42.0f, 33.0f, 24.0f, 18.0f, 8.0f, 0.0f, 95.0f, 90.0f, 87.0f, 81.0f, 78.0f, 67.0f, 59.0f, 54.0f, 44.0f, 37.0f, 33.0f, 27.0f, 24.0f, 9.0f};
+
+  Size  textSize32( 110.0f, 60.0f );
+  float positions32[] = {  104.0f, 98.0f, 83.0f, 75.0f, 66.0f, 60.0f, 49.0f, 44.0f, 39.0f, 30.0f, 22.0f, 17.0f, 102.0f, 93.0f, 83.0f, 78.0f, 76.0f, 69.0f, 66.0f, 56.0f, 47.0f, 42.0f, 23.0f };
+
+  Size  textSize33( 110.0f, 60.0f );
+  float positions33[] = { 104.0f, 98.0f, 83.0f, 75.0f, 66.0f, 60.0f, 49.0f, 44.0f, 39.0f, 30.0f, 22.0f, 17.0f, 102.0f, 93.0f, 83.0f, 78.0f, 76.0f, 69.0f, 66.0f, 56.0f, 47.0f, 42.0f, 23.0f };
+
+  Size  textSize34( 120.0f, 30.0f );
+  float positions34[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 98.0f };
+
+  Size  textSize35( 120.0f, 30.0f );
+  float positions35[] = { 2.0f, 20.0f, 29.0f, 39.0f, 44.0f, 60.0f, 69.0f, 74.0f, 83.0f, 92.0f, 108.0f };
+
+  Size  textSize36( 120.0f, 30.0f );
+  float positions36[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f };
+
+  struct ElideData data[] =
+  {
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+   //END LTR cases
+    {
+      "EllipsisPosition: TextLabel: Basic case SingleLine LTR END",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize01,
+      1u,
+      10u,
+      positions01
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR END",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize02,
+      2u,
+      22u,
+      positions02
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize03,
+      3u,
+      29u,
+      positions03
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize04,
+      3u,
+      40u,
+      positions04
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize05,
+      3u,
+      32u,
+      positions05
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize06,
+      3u,
+      28u,
+      positions06
+    },
+
+   //START LTR cases
+    {
+      "EllipsisPosition: TextLabel: Basic case SingleLine LTR START",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize07,
+      1u,
+      11u,
+      positions07
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR START",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize08,
+      2u,
+      23u,
+      positions08
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize09,
+      3u,
+      33u,
+      positions09
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize10,
+      3u,
+      37u,
+      positions10
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize11,
+      3u,
+      25u,
+      positions11
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize12,
+      3u,
+      25u,
+      positions12
+    },
+
+  //END RTL cases
+    {
+      "EllipsisPosition: TextLabel: SingleLine RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize13,
+      1u,
+      14u,
+      positions13
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize14,
+      3u,
+      41u,
+      positions14
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize15,
+      3u,
+      42u,
+      positions15
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize16,
+      3u,
+      39u,
+      positions16
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize17,
+      3u,
+      39u,
+      positions17
+    },
+
+   //START RTL cases
+    {
+      "EllipsisPosition: TextLabel: SingleLine RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize18,
+      1u,
+      13u,
+      positions18
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize19,
+      3u,
+      33u,
+      positions19
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize20,
+      3u,
+      30u,
+      positions20
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize21,
+      3u,
+      33u,
+      positions21
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize22,
+      3u,
+      33u,
+      positions22
+    },
+
+  //MIDDLE LTR cases
+    {
+      "EllipsisPosition: TextLabel: Basic case SingleLine LTR MIDDLE",
+      "ABCDEFGHIJKLMNPQRSTUVWXYZ abcdefghijklmnpqrstuvwxyz",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize23,
+      1u,
+      10u,
+      positions23
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Basic case Mulitlines LineWrap-WORD LTR MIDDLE",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize24,
+      2u,
+      22u,
+      positions24
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize25,
+      3u,
+      24u,
+      positions25
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize26,
+      3u,
+      36u,
+      positions26
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHAN LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize27,
+      3u,
+      27u,
+      positions27
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize28,
+      3u,
+      24u,
+      positions28
+    },
+
+//MIDDLE RTL cases
+    {
+      "EllipsisPosition: TextLabel: SingleLine RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize29,
+      1u,
+      12u,
+      positions29
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-WORD RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize30,
+      3u,
+      31u,
+      positions30
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-CHARACTER RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize31,
+      3u,
+      30u,
+      positions31
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-HYPHENATION RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize32,
+      3u,
+      31u,
+      positions32
+    },
+
+    {
+      "EllipsisPosition: TextLabel: Mulitlines LineWrap-MIXED RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize33,
+      3u,
+      31u,
+      positions33
+    },
+
+    {
+      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize34,
+      1u,
+      13u,
+      positions34
+    },
+
+    {
+      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize35,
+      1u,
+      11u,
+      positions35
+    },
+
+    {
+      "EllipsisPosition: TextLabel: One-Line for Mulitlines LineWrap-WORD LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize36,
+      1u,
+      12u,
+      positions36
+    },
+
+  };
+  const unsigned int numberOfTests = 39u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !ElideTestViewModel( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+
+int UtcDaliTextFieldlElideTextLocation(void)
+{
+  tet_infoline(" UtcDaliTextFieldlElideTextLocation ");
+
+  Size textSize00( 100.f, 100.f );
+
+  Size  textSize01( 120.0f, 50.0f );
+  float positions01[] = { 0.0f, 11.0f, 23.0f, 32.0f, 42.0f, 52.0f, 62.0f, 73.0f, 83.0f, 95.0f };
+
+  Size  textSize02( 120.0f, 50.0f );
+  float positions02[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 98.0f };
+
+  Size  textSize03( 120.0f, 50.0f );
+  float positions03[] = { 118.0f, 111.0f, 97.0f, 89.0f, 80.0f, 74.0f, 63.0f, 58.0f, 53.0f, 44.0f, 35.0f, 29.0f, 20.0f, 7.0f };
+
+  Size  textSize04( 120.0f, 50.0f );
+  float positions04[] = { 6.0f, 23.0f, 32.0f, 42.0f, 53.0f, 63.0f, 73.0f, 83.0f, 93.0f, 104.0f, 113.0f };
+
+  Size  textSize05( 120.0f, 50.0f );
+  float positions05[] = { 2.0f, 20.0f, 29.0f, 39.0f, 44.0f, 60.0f, 69.0f, 74.0f, 83.0f, 92.0f, 108.0f };
+
+  Size  textSize06( 120.0f, 50.0f );
+  float positions06[] = { 99.0f, 87.0f, 78.0f, 76.0f, 69.0f, 64.0f, 58.0f, 49.0f, 35.0f, 32.0f, 20.0f, 13.0f, 6.0f };
+
+  Size  textSize07( 120.0f, 50.0f );
+  float positions07[] = { 0.0f, 11.0f, 23.0f, 32.0f, 42.0f, 57.0f, 73.0f };
+
+  Size  textSize08( 120.0f, 50.0f );
+  float positions08[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 98.0f };
+
+  Size  textSize09( 120.0f, 50.0f );
+  float positions09[] = { 118.0f, 111.0f, 97.0f, 89.0f, 80.0f, 74.0f, 63.0f, 58.0f, 53.0f, 44.0f, 35.0f, 29.0f, 20.0f, 7.0f };
+
+  Size  textSize10( 120.0f, 50.0f );
+  float positions10[] = { 118.0f, 113.0f, 107.0f, 102.0f, 97.0f, 92.0f, 87.0f, 82.0f, 79.0f, 72.0f, 57.0f, 49.0f, 40.0f, 34.0f, 23.0f, 11.0f };
+
+  Size  textSize11( 120.0f, 50.0f );
+  float positions11[] = { 95.0f, 78.0f, 75.0f, 64.0f, 56.0f, 49.0f, 44.0f, 39.0f, 34.0f, 29.0f, 23.0f, 18.0f, 13.0f, 8.0f, 3.0f };
+
+  Size  textSize12( 120.0f, 50.0f );
+  float positions12[] = { 113.0f, 108.0f, 103.0f, 98.0f, 93.0f, 88.0f, 83.0f, 78.0f, 74.0f, 67.0f };
+
+  struct ElideData data[] =
+  {
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "EllipsisPosition: TextField: Basic case SingleLine LTR END",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize01,
+      1u,
+      10u,
+      positions01
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize02,
+      1u,
+      13u,
+      positions02
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize03,
+      1u,
+      14u,
+      positions03
+    },
+
+    {
+      "EllipsisPosition: TextField: Basic case SingleLine LTR START",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize04,
+      1u,
+      11u,
+      positions04
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize05,
+      1u,
+      11u,
+      positions05
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize06,
+      1u,
+      13u,
+      positions06
+    },
+
+    {
+      "EllipsisPosition: TextField: Basic case SingleLine LTR MIDDLE",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize07,
+      1u,
+      11u,
+      positions07
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Goodbye" ,
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize08,
+      1u,
+      13u,
+      positions08
+    },
+
+    {
+      "EllipsisPosition: TextField: SingleLine RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize09,
+      1u,
+      12u,
+      positions09
+    },
+
+    {
+      "EllipsisPosition: TextField: Head and Tail whitespaces RTL END",
+      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize10,
+      1u,
+      16u,
+      positions10
+    },
+
+    {
+      "EllipsisPosition: TextField: Head and Tail whitespaces RTL START",
+      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize11,
+      1u,
+      15u,
+      positions11
+    },
+
+    {
+      "EllipsisPosition: TextField: Head and Tail whitespaces RTL MIDDLE",
+      "        السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة         ",
+      false,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize12,
+      1u,
+      20u,
+      positions12
+    },
+
+  };
+
+  const unsigned int numberOfTests = 15u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !ElideTestTextView( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+  tet_result(TET_PASS);
+  END_TEST;
+
+}
+
+
+int UtcDaliTextEditorElideTextLocation(void)
+{
+  tet_infoline(" UtcDaliTextEditorElideTextLocation ");
+
+  Size textSize00( 100.f, 100.f );
+
+  Size  textSize01( 120.0f, 50.0f );
+  float positions01[] = { 0.0f, 11.0f, 23.0f, 32.0f, 42.0f, 52.0f, 62.0f, 73.0f, 83.0f, 93.0f, 103.0f, 112.0f, 0.0f, 10.0f, 22.0f, 31.0f, 41.0f, 51.0f, 61.0f, 72.0f, 82.0f, 94.0f };
+
+  Size  textSize02( 120.0f, 60.0f );
+  float positions02[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 0.0f, 10.0f, 19.0f, 29.0f, 39.0f, 46.0f, 50.0f, 66.0f, 76.0f, 85.0f, 0.0f, 15.0f, 25.0f, 30.0f, 38.0f, 48.0f, 64.0f, 73.0f, 79.0f, 93.0f };
+
+  Size  textSize03( 120.0f, 60.0f );
+  float positions03[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 96.0f, 106.0f, 113.0f, 0.0f, 15.0f, 25.0f, 34.0f, 39.0f, 55.0f, 65.0f, 69.0f, 78.0f, 88.0f, 104.0f, 112.0f, 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 98.0f };
+
+  Size  textSize04( 110.0f, 60.0f );
+  float positions04[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 0.0f, 10.0f, 20.0f, 26.0f, 31.0f, 46.0f, 56.0f, 65.0f, 70.0f, 86.0f, 96.0f, 0.0f, 8.0f, 18.0f, 34.0f, 43.0f, 49.0f, 61.0f, 71.0f, 75.0f, 81.0f };
+
+  Size  textSize05( 110.0f, 60.0f );
+  float positions05[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 0.0f, 10.0f, 19.0f, 29.0f, 39.0f, 46.0f, 50.0f, 66.0f, 76.0f, 85.0f, 0.0f, 15.0f, 25.0f, 30.0f, 38.0f, 48.0f, 64.0f, 73.0f, 81.0f };
+
+  Size  textSize06( 120.0f, 50.0f );
+  float positions06[] = { 5.0f, 22.0f, 31.0f, 41.0f, 51.0f, 62.0f, 72.0f, 82.0f, 92.0f, 102.0f, 112.0f };
+
+  Size  textSize07( 120.0f, 60.0f );
+  float positions07[] = { 9.f, 25.f, 30.f, 38.f, 48.f, 64.f, 73.f, 79.f, 91.f, 101.f, 105.f, 110.f, 118.f };
+
+  Size  textSize08( 120.0f, 60.0f );
+  float positions08[] = { 8.f, 25.f, 34.f, 39.f, 55.f, 65.f, 69.f, 78.f, 88.f, 104.f, 112.f };
+
+  Size  textSize09( 100.0f, 60.0f );
+  float positions09[] = { 5.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f  };
+
+  Size  textSize10( 100.0f, 60.0f );
+  float positions10[] = { 5.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f };
+
+  Size  textSize11( 120.0f, 60.0f );
+  float positions11[] = { 119.0f, 112.0f, 98.0f, 89.0f, 80.0f, 74.0f, 63.0f, 58.0f, 53.0f, 45.0f, 36.0f, 31.0f, 112.0f, 103.0f, 93.0f };
+
+  Size  textSize12( 110.0f, 60.0f );
+  float positions12[] = { 115.0f, 108.0f, 94.0f, 85.0f, 76.0f, 70.0f, 60.0f, 54.0f, 50.0f, 41.0f, 32.0f };
+
+  Size  textSize13( 110.0f, 60.0f );
+  float positions13[] = { 113.0f, 106.0f, 92.0f, 83.0f, 74.0f, 68.0f, 58.0f, 52.0f, 48.0f, 39.0f, 30.0f, 25.0f, 106.0f };
+
+  Size  textSize14( 110.0f, 60.0f );
+  float positions14[] = { 113.0f, 106.0f, 92.0f, 83.0f, 74.0f, 68.0f, 58.0f, 52.0f, 48.0f, 39.0f, 30.0f, 25.0f, 106.0f };
+
+  Size  textSize15( 120.0f, 60.0f );
+  float positions15[] = { 125.f, 112.f, 107.f, 105.f, 98.f, 95.f, 85.f, 76.f, 71.f, 61.f, 54.f, 51.f, 46.f };
+
+  Size  textSize16( 110.0f, 60.0f );
+  float positions16[] = { 89.f, 81.f, 78.f, 67.f, 59.f, 54.f, 44.f, 37.f, 33.f, 27.f, 24.f, 12.f, 7.f, 2.f, 0.f };
+
+  Size  textSize17( 110.0f, 60.0f );
+  float positions17[] = { 105.f, 92.f, 87.f, 85.f, 78.f, 75.f, 65.f, 56.f, 51.f, 41.f, 34.f, 31.f, 26.f };
+
+  Size  textSize18( 110.0f, 60.0f );
+  float positions18[] = { 105.f, 92.f, 87.f, 85.f, 78.f, 75.f, 65.f, 56.f, 51.f, 41.f, 34.f, 31.f, 26.f };
+
+  Size  textSize19( 120.0f, 50.0f );
+  float positions19[] = { 0.f, 11.f, 23.f, 32.f, 42.f, 52.f, 62.f, 73.f, 83.f, 95.f };
+
+  Size  textSize20( 120.0f, 60.0f );
+  float positions20[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 0.f, 10.f, 19.f, 29.f, 39.f, 46.f, 50.f, 68.f };
+
+  Size  textSize21( 120.0f, 60.0f );
+  float positions21[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f, 86.f, 96.f, 106.f, 113.f, 0.f, 15.f, 25.f, 34.f, 39.f, 55.f, 65.f, 69.f, 78.f, 90.f };
+
+  Size  textSize22( 110.0f, 60.0f );
+  float positions22[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 67.f, 77.f, 0.f, 10.f, 20.f, 26.f, 31.f, 46.f, 56.f, 65.f, 72.f };
+
+  Size  textSize23( 110.0f, 60.0f );
+  float positions23[] = { 0.f, 12.f, 21.f, 26.f, 30.f, 39.f, 45.f, 57.f, 61.f, 0.f, 10.f, 19.f, 29.f, 39.f, 46.f, 50.f, 68.f };
+
+  Size  textSize24( 120.0f, 60.0f );
+  float positions24[] = { 137.0f, 131.0f, 116.0f, 108.0f, 99.0f, 93.0f, 82.0f, 77.0f, 72.0f, 63.0f, 55.0f };
+
+  Size  textSize25( 110.0f, 60.0f );
+  float positions25[] = { 107.f, 100.f, 86.f, 77.f, 68.f, 62.f, 52.f, 46.f, 42.f, 33.f, 24.f, 18.f, 8.f, 0.f, 95.f, 90.f, 87.f, 81.f, 78.f, 67.f, 59.f, 54.f, 44.f, 37.f, 33.f, 27.f, 24.f, 9.f };
+
+  Size  textSize26( 110.0f, 60.0f );
+  float positions26[] = { 117.0f, 111.0f, 96.0f, 88.0f, 79.0f, 73.0f, 62.0f, 57.0f, 52.0f, 43.0f, 35.0f };
+
+  Size  textSize27( 110.0f, 60.0f );
+  float positions27[] = { 117.0f, 111.0f, 96.0f, 88.0f, 79.0f, 73.0f, 62.0f, 57.0f, 52.0f, 43.0f, 35.0f };
+
+  Size  textSize28( 120.0f, 30.0f );
+  float positions28[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f, 61.0f, 67.0f, 77.0f, 86.0f, 98.0f };
+
+  Size  textSize29( 120.0f, 30.0f );
+  float positions29[] = { 2.0f, 20.0f, 29.0f, 39.0f, 44.0f, 60.0f, 69.0f, 74.0f, 83.0f, 92.0f, 108.0f };
+
+  Size  textSize30( 120.0f, 30.0f );
+  float positions30[] = { 0.0f, 12.0f, 21.0f, 26.0f, 30.0f, 39.0f, 45.0f, 57.0f };
+
+
+  struct ElideData data[] =
+  {
+    {
+      "void text",
+      "",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+    {
+      "void text",
+      "",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize00,
+      0u,
+      0u,
+      nullptr
+    },
+
+   //END LTR cases
+
+    {
+      "EllipsisPosition: TextEditor: Basic case Mulitlines LineWrap-WORD LTR END",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize01,
+      2u,
+      22u,
+      positions01
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize02,
+      3u,
+      29u,
+      positions02
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize03,
+      3u,
+      40u,
+      positions03
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHAN LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize04,
+      3u,
+      32u,
+      positions04
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize05,
+      3u,
+      28u,
+      positions05
+    },
+
+   //START LTR cases
+
+    {
+      "EllipsisPosition: TextEditor: Basic case Mulitlines LineWrap-WORD LTR START",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize06,
+      2u,
+      23u,
+      positions06
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize07,
+      3u,
+      33u,
+      positions07
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize08,
+      3u,
+      37u,
+      positions08
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHAN LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize09,
+      3u,
+      25u,
+      positions09
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize10,
+      3u,
+      25u,
+      positions10
+    },
+
+  //END RTL cases
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize11,
+      3u,
+      41u,
+      positions11
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize12,
+      3u,
+      42u,
+      positions12
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHENATION RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize13,
+      3u,
+      39u,
+      positions13
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED RTL END",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize14,
+      3u,
+      39u,
+      positions14
+    },
+
+   //START RTL cases
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize15,
+      3u,
+      33u,
+      positions15
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize16,
+      3u,
+      30u,
+      positions16
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHENATION RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize17,
+      3u,
+      33u,
+      positions17
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED RTL START",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize18,
+      3u,
+      33u,
+      positions18
+    },
+
+//MIDDLE LTR cases
+
+    {
+      "EllipsisPosition: TextEditor: Basic case Mulitlines LineWrap-WORD LTR MIDDLE",
+      "A0123456789 B0123456789 C0123456789 D0123456789 ",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize19,
+      2u,
+      22u,
+      positions19
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize20,
+      3u,
+      24u,
+      positions20
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize21,
+      3u,
+      36u,
+      positions21
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHAN LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize22,
+      3u,
+      27u,
+      positions22
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize23,
+      3u,
+      24u,
+      positions23
+    },
+
+//MIDDLE RTL cases
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-WORD RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize24,
+      3u,
+      31u,
+      positions24
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-CHARACTER RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::CHARACTER,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize25,
+      3u,
+      30u,
+      positions25
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-HYPHENATION RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::HYPHENATION,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize26,
+      3u,
+      31u,
+      positions26
+    },
+
+    {
+      "EllipsisPosition: TextEditor: Mulitlines LineWrap-MIXED RTL MIDDLE",
+      "السلام عليكم مرحبا اهلا هذا اختبار شكرا للمساعدة",
+      true,
+      DevelText::LineWrap::MIXED,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize27,
+      3u,
+      31u,
+      positions27
+    },
+
+    {
+      "EllipsisPosition: TextEditor: One-Line for Mulitlines LineWrap-WORD LTR END",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::END,
+      false,
+      textSize28,
+      1u,
+      13u,
+      positions28
+    },
+
+    {
+      "EllipsisPosition: TextEditor: One-Line for Mulitlines LineWrap-WORD LTR START",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::START,
+      false,
+      textSize29,
+      1u,
+      11u,
+      positions29
+    },
+
+    {
+      "EllipsisPosition: TextEditor: One-Line for Mulitlines LineWrap-WORD LTR MIDDLE",
+      "Hello Hi Experimen Welcome Hello Hi Experimen Welcome" ,
+      true,
+      DevelText::LineWrap::WORD,
+      DevelText::EllipsisPosition::MIDDLE,
+      false,
+      textSize30,
+      1u,
+      12u,
+      positions30
+    },
+
+  };
+  const unsigned int numberOfTests = 33u;
+
+  for( unsigned int index = 0u; index < numberOfTests; ++index )
+  {
+    ToolkitTestApplication application;
+    if( !ElideTestTextView( data[index] ) )
+    {
+      tet_result(TET_FAIL);
+    }
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index ccc8463..402cc40 100755 (executable)
@@ -91,7 +91,9 @@ bool LayoutTextTest( const LayoutTextData& data )
                    textModel,
                    metrics,
                    false,
-                   data.wrapMode );
+                   data.wrapMode,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   Vector<LineRun>& lines = textModel->mVisualModel->mLines;
 
@@ -157,7 +159,7 @@ int UtcDaliTextHyphenWrapping(void)
   Vector<FontDescriptionRun> fontDescriptionRuns;
   fontDescriptionRuns.PushBack( fontDescriptionRun1 );
   Size textArea(65.0f, 200.f);
-  
+
   LineRun line1 =
   {
     { 0u, 5u },
@@ -184,7 +186,7 @@ int UtcDaliTextHyphenWrapping(void)
     false,
     false
   };
-  
+
   Vector<LineRun> lines;
   lines.PushBack( line1 );
   lines.PushBack( line2 );
@@ -237,7 +239,7 @@ int UtcDaliTextMixedWrapping(void)
   Vector<FontDescriptionRun> fontDescriptionRuns;
   fontDescriptionRuns.PushBack( fontDescriptionRun1 );
   Size textArea(72.0f, 200.f);
-  
+
   LineRun line1 =
   {
     { 0u, 3u },
@@ -277,7 +279,7 @@ int UtcDaliTextMixedWrapping(void)
     false,
     false
   };
-  
+
   Vector<LineRun> lines;
   lines.PushBack( line1 );
   lines.PushBack( line2 );
index 8bdecaa..f670d49 100755 (executable)
@@ -41,21 +41,22 @@ const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
 
 struct LayoutTextData
 {
-  std::string          description;
-  std::string          text;
-  Size                 textArea;
-  unsigned int         numberOfFonts;
-  FontDescriptionRun*  fontDescriptions;
-  Size                 layoutSize;
-  unsigned int         totalNumberOfGlyphs;
-  float*               positions;
-  unsigned int         numberOfLines;
-  LineRun*             lines;
-  Layout::Engine::Type layout;
-  unsigned int         startIndex;
-  unsigned int         numberOfGlyphs;
-  bool                 ellipsis:1;
-  bool                 updated:1;
+  std::string                                       description;
+  std::string                                       text;
+  Size                                              textArea;
+  unsigned int                                      numberOfFonts;
+  FontDescriptionRun*                               fontDescriptions;
+  Size                                              layoutSize;
+  unsigned int                                      totalNumberOfGlyphs;
+  float*                                            positions;
+  unsigned int                                      numberOfLines;
+  LineRun*                                          lines;
+  Layout::Engine::Type                              layout;
+  unsigned int                                      startIndex;
+  unsigned int                                      numberOfGlyphs;
+  bool                                              ellipsis:1;
+  DevelText::EllipsisPosition::Type                 ellipsisPosition;
+  bool                                              updated:1;
 };
 
 void Print( const LineRun& line )
@@ -109,7 +110,9 @@ bool LayoutTextTest( const LayoutTextData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -162,7 +165,6 @@ bool LayoutTextTest( const LayoutTextData& data )
   textModel->mHorizontalAlignment = Text::HorizontalAlignment::BEGIN;
   textModel->mLineWrapMode = LineWrap::WORD;
   textModel->mIgnoreSpacesAfterText = true;
-  textModel->mMatchSystemLanguageDirection = false;
   Layout::Parameters layoutParameters( data.textArea,
                                        textModel );
 
@@ -180,7 +182,8 @@ bool LayoutTextTest( const LayoutTextData& data )
   const bool updated = engine.LayoutText( layoutParameters,
                                           layoutSize,
                                           data.ellipsis,
-                                          isAutoScroll );
+                                          isAutoScroll,
+                                          data.ellipsisPosition );
 
   // 4) Compare the results.
 
@@ -365,7 +368,9 @@ bool AlignTest( const AlignData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -502,6 +507,7 @@ int UtcDaliTextLayoutNoText(void)
     0u,
     0u,
     false,
+    DevelText::EllipsisPosition::END,
     false
   };
 
@@ -556,6 +562,7 @@ int UtcDaliTextLayoutSmallTextArea01(void)
     0u,
     11u,
     false,
+    DevelText::EllipsisPosition::END,
     false
   };
 
@@ -627,6 +634,7 @@ int UtcDaliTextLayoutSmallTextArea02(void)
     0u,
     11u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -775,6 +783,7 @@ int UtcDaliTextLayoutMultilineText01(void)
     0u,
     48u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -989,6 +998,7 @@ int UtcDaliTextLayoutMultilineText02(void)
     0u,
     55u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -1093,6 +1103,7 @@ int UtcDaliTextLayoutMultilineText03(void)
     0u,
     29u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -1180,6 +1191,7 @@ int UtcDaliTextLayoutMultilineText04(void)
     0u,
     13u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -1296,6 +1308,7 @@ int UtcDaliTextLayoutMultilineText05(void)
     0u,
     17u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -1384,6 +1397,7 @@ int UtcDaliTextLayoutMultilineText06(void)
     0u,
     10u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -1487,6 +1501,7 @@ int UtcDaliTextLayoutMultilineText07(void)
     0u,
     9u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -2062,6 +2077,7 @@ int UtcDaliTextUpdateLayout01(void)
     0u,
     64u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -2637,6 +2653,7 @@ int UtcDaliTextUpdateLayout02(void)
     64u,
     64u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3212,6 +3229,7 @@ int UtcDaliTextUpdateLayout03(void)
     128u,
     64u,
     false,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3289,6 +3307,7 @@ int UtcDaliTextLayoutEllipsis01(void)
     0u,
     51u,
     true,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3381,6 +3400,7 @@ int UtcDaliTextLayoutEllipsis02(void)
     0u,
     51u,
     true,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3524,6 +3544,7 @@ int UtcDaliTextLayoutEllipsis03(void)
     0u,
     72u,
     true,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3682,6 +3703,7 @@ int UtcDaliTextLayoutEllipsis04(void)
     0u,
     72u,
     true,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -3757,6 +3779,7 @@ int UtcDaliTextLayoutEllipsis05(void)
     0u,
     11u,
     true,
+    DevelText::EllipsisPosition::END,
     true
   };
 
@@ -5378,6 +5401,7 @@ int UtcDaliTextLayoutGetGlyphMetrics(void)
       0u,
       1u,
       false,
+      DevelText::EllipsisPosition::END,
       true
     },
     {
@@ -5395,6 +5419,7 @@ int UtcDaliTextLayoutGetGlyphMetrics(void)
       0u,
       2u,
       false,
+      DevelText::EllipsisPosition::END,
       true
     },
    {
@@ -5412,6 +5437,7 @@ int UtcDaliTextLayoutGetGlyphMetrics(void)
       0u,
       2u,
       false,
+      DevelText::EllipsisPosition::END,
       true
     }
   };
index 52c8808..8c056dd 100755 (executable)
@@ -141,7 +141,9 @@ bool ShapeInfoTest( const ShapeInfoData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index fc4f9ac..b9de8c1 100755 (executable)
@@ -604,10 +604,10 @@ int UtcDaliTextViewModelElideText02(void)
   float positions01[] = { 0.f, 8.f, 16.f, 26.f, 34.f, 43.f, 47.f, 58.f, 64.0f };
 
   Size textSize02( 80.f, 100.f );
-  float positions02[] = { 69.f, 63.f, 58.f, 50.f, 45.f, 41.f, 32.f, 23.f, 9.f };
+  float positions02[] = { 69.f, 63.f, 58.f, 50.f, 45.f, 41.f, 32.f, 23.f, 5.f };
 
   Size textSize03( 80.f, 100.f );
-  float positions03[] = { 54.f, 47.f, 44.f, 41.f, 36.f, 29.f, 25.f, 20.f, 13.f, 8.f, 4.f, 6.f };
+  float positions03[] = { 72.f, 65.f, 61.f, 59.f, 53.f, 47.f, 43.f, 38.f, 30.f, 25.f, 21.f, 7.f };
 
   Size textSize04( 80.f, 10.f );
   float positions04[] = { 2.f };
index 09c5078..0b18d11 100755 (executable)
@@ -90,13 +90,13 @@ int UtcDaliTextEditorMarkupUnderline(void)
   uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
 
   Toolkit::Internal::TextEditor& textEditorImpl = GetImpl( textEditor );
-  const Text::Length numberOfUnderlineRuns = textEditorImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns();
+  const Text::Length numberOfUnderlineRuns = textEditorImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
   DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION );
 
   Vector<GlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
-  textEditorImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+  textEditorImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
 
   //ABC are underlined
   DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION);
@@ -184,7 +184,7 @@ int UtcDaliTextEditorBackgroundTag(void)
   application.Render();
 
   Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor );
-  const ColorIndex* const backgroundColorIndicesBuffer = editorImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+  const ColorIndex* const backgroundColorIndicesBuffer = editorImpl.GetTextController()->GetTextModel()->GetBackgroundColorIndices();
 
   DALI_TEST_CHECK( backgroundColorIndicesBuffer );
 
@@ -226,7 +226,7 @@ int UtcDaliTextEditorTextWithSpan(void)
   DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
 
   Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor );
-  const ColorIndex* const colorIndicesBuffer1 = editorImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer1 = editorImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer1 );
 
@@ -245,7 +245,7 @@ int UtcDaliTextEditorTextWithSpan(void)
   application.SendNotification();
   application.Render();
 
-  const ColorIndex* const colorIndicesBuffer2 = editorImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer2 = editorImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer2 );
 
@@ -262,4 +262,39 @@ int UtcDaliTextEditorTextWithSpan(void)
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliTextEditorControlBackgroundColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextEditorControlBackgroundColor\n");
+
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK(editor);
+
+  Vector4 backgroundColor;
+
+  editor.SetProperty(TextEditor::Property::TEXT, "Background Color");
+  application.GetScene().Add(editor);
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextEditor& editorImpl = GetImpl(editor);
+  ControllerPtr controller = editorImpl.GetTextController();
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // Default color is transparent
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::TRANSPARENT, TEST_LOCATION);
+
+  // Set background color to red
+  editor.SetBackgroundColor(Color::RED);
+  application.SendNotification();
+  application.Render();
+
+  // Should be red
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::RED, TEST_LOCATION);
+
+  END_TEST;
+}
index 1fbc13e..7cf4084 100755 (executable)
@@ -172,13 +172,13 @@ int UtcDaliTextFieldMarkupUnderline(void)
   uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
 
   Toolkit::Internal::TextField& textFieldImpl = GetImpl( textField );
-  const Text::Length numberOfUnderlineRuns = textFieldImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns();
+  const Text::Length numberOfUnderlineRuns = textFieldImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
   DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION );
 
   Vector<GlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
-  textFieldImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+  textFieldImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
 
   //ABC are underlined
   DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION);
@@ -268,7 +268,7 @@ int UtcDaliTextFieldBackgroundTag(void)
   application.Render();
 
   Toolkit::Internal::TextField& fieldImpl = GetImpl( field );
-  const ColorIndex* const backgroundColorIndicesBuffer = fieldImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+  const ColorIndex* const backgroundColorIndicesBuffer = fieldImpl.GetTextController()->GetTextModel()->GetBackgroundColorIndices();
 
   DALI_TEST_CHECK( backgroundColorIndicesBuffer );
 
@@ -284,6 +284,40 @@ int UtcDaliTextFieldBackgroundTag(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextFieldEllipsisInternalAPIs(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs ");
+  TextField textField = TextField::New();
+
+  Toolkit::Internal::TextField& textFieldImpl = GetImpl( textField );
+  Text::ViewInterface& view = textFieldImpl.GetTextController()->GetView();
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - ELLIPSIS Disabled");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS, false);
+  DALI_TEST_EQUALS( textField.GetProperty< bool >( DevelTextField::Property::ELLIPSIS ), false, TEST_LOCATION );
+  DALI_TEST_CHECK(!(view.IsTextElideEnabled()));
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - ELLIPSIS Enabled");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS, true);
+  DALI_TEST_EQUALS( textField.GetProperty< bool >( DevelTextField::Property::ELLIPSIS ), true, TEST_LOCATION );
+  DALI_TEST_CHECK(view.IsTextElideEnabled());
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - GetStartIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( view.GetStartIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - GetEndIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( view.GetEndIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - GetFirstMiddleIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( view.GetFirstMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisInternalAPIs - GetSecondMiddleIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( view.GetSecondMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+
+  END_TEST;
+}
 int UtcDaliTextFieldTextWithSpan(void)
 {
   ToolkitTestApplication application;
@@ -310,7 +344,7 @@ int UtcDaliTextFieldTextWithSpan(void)
   DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
 
   Toolkit::Internal::TextField& fieldImpl = GetImpl( field );
-  const ColorIndex* const colorIndicesBuffer1 = fieldImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer1 = fieldImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer1 );
 
@@ -329,7 +363,7 @@ int UtcDaliTextFieldTextWithSpan(void)
   application.SendNotification();
   application.Render();
 
-  const ColorIndex* const colorIndicesBuffer2 = fieldImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer2 = fieldImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer2 );
 
@@ -346,4 +380,39 @@ int UtcDaliTextFieldTextWithSpan(void)
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliTextFieldControlBackgroundColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextFieldControlBackgroundColor\n");
+
+  TextField field = TextField::New();
+  DALI_TEST_CHECK(field);
+
+  Vector4 backgroundColor;
+
+  field.SetProperty(TextField::Property::TEXT, "Background Color");
+  application.GetScene().Add(field);
+  application.SendNotification();
+  application.Render();
+
+  Toolkit::Internal::TextField& fieldImpl = GetImpl(field);
+  ControllerPtr controller = fieldImpl.GetTextController();
+  Controller::Impl& controllerImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  // Default color is transparent
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::TRANSPARENT, TEST_LOCATION);
+
+  // Set background color to red
+  field.SetBackgroundColor(Color::RED);
+  application.SendNotification();
+  application.Render();
+
+  // Should be red
+  controllerImpl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+  DALI_TEST_EQUALS(backgroundColor, Color::RED, TEST_LOCATION);
+
+  END_TEST;
+}
index e03fec1..b72dcb4 100755 (executable)
@@ -24,6 +24,8 @@
 #include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/rendering/text-typesetter.h>
+#include <dali-toolkit/internal/text/rendering/view-model.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -47,13 +49,13 @@ int UtcDaliTextLabelMarkupUnderline(void)
   uint32_t expectedNumberOfUnderlinedGlyphs = 5u;
 
   Toolkit::Internal::TextLabel& textLabelImpl = GetImpl( textLabel );
-  const Text::Length numberOfUnderlineRuns = textLabelImpl.getController()->GetTextModel()->GetNumberOfUnderlineRuns();
+  const Text::Length numberOfUnderlineRuns = textLabelImpl.GetTextController()->GetTextModel()->GetNumberOfUnderlineRuns();
 
   DALI_TEST_EQUALS( numberOfUnderlineRuns, expectedNumberOfUnderlinedGlyphs, TEST_LOCATION );
 
   Vector<GlyphRun> underlineRuns;
   underlineRuns.Resize(numberOfUnderlineRuns);
-  textLabelImpl.getController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
+  textLabelImpl.GetTextController()->GetTextModel()->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns);
 
   //ABC are underlined
   DALI_TEST_EQUALS( underlineRuns[0u].glyphIndex, 0u, TEST_LOCATION);
@@ -83,7 +85,7 @@ int UtcDaliTextLabelBackgroundTag(void)
   application.Render();
 
   Toolkit::Internal::TextLabel& labelImpl = GetImpl( label );
-  const ColorIndex* const backgroundColorIndicesBuffer = labelImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+  const ColorIndex* const backgroundColorIndicesBuffer = labelImpl.GetTextController()->GetTextModel()->GetBackgroundColorIndices();
 
   DALI_TEST_CHECK( backgroundColorIndicesBuffer );
 
@@ -99,6 +101,62 @@ int UtcDaliTextLabelBackgroundTag(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextlabelEllipsisInternalAPIs(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs ");
+  TextLabel textLabel = TextLabel::New();
+
+  Toolkit::Internal::TextLabel& textLabelImpl = GetImpl( textLabel );
+  const ModelInterface* const textModel = textLabelImpl.GetTextController()->GetTextModel();
+
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - ELLIPSIS Disabled");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS, false);
+  DALI_TEST_EQUALS( textLabel.GetProperty< bool >( DevelTextLabel::Property::ELLIPSIS ), false, TEST_LOCATION );
+  DALI_TEST_CHECK(!(textModel->IsTextElideEnabled()));
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - ELLIPSIS Enabled");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS, true);
+  DALI_TEST_EQUALS( textLabel.GetProperty< bool >( DevelTextLabel::Property::ELLIPSIS ), true, TEST_LOCATION );
+  DALI_TEST_CHECK(textModel->IsTextElideEnabled());
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetStartIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( textModel->GetStartIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetEndIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( textModel->GetEndIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetFirstMiddleIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( textModel->GetFirstMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetSecondMiddleIndexOfElidedGlyphs Default");
+  DALI_TEST_EQUALS( textModel->GetSecondMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  // Tests the rendering controller has been created.
+  TypesetterPtr typesetter = Typesetter::New( textModel );
+  DALI_TEST_CHECK(typesetter);
+
+  // Tests the view model has been created.
+  ViewModel* model = typesetter->GetViewModel();
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - IsTextElideEnabled ViewModel");
+  DALI_TEST_CHECK(model->IsTextElideEnabled());
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetStartIndexOfElidedGlyphs ViewModel");
+  DALI_TEST_EQUALS( model->GetStartIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetEndIndexOfElidedGlyphs ViewModel");
+  DALI_TEST_EQUALS( model->GetEndIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetFirstMiddleIndexOfElidedGlyphs ViewModel");
+  DALI_TEST_EQUALS( model->GetFirstMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisInternalAPIs - GetSecondMiddleIndexOfElidedGlyphs ViewModel");
+  DALI_TEST_EQUALS( model->GetSecondMiddleIndexOfElidedGlyphs(), 0u, TEST_LOCATION );
+
+  END_TEST;
+}
 int UtcDaliTextLabelTextWithSpan(void)
 {
   ToolkitTestApplication application;
@@ -125,7 +183,7 @@ int UtcDaliTextLabelTextWithSpan(void)
   DALI_TEST_GREATER(spanSize.width, originalSize.width, TEST_LOCATION);
 
   Toolkit::Internal::TextLabel& labelImpl = GetImpl( label );
-  const ColorIndex* const colorIndicesBuffer1 = labelImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer1 = labelImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer1 );
 
@@ -144,7 +202,7 @@ int UtcDaliTextLabelTextWithSpan(void)
   application.SendNotification();
   application.Render();
 
-  const ColorIndex* const colorIndicesBuffer2 = labelImpl.getController()->GetTextModel()->GetColorIndices();
+  const ColorIndex* const colorIndicesBuffer2 = labelImpl.GetTextController()->GetTextModel()->GetColorIndices();
 
   DALI_TEST_CHECK( colorIndicesBuffer2 );
 
@@ -161,4 +219,4 @@ int UtcDaliTextLabelTextWithSpan(void)
   DALI_TEST_EQUALS( colorIndicesBuffer2[7], 0u, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
index 43157ff..2453771 100644 (file)
@@ -80,7 +80,9 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
@@ -165,7 +167,9 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
                    textModel,
                    metrics,
                    false,
-                   LineWrap::WORD );
+                   LineWrap::WORD,
+                   false,
+                   Toolkit::DevelText::EllipsisPosition::END );
 
   LogicalModelPtr logicalModel = textModel->mLogicalModel;
   VisualModelPtr visualModel = textModel->mVisualModel;
index 962ad8e..c57ec89 100644 (file)
@@ -42,6 +42,18 @@ int UtcDaliVisualUrlConstructor(void)
   DALI_TEST_EQUALS( true, visualUrl3.IsValid(), TEST_LOCATION );
   DALI_TEST_EQUALS( visualUrl3.GetType(), VisualUrl::GIF, TEST_LOCATION );
   DALI_TEST_EQUALS( visualUrl3.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION );
+
+  VisualUrl visualUrl4("dali://0");
+  visualUrl4 = visualUrl;
+  DALI_TEST_EQUALS( true, visualUrl4.IsValid(), TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl4.GetType(), VisualUrl::GIF, TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl4.GetProtocolType(), VisualUrl::LOCAL, TEST_LOCATION );
+
+  VisualUrl visualUrl5("dali://1");
+  visualUrl4 = visualUrl5;
+  DALI_TEST_EQUALS( true, visualUrl4.IsValid(), TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl4.GetType(), VisualUrl::REGULAR_IMAGE, TEST_LOCATION );
+  DALI_TEST_EQUALS( visualUrl4.GetProtocolType(), VisualUrl::TEXTURE, TEST_LOCATION );
   END_TEST;
 }
 
index 9b2691c..0e984f0 100755 (executable)
@@ -26,6 +26,7 @@ SET(TC_SOURCES
   utc-Dali-Image.cpp
   utc-Dali-ImageView.cpp
   utc-Dali-ImageVisual.cpp
+  utc-Dali-ImageUrl.cpp
   utc-Dali-JsonParser.cpp
   utc-Dali-KeyInputFocusManager.cpp
   utc-Dali-PageTurnView.cpp
index 4b465a7..4532c6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -149,16 +149,23 @@ void TestEndPan(TestApplication& application, Vector2 pos, uint32_t time)
   application.ProcessEvent(GenerateSingleTouch(PointState::UP, pos, time));
 }
 
+void TestTriggerTap(TestApplication& application)
+{
+  application.GetPlatform().TriggerTimer();
+}
+
 void TestGenerateTap(TestApplication& application, float x, float y, uint32_t time_down)
 {
   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(x, y), time_down));
   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(x, y), time_down + 20));
+  TestTriggerTap(application);
 }
 
 void TestGenerateTwoPointTap(TestApplication& application, float x1, float y1, float x2, float y2, uint32_t time_down)
 {
   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(x1, y1), PointState::DOWN, Vector2(x2, y2), time_down));
   application.ProcessEvent(GenerateDoubleTouch(PointState::UP, Vector2(x1, y1), PointState::UP, Vector2(x2, y2), time_down + 20));
+  TestTriggerTap(application);
 }
 
 void TestGenerateRotation(TestApplication& application)
index e6e367d..cb3b1a6 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_GESTURE_GENERATOR_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -94,6 +94,11 @@ void TestMovePan(TestApplication& application, Vector2 pos, uint32_t time = 400)
 void TestEndPan(TestApplication& application, Vector2 pos, uint32_t time = 500);
 
 /**
+ * Triggers the timer to begin a tap gesture
+ */
+void TestTriggerTap(TestApplication& application);
+
+/**
  * Produces a single point tap gesture with a 20ms interval
  */
 void TestGenerateTap(TestApplication& application, float x = 20.0f, float y = 20.0f, uint32_t time_down = 100);
index d59f29f..8493992 100644 (file)
@@ -240,9 +240,10 @@ bool TestGraphicsReflection::GetNamedUniform(const std::string& name, Dali::Grap
   return true;
 }
 
-std::vector<Dali::Graphics::UniformInfo> TestGraphicsReflection::GetSamplers() const
+const std::vector<Dali::Graphics::UniformInfo>& TestGraphicsReflection::GetSamplers() const
 {
-  return std::vector<Dali::Graphics::UniformInfo>{};
+  static std::vector<Dali::Graphics::UniformInfo> samplers{};
+  return samplers;
 }
 
 Graphics::ShaderLanguage TestGraphicsReflection::GetLanguage() const
index 7af052e..2147cae 100644 (file)
@@ -28,22 +28,22 @@ class TestGraphicsReflection : public Graphics::Reflection
 public:
   TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector<UniformData>& customUniforms);
 
-  uint32_t                                   GetVertexAttributeLocation(const std::string& name) const override;
-  Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeFormat(uint32_t location) const override;
-  std::string                                GetVertexAttributeName(uint32_t location) const override;
-  std::vector<uint32_t>                      GetVertexAttributeLocations() const override;
-  uint32_t                                   GetUniformBlockCount() const override;
-  uint32_t                                   GetUniformBlockBinding(uint32_t index) const override;
-  uint32_t                                   GetUniformBlockSize(uint32_t index) const override;
-  bool                                       GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const override;
-  std::vector<uint32_t>                      GetUniformBlockLocations() const override;
-  std::string                                GetUniformBlockName(uint32_t blockIndex) const override;
-  uint32_t                                   GetUniformBlockMemberCount(uint32_t blockIndex) const override;
-  std::string                                GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const override;
-  uint32_t                                   GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const override;
-  bool                                       GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const override;
-  std::vector<Dali::Graphics::UniformInfo>   GetSamplers() const override;
-  Graphics::ShaderLanguage                   GetLanguage() const override;
+  uint32_t                                        GetVertexAttributeLocation(const std::string& name) const override;
+  Dali::Graphics::VertexInputAttributeFormat      GetVertexAttributeFormat(uint32_t location) const override;
+  std::string                                     GetVertexAttributeName(uint32_t location) const override;
+  std::vector<uint32_t>                           GetVertexAttributeLocations() const override;
+  uint32_t                                        GetUniformBlockCount() const override;
+  uint32_t                                        GetUniformBlockBinding(uint32_t index) const override;
+  uint32_t                                        GetUniformBlockSize(uint32_t index) const override;
+  bool                                            GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const override;
+  std::vector<uint32_t>                           GetUniformBlockLocations() const override;
+  std::string                                     GetUniformBlockName(uint32_t blockIndex) const override;
+  uint32_t                                        GetUniformBlockMemberCount(uint32_t blockIndex) const override;
+  std::string                                     GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const override;
+  uint32_t                                        GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const override;
+  bool                                            GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const override;
+  const std::vector<Dali::Graphics::UniformInfo>& GetSamplers() const override;
+  Graphics::ShaderLanguage                        GetLanguage() const override;
 
 public: // Test methods
   void SetAttributes(std::vector<std::string> locations)
index 33a27b5..2ccf2c1 100755 (executable)
@@ -52,6 +52,7 @@ public:
     mDelayTime(0),
     mDroppedFrames(0),
     mFrameRate( 60.0f ),
+    mTestFrameDrop(false),
     mNeedDroppedFrames(false),
     mEventThreadCallback( new EventThreadCallback( MakeCallback( this, &VectorAnimationRenderer::OnTriggered ) ) )
   {
@@ -79,6 +80,7 @@ public:
     {
       // Change total frame number for test
       mTotalFrameNumber = 200;
+      mTestFrameDrop = true;
     }
     return true;
   }
@@ -112,10 +114,10 @@ public:
 
   bool Render( uint32_t frameNumber )
   {
-    if(mDelayTime != 0)
+    if(mTestFrameDrop)
     {
       std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int32_t>(mDelayTime)));
-      mDelayTime = 0;
+      mTestFrameDrop = false;
       mNeedDroppedFrames = true;
     }
     else if(mNeedDroppedFrames)
@@ -199,6 +201,7 @@ public:
   uint32_t mDelayTime;
   uint32_t mDroppedFrames;
   float mFrameRate;
+  bool mTestFrameDrop;
   bool mNeedDroppedFrames;
   Dali::VectorAnimationRenderer::UploadCompletedSignalType mUploadCompletedSignal;
   std::unique_ptr< EventThreadCallback > mEventThreadCallback;
index b30d3b6..e6f47a8 100755 (executable)
@@ -118,6 +118,22 @@ public:
 
   void SetProxyUri( const std::string& uri ) override
   {
+    mockProxyUri = uri;
+  }
+
+  std::string GetProxyUri() const override
+  {
+    return mockProxyUri;
+  }
+
+  void SetProxyBypassRule(const std::string& proxy, const std::string& bypass) override
+  {
+    mockBypassRule = bypass;
+  }
+
+  std::string GetProxyBypassRule() const override
+  {
+    return mockBypassRule;
   }
 
   void SetDefaultProxyAuth( const std::string& username, const std::string& password ) override
@@ -126,6 +142,12 @@ public:
 
   void SetCertificateFilePath( const std::string& certificatePath ) override
   {
+    mockCertificateFilePath = certificatePath;
+  }
+
+  std::string GetCertificateFilePath() const override
+  {
+    return mockCertificateFilePath;
   }
 
   void DeleteAllWebDatabase() override
@@ -218,36 +240,32 @@ public:
 
   void EnableCache( bool cacheEnabled ) override
   {
+    mockCacheEnabled = cacheEnabled;
   }
 
   bool IsCacheEnabled() const override
   {
-    return true;
+    return mockCacheEnabled;
   }
 
-  std::string GetContextCertificateFile() const override
+  void SetAppId(const std::string& appID) override
   {
-    return "test";
   }
 
-  void SetContextAppId(const std::string& appID) override
-  {
-  }
-
-  bool SetContextAppVersion(const std::string& appVersion) override
+  bool SetAppVersion(const std::string& appVersion) override
   {
     return true;
   }
 
-  void SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType) override
+  void SetApplicationType(const Dali::WebEngineContext::ApplicationType applicationType) override
   {
   }
 
-  void SetContextTimeOffset(float timeOffset) override
+  void SetTimeOffset(float timeOffset) override
   {
   }
 
-  void SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime) override
+  void SetTimeZoneOffset(float timeZoneOffset, float daylightSavingTime) override
   {
   }
 
@@ -261,11 +279,12 @@ public:
 
   void SetDefaultZoomFactor(float zoomFactor) override
   {
+    mockZoomFactor = zoomFactor;
   }
 
-  float GetContextDefaultZoomFactor() const override
+  float GetDefaultZoomFactor() const override
   {
-    return 0;
+    return mockZoomFactor;
   }
 
   bool DeleteAllApplicationCache() override
@@ -290,20 +309,6 @@ public:
   {
   }
 
-  std::string GetContextProxy() const override
-  {
-    return "test";
-  }
-
-  void SetContextProxy(const std::string& proxy, const std::string& bypass) override
-  {
-  }
-
-  std::string GetProxyBypassRule() const override
-  {
-    return "test";
-  }
-
   bool FreeUnusedMemory() override
   {
     return true;
@@ -318,6 +323,11 @@ public:
 
 private:
   Dali::WebEngineContext::CacheModel mockModel;
+  std::string                        mockProxyUri;
+  std::string                        mockBypassRule;
+  std::string                        mockCertificateFilePath;
+  bool                               mockCacheEnabled;
+  float                              mockZoomFactor;
 };
 
 class MockWebEngineCookieManager : public Dali::WebEngineCookieManager
@@ -751,11 +761,6 @@ public:
     return result;
   }
 
-  Dali::Vector2 GetPosition() const override
-  {
-    return Dali::Vector2(100, 100);
-  }
-
   bool RemoveItem(WebEngineContextMenuItem& item) override
   {
     return true;
@@ -1148,8 +1153,6 @@ class WebEngine: public Dali::BaseObject
 {
 public:
 
-  using JavaScriptEvaluatedResultCallback = std::function<void(const std::string&)>;
-
   WebEngine()
     : mUrl()
     , mCurrentPlusOnePos( 0 )
@@ -1217,7 +1220,7 @@ public:
     ConnectToGlobalSignal( &OnLoadUrl );
   }
 
-  const std::string& GetUrl() const
+  std::string GetUrl() const
   {
     return mUrl;
   }
@@ -1325,7 +1328,7 @@ public:
     ConnectToGlobalSignal( &OnClearHistory );
   }
 
-  const std::string& GetUserAgent() const
+  std::string GetUserAgent() const
   {
     return mUserAgent;
   }
@@ -1449,84 +1452,84 @@ public:
     }
   }
 
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadStartedSignal()
+  Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType& FrameRenderedSignal()
   {
-    return mPageLoadStartedSignal;
+    return mFrameRenderedSignal;
   }
 
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadInProgressSignal()
+  void RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
   {
-    return mPageLoadInProgressSignal;
+    mPageLoadStartedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType& PageLoadFinishedSignal()
+  void RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
   {
-    return mPageLoadFinishedSignal;
+    mPageLoadInProgressCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType& PageLoadErrorSignal()
+  void RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
   {
-    return mPageLoadErrorSignal;
+    mPageLoadFinishedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType& ScrollEdgeReachedSignal()
+  void RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
   {
-    return mScrollEdgeReachedSignal;
+    mPageLoadErrorCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineUrlChangedSignalType& UrlChangedSignal()
+  void RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
   {
-    return mUrlChangedSignal;
+    mScrollEdgeReachedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineFormRepostDecisionSignalType& FormRepostDecisionSignal()
+  void RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
   {
-    return mFormRepostDecisionSignal;
+    mUrlChangedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType& FrameRenderedSignal()
+  void RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback)
   {
-    return mFrameRenderedSignal;
+    mFormRepostDecidedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineRequestInterceptorSignalType& RequestInterceptorSignal()
+  void RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback)
   {
-    return mRequestInterceptorSignal;
+    mRequestInterceptorCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& ConsoleMessageSignal()
+  void RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback)
   {
-    return mConsoleMessageSignal;
+    mConsoleMessageCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal()
+  void RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback)
   {
-    return mResponsePolicyDecisionSignal;
+    mResponsePolicyDecisionCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineCertificateSignalType& CertificateConfirmSignal()
+  void RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
   {
-    return mCertificateConfirmSignal;
+    mCertificateConfirmCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineCertificateSignalType& SslCertificateChangedSignal()
+  void RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
   {
-    return mSslCertificateChangedSignal;
+    mSslCertificateChangedCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineHttpAuthHandlerSignalType& HttpAuthHandlerSignal()
+  void RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback)
   {
-    return mHttpAuthHandlerSignal;
+    mHttpAuthHandlerCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineContextMenuCustomizedSignalType& ContextMenuCustomizedSignal()
+  void RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback)
   {
-    return mContextMenuCustomizedSignal;
+    mContextMenuShownCallback = callback;
   }
 
-  Dali::WebEnginePlugin::WebEngineContextMenuItemSelectedSignalType& ContextMenuItemSelectedSignal()
+  void RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback)
   {
-    return mContextMenuItemSelectedSignal;
+    mContextMenuHiddenCallback = callback;
   }
 
   std::string              mUrl;
@@ -1534,22 +1537,7 @@ public:
   size_t                   mCurrentPlusOnePos;
   std::string              mUserAgent;
 
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType                mPageLoadStartedSignal;
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType                mPageLoadInProgressSignal;
-  Dali::WebEnginePlugin::WebEnginePageLoadSignalType                mPageLoadFinishedSignal;
-  Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType           mPageLoadErrorSignal;
-  Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType       mScrollEdgeReachedSignal;
-  Dali::WebEnginePlugin::WebEngineUrlChangedSignalType              mUrlChangedSignal;
-  Dali::WebEnginePlugin::WebEngineFormRepostDecisionSignalType      mFormRepostDecisionSignal;
-  Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType           mFrameRenderedSignal;
-  Dali::WebEnginePlugin::WebEngineRequestInterceptorSignalType      mRequestInterceptorSignal;
-  Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType          mConsoleMessageSignal;
-  Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType  mResponsePolicyDecisionSignal;
-  Dali::WebEnginePlugin::WebEngineCertificateSignalType             mCertificateConfirmSignal;
-  Dali::WebEnginePlugin::WebEngineCertificateSignalType             mSslCertificateChangedSignal;
-  Dali::WebEnginePlugin::WebEngineHttpAuthHandlerSignalType         mHttpAuthHandlerSignal;
-  Dali::WebEnginePlugin::WebEngineContextMenuCustomizedSignalType   mContextMenuCustomizedSignal;
-  Dali::WebEnginePlugin::WebEngineContextMenuItemSelectedSignalType mContextMenuItemSelectedSignal;
+  Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType mFrameRenderedSignal;
 
   bool  mEvaluating;
   float mPageZoomFactor;
@@ -1564,14 +1552,31 @@ public:
   WebEngineCookieManager*   mockWebEngineCookieManager;
   WebEngineSettings*        mockWebEngineSettings;
 
-  std::vector<JavaScriptEvaluatedResultCallback>         mResultCallbacks;
-  Dali::WebEnginePlugin::JavaScriptAlertCallback         mJavaScriptAlertCallback;
-  Dali::WebEnginePlugin::JavaScriptConfirmCallback       mJavaScriptConfirmCallback;
-  Dali::WebEnginePlugin::JavaScriptPromptCallback        mJavaScriptPromptCallback;
-  Dali::WebEnginePlugin::ScreenshotCapturedCallback      mScreenshotCapturedCallback;
-  Dali::WebEnginePlugin::VideoPlayingCallback            mVideoPlayingCallback;
-  Dali::WebEnginePlugin::GeolocationPermissionCallback   mGeolocationPermissionCallback;
-  Dali::WebEnginePlugin::WebEngineHitTestCreatedCallback mHitTestCreatedCallback;
+  std::vector<Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback> mResultCallbacks;
+
+  Dali::WebEnginePlugin::WebEnginePageLoadCallback               mPageLoadStartedCallback;
+  Dali::WebEnginePlugin::WebEnginePageLoadCallback               mPageLoadInProgressCallback;
+  Dali::WebEnginePlugin::WebEnginePageLoadCallback               mPageLoadFinishedCallback;
+  Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback          mPageLoadErrorCallback;
+  Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback      mScrollEdgeReachedCallback;
+  Dali::WebEnginePlugin::WebEngineUrlChangedCallback             mUrlChangedCallback;
+  Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback      mFormRepostDecidedCallback;
+  Dali::WebEnginePlugin::WebEngineFrameRenderedCallback          mFrameRenderedCallback;
+  Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback     mRequestInterceptorCallback;
+  Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback mConsoleMessageCallback;
+  Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback  mResponsePolicyDecisionCallback;
+  Dali::WebEnginePlugin::WebEngineCertificateCallback            mCertificateConfirmCallback;
+  Dali::WebEnginePlugin::WebEngineCertificateCallback            mSslCertificateChangedCallback;
+  Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback        mHttpAuthHandlerCallback;
+  Dali::WebEnginePlugin::WebEngineContextMenuShownCallback       mContextMenuShownCallback;
+  Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback      mContextMenuHiddenCallback;
+  Dali::WebEnginePlugin::JavaScriptAlertCallback                 mJavaScriptAlertCallback;
+  Dali::WebEnginePlugin::JavaScriptConfirmCallback               mJavaScriptConfirmCallback;
+  Dali::WebEnginePlugin::JavaScriptPromptCallback                mJavaScriptPromptCallback;
+  Dali::WebEnginePlugin::ScreenshotCapturedCallback              mScreenshotCapturedCallback;
+  Dali::WebEnginePlugin::VideoPlayingCallback                    mVideoPlayingCallback;
+  Dali::WebEnginePlugin::GeolocationPermissionCallback           mGeolocationPermissionCallback;
+  Dali::WebEnginePlugin::WebEngineHitTestCreatedCallback         mHitTestCreatedCallback;
 };
 
 
@@ -1612,35 +1617,77 @@ bool OnLoadUrl()
     }
     gInstance->mHistory.push_back( gInstance->mUrl );
     gInstance->mCurrentPlusOnePos++;
-    gInstance->mPageLoadStartedSignal.Emit( gInstance->mUrl );
-    gInstance->mPageLoadInProgressSignal.Emit( gInstance->mUrl );
-    gInstance->mPageLoadFinishedSignal.Emit( gInstance->mUrl );
-    gInstance->mUrlChangedSignal.Emit( "http://new-test" );
-
-    std::shared_ptr<Dali::WebEngineFormRepostDecision> repostDecision(new MockWebEngineFormRepostDecision());
-    gInstance->mFormRepostDecisionSignal.Emit(std::move(repostDecision));
+    if (gInstance->mPageLoadStartedCallback)
+    {
+      gInstance->mPageLoadStartedCallback( gInstance->mUrl );
+    }
+    if (gInstance->mPageLoadInProgressCallback)
+    {
+      gInstance->mPageLoadInProgressCallback( gInstance->mUrl );
+    }
+    if (gInstance->mPageLoadFinishedCallback)
+    {
+      gInstance->mPageLoadFinishedCallback( gInstance->mUrl );
+    }
+    if (gInstance->mPageLoadErrorCallback)
+    {
+      std::unique_ptr<Dali::WebEngineLoadError> error(new MockWebEngineLoadError(gInstance->mUrl));
+      gInstance->mPageLoadErrorCallback(std::move(error));
+    }
+    if (gInstance->mUrlChangedCallback)
+    {
+      gInstance->mUrlChangedCallback( "http://new-test" );
+    }
+    if (gInstance->mFormRepostDecidedCallback)
+    {
+      std::unique_ptr<Dali::WebEngineFormRepostDecision> repostDecision(new MockWebEngineFormRepostDecision());
+      gInstance->mFormRepostDecidedCallback(std::move(repostDecision));
+    }
     gInstance->mFrameRenderedSignal.Emit();
-    std::shared_ptr<Dali::WebEngineRequestInterceptor> interceptor(new MockWebEngineRequestInterceptor());
-    gInstance->mRequestInterceptorSignal.Emit(std::move(interceptor));
-
-    std::shared_ptr<Dali::WebEngineLoadError> error(new MockWebEngineLoadError(gInstance->mUrl));
-    gInstance->mPageLoadErrorSignal.Emit(std::move(error));
-    std::shared_ptr<Dali::WebEngineConsoleMessage> message(new MockWebEngineConsoleMessage());
-    gInstance->mConsoleMessageSignal.Emit(std::move(message));
-    std::shared_ptr<Dali::WebEnginePolicyDecision> policyDecision(new MockWebEnginePolicyDecision());
-    gInstance->mResponsePolicyDecisionSignal.Emit(std::move(policyDecision));
-
-    std::shared_ptr<Dali::WebEngineCertificate> certificate(new MockWebEngineCertificate());
-    gInstance->mCertificateConfirmSignal.Emit(std::move(certificate));
-    std::shared_ptr<Dali::WebEngineCertificate> sslCertificate(new MockWebEngineCertificate());
-    gInstance->mSslCertificateChangedSignal.Emit(std::move(sslCertificate));
-    std::shared_ptr<Dali::WebEngineHttpAuthHandler> handler(new MockWebEngineHttpAuthHandler());
-    gInstance->mHttpAuthHandlerSignal.Emit(std::move(handler));
-
-    std::shared_ptr<Dali::WebEngineContextMenu> menu(new MockWebEngineContextMenu());
-    gInstance->mContextMenuCustomizedSignal.Emit(std::move(menu));
-    std::shared_ptr<Dali::WebEngineContextMenuItem> item(new MockWebEngineContextMenuItem());
-    gInstance->mContextMenuItemSelectedSignal.Emit(std::move(item));
+    if (gInstance->mFrameRenderedCallback)
+    {
+      gInstance->mFrameRenderedCallback();
+    }
+    if (gInstance->mRequestInterceptorCallback)
+    {
+      std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor(new MockWebEngineRequestInterceptor());
+      gInstance->mRequestInterceptorCallback(std::move(interceptor));
+    }
+    if (gInstance->mConsoleMessageCallback)
+    {
+      std::unique_ptr<Dali::WebEngineConsoleMessage> message(new MockWebEngineConsoleMessage());
+      gInstance->mConsoleMessageCallback(std::move(message));
+    }
+    if (gInstance->mResponsePolicyDecisionCallback)
+    {
+      std::unique_ptr<Dali::WebEnginePolicyDecision> policyDecision(new MockWebEnginePolicyDecision());
+      gInstance->mResponsePolicyDecisionCallback(std::move(policyDecision));
+    }
+    if (gInstance->mCertificateConfirmCallback)
+    {
+      std::unique_ptr<Dali::WebEngineCertificate> certificate(new MockWebEngineCertificate());
+      gInstance->mCertificateConfirmCallback(std::move(certificate));
+    }
+    if (gInstance->mSslCertificateChangedCallback)
+    {
+      std::unique_ptr<Dali::WebEngineCertificate> sslCertificate(new MockWebEngineCertificate());
+      gInstance->mSslCertificateChangedCallback(std::move(sslCertificate));
+    }
+    if (gInstance->mHttpAuthHandlerCallback)
+    {
+      std::unique_ptr<Dali::WebEngineHttpAuthHandler> handler(new MockWebEngineHttpAuthHandler());
+      gInstance->mHttpAuthHandlerCallback(std::move(handler));
+    }
+    if (gInstance->mContextMenuShownCallback)
+    {
+      std::unique_ptr<Dali::WebEngineContextMenu> menu(new MockWebEngineContextMenu());
+      gInstance->mContextMenuShownCallback(std::move(menu));
+    }
+    if (gInstance->mContextMenuHiddenCallback)
+    {
+      std::unique_ptr<Dali::WebEngineContextMenu> hiddenMenu(new MockWebEngineContextMenu());
+      gInstance->mContextMenuHiddenCallback(std::move(hiddenMenu));
+    }
   }
   return false;
 }
@@ -1649,9 +1696,9 @@ bool OnScrollEdge()
 {
   DisconnectFromGlobalSignal( &OnScrollEdge );
 
-  if( gInstance )
+  if( gInstance && gInstance->mScrollEdgeReachedCallback )
   {
-    gInstance->mScrollEdgeReachedSignal.Emit( Dali::WebEnginePlugin::ScrollEdge::BOTTOM );
+    gInstance->mScrollEdgeReachedCallback( Dali::WebEnginePlugin::ScrollEdge::BOTTOM );
   }
 
   return false;
@@ -1941,7 +1988,7 @@ Dali::PixelData WebEngine::GetFavicon() const
   return Internal::Adaptor::GetImplementation( *this ).GetFavicon();
 }
 
-const std::string& WebEngine::GetUrl()
+std::string WebEngine::GetUrl() const
 {
   return Internal::Adaptor::GetImplementation( *this ).GetUrl();
 }
@@ -2134,7 +2181,7 @@ void WebEngine::RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::Geo
   Internal::Adaptor::GetImplementation( *this ).RegisterGeolocationPermissionCallback(callback);
 }
 
-const std::string& WebEngine::GetUserAgent() const
+std::string WebEngine::GetUserAgent() const
 {
   return Internal::Adaptor::GetImplementation( *this ).GetUserAgent();
 }
@@ -2264,84 +2311,84 @@ void WebEngine::EnableKeyEvents( bool enabled )
 {
 }
 
-Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadStartedSignal()
+Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType& WebEngine::FrameRenderedSignal()
 {
-  return Internal::Adaptor::GetImplementation( *this ).PageLoadStartedSignal();
+  return Internal::Adaptor::GetImplementation(*this).FrameRenderedSignal();
 }
 
-Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadInProgressSignal()
+void WebEngine::RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).PageLoadInProgressSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadStartedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEnginePageLoadSignalType& WebEngine::PageLoadFinishedSignal()
+void WebEngine::RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).PageLoadFinishedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadInProgressCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEnginePageLoadErrorSignalType& WebEngine::PageLoadErrorSignal()
+void WebEngine::RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).PageLoadErrorSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadFinishedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineScrollEdgeReachedSignalType& WebEngine::ScrollEdgeReachedSignal()
+void WebEngine::RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).ScrollEdgeReachedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterPageLoadErrorCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineUrlChangedSignalType& WebEngine::UrlChangedSignal()
+void WebEngine::RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).UrlChangedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterScrollEdgeReachedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineFormRepostDecisionSignalType& WebEngine::FormRepostDecisionSignal()
+void WebEngine::RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).FormRepostDecisionSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterUrlChangedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineFrameRenderedSignalType& WebEngine::FrameRenderedSignal()
+void WebEngine::RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).FrameRenderedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterFormRepostDecidedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineRequestInterceptorSignalType& WebEngine::RequestInterceptorSignal()
+void WebEngine::RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).RequestInterceptorSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterRequestInterceptorCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& WebEngine::ConsoleMessageSignal()
+void WebEngine::RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).ConsoleMessageSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterConsoleMessageReceivedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal()
+void WebEngine::RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).ResponsePolicyDecisionSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterResponsePolicyDecidedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal()
+void WebEngine::RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).CertificateConfirmSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterCertificateConfirmedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::SslCertificateChangedSignal()
+void WebEngine::RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).SslCertificateChangedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterSslCertificateChangedCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineHttpAuthHandlerSignalType& WebEngine::HttpAuthHandlerSignal()
+void WebEngine::RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback)
 {
-  return Internal::Adaptor::GetImplementation(*this).HttpAuthHandlerSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterHttpAuthHandlerCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineContextMenuCustomizedSignalType& WebEngine::ContextMenuCustomizedSignal()
+void WebEngine::RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).ContextMenuCustomizedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterContextMenuShownCallback(callback);
 }
 
-Dali::WebEnginePlugin::WebEngineContextMenuItemSelectedSignalType& WebEngine::ContextMenuItemSelectedSignal()
+void WebEngine::RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback)
 {
-  return Internal::Adaptor::GetImplementation( *this ).ContextMenuItemSelectedSignal();
+  Internal::Adaptor::GetImplementation( *this ).RegisterContextMenuHiddenCallback(callback);
 }
 
 } // namespace Dali;
index d2be632..5d46d68 100644 (file)
@@ -1593,23 +1593,24 @@ int UtcDaliAnimatedVectorImageVisualFrameDrops(void)
   application.SendNotification();
   application.Render();
 
+  // Trigger count is 1 - render the first frame
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
   Property::Map attributes;
   DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes);
 
+  // Make delay to drop frames
+  Test::VectorAnimationRenderer::DelayRendering(170); // longer than 16.6 * 10frames
+
   application.SendNotification();
   application.Render();
 
-  // Trigger count is 1 - render the first frame
+  // Wait for calculating frame drops
   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
 
-  // Make delay to drop frames
-  Test::VectorAnimationRenderer::DelayRendering(170); // longer than 16.6 * 10frames
-
   // Check dropped frame
-  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
-
   uint32_t frames = Test::VectorAnimationRenderer::GetDroppedFrames();
-  DALI_TEST_CHECK(frames >= 9);
+  DALI_TEST_CHECK(frames > 0);
 
   END_TEST;
 }
index f19d181..37e3b5e 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/public-api/rendering/frame-buffer.h>
 #include <dali/public-api/adaptor-framework/native-image-source.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -51,9 +52,9 @@ int UtcDaliImageConvertFrameBufferToUrl1(void)
   FrameBuffer frameBuffer = FrameBuffer::New( width, height, FrameBuffer::Attachment::NONE );
 
   DALI_TEST_CHECK( frameBuffer );
-  std::string url = Dali::Toolkit::Image::GenerateUrl( frameBuffer, Pixel::Format::RGBA8888, width, height );
+  ImageUrl url = Dali::Toolkit::Image::GenerateUrl( frameBuffer, Pixel::Format::RGBA8888, width, height );
 
-  DALI_TEST_CHECK( url.size() > 0u );
+  DALI_TEST_CHECK( url.GetUrl().size() > 0u );
 
   END_TEST;
 }
@@ -71,7 +72,7 @@ int UtcDaliImageConvertFrameBufferToUrl2(void)
   Texture texture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height );
   frameBuffer.AttachColorTexture( texture );
 
-  DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( frameBuffer, 0 ).size() > 0u );
+  DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( frameBuffer, 0 ).GetUrl().size() > 0u );
 
   END_TEST;
 }
@@ -89,7 +90,7 @@ int UtcDaliImageConvertPixelDataToUrl(void)
   unsigned char* buffer= reinterpret_cast<unsigned char*>( malloc( bufferSize ) );
   PixelData pixelData = PixelData::New( buffer, bufferSize, width, height, Pixel::RGB888, PixelData::FREE );
 
-  DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( pixelData ).size() > 0u );
+  DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( pixelData ).GetUrl().size() > 0u );
 
   END_TEST;
 }
@@ -106,7 +107,7 @@ int UtcDaliImageConvertNativeImageSourceToUrl(void)
   {
     NativeImageSourcePtr nativeImageSource = NativeImageSource::New(width, height, NativeImageSource::COLOR_DEPTH_DEFAULT );
 
-    DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( nativeImageSource ).size() > 0u );
+    DALI_TEST_CHECK( Dali::Toolkit::Image::GenerateUrl( nativeImageSource ).GetUrl().size() > 0u );
   }
   catch(Dali::DaliException& e)
   {
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageUrl.cpp
new file mode 100644 (file)
index 0000000..09cc7cd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021 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-test-suite-utils.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+int UtcImageUrlConstructor(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline(" UtcImageUrlValid ");
+
+  // Test default constructor.
+  ImageUrl imageUrl;
+  DALI_TEST_CHECK( !imageUrl );
+
+  // Test object creation
+  Texture image = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u); // test texture
+  imageUrl = ImageUrl::New(image);
+  DALI_TEST_CHECK( imageUrl );
+
+  // Test copy constructor
+  ImageUrl ImageUrlCopy( imageUrl );
+  DALI_TEST_CHECK( ImageUrlCopy );
+
+  // Test down cast
+  BaseHandle baseUrl;
+  baseUrl = imageUrl;
+  ImageUrl downcastUrl = ImageUrl::DownCast( baseUrl );
+  DALI_TEST_CHECK( downcastUrl );
+  END_TEST;
+}
\ No newline at end of file
index fdf1697..40ca439 100644 (file)
@@ -25,6 +25,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include "dummy-control.h"
 
@@ -424,7 +425,8 @@ int UtcDaliImageVisualWithNativeImage(void)
   tet_infoline( "Use Native Image as url" );
 
   NativeImageSourcePtr nativeImageSource = NativeImageSource::New(500, 500, NativeImageSource::COLOR_DEPTH_DEFAULT);
-  std::string url = Dali::Toolkit::Image::GenerateUrl(nativeImageSource);
+  ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSource);
+  std::string url = imageUrl.GetUrl();
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -462,6 +464,62 @@ int UtcDaliImageVisualWithNativeImage(void)
   END_TEST;
 }
 
+int UtcDaliImageVisualWithNativeImageRemoved(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "Use Native Image as url" );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  NativeImageSourcePtr nativeImageSource = NativeImageSource::New(500, 500, NativeImageSource::COLOR_DEPTH_DEFAULT);
+  ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(nativeImageSource);
+  std::string url = imageUrl.GetUrl();
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK( factory );
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Toolkit::Visual::Property::TYPE,  Visual::IMAGE );
+  propertyMap.Insert( ImageVisual::Property::URL,  url );
+
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  DummyControl actor = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(  DummyControl::Property::TEST_VISUAL, visual );
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+  application.GetScene().Add( actor );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION );
+
+  tet_infoline( "No delete texture because reference count is not zero" );
+  imageUrl.Reset();
+  application.GetScene().Remove( actor );
+  dummyImpl.UnregisterVisual( DummyControl::Property::TEST_VISUAL );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 0, TEST_LOCATION );
+
+  tet_infoline( "Delete texture because reference count is zero" );
+  visual.Reset();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( textureTrace.CountMethod("DeleteTextures"), 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
 int UtcDaliImageVisualTextureReuse1(void)
 {
   ToolkitTestApplication application;
index 053b25c..37c6ded 100644 (file)
@@ -1689,6 +1689,9 @@ int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void)
   focusChangedCallback.Reset();
 
   // without set the navigation properties, but we can focus move
+  // enable the default algorithm
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, true);
+  DALI_TEST_CHECK( Dali::Toolkit::DevelKeyboardFocusManager::IsDefaultAlgorithmEnabled(manager) );
 
   // Move the focus towards right
   // button1 -- [button2]
@@ -1898,4 +1901,95 @@ int UtcDaliKeyboardFocusManagerSetAndGetCurrentFocusActorInTouchMode(void)
   DALI_TEST_CHECK(manager.GetCurrentFocusActor() == second);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliKeyboardFocusManagerEnableDefaultAlgorithm(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline(" UtcDaliKeyboardFocusManagerEnableDefaultAlgorithm");
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "KeyboardFocusManager" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+
+  bool focusChangedSignalVerified = false;
+  FocusChangedCallback focusChangedCallback(focusChangedSignalVerified);
+  manager.FocusChangedSignal().Connect( &focusChangedCallback, &FocusChangedCallback::Callback );
+
+  PushButton button1 = PushButton::New();
+  PushButton button2 = PushButton::New();
+
+  button1.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+  button2.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+
+  button1.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+  button2.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+
+  application.GetScene().Add(button1);
+  application.GetScene().Add(button2);
+
+  // set position
+  // button1 -- button2
+  button1.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
+  button2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 0.0f));
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Set the focus to the button1
+  // [button1] -- button2
+  DALI_TEST_CHECK(manager.SetCurrentFocusActor(button1) == true);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == button1);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
+  focusChangedCallback.Reset();
+
+  // without set the navigation properties, but we can focus move
+  // enable the default algorithm
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, true);
+  DALI_TEST_CHECK( Dali::Toolkit::DevelKeyboardFocusManager::IsDefaultAlgorithmEnabled(manager) );
+
+  // Move the focus towards right
+  // button1 -- [button2]
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+
+  // Confirm whether focus is moved to button2
+  DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button1);
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button2);
+  focusChangedCallback.Reset();
+
+  // disable the default algorithm
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, false);
+  DALI_TEST_CHECK( !Dali::Toolkit::DevelKeyboardFocusManager::IsDefaultAlgorithmEnabled(manager) );
+
+  // Move the focus towards left, The focus move will fail because the default algorithm is disabled.
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == false);
+
+  // enable the default algorithm
+  Dali::Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm(manager, true);
+  DALI_TEST_CHECK( Dali::Toolkit::DevelKeyboardFocusManager::IsDefaultAlgorithmEnabled(manager) );
+
+  // Move the focus towards left, The focus move will success because the default algorithm is enabled.
+  // [button1] -- button2
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
+  // Confirm whether focus is moved to button2
+  DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2);
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
+  focusChangedCallback.Reset();
+
+
+  END_TEST;
+}
index 31d1762..b518743 100644 (file)
@@ -107,6 +107,7 @@ const char* const PROPERTY_NAME_FONT_SIZE_SCALE                      = "fontSize
 const char* const PROPERTY_NAME_GRAB_HANDLE_COLOR                    = "grabHandleColor";
 const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP             = "enableGrabHandlePopup";
 const char* const PROPERTY_NAME_INPUT_METHOD_SETTINGS                = "inputMethodSettings";
+const char* const PROPERTY_NAME_INPUT_FILTER                         = "inputFilter";
 
 const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
 const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color.
@@ -135,6 +136,8 @@ const std::string DEFAULT_DEVICE_NAME("hwKeyboard");
 static bool gAnchorClickedCallBackCalled;
 static bool gAnchorClickedCallBackNotCalled;
 static bool gTextChangedCallBackCalled;
+static bool gInputFilteredAcceptedCallbackCalled;
+static bool gInputFilteredRejectedCallbackCalled;
 static bool gInputStyleChangedCallbackCalled;
 static bool gMaxCharactersCallBackCalled;
 static Dali::Toolkit::TextEditor::InputStyle::Mask gInputStyleMask;
@@ -187,6 +190,20 @@ static void TestMaxLengthReachedCallback( TextEditor control )
   gMaxCharactersCallBackCalled = true;
 }
 
+static void TestInputFilteredCallback(TextEditor control, Toolkit::InputFilter::Property::Type type)
+{
+  tet_infoline(" TestInputFilteredCallback");
+
+  if(type == Toolkit::InputFilter::Property::ACCEPTED)
+  {
+    gInputFilteredAcceptedCallbackCalled = true;
+  }
+  else if(type == Toolkit::InputFilter::Property::REJECTED)
+  {
+    gInputFilteredRejectedCallbackCalled = true;
+  }
+}
+
 // Generate a KeyEvent to send to Core.
 Integration::KeyEvent GenerateKey( const std::string& keyName,
                                    const std::string& logicalKey,
@@ -515,6 +532,7 @@ int UtcDaliTextEditorGetPropertyP(void)
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_GRAB_HANDLE_COLOR ) == DevelTextEditor::Property::GRAB_HANDLE_COLOR );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP ) == DevelTextEditor::Property::ENABLE_GRAB_HANDLE_POPUP );
   DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_METHOD_SETTINGS ) == DevelTextEditor::Property::INPUT_METHOD_SETTINGS );
+  DALI_TEST_CHECK( editor.GetPropertyIndex( PROPERTY_NAME_INPUT_FILTER ) == DevelTextEditor::Property::INPUT_FILTER );
 
   END_TEST;
 }
@@ -969,6 +987,21 @@ int UtcDaliTextEditorSetPropertyP(void)
   DALI_TEST_CHECK( map[ "VARIATION" ].Get( variation ) );
   DALI_TEST_EQUALS( inputVariation, variation, TEST_LOCATION );
 
+  // Check the input filter property
+  Property::Map inputFilterMapSet;
+  Property::Map inputFilterMapGet;
+  inputFilterMapSet[InputFilter::Property::ACCEPTED] = "[\\w]";
+  inputFilterMapSet[InputFilter::Property::REJECTED] = "[\\d]";
+
+  editor.SetProperty(DevelTextEditor::Property::INPUT_FILTER, inputFilterMapSet);
+
+  inputFilterMapGet = editor.GetProperty<Property::Map>(DevelTextEditor::Property::INPUT_FILTER);
+  DALI_TEST_EQUALS(inputFilterMapGet.Count(), inputFilterMapSet.Count(), TEST_LOCATION);
+
+  // Clear
+  inputFilterMapSet.Clear();
+  editor.SetProperty(DevelTextEditor::Property::INPUT_FILTER, inputFilterMapSet);
+
   application.SendNotification();
   application.Render();
 
@@ -3105,6 +3138,58 @@ int utcDaliTextEditorMaxCharactersReached(void)
   END_TEST;
 }
 
+int utcDaliTextEditorInputFiltered(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextEditorInputFiltered");
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK(editor);
+
+  application.GetScene().Add(editor);
+
+  Property::Map inputFilter;
+
+  // Only digit is accepted.
+  inputFilter[InputFilter::Property::ACCEPTED] = "[\\d]";
+
+  // Set input filter to TextEditor.
+  editor.SetProperty(DevelTextEditor::Property::INPUT_FILTER, inputFilter);
+
+  editor.SetKeyInputFocus();
+
+  // connect to the input filtered signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  DevelTextEditor::InputFilteredSignal(editor).Connect(&TestInputFilteredCallback);
+  bool inputFilteredSignal = false;
+  editor.ConnectSignal(testTracker, "inputFiltered", CallbackFunctor(&inputFilteredSignal));
+
+  gInputFilteredAcceptedCallbackCalled = false;
+
+  application.ProcessEvent(GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ));
+
+  DALI_TEST_CHECK(gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(inputFilteredSignal);
+
+  // Word is rejected.
+  inputFilter[InputFilter::Property::ACCEPTED] = "";
+  inputFilter[InputFilter::Property::REJECTED] = "[\\w]";
+
+  // Set input filter to TextEditor.
+  editor.SetProperty(DevelTextEditor::Property::INPUT_FILTER, inputFilter);
+
+  editor.SetKeyInputFocus();
+
+  inputFilteredSignal = false;
+  gInputFilteredRejectedCallbackCalled = false;
+
+  application.ProcessEvent(GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  DALI_TEST_CHECK(gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(inputFilteredSignal);
+
+  END_TEST;
+}
+
 int UtcDaliTextEditorSelectWholeText(void)
 {
   ToolkitTestApplication application;
@@ -3770,4 +3855,64 @@ int UtcDaliTextEditorHyphenWrapMode(void)
   DALI_TEST_EQUALS( lineCount, 3, TEST_LOCATION );
 
   END_TEST;
+}
+
+int UtcDaliToolkitTextEditorEllipsisPositionProperty(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty ");
+  TextEditor textEditor = TextEditor::New();
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Default is END");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to START");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to MIDDLE");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::MIDDLE);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to END");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to START using integer");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, 1);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to MIDDLE using integer");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, 2);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextEditorEllipsisPositionProperty - Change to END using integer");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, 0);
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - uppercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "START");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - uppercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "MIDDLE");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - uppercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "END");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - lowercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "start");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - lowercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "middle");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - lowercase");
+  textEditor.SetProperty(DevelTextEditor::Property::ELLIPSIS_POSITION, "end");
+  DALI_TEST_EQUALS( textEditor.GetProperty< int >( DevelTextEditor::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  END_TEST;
 }
\ No newline at end of file
index 2044ea3..f6e24e6 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include "toolkit-clipboard.h"
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -106,6 +107,7 @@ const char* const PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP             = "enableGr
 const char* const PROPERTY_NAME_BACKGROUND                           = "textBackground";
 const char* const PROPERTY_NAME_FONT_SIZE_SCALE                      = "fontSizeScale";
 const char* const PROPERTY_NAME_GRAB_HANDLE_COLOR                    = "grabHandleColor";
+const char* const PROPERTY_NAME_INPUT_FILTER                         = "inputFilter";
 
 const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
 const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color.
@@ -125,6 +127,8 @@ static bool gAnchorClickedCallBackCalled;
 static bool gAnchorClickedCallBackNotCalled;
 static bool gTextChangedCallBackCalled;
 static bool gMaxCharactersCallBackCalled;
+static bool gInputFilteredAcceptedCallbackCalled;
+static bool gInputFilteredRejectedCallbackCalled;
 static bool gInputStyleChangedCallbackCalled;
 static Dali::Toolkit::TextField::InputStyle::Mask gInputStyleMask;
 
@@ -234,6 +238,20 @@ static void TestMaxLengthReachedCallback( TextField control )
   gMaxCharactersCallBackCalled = true;
 }
 
+static void TestInputFilteredCallback(TextField control, Toolkit::InputFilter::Property::Type type)
+{
+  tet_infoline(" TestInputFilteredCallback");
+
+  if(type == Toolkit::InputFilter::Property::ACCEPTED)
+  {
+    gInputFilteredAcceptedCallbackCalled = true;
+  }
+  else if(type == Toolkit::InputFilter::Property::REJECTED)
+  {
+    gInputFilteredRejectedCallbackCalled = true;
+  }
+}
+
 static void TestInputStyleChangedCallback( TextField control, TextField::InputStyle::Mask mask )
 {
   tet_infoline(" TestInputStyleChangedCallback");
@@ -526,6 +544,7 @@ int UtcDaliTextFieldGetPropertyP(void)
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_GRAB_HANDLE_POPUP ) == DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_BACKGROUND ) == DevelTextField::Property::BACKGROUND );
   DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_GRAB_HANDLE_COLOR ) == DevelTextField::Property::GRAB_HANDLE_COLOR );
+  DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_FILTER ) == DevelTextField::Property::INPUT_FILTER );
 
   END_TEST;
 }
@@ -1000,6 +1019,21 @@ int UtcDaliTextFieldSetPropertyP(void)
   field.SetProperty( DevelTextField::Property::GRAB_HANDLE_COLOR, Color::GREEN );
   DALI_TEST_EQUALS( field.GetProperty<Vector4>( DevelTextField::Property::GRAB_HANDLE_COLOR ), Color::GREEN, TEST_LOCATION );
 
+  // Check the input filter property
+  Property::Map inputFilterMapSet;
+  Property::Map inputFilterMapGet;
+  inputFilterMapSet[InputFilter::Property::ACCEPTED] = "[\\w]";
+  inputFilterMapSet[InputFilter::Property::REJECTED] = "[\\d]";
+
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilterMapSet);
+
+  inputFilterMapGet = field.GetProperty<Property::Map>(DevelTextField::Property::INPUT_FILTER);
+  DALI_TEST_EQUALS(inputFilterMapGet.Count(), inputFilterMapSet.Count(), TEST_LOCATION);
+
+  // Clear
+  inputFilterMapSet.Clear();
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilterMapSet);
+
   application.SendNotification();
   application.Render();
 
@@ -1544,6 +1578,135 @@ int utcDaliTextFieldMaxCharactersReachedN(void)
   END_TEST;
 }
 
+// Positive test for Input Filtered signal.
+int utcDaliTextFieldInputFilteredP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldInputFilteredP");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK(field);
+
+  application.GetScene().Add(field);
+
+  Property::Map inputFilter;
+
+  // Only digit is accepted.
+  inputFilter[InputFilter::Property::ACCEPTED] = "[\\d]";
+
+  // Set input filter to TextField.
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilter);
+
+  field.SetKeyInputFocus();
+
+  // connect to the input filtered signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  DevelTextField::InputFilteredSignal(field).Connect(&TestInputFilteredCallback);
+  bool inputFilteredSignal = false;
+  field.ConnectSignal(testTracker, "inputFiltered", CallbackFunctor(&inputFilteredSignal));
+
+  gInputFilteredAcceptedCallbackCalled = false;
+
+  application.ProcessEvent(GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ));
+
+  DALI_TEST_CHECK(gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(inputFilteredSignal);
+
+  // Word is rejected.
+  inputFilter[InputFilter::Property::ACCEPTED] = "";
+  inputFilter[InputFilter::Property::REJECTED] = "[\\w]";
+
+  // Set input filter to TextField.
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilter);
+
+  field.SetKeyInputFocus();
+
+  inputFilteredSignal = false;
+  gInputFilteredRejectedCallbackCalled = false;
+
+  application.ProcessEvent(GenerateKey( "a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  DALI_TEST_CHECK(gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(inputFilteredSignal);
+
+  END_TEST;
+}
+
+// Negative test for Input Filtered signal.
+int utcDaliTextFieldInputFilteredN(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldInputFilteredP");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK(field);
+
+  application.GetScene().Add(field);
+
+  Property::Map inputFilter;
+
+  // Only word is accepted.
+  inputFilter[InputFilter::Property::ACCEPTED] = "[\\w]";
+
+  // Set input filter to TextField.
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilter);
+
+  field.SetKeyInputFocus();
+
+  // connect to the input filtered signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  DevelTextField::InputFilteredSignal(field).Connect(&TestInputFilteredCallback);
+  bool inputFilteredSignal = false;
+  field.ConnectSignal(testTracker, "inputFiltered", CallbackFunctor(&inputFilteredSignal));
+
+  gInputFilteredAcceptedCallbackCalled = false;
+
+  // Key a, d should not be filtered.
+  application.ProcessEvent(GenerateKey("a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::UP, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("d", "", "d", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "d", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("d", "", "d", KEY_D_CODE, 0, 0, Integration::KeyEvent::UP, "d", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Backspace, Delete should not be filtered.
+  application.ProcessEvent(GenerateKey( "", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey( "Delete", "", "Delete", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "Delete", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(!gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(!inputFilteredSignal);
+
+  // Digit is rejected.
+  inputFilter[InputFilter::Property::ACCEPTED] = "";
+  inputFilter[InputFilter::Property::REJECTED] = "[\\d]";
+
+  field.SetProperty(DevelTextField::Property::INPUT_FILTER, inputFilter);
+
+  field.SetKeyInputFocus();
+
+  inputFilteredSignal = false;
+  gInputFilteredRejectedCallbackCalled = false;
+
+  // Key a, d should not be filtered.
+  application.ProcessEvent(GenerateKey("a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("a", "", "a", KEY_A_CODE, 0, 0, Integration::KeyEvent::UP, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("d", "", "d", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "d", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey("d", "", "d", KEY_D_CODE, 0, 0, Integration::KeyEvent::UP, "d", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Backspace, Delete should not be filtered.
+  application.ProcessEvent(GenerateKey( "", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+  application.ProcessEvent(GenerateKey( "Delete", "", "Delete", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "Delete", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE));
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(!gInputFilteredAcceptedCallbackCalled);
+  DALI_TEST_CHECK(!inputFilteredSignal);
+
+  END_TEST;
+}
+
 int utcDaliTextFieldInputStyleChanged01(void)
 {
   // The text-field emits signals when the input style changes. These changes of style are
@@ -3628,4 +3791,64 @@ int UtcDaliTextFieldAtlasLimitationIsEnabledPerformanceCases(void)
   }
 
   END_TEST;
+}
+
+int UtcDaliToolkitTextFieldEllipsisPositionProperty(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty ");
+  TextField textField = TextField::New();
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Default is END");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to START");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to MIDDLE");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::MIDDLE);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to END");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to START using integer");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, 1);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to MIDDLE using integer");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, 2);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextFieldEllipsisPositionProperty - Change to END using integer");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, 0);
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - uppercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "START");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - uppercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "MIDDLE");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - uppercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "END");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - lowercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "start");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - lowercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "middle");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - lowercase");
+  textField.SetProperty(DevelTextField::Property::ELLIPSIS_POSITION, "end");
+  DALI_TEST_EQUALS( textField.GetProperty< int >( DevelTextField::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  END_TEST;
 }
\ No newline at end of file
index f505faf..e91c2b8 100644 (file)
@@ -74,6 +74,8 @@ const char* const PROPERTY_NAME_ELLIPSIS = "ellipsis";
 const char* const PROPERTY_NAME_AUTO_SCROLL_LOOP_DELAY = "autoScrollLoopDelay";
 const char* const PROPERTY_NAME_FONT_SIZE_SCALE = "fontSizeScale";
 
+const char* const PROPERTY_NAME_ELLIPSIS_POSITION = "ellipsisPosition";
+
 const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
 const unsigned int EMOJI_FONT_SIZE = 3840u; // 60 * 64
 
@@ -341,6 +343,7 @@ int UtcDaliToolkitTextLabelGetPropertyP(void)
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ELLIPSIS ) == TextLabel::Property::ELLIPSIS );
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_AUTO_SCROLL_LOOP_DELAY ) == TextLabel::Property::AUTO_SCROLL_LOOP_DELAY );
   DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_FONT_SIZE_SCALE ) == DevelTextLabel::Property::FONT_SIZE_SCALE );
+  DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_ELLIPSIS_POSITION ) == DevelTextLabel::Property::ELLIPSIS_POSITION );
 
   END_TEST;
 }
@@ -1929,4 +1932,65 @@ int utcDaliTextLabelGetHeightForWidthChangeLineCountWhenTextChanged(void)
 
 
   END_TEST;
+}
+
+int UtcDaliToolkitTextlabelEllipsisPositionProperty(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty ");
+  TextLabel textLabel = TextLabel::New();
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Default is END");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::START);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::MIDDLE);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, DevelText::EllipsisPosition::END);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using integer");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, 1);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using integer");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, 2);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using integer");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, 0);
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - uppercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "START");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - uppercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "MIDDLE");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - uppercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "END");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to START using string - lowercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "start");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::START ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to MIDDLE using string - lowercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "middle");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::MIDDLE ), TEST_LOCATION );
+
+  tet_infoline(" UtcDaliToolkitTextlabelEllipsisPositionProperty - Change to END using string - lowercase");
+  textLabel.SetProperty(DevelTextLabel::Property::ELLIPSIS_POSITION, "end");
+  DALI_TEST_EQUALS( textLabel.GetProperty< int >( DevelTextLabel::Property::ELLIPSIS_POSITION ), static_cast< int >( Toolkit::DevelText::EllipsisPosition::END ), TEST_LOCATION );
+
+
+  END_TEST;
 }
\ No newline at end of file
index b694a69..955e15e 100755 (executable)
@@ -94,6 +94,9 @@ int UtcDaliTransitionSetGetProperty01(void)
   controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
   controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, 1.f);
   control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1);
 
   Control control2 = Control::New();
@@ -104,6 +107,9 @@ int UtcDaliTransitionSetGetProperty01(void)
   controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, -1.f);
   control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
 
   application.GetScene().Add(control1);
@@ -148,6 +154,9 @@ int UtcDaliTransitionSetGetProperty02(void)
   controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
   controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, Vector4(50.0f, 30.0f, 40.0f, 20.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, -1.f);
   control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1);
 
   Control control2 = Control::New();
@@ -158,6 +167,9 @@ int UtcDaliTransitionSetGetProperty02(void)
   controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, Vector4(32.f, 54.0f, 24.0f, 42.0f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, -1.f);
   control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
 
   application.GetScene().Add(control1);
@@ -200,6 +212,9 @@ int UtcDaliTransitionBetweenControlPair(void)
   Vector4 destinationColor(1.0f, 0.5f, 1.0f, 0.8f);
   float destinationOpacity(0.8f);
   float destinationRadius(50.f);
+  float destinationBorderlineWidth(80.0f);
+  Vector4 destinationBorderlineColor(0.5f, 1.0f, 0.5f, 0.3f);
+  float destinationBorderlineOffset(-1.0f);
   Vector4 destinationRadiusV4 = Vector4(destinationRadius, destinationRadius, destinationRadius, destinationRadius);
 
   Control control1 = Control::New();
@@ -214,6 +229,9 @@ int UtcDaliTransitionBetweenControlPair(void)
   controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
   controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 60.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, 1.f);
   control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1);
 
   Control control2 = Control::New();
@@ -228,12 +246,21 @@ int UtcDaliTransitionBetweenControlPair(void)
   controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
   control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
 
   DALI_TEST_EQUALS(destinationPosition, control2.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
   Property::Map backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
   Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
   DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+  float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   application.GetScene().Add(control1);
   application.GetScene().Add(control2);
@@ -263,6 +290,15 @@ int UtcDaliTransitionBetweenControlPair(void)
   Property::Index index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
   cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
   DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION);
 
   application.SendNotification();
   application.Render(700);
@@ -284,6 +320,15 @@ int UtcDaliTransitionBetweenControlPair(void)
   index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
   cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
   DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+  borderlineWidth = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+  borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+  borderlineOffset = renderer.GetCurrentProperty<float>(index);
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   END_TEST;
 }
@@ -294,6 +339,9 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
   tet_infoline(" UtcDaliTransitionBetweenControlPair");
 
   Vector4 destinationRadius(50.f, 30.f, 40.f, 0.f);
+  float   destinationBorderlineWidth(40.f);
+  Vector4 destinationBorderlineColor(1.0f, 0.5f, 0.2f, 0.8f);
+  float   destinationBorderlineOffset(1.f);
 
   Control control1 = Control::New();
   control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
@@ -308,11 +356,20 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
   controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
   controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
   control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
 
   Property::Map backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
   Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
   DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION);
+  float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   application.GetScene().Add(control1);
   application.GetScene().Add(control2);
@@ -339,6 +396,12 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
   backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
   cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
   DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION);
+  borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   application.SendNotification();
   application.Render(700);
@@ -353,6 +416,12 @@ int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
   backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
   cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
   DALI_TEST_EQUALS(destinationRadius, cornerRadius, TEST_LOCATION);
+  borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+  borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+  DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+  borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+  DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
 
   END_TEST;
 }
@@ -374,6 +443,9 @@ int UtcDaliTransitionBetweenImageViewPair(void)
   controlProperty1.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
   controlProperty1.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.5f, 0.5f));
   controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, 1.f);
   control1.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty1);
 
   ImageView control2 = ImageView::New();
@@ -386,6 +458,9 @@ int UtcDaliTransitionBetweenImageViewPair(void)
   controlProperty2.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
   controlProperty2.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(0.0f, 1.0f, 1.0f, 0.5f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, -1.f);
   control2.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty2);
 
   DALI_TEST_EQUALS(destinationPosition, control2.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
@@ -456,6 +531,9 @@ int UtcDaliTransitionBetweenImageViewPairWithDelay(void)
   controlProperty1.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
   controlProperty1.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.5f, 0.5f));
   controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 50.f);
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+  controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, 1.f);
   control1.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty1);
 
   ImageView control2 = ImageView::New();
@@ -468,6 +546,9 @@ int UtcDaliTransitionBetweenImageViewPairWithDelay(void)
   controlProperty2.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
   controlProperty2.Insert(Toolkit::Visual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
   controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, 30.f);
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, Vector4(0.0f, 1.0f, 1.0f, 0.5f));
+  controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, -1.f);
   control2.SetProperty(Toolkit::ImageView::Property::IMAGE, controlProperty2);
 
   DALI_TEST_EQUALS(destinationPosition, control2.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
index 4fbe8c1..4f7d8fa 100755 (executable)
@@ -61,7 +61,7 @@ static int gPageLoadStartedCallbackCalled = 0;
 static int gPageLoadInProgressCallbackCalled = 0;
 static int gPageLoadFinishedCallbackCalled = 0;
 static int gPageLoadErrorCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineLoadError> gPageLoadErrorInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineLoadError> gPageLoadErrorInstance = nullptr;
 static int gScrollEdgeReachedCallbackCalled = 0;
 static int gUrlChangedCallbackCalled = 0;
 static int gEvaluateJavaScriptCallbackCalled = 0;
@@ -74,21 +74,21 @@ static int gGeolocationPermissionCallbackCalled = 0;
 static bool gTouched = false;
 static bool gHovered = false;
 static bool gWheelEventHandled = false;
-static int gFormRepostDecisionCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineFormRepostDecision> gFormRepostDecisionInstance = nullptr;
+static int gFormRepostDecidedCallbackCalled = 0;
+static std::unique_ptr<Dali::WebEngineFormRepostDecision> gFormRepostDecidedInstance = nullptr;
 static int gFrameRenderedCallbackCalled = 0;
 static int gRequestInterceptorCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineRequestInterceptor> gRequestInterceptorInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineRequestInterceptor> gRequestInterceptorInstance = nullptr;
 static int gConsoleMessageCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineConsoleMessage> gConsoleMessageInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineConsoleMessage> gConsoleMessageInstance = nullptr;
 static int gResponsePolicyDecidedCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEnginePolicyDecision> gResponsePolicyDecisionInstance = nullptr;
+static std::unique_ptr<Dali::WebEnginePolicyDecision> gResponsePolicyDecisionInstance = nullptr;
 static int gCertificateConfirmCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineCertificate> gCertificateConfirmInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineCertificate> gCertificateConfirmInstance = nullptr;
 static int gSslCertificateChangedCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineCertificate> gSslCertificateInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineCertificate> gSslCertificateInstance = nullptr;
 static int gHttpAuthHandlerCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineHttpAuthHandler> gHttpAuthInstance = nullptr;
+static std::unique_ptr<Dali::WebEngineHttpAuthHandler> gHttpAuthInstance = nullptr;
 static int gSecurityOriginsAcquiredCallbackCalled = 0;
 static int gStorageUsageAcquiredCallbackCalled = 0;
 static int gFormPasswordsAcquiredCallbackCalled = 0;
@@ -96,10 +96,10 @@ static int gDownloadStartedCallbackCalled = 0;
 static int gMimeOverriddenCallbackCalled = 0;
 static std::vector<std::unique_ptr<Dali::WebEngineSecurityOrigin>> gSecurityOriginList;
 static std::vector<std::unique_ptr<Dali::WebEngineContext::PasswordData>> gPasswordDataList;
-static int gContextMenuCustomizedCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineContextMenu> gContextMenuInstance = nullptr;
-static int gContextMenuItemSelectedCallbackCalled = 0;
-static std::shared_ptr<Dali::WebEngineContextMenuItem> gContextMenuItemInstance = nullptr;
+static int gContextMenuShownCallbackCalled = 0;
+static std::unique_ptr<Dali::WebEngineContextMenu> gContextMenuShownInstance = nullptr;
+static int gContextMenuHiddenCallbackCalled = 0;
+static std::unique_ptr<Dali::WebEngineContextMenu> gContextMenuHiddenInstance = nullptr;
 static int gHitTestCreatedCallbackCalled = 0;
 static int gCookieManagerChangsWatchCallbackCalled = 0;
 
@@ -117,33 +117,33 @@ struct CallbackFunctor
   bool* mCallbackFlag;
 };
 
-static void OnPageLoadStarted( WebView view, const std::string& url )
+static void OnPageLoadStarted(const std::string& url)
 {
   gPageLoadStartedCallbackCalled++;
 }
 
-static void OnPageLoadInProgress( WebView view, const std::string& url )
+static void OnPageLoadInProgress(const std::string& url)
 {
   gPageLoadInProgressCallbackCalled++;
 }
 
-static void OnPageLoadFinished( WebView view, const std::string& url )
+static void OnPageLoadFinished(const std::string& url)
 {
   gPageLoadFinishedCallbackCalled++;
 }
 
-static void OnScrollEdgeReached( WebView view, Dali::WebEnginePlugin::ScrollEdge edge )
+static void OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge)
 {
   gScrollEdgeReachedCallbackCalled++;
 }
 
-static void OnResponsePolicyDecided(WebView view, std::shared_ptr<Dali::WebEnginePolicyDecision> decision)
+static void OnResponsePolicyDecided(std::unique_ptr<Dali::WebEnginePolicyDecision> decision)
 {
   gResponsePolicyDecidedCallbackCalled++;
   gResponsePolicyDecisionInstance = std::move(decision);
 }
 
-static void OnUrlChanged( WebView view, const std::string& url )
+static void OnUrlChanged(const std::string& url)
 {
   gUrlChangedCallbackCalled++;
 }
@@ -154,30 +154,30 @@ static bool OnHitTestCreated(std::unique_ptr<Dali::WebEngineHitTest> test)
   return true;
 }
 
-static void OnPageLoadError(WebView view, std::shared_ptr<Dali::WebEngineLoadError> error)
+static void OnPageLoadError(std::unique_ptr<Dali::WebEngineLoadError> error)
 {
   gPageLoadErrorCallbackCalled++;
   gPageLoadErrorInstance = std::move(error);
 }
 
-static void OnEvaluateJavaScript( const std::string& result )
+static void OnEvaluateJavaScript(const std::string& result)
 {
   gEvaluateJavaScriptCallbackCalled++;
 }
 
-static bool OnJavaScriptAlert( const std::string& result )
+static bool OnJavaScriptAlert(const std::string& result)
 {
   gJavaScriptAlertCallbackCalled++;
   return true;
 }
 
-static bool OnJavaScriptConfirm( const std::string& result )
+static bool OnJavaScriptConfirm(const std::string& result)
 {
   gJavaScriptConfirmCallbackCalled++;
   return true;
 }
 
-static bool OnJavaScriptPrompt( const std::string& meesage1, const std::string& message2 )
+static bool OnJavaScriptPrompt(const std::string& meesage1, const std::string& message2)
 {
   gJavaScriptPromptCallbackCalled++;
   return true;
@@ -210,54 +210,54 @@ static void OnChangesWatch()
   gCookieManagerChangsWatchCallbackCalled++;
 }
 
-static bool OnHovered( Actor actor, const Dali::HoverEvent& hover )
+static bool OnHovered(Actor actor, const Dali::HoverEvent& hover)
 {
   gHovered = true;
   return true;
 }
 
-static bool OnWheelEvent( Actor actor, const Dali::WheelEvent& wheel )
+static bool OnWheelEvent(Actor actor, const Dali::WheelEvent& wheel)
 {
   gWheelEventHandled = true;
   return true;
 }
 
-static void OnFormRepostDecision(WebView, std::shared_ptr<Dali::WebEngineFormRepostDecision> decision)
+static void OnFormRepostDecided(std::unique_ptr<Dali::WebEngineFormRepostDecision> decision)
 {
-  gFormRepostDecisionCallbackCalled++;
-  gFormRepostDecisionInstance = std::move(decision);
+  gFormRepostDecidedCallbackCalled++;
+  gFormRepostDecidedInstance = std::move(decision);
 }
 
-static void OnFrameRendered(WebView)
+static void OnFrameRendered()
 {
   gFrameRenderedCallbackCalled++;
 }
 
-static void OnRequestInterceptor(WebView view, std::shared_ptr<Dali::WebEngineRequestInterceptor> interceptor)
+static void OnRequestInterceptor(std::unique_ptr<Dali::WebEngineRequestInterceptor> interceptor)
 {
   gRequestInterceptorCallbackCalled++;
   gRequestInterceptorInstance = std::move(interceptor);
 }
 
-static void OnConsoleMessage(WebView view, std::shared_ptr<Dali::WebEngineConsoleMessage> message)
+static void OnConsoleMessage(std::unique_ptr<Dali::WebEngineConsoleMessage> message)
 {
   gConsoleMessageCallbackCalled++;
   gConsoleMessageInstance = std::move(message);
 }
 
-static void OnCertificateConfirm(WebView view, std::shared_ptr<Dali::WebEngineCertificate> certificate )
+static void OnCertificateConfirm(std::unique_ptr<Dali::WebEngineCertificate> certificate)
 {
   gCertificateConfirmCallbackCalled++;
   gCertificateConfirmInstance = std::move(certificate);
 }
 
-static void OnSslCertificateChanged(WebView view, std::shared_ptr<Dali::WebEngineCertificate> certificate )
+static void OnSslCertificateChanged(std::unique_ptr<Dali::WebEngineCertificate> certificate)
 {
   gSslCertificateChangedCallbackCalled++;
   gSslCertificateInstance = std::move(certificate);
 }
 
-static void OnHttpAuthHandler( WebView view, std::shared_ptr<Dali::WebEngineHttpAuthHandler> hander )
+static void OnHttpAuthHandler(std::unique_ptr<Dali::WebEngineHttpAuthHandler> hander)
 {
   gHttpAuthHandlerCallbackCalled++;
   gHttpAuthInstance = std::move(hander);
@@ -293,16 +293,16 @@ static bool OnMimeOverridden(const std::string&, const std::string&, std::string
   return false;
 }
 
-static void OnContextMenuCustomized(WebView view, std::shared_ptr<Dali::WebEngineContextMenu> menu)
+static void OnContextMenuShown(std::unique_ptr<Dali::WebEngineContextMenu> menu)
 {
-  gContextMenuCustomizedCallbackCalled++;
-  gContextMenuInstance = std::move(menu);
+  gContextMenuShownCallbackCalled++;
+  gContextMenuShownInstance = std::move(menu);
 }
 
-static void OnContextMenuItemSelected(WebView view, std::shared_ptr<Dali::WebEngineContextMenuItem> item)
+static void OnContextMenuHidden(std::unique_ptr<Dali::WebEngineContextMenu> menu)
 {
-  gContextMenuItemSelectedCallbackCalled++;
-  gContextMenuItemInstance = std::move(item);
+  gContextMenuHiddenCallbackCalled++;
+  gContextMenuHiddenInstance = std::move(menu);
 }
 
 } // namespace
@@ -375,21 +375,10 @@ int UtcDaliWebViewPageNavigation(void)
   application.Render();
   DALI_TEST_CHECK( view );
 
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.PageLoadStartedSignal().Connect( &OnPageLoadStarted );
-  view.PageLoadInProgressSignal().Connect( &OnPageLoadInProgress );
-  view.PageLoadFinishedSignal().Connect( &OnPageLoadFinished );
-  view.UrlChangedSignal().Connect( &OnUrlChanged );
-  bool signal1 = false;
-  bool signal2 = false;
-  bool signal3 = false;
-  bool signal4 = false;
-  bool signal5 = false;
-  view.ConnectSignal( testTracker, "pageLoadStarted", CallbackFunctor(&signal1) );
-  view.ConnectSignal( testTracker, "pageLoadInProgress", CallbackFunctor(&signal2) );
-  view.ConnectSignal( testTracker, "pageLoadFinished", CallbackFunctor(&signal3) );
-  view.ConnectSignal( testTracker, "urlChanged", CallbackFunctor(&signal4) );
-  view.ConnectSignal( testTracker, "invalidname", CallbackFunctor(&signal5) );
+  view.RegisterPageLoadStartedCallback( &OnPageLoadStarted );
+  view.RegisterPageLoadInProgressCallback( &OnPageLoadInProgress );
+  view.RegisterPageLoadFinishedCallback( &OnPageLoadFinished );
+  view.RegisterUrlChangedCallback( &OnUrlChanged );
   DALI_TEST_EQUALS( gPageLoadStartedCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gPageLoadInProgressCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gPageLoadFinishedCallbackCalled, 0, TEST_LOCATION );
@@ -403,8 +392,6 @@ int UtcDaliWebViewPageNavigation(void)
   DALI_TEST_EQUALS( gPageLoadInProgressCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gPageLoadFinishedCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gUrlChangedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 & signal2 & signal3 & signal4 );
-  DALI_TEST_CHECK( !signal5 );
 
   view.LoadUrl( TEST_URL2 );
   view.Suspend();
@@ -454,13 +441,8 @@ int UtcDaliWebViewPageLoadErrorConsoleMessage(void)
   application.Render();
   DALI_TEST_CHECK( view );
 
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.PageLoadErrorSignal().Connect( &OnPageLoadError );
-  view.ConsoleMessageSignal().Connect( &OnConsoleMessage );
-  bool signal1 = false;
-  bool signal2 = false;
-  view.ConnectSignal( testTracker, "pageLoadError", CallbackFunctor(&signal1) );
-  view.ConnectSignal( testTracker, "consoleMessage", CallbackFunctor(&signal2) );
+  view.RegisterPageLoadErrorCallback( &OnPageLoadError );
+  view.RegisterConsoleMessageReceivedCallback( &OnConsoleMessage );
   DALI_TEST_EQUALS( gPageLoadErrorCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gConsoleMessageCallbackCalled, 0, TEST_LOCATION );
 
@@ -468,7 +450,6 @@ int UtcDaliWebViewPageLoadErrorConsoleMessage(void)
   Test::EmitGlobalTimerSignal();
   DALI_TEST_EQUALS( gPageLoadErrorCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gConsoleMessageCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 & signal2);
 
   // error code.
   DALI_TEST_CHECK(gPageLoadErrorInstance);
@@ -670,8 +651,8 @@ int UtcDaliWebViewPropertyVideoHoleEnabled(void)
   WebView view = WebView::New();
   DALI_TEST_CHECK( view );
 
-  const bool kDefaultValue = true;
-  const bool kTestValue = false;
+  const bool kDefaultValue = false;
+  const bool kTestValue = true;
 
   // Check default value
   bool output;
@@ -794,7 +775,7 @@ int UtcDaliWebViewHoverAndWheel(void)
   END_TEST;
 }
 
-int UtcDaliWebViewFormRepostDecisionFrameRendering(void)
+int UtcDaliWebViewFormRepostDecidedFrameRendering(void)
 {
   ToolkitTestApplication application;
 
@@ -808,28 +789,22 @@ int UtcDaliWebViewFormRepostDecisionFrameRendering(void)
   application.Render();
   DALI_TEST_CHECK( view );
 
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.FormRepostDecisionSignal().Connect(&OnFormRepostDecision);
-  view.FrameRenderedSignal().Connect(&OnFrameRendered);
-  bool signal1 = false;
-  bool signal2 = false;
-  view.ConnectSignal( testTracker, "formRepostDecision", CallbackFunctor(&signal1) );
-  view.ConnectSignal( testTracker, "frameRendered", CallbackFunctor(&signal2) );
-  DALI_TEST_EQUALS( gFormRepostDecisionCallbackCalled, 0, TEST_LOCATION );
+  view.RegisterFormRepostDecidedCallback(&OnFormRepostDecided);
+  view.RegisterFrameRenderedCallback(&OnFrameRendered);
+  DALI_TEST_EQUALS( gFormRepostDecidedCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gFrameRenderedCallbackCalled, 0, TEST_LOCATION );
 
   view.LoadUrl( TEST_URL1 );
   Test::EmitGlobalTimerSignal();
-  DALI_TEST_EQUALS( gFormRepostDecisionCallbackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( gFormRepostDecidedCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gFrameRenderedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 & signal2);
 
   // form repost decision.
-  DALI_TEST_CHECK(gFormRepostDecisionInstance);
-  gFormRepostDecisionInstance->Reply(true);
+  DALI_TEST_CHECK(gFormRepostDecidedInstance);
+  gFormRepostDecidedInstance->Reply(true);
 
   // reset
-  gFormRepostDecisionInstance = nullptr;
+  gFormRepostDecidedInstance = nullptr;
 
   END_TEST;
 }
@@ -848,16 +823,9 @@ int UtcDaliWebViewSslCertificateHttpAuthentication(void)
   application.Render();
   DALI_TEST_CHECK( view );
 
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.CertificateConfirmSignal().Connect(&OnCertificateConfirm);
-  view.SslCertificateChangedSignal().Connect(&OnSslCertificateChanged);
-  view.HttpAuthHandlerSignal().Connect(&OnHttpAuthHandler);
-  bool signal1 = false;
-  bool signal2 = false;
-  bool signal3 = false;
-  view.ConnectSignal( testTracker, "certificateConfirm", CallbackFunctor(&signal1) );
-  view.ConnectSignal( testTracker, "sslCertificateChanged", CallbackFunctor(&signal2) );
-  view.ConnectSignal( testTracker, "httpAuthRequest", CallbackFunctor(&signal3) );
+  view.RegisterCertificateConfirmedCallback(&OnCertificateConfirm);
+  view.RegisterSslCertificateChangedCallback(&OnSslCertificateChanged);
+  view.RegisterHttpAuthHandlerCallback(&OnHttpAuthHandler);
   DALI_TEST_EQUALS( gCertificateConfirmCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gSslCertificateChangedCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_EQUALS( gHttpAuthHandlerCallbackCalled, 0, TEST_LOCATION );
@@ -867,7 +835,6 @@ int UtcDaliWebViewSslCertificateHttpAuthentication(void)
   DALI_TEST_EQUALS( gCertificateConfirmCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gSslCertificateChangedCallbackCalled, 1, TEST_LOCATION );
   DALI_TEST_EQUALS( gHttpAuthHandlerCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 & signal2 & signal3);
 
   // certificate.
   DALI_TEST_CHECK(gCertificateConfirmInstance);
@@ -1072,7 +1039,7 @@ int UtcDaliWebViewPropertyTitleFavicon(void)
   END_TEST;
 }
 
-int UtcDaliWebViewContextMenuCustomizedAndItemSelected(void)
+int UtcDaliWebViewContextMenuShownAndHidden(void)
 {
   ToolkitTestApplication application;
 
@@ -1080,55 +1047,47 @@ int UtcDaliWebViewContextMenuCustomizedAndItemSelected(void)
   DALI_TEST_CHECK( view );
 
   // load url.
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.ContextMenuCustomizedSignal().Connect( &OnContextMenuCustomized );
-  view.ContextMenuItemSelectedSignal().Connect( &OnContextMenuItemSelected );
-  bool signal1 = false;
-  bool signal2 = false;
-  view.ConnectSignal( testTracker, "contextMenuCustomized", CallbackFunctor(&signal1) );
-  view.ConnectSignal( testTracker, "contextMenuItemSelected", CallbackFunctor(&signal2) );
-  DALI_TEST_EQUALS( gContextMenuCustomizedCallbackCalled, 0, TEST_LOCATION );
-  DALI_TEST_EQUALS( gContextMenuItemSelectedCallbackCalled, 0, TEST_LOCATION );
-  DALI_TEST_CHECK(gContextMenuInstance == 0);
-  DALI_TEST_CHECK(gContextMenuItemInstance == 0);
+  view.RegisterContextMenuShownCallback( &OnContextMenuShown );
+  view.RegisterContextMenuHiddenCallback( &OnContextMenuHidden );
+  DALI_TEST_EQUALS( gContextMenuShownCallbackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( gContextMenuHiddenCallbackCalled, 0, TEST_LOCATION );
+  DALI_TEST_CHECK(gContextMenuShownInstance == 0);
+  DALI_TEST_CHECK(gContextMenuHiddenInstance == 0);
 
   view.LoadUrl( TEST_URL1 );
   Test::EmitGlobalTimerSignal();
-  DALI_TEST_EQUALS( gContextMenuCustomizedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_EQUALS( gContextMenuItemSelectedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 );
-  DALI_TEST_CHECK( signal2 );
+  DALI_TEST_EQUALS( gContextMenuShownCallbackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( gContextMenuHiddenCallbackCalled, 1, TEST_LOCATION );
 
   // check context meun & its items.
-  DALI_TEST_CHECK(gContextMenuInstance != 0);
-  std::unique_ptr<Dali::WebEngineContextMenuItem> item = gContextMenuInstance->GetItemAt(0);
+  DALI_TEST_CHECK(gContextMenuShownInstance != 0);
+  std::unique_ptr<Dali::WebEngineContextMenuItem> item = gContextMenuShownInstance->GetItemAt(0);
   DALI_TEST_CHECK(item.get() != 0);
-  std::vector<std::unique_ptr<Dali::WebEngineContextMenuItem>> itemList = gContextMenuInstance->GetItemList();
+  std::vector<std::unique_ptr<Dali::WebEngineContextMenuItem>> itemList = gContextMenuShownInstance->GetItemList();
   DALI_TEST_CHECK(itemList.size() == 1);
-  Dali::Vector2 testPosition = Dali::Vector2(100, 100);
-  DALI_TEST_EQUALS(gContextMenuInstance->GetPosition(), testPosition, TEST_LOCATION);
-  DALI_TEST_CHECK(gContextMenuInstance->RemoveItem(*(item.get())));
-  DALI_TEST_CHECK(gContextMenuInstance->AppendItemAsAction(WebEngineContextMenuItem::ItemTag::NO_ACTION, "", false));
-  DALI_TEST_CHECK(gContextMenuInstance->AppendItem(WebEngineContextMenuItem::ItemTag::NO_ACTION, "", "", false));
-  DALI_TEST_CHECK(gContextMenuInstance->SelectItem(*(item.get())));
-  DALI_TEST_CHECK(gContextMenuInstance->Hide());
-
-  DALI_TEST_CHECK(gContextMenuItemInstance != 0);
+  DALI_TEST_CHECK(gContextMenuShownInstance->RemoveItem(*(item.get())));
+  DALI_TEST_CHECK(gContextMenuShownInstance->AppendItemAsAction(WebEngineContextMenuItem::ItemTag::NO_ACTION, "", false));
+  DALI_TEST_CHECK(gContextMenuShownInstance->AppendItem(WebEngineContextMenuItem::ItemTag::NO_ACTION, "", "", false));
+  DALI_TEST_CHECK(gContextMenuShownInstance->SelectItem(*(item.get())));
+  DALI_TEST_CHECK(gContextMenuShownInstance->Hide());
+
   Dali::WebEngineContextMenuItem::ItemTag testItemTag = Dali::WebEngineContextMenuItem::ItemTag::NO_ACTION;
-  DALI_TEST_EQUALS(gContextMenuItemInstance->GetTag(), testItemTag, TEST_LOCATION);
+  DALI_TEST_EQUALS(item->GetTag(), testItemTag, TEST_LOCATION);
   Dali::WebEngineContextMenuItem::ItemType testItemType = Dali::WebEngineContextMenuItem::ItemType::ACTION;
-  DALI_TEST_EQUALS(gContextMenuItemInstance->GetType(), testItemType, TEST_LOCATION);
-  DALI_TEST_CHECK(gContextMenuItemInstance->IsEnabled());
+  DALI_TEST_EQUALS(item->GetType(), testItemType, TEST_LOCATION);
+  DALI_TEST_CHECK(item->IsEnabled());
   std::string testLinkUrl("http://test.html");
-  DALI_TEST_EQUALS(gContextMenuItemInstance->GetLinkUrl(), testLinkUrl, TEST_LOCATION);
+  DALI_TEST_EQUALS(item->GetLinkUrl(), testLinkUrl, TEST_LOCATION);
   std::string testImageUrl("http://test.jpg");
-  DALI_TEST_EQUALS(gContextMenuItemInstance->GetImageUrl(), testImageUrl, TEST_LOCATION);
+  DALI_TEST_EQUALS(item->GetImageUrl(), testImageUrl, TEST_LOCATION);
   std::string testTitle("title");
-  DALI_TEST_EQUALS(gContextMenuItemInstance->GetTitle(), testTitle, TEST_LOCATION);
-  DALI_TEST_CHECK(gContextMenuItemInstance->GetParentMenu().get() == 0);
+  DALI_TEST_EQUALS(item->GetTitle(), testTitle, TEST_LOCATION);
+  DALI_TEST_CHECK(item->GetParentMenu().get() == 0);
 
-  gContextMenuInstance = nullptr;
-  gContextMenuItemInstance = nullptr;
+  DALI_TEST_CHECK(gContextMenuHiddenInstance != 0);
+
+  gContextMenuShownInstance = nullptr;
+  gContextMenuHiddenInstance = nullptr;
 
   END_TEST;
 }
@@ -1141,10 +1100,7 @@ int UtcDaliWebViewScrollBy(void)
   DALI_TEST_CHECK( view );
 
   // load url.
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.ScrollEdgeReachedSignal().Connect( &OnScrollEdgeReached );
-  bool signal1 = false;
-  view.ConnectSignal( testTracker, "scrollEdgeReached", CallbackFunctor(&signal1) );
+  view.RegisterScrollEdgeReachedCallback( &OnScrollEdgeReached );
   DALI_TEST_EQUALS( gScrollEdgeReachedCallbackCalled, 0, TEST_LOCATION );
 
   view.LoadUrl( TEST_URL1 );
@@ -1164,7 +1120,6 @@ int UtcDaliWebViewScrollBy(void)
   view.GetProperty( WebView::Property::SCROLL_POSITION ).Get( output );
   DALI_TEST_CHECK( output.x == 150 && output.y == 150 );
   DALI_TEST_EQUALS( gScrollEdgeReachedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 );
 
   // scroll by and trigger scrollEdgeReached event.
   bool result = view.ScrollEdgeBy( 50, 50 );
@@ -1174,7 +1129,6 @@ int UtcDaliWebViewScrollBy(void)
   view.GetProperty( WebView::Property::SCROLL_POSITION ).Get( output );
   DALI_TEST_CHECK( output.x == 200 && output.y == 200 );
   DALI_TEST_EQUALS( gScrollEdgeReachedCallbackCalled, 2, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 );
 
   END_TEST;
 }
@@ -1278,17 +1232,13 @@ int UtcDaliWebViewHttpRequestInterceptor(void)
   DALI_TEST_CHECK( view );
 
   // load url.
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.RequestInterceptorSignal().Connect( &OnRequestInterceptor );
-  bool signal1 = false;
-  view.ConnectSignal( testTracker, "requestInterceptor", CallbackFunctor(&signal1) );
+  view.RegisterRequestInterceptorCallback( &OnRequestInterceptor );
   DALI_TEST_EQUALS( gRequestInterceptorCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_CHECK(gRequestInterceptorInstance == 0);
 
   view.LoadUrl( TEST_URL1 );
   Test::EmitGlobalTimerSignal();
   DALI_TEST_EQUALS( gRequestInterceptorCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 );
 
   // check request interceptor.
   DALI_TEST_CHECK(gRequestInterceptorInstance != 0);
@@ -1312,17 +1262,13 @@ int UtcDaliWebViewResponsePolicyDecisionRequest(void)
   DALI_TEST_CHECK( view );
 
   // load url.
-  ConnectionTracker* testTracker = new ConnectionTracker();
-  view.ResponsePolicyDecisionSignal().Connect( &OnResponsePolicyDecided );
-  bool signal1 = false;
-  view.ConnectSignal( testTracker, "responsePolicyDecided", CallbackFunctor(&signal1) );
+  view.RegisterResponsePolicyDecidedCallback( &OnResponsePolicyDecided );
   DALI_TEST_EQUALS( gResponsePolicyDecidedCallbackCalled, 0, TEST_LOCATION );
   DALI_TEST_CHECK(gResponsePolicyDecisionInstance == 0);
 
   view.LoadUrl( TEST_URL1 );
   Test::EmitGlobalTimerSignal();
   DALI_TEST_EQUALS( gResponsePolicyDecidedCallbackCalled, 1, TEST_LOCATION );
-  DALI_TEST_CHECK( signal1 );
 
   // check response policy decision & its frame.
   DALI_TEST_CHECK(gResponsePolicyDecisionInstance != 0);
@@ -1516,6 +1462,7 @@ int UtcDaliWebViewMethodsForCoverage(void)
     []( const std::string& arg ) {
     }
   );
+  view.SetTtsFocus(true);
 
   DALI_TEST_CHECK( view );
 
@@ -1585,19 +1532,15 @@ int UtcDaliWebContextGetSetCacheModel(void)
   std::string kDefaultValue;
 
   // Reset something
-  context->SetProxyUri( kDefaultValue );
-  context->SetCertificateFilePath( kDefaultValue );
-  context->EnableCache( true );
+  context->SetAppId( "id" );
+  context->SetApplicationType( Dali::WebEngineContext::ApplicationType::OTHER );
+  context->SetTimeOffset( 0 );
+  context->SetTimeZoneOffset( 0, 0 );
   context->SetDefaultProxyAuth( kDefaultValue, kDefaultValue );
   context->DeleteAllWebDatabase();
   context->DeleteAllWebStorage();
   context->DeleteLocalFileSystem();
   context->ClearCache();
-  context->SetContextAppId( "id" );
-  context->SetContextApplicationType( Dali::WebEngineContext::ApplicationType::OTHER );
-  context->SetContextTimeOffset( 0 );
-  context->SetContextTimeZoneOffset( 0, 0 );
-  context->SetDefaultZoomFactor( 0 );
   context->DeleteAllFormPasswordData();
   context->DeleteAllFormCandidateData();
 
@@ -1611,14 +1554,16 @@ int UtcDaliWebContextGetSetCacheModel(void)
   DALI_TEST_CHECK( value == Dali::WebEngineContext::CacheModel::DOCUMENT_BROWSER );
 
   // Get cache enabled
+  context->EnableCache( true );
   DALI_TEST_CHECK( context->IsCacheEnabled() );
 
   // Get certificate
-  std::string str = context->GetContextCertificateFile();
+  context->SetCertificateFilePath( "test" );
+  std::string str = context->GetCertificateFilePath();
   DALI_TEST_EQUALS( str, "test", TEST_LOCATION );
 
   // Set version
-  DALI_TEST_CHECK( context->SetContextAppVersion( "test" ) );
+  DALI_TEST_CHECK( context->SetAppVersion( "test" ) );
 
   // Register
   std::vector<std::string> temp;
@@ -1626,16 +1571,18 @@ int UtcDaliWebContextGetSetCacheModel(void)
   context->RegisterJsPluginMimeTypes( temp );
   context->DeleteFormPasswordDataList( temp );
 
-  // Get zoom
-  DALI_TEST_EQUALS( context->GetContextDefaultZoomFactor(), float( 0 ), TEST_LOCATION );
+  // Get zoom factor
+  context->SetDefaultZoomFactor( 1.0f );
+  DALI_TEST_EQUALS( context->GetDefaultZoomFactor(), float( 1.0f ), TEST_LOCATION );
 
   // Delete cache and database
   DALI_TEST_CHECK( context->DeleteAllApplicationCache() );
   DALI_TEST_CHECK( context->DeleteAllWebIndexedDatabase() );
 
   // Get contextProxy
-  context->SetContextProxy("", "");
-  DALI_TEST_EQUALS( context->GetContextProxy(), "test", TEST_LOCATION );
+  context->SetProxyUri( "test" );
+  DALI_TEST_EQUALS( context->GetProxyUri(), "test", TEST_LOCATION );
+  context->SetProxyBypassRule("", "test");
   DALI_TEST_EQUALS( context->GetProxyBypassRule(), "test", TEST_LOCATION );
 
   //Notify low memory
index 1cf4adc..839e96d 100644 (file)
@@ -44,6 +44,7 @@
 #include <dali-toolkit/public-api/controls/scrollable/scrollable.h>
 #include <dali-toolkit/public-api/controls/slider/slider.h>
 #include <dali-toolkit/public-api/controls/text-controls/hidden-input-properties.h>
+#include <dali-toolkit/public-api/controls/text-controls/input-filter-properties.h>
 #include <dali-toolkit/public-api/controls/text-controls/placeholder-properties.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-field.h>
index fd3e72e..c42cb8a 100644 (file)
 #include "accessible-impl.h"
 
 // EXTERNAL INCLUDES
+#ifdef DGETTEXT_ENABLED
+#include <libintl.h>
+#endif
+
 #include <dali/devel-api/actors/actor-devel.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
 
-namespace Dali::Toolkit::DevelControl {
+namespace Dali::Toolkit::DevelControl
+{
+
+static std::string GetLocaleText(std::string string, const char *domain = "dali-toolkit")
+{
+#ifdef DGETTEXT_ENABLED
+    /*TODO: currently non-localized string is used as a key for translation lookup. In case the lookup key formatting is forced
+          consider calling utility function for converting non-localized string into well-formatted key before lookup. */
+    return dgettext(domain, string.c_str());
+#else
+    return string;
+#endif
+}
 
 AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
-: self(self),
-  modal(modal)
+: mSelf(self),
+  mIsModal(modal)
 {
   auto control = Dali::Toolkit::Control::DownCast(Self());
 
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
   if(controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN)
+  {
     controlImpl.mAccessibilityRole = role;
+  }
 
   Self().PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle& handle, Dali::Property::Index index, Dali::Property::Value value) {
     if(this->Self() != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
@@ -72,21 +90,31 @@ std::string AccessibleImpl::GetName()
 
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
+  std::string name;
 
   if(!controlImpl.mAccessibilityGetNameSignal.Empty())
   {
-    std::string ret;
-    controlImpl.mAccessibilityGetNameSignal.Emit(ret);
-    return ret;
+    controlImpl.mAccessibilityGetNameSignal.Emit(name);
+  }
+  else if(controlImpl.mAccessibilityNameSet)
+  {
+    name = controlImpl.mAccessibilityName;
+  }
+  else if(auto raw = GetNameRaw(); !raw.empty())
+  {
+    name = raw;
+  }
+  else
+  {
+    name = Self().GetProperty<std::string>(Actor::Property::NAME);
   }
 
-  if(controlImpl.mAccessibilityNameSet)
-    return controlImpl.mAccessibilityName;
-
-  if(auto raw = GetNameRaw(); !raw.empty())
-    return raw;
+  if(controlImpl.mAccessibilityTranslationDomainSet)
+  {
+    return GetLocaleText(name, controlImpl.mAccessibilityTranslationDomain.c_str());
+  }
 
-  return Self().GetProperty<std::string>(Actor::Property::NAME);
+  return GetLocaleText(name);
 }
 
 std::string AccessibleImpl::GetNameRaw()
@@ -100,23 +128,31 @@ std::string AccessibleImpl::GetDescription()
 
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
+  std::string description;
 
   if(!controlImpl.mAccessibilityGetDescriptionSignal.Empty())
   {
-    std::string ret;
-    controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
-    return ret;
+    controlImpl.mAccessibilityGetDescriptionSignal.Emit(description);
+  }
+  else if(controlImpl.mAccessibilityDescriptionSet)
+  {
+    description = controlImpl.mAccessibilityDescription;
+  }
+  else
+  {
+    description = GetDescriptionRaw();
+  }
+  if(controlImpl.mAccessibilityTranslationDomainSet)
+  {
+    return GetLocaleText(description, controlImpl.mAccessibilityTranslationDomain.c_str());
   }
 
-  if(controlImpl.mAccessibilityDescriptionSet)
-    return controlImpl.mAccessibilityDescription;
-
-  return GetDescriptionRaw();
+  return GetLocaleText(description);
 }
 
 std::string AccessibleImpl::GetDescriptionRaw()
 {
-  return "";
+  return {};
 }
 
 Dali::Accessibility::Accessible* AccessibleImpl::GetParent()
@@ -136,15 +172,18 @@ Dali::Accessibility::Accessible* AccessibleImpl::GetChildAtIndex(size_t index)
 
 size_t AccessibleImpl::GetIndexInParent()
 {
-  auto s      = Self();
-  auto parent = s.GetParent();
+  auto self = Self();
+  auto parent = self.GetParent();
   DALI_ASSERT_ALWAYS(parent && "can't call GetIndexInParent on object without parent");
+
   auto count = parent.GetChildCount();
   for(auto i = 0u; i < count; ++i)
   {
-    auto c = parent.GetChildAt(i);
-    if(c == s)
+    auto child = parent.GetChildAt(i);
+    if(child == self)
+    {
       return i;
+    }
   }
   DALI_ASSERT_ALWAYS(false && "object isn't child of it's parent");
   return static_cast<size_t>(-1);
@@ -155,28 +194,40 @@ Dali::Accessibility::Role AccessibleImpl::GetRole()
   return Self().GetProperty<Dali::Accessibility::Role>(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE);
 }
 
+std::string AccessibleImpl::GetLocalizedRoleName()
+{
+  return GetLocaleText(GetRoleName());
+}
+
 Dali::Accessibility::States AccessibleImpl::CalculateStates()
 {
   Dali::Actor self = Self();
-  Dali::Accessibility::States s;
-  s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE);
-  s[Dali::Accessibility::State::FOCUSED]   = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
+  Dali::Accessibility::States state;
+  state[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE);
+  state[Dali::Accessibility::State::FOCUSED]   = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
+
   if(self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).GetType() == Dali::Property::NONE)
-    s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
+  {
+    state[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
+  }
   else
-    s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).Get<bool>();
-  s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
-  s[Dali::Accessibility::State::ENABLED]     = true;
-  s[Dali::Accessibility::State::SENSITIVE]   = true;
-  s[Dali::Accessibility::State::VISIBLE]     = true;
-  if(modal)
   {
-    s[Dali::Accessibility::State::MODAL] = true;
+    state[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).Get<bool>();
+  }
+
+  state[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
+  state[Dali::Accessibility::State::ENABLED]     = true;
+  state[Dali::Accessibility::State::SENSITIVE]   = true;
+  state[Dali::Accessibility::State::VISIBLE]     = true;
+
+  if(mIsModal)
+  {
+    state[Dali::Accessibility::State::MODAL] = true;
   }
-  s[Dali::Accessibility::State::SHOWING] = !self.GetProperty(Dali::DevelActor::Property::CULLED).Get<bool>() && self.GetCurrentProperty<bool>(Actor::Property::VISIBLE);
+  state[Dali::Accessibility::State::SHOWING] = !self.GetProperty(Dali::DevelActor::Property::CULLED).Get<bool>() && self.GetCurrentProperty<bool>(Actor::Property::VISIBLE);
 
-  s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
-  return s;
+  state[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
+  return state;
 }
 
 Dali::Accessibility::States AccessibleImpl::GetStates()
@@ -186,32 +237,30 @@ Dali::Accessibility::States AccessibleImpl::GetStates()
 
 Dali::Accessibility::Attributes AccessibleImpl::GetAttributes()
 {
-  std::unordered_map<std::string, std::string> attribute_map;
-  auto                                         q = Dali::Toolkit::Control::DownCast(Self());
-  auto                                         w =
-    q.GetProperty(Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES);
-  auto z = w.GetMap();
+  std::unordered_map<std::string, std::string> attributeMap;
+  auto control = Dali::Toolkit::Control::DownCast(Self());
+  auto attribute = control.GetProperty(Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES);
+  auto map = attribute.GetMap();
 
-  if(z)
+  if(map)
   {
-    auto map_size = z->Count();
+    auto mapSize = map->Count();
 
-    for(unsigned int i = 0; i < map_size; i++)
+    for(unsigned int i = 0; i < mapSize; i++)
     {
-      auto map_key = z->GetKeyAt(i);
-      if(map_key.type == Dali::Property::Key::STRING)
+      auto mapKey = map->GetKeyAt(i);
+      if(mapKey.type == Dali::Property::Key::STRING)
       {
-        std::string map_value;
-        if(z->GetValue(i).Get(map_value))
+        std::string mapValue;
+        if(map->GetValue(i).Get(mapValue))
         {
-          attribute_map.emplace(std::move(map_key.stringKey),
-                                std::move(map_value));
+          attributeMap.emplace(std::move(mapKey.stringKey), std::move(mapValue));
         }
       }
     }
   }
 
-  return attribute_map;
+  return attributeMap;
 }
 
 Dali::Accessibility::ComponentLayer AccessibleImpl::GetLayer()
@@ -219,21 +268,15 @@ Dali::Accessibility::ComponentLayer AccessibleImpl::GetLayer()
   return Dali::Accessibility::ComponentLayer::WINDOW;
 }
 
-Dali::Rect<> AccessibleImpl::GetExtents(Dali::Accessibility::CoordType ctype)
+Dali::Rect<> AccessibleImpl::GetExtents(Dali::Accessibility::CoordinateType type)
 {
   Dali::Actor self = Self();
-  Vector2 screenPosition =
-    self.GetProperty(Dali::DevelActor::Property::SCREEN_POSITION)
-      .Get<Vector2>();
+
+  Vector2 screenPosition = self.GetProperty(Dali::DevelActor::Property::SCREEN_POSITION).Get<Vector2>();
   auto size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * self.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
-  bool positionUsesAnchorPoint =
-    self.GetProperty(Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT)
-      .Get<bool>();
-  Vector3 anchorPointOffSet =
-    size * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT)
-                                    : AnchorPoint::TOP_LEFT);
-  Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x,
-                             screenPosition.y - anchorPointOffSet.y);
+  bool positionUsesAnchorPoint = self.GetProperty(Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
+  Vector3 anchorPointOffSet = size * (positionUsesAnchorPoint ? self.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
+  Vector2 position = Vector2((screenPosition.x - anchorPointOffSet.x), (screenPosition.y - anchorPointOffSet.y));
 
   return {position.x, position.y, size.x, size.y};
 }
@@ -256,11 +299,13 @@ static Dali::Actor CreateHighlightIndicatorActor()
 {
   std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
   focusBorderImagePath += "/keyboard_focus.9.png";
+
   // Create the default if it hasn't been set and one that's shared by all the
   // keyboard focusable actors
   auto actor = Toolkit::ImageView::New(focusBorderImagePath);
   actor.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
-  DevelControl::AppendAccessibilityAttribute(actor, "highlight", "");
+
+  DevelControl::AppendAccessibilityAttribute(actor, "highlight", std::string());
   actor.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false);
 
   return actor;
@@ -286,24 +331,35 @@ void AccessibleImpl::ScrollToSelf()
 bool AccessibleImpl::GrabHighlight()
 {
   Dali::Actor self = Self();
-  auto old = GetCurrentlyHighlightedActor();
+  auto oldHighlightedActor = GetCurrentlyHighlightedActor();
 
   if(!Dali::Accessibility::IsUp())
+  {
     return false;
-  if(self == old)
+  }
+
+  if(self == oldHighlightedActor)
+  {
     return true;
-  if(old)
+  }
+
+  // Clear the old highlight.
+  if(oldHighlightedActor)
   {
-    auto c = dynamic_cast<Dali::Accessibility::Component*>(Internal::Control::Impl::GetAccessibilityObject(old));
-    if(c)
-      c->ClearHighlight();
+    auto oldHighlightObject = dynamic_cast<Dali::Accessibility::Component*>(Internal::Control::Impl::GetAccessibilityObject(oldHighlightedActor));
+    if(oldHighlightObject)
+    {
+      oldHighlightObject->ClearHighlight();
+    }
   }
+
   auto highlight = GetHighlightActor();
   if(!highlight)
   {
     highlight = CreateHighlightIndicatorActor();
     SetHighlightActor(highlight);
   }
+
   highlight.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
   highlight.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
   highlight.SetProperty(Actor::Property::POSITION_Z, 1.0f);
@@ -311,7 +367,7 @@ bool AccessibleImpl::GrabHighlight()
 
   // Remember the highlight actor, so that when the default is changed with
   // SetHighlightActor(), the currently displayed highlight can still be cleared.
-  currentHighlightActor = highlight;
+  mCurrentHighlightActor = highlight;
   ScrollToSelf();
   self.Add(highlight);
   SetCurrentlyHighlightedActor(self);
@@ -325,11 +381,14 @@ bool AccessibleImpl::ClearHighlight()
   Dali::Actor self = Self();
 
   if(!Dali::Accessibility::IsUp())
+  {
     return false;
+  }
+
   if(GetCurrentlyHighlightedActor() == self)
   {
-    self.Remove(currentHighlightActor.GetHandle());
-    currentHighlightActor = {};
+    self.Remove(mCurrentHighlightActor.GetHandle());
+    mCurrentHighlightActor = {};
     SetCurrentlyHighlightedActor({});
     EmitHighlighted(false);
     return true;
@@ -339,7 +398,11 @@ bool AccessibleImpl::ClearHighlight()
 
 std::string AccessibleImpl::GetActionName(size_t index)
 {
-  if(index >= GetActionCount()) return "";
+  if(index >= GetActionCount())
+  {
+    return {};
+  }
+
   Dali::TypeInfo type;
   Self().GetTypeInfo(type);
   DALI_ASSERT_ALWAYS(type && "no TypeInfo object");
@@ -348,13 +411,12 @@ std::string AccessibleImpl::GetActionName(size_t index)
 
 std::string AccessibleImpl::GetLocalizedActionName(size_t index)
 {
-  // TODO: add localization
-  return GetActionName(index);
+  return GetLocaleText(GetActionName(index));
 }
 
 std::string AccessibleImpl::GetActionDescription(size_t index)
 {
-  return "";
+  return {};
 }
 
 size_t AccessibleImpl::GetActionCount()
@@ -367,7 +429,7 @@ size_t AccessibleImpl::GetActionCount()
 
 std::string AccessibleImpl::GetActionKeyBinding(size_t index)
 {
-  return "";
+  return {};
 }
 
 bool AccessibleImpl::DoAction(size_t index)
@@ -407,13 +469,12 @@ std::vector<Dali::Accessibility::Relation> AccessibleImpl::GetRelationSet()
 
   std::vector<Dali::Accessibility::Relation> ret;
 
-  auto& v = controlImpl.mAccessibilityRelations;
-  for(auto i = 0u; i < v.size(); ++i)
+  auto& relation = controlImpl.mAccessibilityRelations;
+  for(auto i = 0u; i < relation.size(); ++i)
   {
-    if(v[i].empty())
-      continue;
+    if(relation[i].empty()) continue;
 
-    ret.emplace_back(Accessibility::Relation{static_cast<Accessibility::RelationType>(i), v[i]});
+    ret.emplace_back(Accessibility::Relation{static_cast<Accessibility::RelationType>(i), relation[i]});
   }
 
   return ret;
index ab168c6..37e7ad3 100644 (file)
@@ -47,13 +47,14 @@ struct DALI_TOOLKIT_API AccessibleImpl : public virtual Dali::Accessibility::Acc
                                          public virtual Dali::Accessibility::Action
 {
 protected:
-  Dali::WeakHandle<Dali::Actor> self;
-  Dali::WeakHandle<Dali::Actor> currentHighlightActor;
-  bool        modal = false, root = false;
+  Dali::WeakHandle<Dali::Actor> mSelf;
+  Dali::WeakHandle<Dali::Actor> mCurrentHighlightActor;
+  bool mIsModal = false;
+  bool mIsRoot = false;
 
   Dali::Actor Self()
   {
-    auto handle = self.GetHandle();
+    auto handle = mSelf.GetHandle();
 
     // Control::Impl holds a std::unique_ptr to the Accessible object,
     // so that one does not outlive the other.
@@ -113,6 +114,11 @@ public:
   Dali::Accessibility::Role GetRole() override;
 
   /**
+   * @copydoc Dali::Accessibility::Accessible::GetLocalizedRoleName()
+   */
+  std::string GetLocalizedRoleName() override;
+
+  /**
    * @copydoc Dali::Accessibility::Accessible::GetStates()
    */
   Dali::Accessibility::States GetStates() override;
@@ -125,7 +131,7 @@ public:
   /**
    * @copydoc Dali::Accessibility::Component::GetExtents()
    */
-  Dali::Rect<> GetExtents(Dali::Accessibility::CoordType ctype) override;
+  Dali::Rect<> GetExtents(Accessibility::CoordinateType type) override;
 
   /**
    * @copydoc Dali::Accessibility::Component::GetLayer()
index 487aa1b..55becb3 100644 (file)
@@ -135,107 +135,102 @@ void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolki
   }
 }
 
-static Toolkit::Internal::Control::Impl* GetControlImplementationIfAny(Dali::Actor actor)
+static Toolkit::Internal::Control::Impl* GetControlImplementation(Dali::Actor actor)
 {
-  Dali::Toolkit::Control c = Toolkit::Control::DownCast(actor);
-  if(c)
+  Dali::Toolkit::Control control = Toolkit::Control::DownCast(actor);
+  if(control)
   {
-    auto& impl1 = Toolkit::Internal::GetImplementation(c);
-    auto& impl2 = Toolkit::Internal::Control::Impl::Get(impl1);
-    return &impl2;
+    auto& internalControl = Toolkit::Internal::GetImplementation(control);
+    auto& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
+    return &controlDataImpl;
   }
   return nullptr;
 }
 
 Toolkit::DevelControl::AccessibilityActivateSignalType& AccessibilityActivateSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityActivateSignal;
+  return GetControlImplementation(control)->mAccessibilityActivateSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingSkippedSignalType& AccessibilityReadingSkippedSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityReadingSkippedSignal;
+  return GetControlImplementation(control)->mAccessibilityReadingSkippedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingPausedSignalType& AccessibilityReadingPausedSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityReadingPausedSignal;
+  return GetControlImplementation(control)->mAccessibilityReadingPausedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingResumedSignalType& AccessibilityReadingResumedSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityReadingResumedSignal;
+  return GetControlImplementation(control)->mAccessibilityReadingResumedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingCancelledSignalType& AccessibilityReadingCancelledSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityReadingCancelledSignal;
+  return GetControlImplementation(control)->mAccessibilityReadingCancelledSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingStoppedSignalType& AccessibilityReadingStoppedSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityReadingStoppedSignal;
+  return GetControlImplementation(control)->mAccessibilityReadingStoppedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityGetNameSignalType& AccessibilityGetNameSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityGetNameSignal;
+  return GetControlImplementation(control)->mAccessibilityGetNameSignal;
 }
 
 Toolkit::DevelControl::AccessibilityGetDescriptionSignalType& AccessibilityGetDescriptionSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityGetDescriptionSignal;
+  return GetControlImplementation(control)->mAccessibilityGetDescriptionSignal;
 }
 
 Toolkit::DevelControl::AccessibilityDoGestureSignalType& AccessibilityDoGestureSignal(Toolkit::Control control)
 {
-  auto ac = GetControlImplementationIfAny(control);
-  return ac->mAccessibilityDoGestureSignal;
+  return GetControlImplementation(control)->mAccessibilityDoGestureSignal;
 }
 
 void AppendAccessibilityRelation(Dali::Actor control, Actor destination, Dali::Accessibility::RelationType relation)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
     auto index = static_cast<Dali::Property::Array::SizeType>(relation);
-    if(index >= ac->mAccessibilityRelations.size())
+    if(index >= controlDataImpl->mAccessibilityRelations.size())
     {
       DALI_LOG_ERROR("Relation index exceeds vector size.");
       return;
     }
 
-    auto obj = ac->GetAccessibilityObject(destination);
-    if(obj)
-      ac->mAccessibilityRelations[index].push_back(obj->GetAddress());
+    auto object = controlDataImpl->GetAccessibilityObject(destination);
+    if(object)
+    {
+      controlDataImpl->mAccessibilityRelations[index].push_back(object->GetAddress());
+    }
   }
 }
 
 void RemoveAccessibilityRelation(Dali::Actor control, Actor destination, Dali::Accessibility::RelationType relation)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
     auto index = static_cast<Dali::Property::Array::SizeType>(relation);
-    if(index >= ac->mAccessibilityRelations.size())
+    if(index >= controlDataImpl->mAccessibilityRelations.size())
     {
       DALI_LOG_ERROR("Relation index exceeds vector size.");
       return;
     }
 
-    auto obj = ac->GetAccessibilityObject(destination);
-    if(!obj)
+    auto object = controlDataImpl->GetAccessibilityObject(destination);
+    if(!object)
+    {
       return;
+    }
 
-    auto address = obj->GetAddress();
+    auto address = object->GetAddress();
 
-    auto& targets = ac->mAccessibilityRelations[index];
+    auto& targets = controlDataImpl->mAccessibilityRelations[index];
     for(auto i = 0u; i < targets.size(); ++i)
     {
       if(targets[i].ToString() == address.ToString())
@@ -249,110 +244,117 @@ void RemoveAccessibilityRelation(Dali::Actor control, Actor destination, Dali::A
 
 std::vector<std::vector<Accessibility::Address>> GetAccessibilityRelations(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    return ac->mAccessibilityRelations;
+    return controlDataImpl->mAccessibilityRelations;
   }
   return {};
 }
 
 void ClearAccessibilityRelations(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    for(auto& it : ac->mAccessibilityRelations)
+    for(auto& it : controlDataImpl->mAccessibilityRelations)
+    {
       it.clear();
+    }
   }
 }
 
-void SetAccessibilityConstructor(Dali::Actor                                                                  control,
-                                 std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Dali::Actor)> constructor)
+void SetAccessibilityConstructor(Dali::Actor control, std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Dali::Actor)> constructor)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->accessibilityConstructor = constructor;
+    controlDataImpl->mAccessibilityConstructor = constructor;
   }
 }
 
 void AppendAccessibilityAttribute(Dali::Actor control, const std::string& key, const std::string value)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->AppendAccessibilityAttribute(key, value);
+    controlDataImpl->AppendAccessibilityAttribute(key, value);
   }
 }
 
 void RemoveAccessibilityAttribute(Dali::Actor control, const std::string& key)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->RemoveAccessibilityAttribute(key);
+    controlDataImpl->RemoveAccessibilityAttribute(key);
   }
 }
 
 void ClearAccessibilityAttributes(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->ClearAccessibilityAttributes();
+    controlDataImpl->ClearAccessibilityAttributes();
   }
 }
 
 void SetAccessibilityReadingInfoType(Dali::Actor control, const Dali::Accessibility::ReadingInfoTypes types)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->SetAccessibilityReadingInfoType(types);
+    controlDataImpl->SetAccessibilityReadingInfoType(types);
   }
 }
 
 Dali::Accessibility::ReadingInfoTypes GetAccessibilityReadingInfoType(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    return ac->GetAccessibilityReadingInfoType();
+    return controlDataImpl->GetAccessibilityReadingInfoType();
   }
   return {};
 }
 
 bool ClearAccessibilityHighlight(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    auto ptr = dynamic_cast<Dali::Accessibility::Component*>(ac->GetAccessibilityObject());
-    if(ptr)
-      return ptr->ClearHighlight();
+    auto object = dynamic_cast<Dali::Accessibility::Component*>(controlDataImpl->GetAccessibilityObject());
+    if(object)
+    {
+      return object->ClearHighlight();
+    }
   }
   return false;
 }
 
 bool GrabAccessibilityHighlight(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    auto ptr = dynamic_cast<Dali::Accessibility::Component*>(ac->GetAccessibilityObject());
-    if(ptr)
-      return ptr->GrabHighlight();
+    auto object = dynamic_cast<Dali::Accessibility::Component*>(controlDataImpl->GetAccessibilityObject());
+    if(object)
+    {
+      return object->GrabHighlight();
+    }
   }
   return false;
 }
 
 Dali::Accessibility::States GetAccessibilityStates(Dali::Actor control)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    auto ptr = dynamic_cast<Dali::Accessibility::Component*>(ac->GetAccessibilityObject());
-    if(ptr)
-      return ptr->GetStates();
+    auto object = dynamic_cast<Dali::Accessibility::Component*>(controlDataImpl->GetAccessibilityObject());
+    if(object)
+    {
+      return object->GetStates();
+    }
   }
   return {};
 }
 
-void NotifyAccessibilityStateChange(Dali::Actor control, Dali::Accessibility::States states, bool doRecursive)
+void NotifyAccessibilityStateChange(Dali::Actor control, Dali::Accessibility::States states, bool isRecursive)
 {
-  if(auto ac = GetControlImplementationIfAny(control))
+  if(auto controlDataImpl = GetControlImplementation(control))
   {
-    ac->GetAccessibilityObject()->NotifyAccessibilityStateChange(std::move(states), doRecursive);
+    controlDataImpl->GetAccessibilityObject()->NotifyAccessibilityStateChange(std::move(states), isRecursive);
   }
 }
 
index d977c34..51cf1cc 100644 (file)
@@ -555,9 +555,9 @@ DALI_TOOLKIT_API Dali::Accessibility::States GetAccessibilityStates(Dali::Actor
  *
  * @param control object to append attribute to
  * @param states      mask with states expected to broadcast
- * @param doRecursive flag pointing if notifications of children's state would be sent
+ * @param isRecursive flag pointing if notifications of children's state would be sent
  */
-DALI_TOOLKIT_API void NotifyAccessibilityStateChange(Dali::Actor control, Dali::Accessibility::States states, bool doRecursive);
+DALI_TOOLKIT_API void NotifyAccessibilityStateChange(Dali::Actor control, Dali::Accessibility::States states, bool isRecursive);
 
 /**
  * The method allows to set specific constructor for creating accessibility structure
index 37678d8..a685aee 100644 (file)
@@ -40,6 +40,11 @@ AnchorClickedSignalType& AnchorClickedSignal(TextEditor textEditor)
   return GetImpl(textEditor).AnchorClickedSignal();
 }
 
+InputFilteredSignalType& InputFilteredSignal(TextEditor textEditor)
+{
+  return GetImpl(textEditor).InputFilteredSignal();
+}
+
 void SelectWholeText(TextEditor textEditor)
 {
   GetImpl(textEditor).SelectWholeText();
index 665af7a..695ca1b 100644 (file)
@@ -21,6 +21,7 @@
 #include <dali/devel-api/adaptor-framework/input-method-context.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/text-controls/input-filter-properties.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 
 namespace Dali
@@ -111,7 +112,7 @@ enum Type
   /**
    * @brief Modifies the default text alignment to match the direction of the system language.
    * @details Name "matchSystemLanguageDirection", type (Property::BOOLEAN), Read/Write
-   * @note The default value is false
+   * @note The default value is true
    */
   MATCH_SYSTEM_LANGUAGE_DIRECTION,
 
@@ -220,6 +221,52 @@ enum Type
    * @endcode
    */
   INPUT_METHOD_SETTINGS,
+
+  /**
+   * @brief The input filter
+   * @details Name "inputFilter", type Property::MAP.
+   *
+   * The inputFilter map contains the following keys:
+   *
+   * | %Property Name       | Type     | Required | Description                                                                                                         |
+   * |----------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------|
+   * | accepted             | STRING   | No       | A regular expression in the set of characters to be accepted by the inputFilter (the default value is empty string) |
+   * | rejected             | STRING   | No       | A regular expression in the set of characters to be rejected by the inputFilter (the default value is empty string) |
+   *
+   * @note Optional.
+   * The character set must follow the regular expression rules.
+   * Behaviour can not be guaranteed for incorrect grammars.
+   * Refer the link below for detailed rules.
+   * The functions in std::regex library use the ECMAScript grammar:
+   * http://cplusplus.com/reference/regex/ECMAScript/
+   *
+   * You can use enums instead of "accepted" and "rejected" strings.
+   * @see Dali::Toolkit::InputFilter::Property::Type
+   *
+   * Example Usage:
+   * @code
+   *   Property::Map filter;
+   *   filter[InputFilter::Property::ACCEPTED] = "[\\d]"; // accept whole digits
+   *   filter[InputFilter::Property::REJECTED] = "[0-5]"; // reject 0, 1, 2, 3, 4, 5
+   *
+   *   editor.SetProperty(DevelTextEditor::Property::INPUT_FILTER, filter); // acceptable inputs are 6, 7, 8, 9
+   * @endcode
+   */
+  INPUT_FILTER,
+
+  /**
+  * @brief Whether we should show the ellipsis if required.
+  * @details Name "ellipsis", type Property::BOOLEAN.
+  */
+  ELLIPSIS,
+
+  /**
+  * @brief The enumerations used to specify whether to position the ellipsis at the END, START or MIDDLE of the text.
+  * @details Name "EllipsisPosition", type [Type](@ref Dali::Toolkit::DevelText::EllipsisPosition::Type) (Property::INTEGER), or Property::STRING. Read/Write
+  * @note Default is EllipsisPosition::END.
+  * @see DevelText::EllipsisPosition
+  */
+  ELLIPSIS_POSITION,
 };
 
 } // namespace Property
@@ -271,6 +318,37 @@ using AnchorClickedSignalType = Signal<void(TextEditor, const char*, uint32_t)>;
 DALI_TOOLKIT_API AnchorClickedSignalType& AnchorClickedSignal(TextEditor textEditor);
 
 /**
+ * @brief Input filtered signal type.
+ */
+using InputFilteredSignalType = Signal<void(TextEditor, Toolkit::InputFilter::Property::Type)>;
+
+/**
+ * @brief This signal is emitted when the character to be inserted is filtered by the input filter.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void YourCallbackName(TextEditor textEditor, Toolkit::InputFilter::Property::Type type);
+ *
+ *   DevelTextEditor::InputFilteredSignal(textEditor).Connect(this, &OnInputFiltered);
+ *
+ *   void OnInputFiltered(TextEditor textEditor, InputFilter::Property::Type type)
+ *   {
+ *     if (type == InputFilter::Property::ACCEPTED)
+ *     {
+ *       // If the input has been filtered with an accepted filter, the type is ACCEPTED.
+ *     }
+ *     else if (type == InputFilter::Property::REJECTED)
+ *     {
+ *       // If the input has been filtered with an rejected filter, the type is REJECTED.
+ *     }
+ *   }
+ * @endcode
+ * @param[in] textEditor The instance of TextEditor.
+ * @return The signal to connect to.
+ */
+DALI_TOOLKIT_API InputFilteredSignalType& InputFilteredSignal(TextEditor textEditor);
+
+/**
  * @brief Select the whole text of TextEditor.
  *
  * @param[in] textEditor The instance of TextEditor.
index fdfac30..727b42a 100644 (file)
@@ -35,6 +35,11 @@ AnchorClickedSignalType& AnchorClickedSignal(TextField textField)
   return GetImpl(textField).AnchorClickedSignal();
 }
 
+InputFilteredSignalType& InputFilteredSignal(TextField textField)
+{
+  return GetImpl(textField).InputFilteredSignal();
+}
+
 void SelectWholeText(TextField textField)
 {
   GetImpl(textField).SelectWholeText();
index 3367bec..377b606 100644 (file)
@@ -21,6 +21,7 @@
 #include <dali/devel-api/adaptor-framework/input-method-context.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/text-controls/input-filter-properties.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-field.h>
 
 namespace Dali
@@ -99,7 +100,7 @@ enum
   /**
    * @brief Modifies the default text alignment to match the direction of the system language.
    * @details Name "matchSystemLanguageDirection", type (Property::BOOLEAN), Read/Write
-   * @note The default value is false
+   * @note The default value is true
    */
   MATCH_SYSTEM_LANGUAGE_DIRECTION = ELLIPSIS + 3,
 
@@ -172,6 +173,46 @@ enum
    * @details Name "grabHandleColor", type Property::VECTOR4.
    */
   GRAB_HANDLE_COLOR,
+
+  /**
+   * @brief The input filter
+   * @details Name "inputFilter", type Property::MAP.
+   *
+   * The inputFilter map contains the following keys:
+   *
+   * | %Property Name       | Type     | Required | Description                                                                                                         |
+   * |----------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------|
+   * | accepted             | STRING   | No       | A regular expression in the set of characters to be accepted by the inputFilter (the default value is empty string) |
+   * | rejected             | STRING   | No       | A regular expression in the set of characters to be rejected by the inputFilter (the default value is empty string) |
+   *
+   * @note Optional.
+   * The character set must follow the regular expression rules.
+   * Behaviour can not be guaranteed for incorrect grammars.
+   * Refer the link below for detailed rules.
+   * The functions in std::regex library use the ECMAScript grammar:
+   * http://cplusplus.com/reference/regex/ECMAScript/
+   *
+   * You can use enums instead of "accepted" and "rejected" strings.
+   * @see Dali::Toolkit::InputFilter::Property::Type
+   *
+   * Example Usage:
+   * @code
+   *   Property::Map filter;
+   *   filter[InputFilter::Property::ACCEPTED] = "[\\d]"; // accept whole digits
+   *   filter[InputFilter::Property::REJECTED] = "[0-5]"; // reject 0, 1, 2, 3, 4, 5
+   *
+   *   field.SetProperty(DevelTextField::Property::INPUT_FILTER, filter); // acceptable inputs are 6, 7, 8, 9
+   * @endcode
+   */
+  INPUT_FILTER,
+
+  /**
+  * @brief The enumerations used to specify whether to position the ellipsis at the END, START or MIDDLE of the text.
+  * @details Name "EllipsisPosition", type [Type](@ref Dali::Toolkit::DevelText::EllipsisPosition::Type) (Property::INTEGER), or Property::STRING. Read/Write
+  * @note Default is EllipsisPosition::END.
+  * @see DevelText::EllipsisPosition
+  */
+  ELLIPSIS_POSITION,
 };
 
 } // namespace Property
@@ -206,6 +247,37 @@ using AnchorClickedSignalType = Signal<void(TextField, const char*, uint32_t)>;
 DALI_TOOLKIT_API AnchorClickedSignalType& AnchorClickedSignal(TextField textField);
 
 /**
+ * @brief Input filtered signal type.
+ */
+using InputFilteredSignalType = Signal<void(TextField, Toolkit::InputFilter::Property::Type)>;
+
+/**
+ * @brief This signal is emitted when the character to be inserted is filtered by the input filter.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void YourCallbackName(TextField textField, Toolkit::InputFilter::Property::Type type);
+ *
+ *   DevelTextField::InputFilteredSignal(textField).Connect(this, &OnInputFiltered);
+ *
+ *   void OnInputFiltered(TextField textField, InputFilter::Property::Type type)
+ *   {
+ *     if (type == InputFilter::Property::ACCEPTED)
+ *     {
+ *       // If the input has been filtered with an accepted filter, the type is ACCEPTED.
+ *     }
+ *     else if (type == InputFilter::Property::REJECTED)
+ *     {
+ *       // If the input has been filtered with an rejected filter, the type is REJECTED.
+ *     }
+ *   }
+ * @endcode
+ * @param[in] textField The instance of TextField.
+ * @return The signal to connect to.
+ */
+DALI_TOOLKIT_API InputFilteredSignalType& InputFilteredSignal(TextField textField);
+
+/**
  * @brief Select the whole text of TextField.
  *
  * @param[in] textField The instance of TextField.
index efdad10..ac0f30c 100644 (file)
@@ -95,7 +95,7 @@ enum Type
   /**
      * @brief Modifies the default text alignment to match the direction of the system language.
      * @details Name "matchSystemLanguageDirection", type (Property::BOLEAN), Read/Write
-     * @note The default value is false
+     * @note The default value is true
      *
      * If MATCH_SYSTEM_LANGUAGE_DIRECTION property set true, the default text alignment to match the direction of the system language.
      *
@@ -105,10 +105,10 @@ enum Type
      *
      * | TextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION                 |
      * |-----------------------------------------------------------------------
-     * |        false (default)            |                true              |
+     * |               false               |          true (default)          |
      * |-----------------------------------|----------------------------------|
      * |                     Hello world   |                  Hello world     |
-     * |   ﻡﺮﺤﺑﺍ.                          |                      ﻡﺮﺤﺑﺍ.      |
+     * |   ﻡﺮﺤﺑﺍ.                     |                          ﻡﺮﺤﺑﺍ.      |
      *
      */
   MATCH_SYSTEM_LANGUAGE_DIRECTION,
@@ -154,6 +154,14 @@ enum Type
    *  - fontSize: 10pt, fontSizeScale: 1.5
    */
   FONT_SIZE_SCALE,
+
+  /**
+  * @brief The enumerations used to specify whether to position the ellipsis at the END, START or MIDDLE of the text.
+  * @details Name "EllipsisPosition", type [Type](@ref Dali::Toolkit::DevelText::EllipsisPosition::Type) (Property::INTEGER), or Property::STRING. Read/Write
+  * @note Default is EllipsisPosition::END.
+  * @see DevelText::EllipsisPosition
+  */
+  ELLIPSIS_POSITION,
 };
 
 } // namespace Property
index 2a7090b..12218f7 100755 (executable)
@@ -49,11 +49,31 @@ void WebContext::SetProxyUri(const std::string& uri)
   mWebEngineContext.SetProxyUri(uri);
 }
 
+std::string WebContext::GetProxyUri() const
+{
+  return mWebEngineContext.GetProxyUri();
+}
+
+void WebContext::SetProxyBypassRule(const std::string& proxy, const std::string& bypass)
+{
+  mWebEngineContext.SetProxyBypassRule(proxy, bypass);
+}
+
+std::string WebContext::GetProxyBypassRule() const
+{
+  return mWebEngineContext.GetProxyBypassRule();
+}
+
 void WebContext::SetCertificateFilePath(const std::string& certificatePath)
 {
   mWebEngineContext.SetCertificateFilePath(certificatePath);
 }
 
+std::string WebContext::GetCertificateFilePath() const
+{
+  return mWebEngineContext.GetCertificateFilePath();
+}
+
 void WebContext::SetDefaultProxyAuth(const std::string& username, const std::string& password)
 {
   mWebEngineContext.SetDefaultProxyAuth(username, password);
@@ -134,34 +154,39 @@ bool WebContext::IsCacheEnabled() const
   return mWebEngineContext.IsCacheEnabled();
 }
 
-std::string WebContext::GetContextCertificateFile() const
+void WebContext::SetAppId(const std::string& appId)
 {
-  return mWebEngineContext.GetContextCertificateFile();
+  mWebEngineContext.SetAppId(appId);
 }
 
-void WebContext::SetContextAppId(const std::string& appID)
+bool WebContext::SetAppVersion(const std::string& appVersion)
 {
-  mWebEngineContext.SetContextAppId(appID);
+  return mWebEngineContext.SetAppVersion(appVersion);
 }
 
-bool WebContext::SetContextAppVersion(const std::string& appVersion)
+void WebContext::SetApplicationType(const Dali::WebEngineContext::ApplicationType applicationType)
 {
-  return mWebEngineContext.SetContextAppVersion(appVersion);
+  mWebEngineContext.SetApplicationType(applicationType);
 }
 
-void WebContext::SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType)
+void WebContext::SetTimeOffset(float timeOffset)
 {
-  mWebEngineContext.SetContextApplicationType(applicationType);
+  mWebEngineContext.SetTimeOffset(timeOffset);
 }
 
-void WebContext::SetContextTimeOffset(float timeOffset)
+void WebContext::SetTimeZoneOffset(float timeZoneOffset, float daylightSavingTime)
 {
-  mWebEngineContext.SetContextTimeOffset(timeOffset);
+  mWebEngineContext.SetTimeZoneOffset(timeZoneOffset, daylightSavingTime);
+}
+
+void WebContext::SetDefaultZoomFactor(float zoomFactor)
+{
+  mWebEngineContext.SetDefaultZoomFactor(zoomFactor);
 }
 
-void WebContext::SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime)
+float WebContext::GetDefaultZoomFactor() const
 {
-  mWebEngineContext.SetContextTimeZoneOffset(timeZoneOffset, daylightSavingTime);
+  return mWebEngineContext.GetDefaultZoomFactor();
 }
 
 void WebContext::RegisterUrlSchemesAsCorsEnabled(const std::vector<std::string>& schemes)
@@ -174,16 +199,6 @@ void WebContext::RegisterJsPluginMimeTypes(const std::vector<std::string>& mimeT
   mWebEngineContext.RegisterJsPluginMimeTypes(mimeTypes);
 }
 
-void WebContext::SetDefaultZoomFactor(float zoomFactor)
-{
-  mWebEngineContext.SetDefaultZoomFactor(zoomFactor);
-}
-
-float WebContext::GetContextDefaultZoomFactor() const
-{
-  return mWebEngineContext.GetContextDefaultZoomFactor();
-}
-
 bool WebContext::DeleteAllApplicationCache()
 {
   return mWebEngineContext.DeleteAllApplicationCache();
@@ -209,21 +224,6 @@ void WebContext::DeleteAllFormCandidateData()
   mWebEngineContext.DeleteAllFormCandidateData();
 }
 
-std::string WebContext::GetContextProxy() const
-{
-  return mWebEngineContext.GetContextProxy();
-}
-
-void WebContext::SetContextProxy(const std::string& proxy, const std::string& bypass)
-{
-  mWebEngineContext.SetContextProxy(proxy, bypass);
-}
-
-std::string WebContext::GetProxyBypassRule() const
-{
-  return mWebEngineContext.GetProxyBypassRule();
-}
-
 bool WebContext::FreeUnusedMemory()
 {
   return mWebEngineContext.FreeUnusedMemory();
index 531ec00..56bf2d8 100755 (executable)
@@ -79,6 +79,28 @@ public:
   void SetProxyUri(const std::string& uri);
 
   /**
+   * @brief Get the proxy URI from the network backend of specific context.
+   *
+   * @return current proxy URI or null string if it's not set
+   */
+  std::string GetProxyUri() const;
+
+  /**
+   * @brief Set the given proxy to network backend of specific context.
+   *
+   * @param[in] proxy URI to set
+   * @param[in] bypass rule to set
+   */
+  void SetProxyBypassRule(const std::string& proxy, const std::string& bypass);
+
+  /**
+   * @brief Get the proxy bypass rule from the network backend of specific context.
+   *
+   * @return current proxy bypass rule or null string if it's not set
+   */
+  std::string GetProxyBypassRule() const;
+
+  /**
    * @brief Add CA certificates to persistent NSS certificate database
    *
    * Function accepts a path to a CA certificate file, a path to a directory
@@ -91,6 +113,15 @@ public:
   void SetCertificateFilePath(const std::string& certificatePath);
 
   /**
+   * @brief Get CA certifcate file path
+   *
+   * It returns an internal string and should not be modified.
+   *
+   * @return certificate_file path which is set during ewk_context_certificate_file_set or null string otherwise
+   */
+  std::string GetCertificateFilePath() const;
+
+  /**
    * @brief Set a proxy auth credential to network backend of specific context.
    *
    * @param[in] username username to set
@@ -207,34 +238,25 @@ public:
   /**
    * @brief Query if the cache is enabled
    *
-   * @return @c true is cache is enabled or @c false otherwise
+   * @return true is cache is enabled or false otherwise
    */
   bool IsCacheEnabled() const;
 
   /**
-   * @brief Get CA certifcate file path
-   *
-   * It returns an internal string and should not be modified.
+   * @brief Set application id for context.
    *
-   * @return @c certificate_file is path which is set during ewk_context_certificate_file_set or @c null string otherwise
+   * @param[in] appId application id
    */
-  std::string GetContextCertificateFile() const;
+  void SetAppId(const std::string& appId);
 
   /**
-   * @brief Set application id for @a context.
-   *
-   * @param[in] appID application id
-   */
-  void SetContextAppId(const std::string& appID);
-
-  /**
-   * @brief Set application version for @a context.
+   * @brief Set application version for context.
    *
    * @param[in] appVersion application version
    *
-   * @return @c true if successful, @c false otherwise
+   * @return true if successful, false otherwise
    */
-  bool SetContextAppVersion(const std::string& appVersion);
+  bool SetAppVersion(const std::string& appVersion);
 
   /**
    * @brief To declare application type
@@ -242,14 +264,14 @@ public:
    * @param[in] applicationType The Application_Type enum
    *
    */
-  void SetContextApplicationType(const Dali::WebEngineContext::ApplicationType applicationType);
+  void SetApplicationType(const Dali::WebEngineContext::ApplicationType applicationType);
 
   /**
    * @brief Set time offset
    *
    * @param[in] timeOffset The value will be added to system time as offset
    */
-  void SetContextTimeOffset(float timeOffset);
+  void SetTimeOffset(float timeOffset);
 
   /**
    * @brief Set timezone offset
@@ -257,39 +279,39 @@ public:
    * @param[in] timeZoneOffset offset for time zone.
    * @param[in] daylightSavingTime The value is for daylight saving time use.
    */
-  void SetContextTimeZoneOffset(float timeZoneOffset, float daylightSavingTime);
+  void SetTimeZoneOffset(float timeZoneOffset, float daylightSavingTime);
 
   /**
-   * @brief Register url schemes as CORS enabled
-   *
-   * @param[in] schemes The URL schemes list which will be added to web security policy
+   * @brief Set default zoom factor
    *
+   * @param[in] zoomFactor default zoom factor
    */
-  void RegisterUrlSchemesAsCorsEnabled(const std::vector<std::string>& schemes);
+  void SetDefaultZoomFactor(float zoomFactor);
 
   /**
-   * @brief Register JS plugin mime types.
+   * @brief Get default zoom factor
    *
-   * @param[in] mimeTypes The MIME types will be checked by the renderer frame loader
-   * to skip creating default frame for the object tags with the registered MIME type.
+   * Gets default zoom factor for all pages opened with this context.
+   *
+   * @return default zoom factor or negative value on error
    */
-  void RegisterJsPluginMimeTypes(const std::vector<std::string>& mimeTypes);
+  float GetDefaultZoomFactor() const;
 
   /**
-   * @brief Set default zoom factor
+   * @brief Register url schemes as CORS enabled
+   *
+   * @param[in] schemes The URL schemes list which will be added to web security policy
    *
-   * @param[in] zoomFactor default zoom factor
    */
-  void SetDefaultZoomFactor(float zoomFactor);
+  void RegisterUrlSchemesAsCorsEnabled(const std::vector<std::string>& schemes);
 
   /**
-   * @brief Get default zoom factor
-   *
-   * Gets default zoom factor for all pages opened with this context.
+   * @brief Register JS plugin mime types.
    *
-   * @return @c default zoom factor or negative value on error
+   * @param[in] mimeTypes The MIME types will be checked by the renderer frame loader
+   * to skip creating default frame for the object tags with the registered MIME type.
    */
-  float GetContextDefaultZoomFactor() const;
+  void RegisterJsPluginMimeTypes(const std::vector<std::string>& mimeTypes);
 
   /**
    * @brief Request for deleting all web application caches.
@@ -323,28 +345,6 @@ public:
   void DeleteAllFormCandidateData();
 
   /**
-   * @brief Get the proxy URI from the network backend of specific context.
-   *
-   * @return current proxy URI or @c null string if it's not set
-   */
-  std::string GetContextProxy() const;
-
-  /**
-   * @brief Set the given proxy to network backend of specific context.
-   *
-   * @param[in] proxy URI to set
-   * @param[in] bypass rule to set
-   */
-  void SetContextProxy(const std::string& proxy, const std::string& bypass);
-
-  /**
-   * @brief Get the proxy bypass rule from the network backend of specific context.
-   *
-   * @return current proxy bypass rule or @c null string if it's not set
-   */
-  std::string GetProxyBypassRule() const;
-
-  /**
    * @brief Notify low memory to free unused memory.
    *
    * @return @c true on success or @c false otherwise.
index 5cac9f4..bfa5502 100755 (executable)
@@ -199,7 +199,7 @@ void WebView::GoBack()
   Dali::Toolkit::GetImpl(*this).GoBack();
 }
 
-void WebView::EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler)
+void WebView::EvaluateJavaScript(const std::string& script, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback resultHandler)
 {
   Dali::Toolkit::GetImpl(*this).EvaluateJavaScript(script, resultHandler);
 }
@@ -209,7 +209,7 @@ void WebView::EvaluateJavaScript(const std::string& script)
   Dali::Toolkit::GetImpl(*this).EvaluateJavaScript(script, nullptr);
 }
 
-void WebView::AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler)
+void WebView::AddJavaScriptMessageHandler(const std::string& exposedObjectName, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback handler)
 {
   Dali::Toolkit::GetImpl(*this).AddJavaScriptMessageHandler(exposedObjectName, handler);
 }
@@ -309,84 +309,89 @@ void WebView::RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::Geolo
   Dali::Toolkit::GetImpl(*this).RegisterGeolocationPermissionCallback(callback);
 }
 
-WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
+void WebView::SetTtsFocus(bool focused)
 {
-  return Dali::Toolkit::GetImpl(*this).PageLoadStartedSignal();
+  Dali::Toolkit::GetImpl(*this).SetTtsFocus(focused);
 }
 
-WebView::WebViewPageLoadSignalType& WebView::PageLoadInProgressSignal()
+void WebView::RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).PageLoadInProgressSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterPageLoadStartedCallback(callback);
 }
 
-WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
+void WebView::RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).PageLoadFinishedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterPageLoadInProgressCallback(callback);
 }
 
-WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
+void WebView::RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).PageLoadErrorSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterPageLoadFinishedCallback(callback);
 }
 
-WebView::WebViewScrollEdgeReachedSignalType& WebView::ScrollEdgeReachedSignal()
+void WebView::RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).ScrollEdgeReachedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterPageLoadErrorCallback(callback);
 }
 
-WebView::WebViewUrlChangedSignalType& WebView::UrlChangedSignal()
+void WebView::RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).UrlChangedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterScrollEdgeReachedCallback(callback);
 }
 
-WebView::WebViewFormRepostDecisionSignalType& WebView::FormRepostDecisionSignal()
+void WebView::RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).FormRepostDecisionSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterUrlChangedCallback(callback);
 }
 
-WebView::WebViewFrameRenderedSignalType& WebView::FrameRenderedSignal()
+void WebView::RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).FrameRenderedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterFormRepostDecidedCallback(callback);
 }
 
-WebView::WebViewRequestInterceptorSignalType& WebView::RequestInterceptorSignal()
+void WebView::RegisterFrameRenderedCallback(Dali::WebEnginePlugin::WebEngineFrameRenderedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).RequestInterceptorSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterFrameRenderedCallback(callback);
 }
 
-WebView::WebViewConsoleMessageSignalType& WebView::ConsoleMessageSignal()
+void WebView::RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).ConsoleMessageSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterRequestInterceptorCallback(callback);
 }
 
-WebView::WebViewResponsePolicyDecisionSignalType& WebView::ResponsePolicyDecisionSignal()
+void WebView::RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).ResponsePolicyDecisionSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterConsoleMessageReceivedCallback(callback);
 }
 
-WebView::WebViewCertificateSignalType& WebView::CertificateConfirmSignal()
+void WebView::RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).CertificateConfirmSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterResponsePolicyDecidedCallback(callback);
 }
 
-WebView::WebViewCertificateSignalType& WebView::SslCertificateChangedSignal()
+void WebView::RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).SslCertificateChangedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterCertificateConfirmedCallback(callback);
 }
 
-WebView::WebViewHttpAuthHandlerSignalType& WebView::HttpAuthHandlerSignal()
+void WebView::RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).HttpAuthHandlerSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterSslCertificateChangedCallback(callback);
 }
 
-WebView::WebViewContextMenuCustomizedSignalType& WebView::ContextMenuCustomizedSignal()
+void WebView::RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).ContextMenuCustomizedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterHttpAuthHandlerCallback(callback);
 }
 
-WebView::WebViewContextMenuItemSelectedSignalType& WebView::ContextMenuItemSelectedSignal()
+void WebView::RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback)
 {
-  return Dali::Toolkit::GetImpl(*this).ContextMenuItemSelectedSignal();
+  Dali::Toolkit::GetImpl(*this).RegisterContextMenuShownCallback(callback);
+}
+
+void WebView::RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback)
+{
+  Dali::Toolkit::GetImpl(*this).RegisterContextMenuHiddenCallback(callback);
 }
 
 WebView::WebView(Internal::WebView& implementation)
index b290bfd..b4e7688 100755 (executable)
@@ -33,10 +33,7 @@ namespace Toolkit
 class ImageView;
 class WebBackForwardList;
 class WebContext;
-class WebContextMenu;
-class WebContextMenuItem;
 class WebCookieManager;
-class WebFormRepostDecision;
 class WebSettings;
 
 namespace Internal DALI_INTERNAL
@@ -118,7 +115,7 @@ public:
       /**
        * @brief Whether video hole is enabled or not.
        * @details name "videoHoleEnabled", type Property::BOOLEAN.
-       * @note The value is read-only.
+       * @note False by default.
        */
       VIDEO_HOLE_ENABLED,
 
@@ -193,71 +190,6 @@ public:
    */
   using WebViewScreenshotCapturedCallback = std::function<void(Dali::Toolkit::ImageView)>;
 
-  /**
-   * @brief WebView signal type related with page loading.
-   */
-  using WebViewPageLoadSignalType = Signal<void(WebView, const std::string&)>;
-
-  /**
-   * @brief WebView signal type related with page loading error.
-   */
-  using WebViewPageLoadErrorSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineLoadError>)>;
-
-  /**
-   * @brief WebView signal type related with scroll edge reached.
-   */
-  using WebViewScrollEdgeReachedSignalType = Signal<void(WebView, Dali::WebEnginePlugin::ScrollEdge)>;
-
-  /**
-   * @brief WebView signal type related with url changed.
-   */
-  using WebViewUrlChangedSignalType = Signal<void(WebView, const std::string&)>;
-
-  /**
-   * @brief WebView signal type related with form repost decision.
-   */
-  using WebViewFormRepostDecisionSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineFormRepostDecision>)>;
-
-  /**
-   * @brief WebView signal type related with frame rendered.
-   */
-  using WebViewFrameRenderedSignalType = Signal<void(WebView)>;
-
-  /**
-   * @brief WebView signal type related with http request interceptor.
-   */
-  using WebViewRequestInterceptorSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineRequestInterceptor>)>;
-
-  /**
-   * @brief WebView signal type related with console message.
-   */
-  using WebViewConsoleMessageSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineConsoleMessage>)>;
-
-  /**
-   * @brief WebView signal type related with response policy decision.
-   */
-  using WebViewResponsePolicyDecisionSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
-
-  /**
-   * @brief WebView signal type related with certificate changed.
-   */
-  using WebViewCertificateSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineCertificate>)>;
-
-  /**
-   * @brief WebView signal type related with http authentication.
-   */
-  using WebViewHttpAuthHandlerSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineHttpAuthHandler>)>;
-
-  /**
-   * @brief WebView signal type related with context menu customized.
-   */
-  using WebViewContextMenuCustomizedSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineContextMenu>)>;
-
-  /**
-   * @brief WebView signal type related with context menu item selected.
-   */
-  using WebViewContextMenuItemSelectedSignalType = Signal<void(WebView, std::shared_ptr<Dali::WebEngineContextMenuItem>)>;
-
 public:
   /**
    * @brief Create an initialized WebView.
@@ -501,9 +433,9 @@ public:
    * @brief Evaluate JavaScript code represented as a string.
    *
    * @param[in] script The JavaScript code
-   * @param[in] resultHandler The callback function to be called by the JavaScript runtime. This carries evaluation result
+   * @param[in] resultHandler The callback to be called by the JavaScript runtime. This carries evaluation result
    */
-  void EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler);
+  void EvaluateJavaScript(const std::string& script, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback resultHandler);
 
   /**
    * @brief Evaluate JavaScript code represented as a string.
@@ -536,7 +468,7 @@ public:
    * @param[in] exposedObjectName The name of exposed object
    * @param[in] handler The callback function
    */
-  void AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler);
+  void AddJavaScriptMessageHandler(const std::string& exposedObjectName, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback handler);
 
   /**
    * @brief Register alert callback for javascript.
@@ -683,116 +615,123 @@ public:
   void RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::GeolocationPermissionCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when page loading is started.
+   * @brief Set or unset TTS focus of the webview.
+   * @param[in] focused True if it is gained, false lost.
+   * @note It only works when the webview does not have keyinput focus. If it has keyinput focus, the TTS focus is set automatically.
+   */
+  void SetTtsFocus(bool focused);
+
+  /**
+   * @brief Callback to be called when page loading is started.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewPageLoadSignalType& PageLoadStartedSignal();
+  void RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when page loading is in progress.
+   * @brief Callback to be called when page loading is in progress.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewPageLoadSignalType& PageLoadInProgressSignal();
+  void RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when page loading is finished.
+   * @brief Callback to be called when page loading is finished.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewPageLoadSignalType& PageLoadFinishedSignal();
+  void RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when an error occurs in page loading.
+   * @brief Callback to be called when an error occurs in page loading.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewPageLoadErrorSignalType& PageLoadErrorSignal();
+  void RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when scroll edge is reached.
+   * @brief Callback to be called when scroll edge is reached.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewScrollEdgeReachedSignalType& ScrollEdgeReachedSignal();
+  void RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when url is changed.
+   * @brief Callback to be called when url is changed.
    *
-   * @return A signal object to connect with
+   * @param[in] callback
    */
-  WebViewUrlChangedSignalType& UrlChangedSignal();
+  void RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when form repost decision is requested.
+   * @brief Callback to be called when form repost decision is requested.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewFormRepostDecisionSignalType& FormRepostDecisionSignal();
+  void RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when frame is rendered.
+   * @brief Callback to be called when frame is rendered.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewFrameRenderedSignalType& FrameRenderedSignal();
+  void RegisterFrameRenderedCallback(Dali::WebEnginePlugin::WebEngineFrameRenderedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when http request need be intercepted.
+   * @brief Callback to be called when http request need be intercepted.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewRequestInterceptorSignalType& RequestInterceptorSignal();
+  void RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when console message will be logged.
+   * @brief Callback to be called when console message will be logged.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewConsoleMessageSignalType& ConsoleMessageSignal();
+  void RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when response policy would be decided.
+   * @brief Callback to be called when response policy would be decided.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
+  void RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when certificate need be confirmed.
+   * @brief Callback to be called when certificate need be confirmed.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewCertificateSignalType& CertificateConfirmSignal();
+  void RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when ssl certificate is changed.
+   * @brief Callback to be called when ssl certificate is changed.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewCertificateSignalType& SslCertificateChangedSignal();
+  void RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when http authentication need be confirmed.
+   * @brief Callback to be called when http authentication need be confirmed.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewHttpAuthHandlerSignalType& HttpAuthHandlerSignal();
+  void RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when context menu would be customized.
+   * @brief Callback to be called when context menu would be shown.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewContextMenuCustomizedSignalType& ContextMenuCustomizedSignal();
+  void RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback);
 
   /**
-   * @brief Connect to this signal to be notified when context menu item is selected.
+   * @brief Callback to be called when context menu would be hidden.
    *
-   * @return A signal object to connect with.
+   * @param[in] callback
    */
-  WebViewContextMenuItemSelectedSignalType& ContextMenuItemSelectedSignal();
+  void RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback);
 
 public: // Not intended for application developers
   /// @cond internal
index faa7fc1..f320269 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -40,6 +40,16 @@ bool IsFocusIndicatorEnabled(KeyboardFocusManager keyboardFocusManager)
   return GetImpl(keyboardFocusManager).IsFocusIndicatorEnabled();
 }
 
+void EnableDefaultAlgorithm(KeyboardFocusManager keyboardFocusManager, bool enable)
+{
+  GetImpl(keyboardFocusManager).EnableDefaultAlgorithm(enable);
+}
+
+bool IsDefaultAlgorithmEnabled(KeyboardFocusManager keyboardFocusManager)
+{
+  return GetImpl(keyboardFocusManager).IsDefaultAlgorithmEnabled();
+}
+
 } // namespace DevelKeyboardFocusManager
 
 } // namespace Toolkit
index afe3e43..192c296 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_KEYBOARD_FOCUS_MANAGER_DEVEL_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -84,6 +84,22 @@ DALI_TOOLKIT_API void EnableFocusIndicator(KeyboardFocusManager keyboardFocusMan
  */
 DALI_TOOLKIT_API bool IsFocusIndicatorEnabled(KeyboardFocusManager keyboardFocusManager);
 
+/**
+ * @brief Decide using default focus algorithm or not
+ *
+ * @param[in] keyboardFocusManager The instance of KeyboardFocusManager
+ * @param[in] enable Whether using default focus algorithm or not
+ */
+DALI_TOOLKIT_API void EnableDefaultAlgorithm(KeyboardFocusManager keyboardFocusManager, bool enable);
+
+/**
+ * @brief Check default focus algorithm is enabled or not
+ *
+ * @param[in] keyboardFocusManager The instance of KeyboardFocusManager
+ * @return True when default focus algorithm is enabled
+ */
+DALI_TOOLKIT_API bool IsDefaultAlgorithmEnabled(KeyboardFocusManager keyboardFocusManager);
+
 } // namespace DevelKeyboardFocusManager
 
 } // namespace Toolkit
index a74af43..100d59e 100644 (file)
@@ -56,6 +56,95 @@ enum Mode
 
 } // namespace LineWrap
 
+/**
+ * A enum for defining text layout directions.
+ * It can also be inherited (from a parent) or deduced from the default language script of a locale.
+ * And it can be the direction of the text ifself.
+ */
+enum class MatchLayoutDirection
+{
+  INHERIT, // The text layout direction is inherited. If you change the layout direction, it will be aligned with the changed layout direction.
+  LOCALE,  // The text layout direction is determined by the locale of the system language.
+  CONTENTS // The text layout direction is determined by the text itself.
+};
+
+/**
+ * @brief Contains types which specify where the text is truncated and replaced by Ellipsis glyph.
+ *
+ * If the text cannot fit into layout size then truncate text and replace it by Ellipsis glyph.
+ *
+ * Ellipsis works after layouting text normally according to LineWrap mode.
+ *
+ * Ellipsis glyph is three dots "...".
+ *
+ * The Ellipsis property should be enabled.
+ *
+ *
+ * Example: "Hello here is test goodbye."
+ *
+ * Assume LineWrap is CHARACTER.
+ *
+ * EllipsisPosition::END type in single line, truncate tail of line then add Ellipsis:
+ * @code
+ * +-----------+
+ * |Hello he...|
+ * +-----------+
+ * @endcode
+ *
+ * EllipsisPosition::END type in multi-lines, truncate tail of the last appeared line then add Ellipsis:
+ * @code
+ * +-----------+
+ * |Hello here |
+ * |is test ...|
+ * +-----------+
+ * @endcode
+ *
+ * EllipsisPosition::START type in single line, truncate head of line then add Ellipsis:
+ * @code
+ * +-----------+
+ * |...goodbye.|
+ * +-----------+
+ * @endcode
+ *
+ * EllipsisPosition::START type in multi-lines, truncate head of the first appeared line then add Ellipsis:
+ * @code
+ * +-----------+
+ * |...test goo|
+ * |dbye.      |
+ * +-----------+
+ * @endcode
+ *
+ * EllipsisPosition::MIDDLE type in single line, truncate middle of line then add Ellipsis:
+ * @code
+ * +-----------+
+ * |Hell...bye.|
+ * +-----------+
+ * @endcode
+ *
+ * EllipsisPosition::MIDDLE type in multi-lines, truncate middle lines. In the end of the last appeared line before removed lines add Ellipsis:
+ * @code
+ * +-----------+
+ * |Hello he...|
+ * |dbye.      |
+ * +-----------+
+ * @endcode
+ *
+ */
+namespace EllipsisPosition
+{
+/**
+ * @brief Enumerations specifying where to position the ellipsis glyph.
+ * @see EllipsisPosition
+ */
+enum Type
+{
+  END = 0, ///< END position will truncate tail of text that exceeds the layout size then replace it by Ellipsis glyph in the end of the last appeared line.
+  START,   ///< START position will truncate head of text that exceeds the layout size then replace it by Ellipsis glyph in the start of the first appeared line. In multilines, the lines are removed from top until the text fit into layout height.
+  MIDDLE   ///< MIDDLE position will truncate middle of text that exceeds the layout size then replace it by Ellipsis glyph in the middle of line. In multilines, the lines are removed from middle until the text fit into layout height then add ellipsis glyph in the end of the last line appeared before removed lines.
+};
+
+} // namespace EllipsisPosition
+
 } // namespace DevelText
 
 } // namespace Toolkit
index 99ff139..9609a3b 100644 (file)
@@ -978,6 +978,7 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   const bool               isTextMirrored          = internalDataModel.isTextMirrored;
   const Vector<Character>& mirroredUtf32Characters = internalDataModel.mirroredUtf32Characters;
   const Length             numberOfCharacters      = internalDataModel.numberOfCharacters;
+  const auto               ellipsisPosition        = textModel->mEllipsisPosition;
 
   Layout::Type layout = Layout::SINGLELINE;
 
@@ -1031,9 +1032,8 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   // Resize the vector of positions to have the same size than the vector of glyphs.
   rendererParameters.positions.Resize(numberOfGlyphs);
 
-  textModel->mLineWrapMode                 = Text::LineWrap::WORD;
-  textModel->mIgnoreSpacesAfterText        = false;
-  textModel->mMatchSystemLanguageDirection = false;
+  textModel->mLineWrapMode          = Text::LineWrap::WORD;
+  textModel->mIgnoreSpacesAfterText = false;
   Text::Layout::Parameters layoutParameters(internalDataModel.textLayoutArea,
                                             textModel);
 
@@ -1054,7 +1054,8 @@ Size LayoutText(const RendererParameters& textParameters, TextAbstraction::TextR
   layoutEngine.LayoutText(layoutParameters,
                           newLayoutSize,
                           textParameters.ellipsisEnabled,
-                          isAutoScrollEnabled);
+                          isAutoScrollEnabled,
+                          ellipsisPosition);
 
   return newLayoutSize;
 }
index 54cf75f..70e9c76 100644 (file)
@@ -1324,9 +1324,13 @@ Property::Index Button::AccessibleImpl::GetNamePropertyIndex()
   Property::Map   labelMap = Self().GetProperty<Property::Map>(label);
 
   if(MapContainsTextString(labelMap))
+  {
     return label;
+  }
   else
+  {
     return Property::INVALID_INDEX;
+  }
 }
 
 Dali::Accessibility::States Button::AccessibleImpl::CalculateStates()
index 8308ce1..98733ea 100644 (file)
@@ -85,11 +85,13 @@ void CheckBoxButton::OnInitialize()
 
 Dali::Accessibility::States CheckBoxButton::AccessibleImpl::CalculateStates()
 {
-  auto tmp = Button::AccessibleImpl::CalculateStates();
-  auto slf = Toolkit::Button::DownCast(Self());
-  if(slf.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
-    tmp[Dali::Accessibility::State::CHECKED] = true;
-  return tmp;
+  auto state = Button::AccessibleImpl::CalculateStates();
+  auto self = Toolkit::Button::DownCast(Self());
+  if(self.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
+  {
+    state[Dali::Accessibility::State::CHECKED] = true;
+  }
+  return state;
 }
 
 void CheckBoxButton::OnStateChange(State newState)
@@ -98,8 +100,7 @@ void CheckBoxButton::OnStateChange(State newState)
   if(Dali::Accessibility::IsUp() && (Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self())
      && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
   {
-    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(
-      Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
+    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
   }
 }
 
index 2dc4385..2958766 100644 (file)
@@ -196,10 +196,10 @@ Property::Value PushButton::GetProperty(BaseObject* object, Property::Index prop
 
 Dali::Accessibility::States PushButton::AccessibleImpl::CalculateStates()
 {
-  auto tmp                                 = Button::AccessibleImpl::CalculateStates();
-  auto slf                                 = Toolkit::Button::DownCast(Self());
-  tmp[Dali::Accessibility::State::PRESSED] = slf.GetProperty<bool>(Toolkit::Button::Property::SELECTED);
-  return tmp;
+  auto state = Button::AccessibleImpl::CalculateStates();
+  auto self = Toolkit::Button::DownCast(Self());
+  state[Dali::Accessibility::State::PRESSED] = self.GetProperty<bool>(Toolkit::Button::Property::SELECTED);
+  return state;
 }
 
 void PushButton::OnStateChange(State newState)
@@ -208,13 +208,11 @@ void PushButton::OnStateChange(State newState)
   if(Dali::Accessibility::IsUp() && (Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self())
      && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
   {
-    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(
-      Dali::Accessibility::State::PRESSED, newState == SELECTED_STATE ? 1 : 0, 0);
+    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(Dali::Accessibility::State::PRESSED, newState == SELECTED_STATE ? 1 : 0, 0);
 
     if(Self().GetProperty<bool>(Toolkit::Button::Property::TOGGLABLE))
     {
-      Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(
-        Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
+      Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
     }
   }
 }
index f17a8c9..4b4e070 100644 (file)
@@ -103,23 +103,27 @@ void RadioButton::OnStateChange(State newState)
       }
     }
   }
+
   // TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
   if(Dali::Accessibility::IsUp() && (Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self())
      && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
   {
-    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(
-      Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
+    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
   }
 }
 
 Dali::Accessibility::States RadioButton::AccessibleImpl::CalculateStates()
 {
-  auto tmp = Button::AccessibleImpl::CalculateStates();
-  auto slf = Toolkit::Button::DownCast(Self());
-  if(slf.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
-    tmp[Dali::Accessibility::State::CHECKED] = true;
-  tmp[Dali::Accessibility::State::SELECTABLE] = true;
-  return tmp;
+  auto state = Button::AccessibleImpl::CalculateStates();
+  auto self = Toolkit::Button::DownCast(Self());
+
+  if(self.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
+  {
+    state[Dali::Accessibility::State::CHECKED] = true;
+  }
+
+  state[Dali::Accessibility::State::SELECTABLE] = true;
+  return state;
 }
 
 } // namespace Internal
index 311f6b3..1697b20 100644 (file)
@@ -377,7 +377,9 @@ Dali::Accessibility::States ToggleButton::AccessibleImpl::CalculateStates()
   auto states = Button::AccessibleImpl::CalculateStates();
   auto button = Toolkit::ToggleButton::DownCast(Self());
   if(button.GetProperty<int>(Toolkit::ToggleButton::Property::CURRENT_STATE_INDEX))
+  {
     states[Dali::Accessibility::State::CHECKED] = true;
+  }
   return states;
 }
 
@@ -401,9 +403,8 @@ void ToggleButton::OnStateChange(State newState)
   if(Dali::Accessibility::IsUp() && (Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
      && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
   {
-    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(
-      Dali::Accessibility::State::CHECKED, mCurrentToggleIndex ? 1 : 0, 0);
-      Dali::Accessibility::Accessible::Get(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
+    Dali::Accessibility::Accessible::Get(Self())->EmitStateChanged(Dali::Accessibility::State::CHECKED, mCurrentToggleIndex ? 1 : 0, 0);
+    Dali::Accessibility::Accessible::Get(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
   }
 }
 
index 342784a..6d310cf 100644 (file)
@@ -91,8 +91,6 @@ void CanvasView::OnInitialize()
       new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::IMAGE));
   });
 
-  Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
   Adaptor::Get().RegisterProcessor(*this);
 }
 
index 33670d6..db346bd 100644 (file)
@@ -222,44 +222,57 @@ static bool DoAction(BaseObject* object, const std::string& actionName, const Pr
 
   DALI_ASSERT_ALWAYS(control);
 
-  if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) ||
-     actionName == "activate")
+  if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED) || actionName == "activate")
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityActivateSignal(control).Empty())
+    {
       DevelControl::AccessibilityActivateSignal(control).Emit();
+    }
     else
+    {
       ret = Internal::GetImplementation(control).OnAccessibilityActivated();
+    }
   }
   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED))
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityReadingSkippedSignal(control).Empty())
+    {
       DevelControl::AccessibilityReadingSkippedSignal(control).Emit();
+    }
   }
   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED))
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityReadingPausedSignal(control).Empty())
+    {
       DevelControl::AccessibilityReadingPausedSignal(control).Emit();
+    }
   }
   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED))
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityReadingResumedSignal(control).Empty())
+    {
       DevelControl::AccessibilityReadingResumedSignal(control).Emit();
+    }
   }
   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED))
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityReadingCancelledSignal(control).Empty())
+    {
       DevelControl::AccessibilityReadingCancelledSignal(control).Emit();
+    }
   }
   else if(0 == strcmp(actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED))
   {
     // if cast succeeds there is an implementation so no need to check
     if(!DevelControl::AccessibilityReadingStoppedSignal(control).Empty())
+    {
       DevelControl::AccessibilityReadingStoppedSignal(control).Emit();
+    }
   }
   else
   {
@@ -414,12 +427,12 @@ const PropertyRegistration Control::Impl::PROPERTY_12(typeRegistration, "rightFo
 const PropertyRegistration Control::Impl::PROPERTY_13(typeRegistration, "upFocusableActorId",             Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,            Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_14(typeRegistration, "downFocusableActorId",           Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID,          Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 const PropertyRegistration Control::Impl::PROPERTY_15(typeRegistration, "shadow",                         Toolkit::DevelControl::Property::SHADOW,                           Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
-const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_16(typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_17(typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,        Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_18(typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_19(typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_20(typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty);
+const PropertyRegistration Control::Impl::PROPERTY_21(typeRegistration, "accessibilityAttributes",        Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty);
 // clang-format on
 
 Control::Impl::Impl(Control& controlImpl)
@@ -461,14 +474,13 @@ Control::Impl::Impl(Control& controlImpl)
       return Control::Impl::GetAccessibilityObject(actor);
     });
 
-  accessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor,
-                                                                                             Dali::Accessibility::Role::UNKNOWN));
+  mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
+    return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::UNKNOWN));
   };
 
-  size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
-  mAccessibilityRelations.reserve(len);
-  for(auto i = 0u; i < len; ++i)
+  size_t length = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
+  mAccessibilityRelations.reserve(length);
+  for(auto i = 0u; i < length; ++i)
   {
     mAccessibilityRelations.push_back({});
   }
@@ -958,11 +970,10 @@ void Control::Impl::DoAction(Dali::Property::Index visualIndex, Dali::Property::
   }
 }
 
-void Control::Impl::AppendAccessibilityAttribute(const std::string& key,
-                                                 const std::string  value)
+void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
 {
-  Property::Value* val = mAccessibilityAttributes.Find(key);
-  if(val)
+  Property::Value* checkedValue = mAccessibilityAttributes.Find(key);
+  if(checkedValue)
   {
     mAccessibilityAttributes[key] = Property::Value(value);
   }
@@ -1045,76 +1056,6 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
       }
       break;
 
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
-      {
-        std::string name;
-        if(value.Get(name))
-        {
-          controlImpl.mImpl->mAccessibilityName    = name;
-          controlImpl.mImpl->mAccessibilityNameSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityNameSet = false;
-        }
-      }
-      break;
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
-      {
-        std::string txt;
-        if(value.Get(txt))
-        {
-          controlImpl.mImpl->mAccessibilityDescription    = txt;
-          controlImpl.mImpl->mAccessibilityDescriptionSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityDescriptionSet = false;
-        }
-      }
-      break;
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
-      {
-        std::string txt;
-        if(value.Get(txt))
-        {
-          controlImpl.mImpl->mAccessibilityTranslationDomain    = txt;
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
-        }
-      }
-      break;
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
-      {
-        bool highlightable;
-        if(value.Get(highlightable))
-        {
-          controlImpl.mImpl->mAccessibilityHighlightable    = highlightable;
-          controlImpl.mImpl->mAccessibilityHighlightableSet = true;
-        }
-        else
-        {
-          controlImpl.mImpl->mAccessibilityHighlightableSet = false;
-        }
-      }
-      break;
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
-      {
-        Dali::Accessibility::Role val;
-        if(value.Get(val))
-        {
-          controlImpl.mImpl->mAccessibilityRole = val;
-        }
-      }
-      break;
-
       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
       {
         int focusId;
@@ -1224,6 +1165,76 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         break;
       }
 
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
+      {
+        std::string name;
+        if(value.Get(name))
+        {
+          controlImpl.mImpl->mAccessibilityName    = name;
+          controlImpl.mImpl->mAccessibilityNameSet = true;
+        }
+        else
+        {
+          controlImpl.mImpl->mAccessibilityNameSet = false;
+        }
+      }
+      break;
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
+      {
+        std::string text;
+        if(value.Get(text))
+        {
+          controlImpl.mImpl->mAccessibilityDescription    = text;
+          controlImpl.mImpl->mAccessibilityDescriptionSet = true;
+        }
+        else
+        {
+          controlImpl.mImpl->mAccessibilityDescriptionSet = false;
+        }
+      }
+      break;
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
+      {
+        std::string text;
+        if(value.Get(text))
+        {
+          controlImpl.mImpl->mAccessibilityTranslationDomain    = text;
+          controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
+        }
+        else
+        {
+          controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
+        }
+      }
+      break;
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
+      {
+        Dali::Accessibility::Role role;
+        if(value.Get(role))
+        {
+          controlImpl.mImpl->mAccessibilityRole = role;
+        }
+      }
+      break;
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
+      {
+        bool highlightable;
+        if(value.Get(highlightable))
+        {
+          controlImpl.mImpl->mAccessibilityHighlightable    = highlightable;
+          controlImpl.mImpl->mAccessibilityHighlightableSet = true;
+        }
+        else
+        {
+          controlImpl.mImpl->mAccessibilityHighlightableSet = false;
+        }
+      }
+      break;
+
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
         const Property::Map* map = value.GetMap();
@@ -1279,48 +1290,6 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
         break;
       }
 
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
-      {
-        if(controlImpl.mImpl->mAccessibilityNameSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityName;
-        }
-        break;
-      }
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
-      {
-        if(controlImpl.mImpl->mAccessibilityDescriptionSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityDescription;
-        }
-        break;
-      }
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
-      {
-        if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityTranslationDomain;
-        }
-        break;
-      }
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
-      {
-        if(controlImpl.mImpl->mAccessibilityHighlightableSet)
-        {
-          value = controlImpl.mImpl->mAccessibilityHighlightable;
-        }
-        break;
-      }
-
-      case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
-      {
-        value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
-        break;
-      }
-
       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
       {
         value = controlImpl.mImpl->mUpFocusableActorId;
@@ -1388,6 +1357,48 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
         break;
       }
 
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
+      {
+        if(controlImpl.mImpl->mAccessibilityNameSet)
+        {
+          value = controlImpl.mImpl->mAccessibilityName;
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
+      {
+        if(controlImpl.mImpl->mAccessibilityDescriptionSet)
+        {
+          value = controlImpl.mImpl->mAccessibilityDescription;
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
+      {
+        if(controlImpl.mImpl->mAccessibilityTranslationDomainSet)
+        {
+          value = controlImpl.mImpl->mAccessibilityTranslationDomain;
+        }
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
+      {
+        value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
+        break;
+      }
+
+      case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
+      {
+        if(controlImpl.mImpl->mAccessibilityHighlightableSet)
+        {
+          value = controlImpl.mImpl->mAccessibilityHighlightable;
+        }
+        break;
+      }
+
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
         value = controlImpl.mImpl->mAccessibilityAttributes;
@@ -1401,9 +1412,11 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
 void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
 {
-  Property::Value* val = mAccessibilityAttributes.Find(key);
-  if(val)
+  Property::Value* value = mAccessibilityAttributes.Find(key);
+  if(value)
+  {
     mAccessibilityAttributes[key] = Property::Value();
+  }
 }
 
 void Control::Impl::ClearAccessibilityAttributes()
@@ -1413,7 +1426,7 @@ void Control::Impl::ClearAccessibilityAttributes()
 
 void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
 {
-  std::string value;
+  std::string value{};
   if(types[Dali::Accessibility::ReadingInfoType::NAME])
   {
     value += READING_INFO_TYPE_NAME;
@@ -1447,7 +1460,7 @@ void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::R
 
 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
 {
-  std::string value;
+  std::string value{};
   auto        place = mAccessibilityAttributes.Find(READING_INFO_TYPE_ATTRIBUTE_NAME);
   if(place)
   {
@@ -1830,30 +1843,51 @@ void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolk
 
   Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
   Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
+  float   borderlineWidth(0.0f);
+  Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
+  float   borderlineOffset(0.0f);
 
   if(!destinationMap.Empty())
   {
-    static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+    static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
       Property::Value* propertyValue = map.Find(index);
       if(propertyValue)
       {
         return propertyValue->Get<Vector4>();
       }
-      return Vector4{};
+      return defaultValue;
     };
 
-    mixColor     = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
-    cornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
+    static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
+      Property::Value* propertyValue = map.Find(index);
+      if(propertyValue)
+      {
+        return propertyValue->Get<float>();
+      }
+      return defaultValue;
+    };
+
+    mixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
+    cornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
+    borderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
+    borderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
+    borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
 
     if(sourceMap.Empty())
     {
       sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
       sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
       sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
+      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
+      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
+      sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
     }
 
-    Vector4 sourceMixColor     = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
-    Vector4 sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
+    Vector4 sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
+    Vector4 sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
+    float   sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
+    Vector4 sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
+    float   sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
 
     std::vector<Dali::Property>                              properties;
     std::vector<std::pair<Property::Value, Property::Value>> values;
@@ -1876,6 +1910,24 @@ void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolk
       values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
     }
 
+    if(sourceBorderlineWidth != borderlineWidth)
+    {
+      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
+      values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
+    }
+
+    if(sourceBorderlineColor != borderlineColor)
+    {
+      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
+      values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
+    }
+
+    if(sourceBorderlineOffset != borderlineOffset)
+    {
+      properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
+      values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
+    }
+
     for(uint32_t i = 0; i < properties.size(); ++i)
     {
       if(timePeriod.delaySeconds > 0.0f)
@@ -1947,20 +1999,22 @@ void Control::Impl::OnIdleCallback()
 
 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
 {
-  if(!accessibilityObject)
-    accessibilityObject = accessibilityConstructor(mControlImpl.Self());
-  return accessibilityObject.get();
+  if(!mAccessibilityObject)
+  {
+    mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
+  }
+  return mAccessibilityObject.get();
 }
 
 Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
 {
   if(actor)
   {
-    auto q = Dali::Toolkit::Control::DownCast(actor);
-    if(q)
+    auto control = Dali::Toolkit::Control::DownCast(actor);
+    if(control)
     {
-      auto q2 = static_cast<Internal::Control*>(&q.GetImplementation());
-      return q2->mImpl->GetAccessibilityObject();
+      auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
+      return controlImpl->mImpl->GetAccessibilityObject();
     }
   }
   return nullptr;
index 96290b7..e278390 100644 (file)
@@ -342,8 +342,7 @@ public:
    * Attribute is added if not existed previously or updated
    * if existed.
    */
-  void AppendAccessibilityAttribute(const std::string& key,
-                                    const std::string  value);
+  void AppendAccessibilityAttribute(const std::string& key, const std::string value);
 
   /**
    * @brief Removes accessibility attribute
@@ -405,6 +404,22 @@ public:
    */
   void MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod);
 
+  /**
+   * @brief Gets the current control's accessible object.
+   *
+   * @return The handle to Accessible object
+   */
+  Dali::Accessibility::Accessible* GetAccessibilityObject();
+
+  /**
+   * @brief Gets Accessible object handle.
+   *
+   * The method acquires Accessible handle from Actor object
+   * @param  actor Actor object
+   * @return The handle to Accessible object
+   */
+  static Dali::Accessibility::Accessible* GetAccessibilityObject(Dali::Actor actor);
+
 private:
   /**
    * Used as an alternative to boolean so that it is obvious whether a visual is enabled/disabled.
@@ -475,6 +490,8 @@ public:
   Toolkit::Control::KeyInputFocusSignalType                      mKeyInputFocusLostSignal;
   Toolkit::Control::ResourceReadySignalType                      mResourceReadySignal;
   DevelControl::VisualEventSignalType                            mVisualEventSignal;
+
+  // Accessibility
   Toolkit::DevelControl::AccessibilityActivateSignalType         mAccessibilityActivateSignal;
   Toolkit::DevelControl::AccessibilityReadingSkippedSignalType   mAccessibilityReadingSkippedSignal;
   Toolkit::DevelControl::AccessibilityReadingPausedSignalType    mAccessibilityReadingPausedSignal;
@@ -482,17 +499,15 @@ public:
   Toolkit::DevelControl::AccessibilityReadingCancelledSignalType mAccessibilityReadingCancelledSignal;
   Toolkit::DevelControl::AccessibilityReadingStoppedSignalType   mAccessibilityReadingStoppedSignal;
 
-  Toolkit::DevelControl::AccessibilityGetNameSignalType        mAccessibilityGetNameSignal;
-  Toolkit::DevelControl::AccessibilityGetDescriptionSignalType mAccessibilityGetDescriptionSignal;
-  Toolkit::DevelControl::AccessibilityDoGestureSignalType      mAccessibilityDoGestureSignal;
+  Toolkit::DevelControl::AccessibilityGetNameSignalType          mAccessibilityGetNameSignal;
+  Toolkit::DevelControl::AccessibilityGetDescriptionSignalType   mAccessibilityGetDescriptionSignal;
+  Toolkit::DevelControl::AccessibilityDoGestureSignalType        mAccessibilityDoGestureSignal;
 
   std::string mAccessibilityName;
-  bool        mAccessibilityNameSet = false;
-
   std::string mAccessibilityDescription;
-  bool        mAccessibilityDescriptionSet = false;
-
   std::string mAccessibilityTranslationDomain;
+  bool        mAccessibilityNameSet = false;
+  bool        mAccessibilityDescriptionSet = false;
   bool        mAccessibilityTranslationDomainSet = false;
 
   bool mAccessibilityHighlightable    = false;
@@ -500,7 +515,9 @@ public:
 
   Dali::Accessibility::Role mAccessibilityRole = Dali::Accessibility::Role::UNKNOWN;
 
-  std::vector<std::vector<Accessibility::Address>> mAccessibilityRelations;
+  std::vector<std::vector<Accessibility::Address>>                       mAccessibilityRelations;
+  std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Actor)> mAccessibilityConstructor;
+  std::unique_ptr<Dali::Accessibility::Accessible>                       mAccessibilityObject;
 
   // Gesture Detection
   PinchGestureDetector     mPinchGestureDetector;
@@ -545,17 +562,6 @@ public:
   static const PropertyRegistration PROPERTY_20;
   static const PropertyRegistration PROPERTY_21;
   static const PropertyRegistration PROPERTY_22;
-
-  /**
-   * The method acquires Accessible handle from Actor object
-   * @param  actor Actor object
-   * @return       handle to Accessible object
-   */
-  static Dali::Accessibility::Accessible* GetAccessibilityObject(Dali::Actor actor);
-  Dali::Accessibility::Accessible*        GetAccessibilityObject();
-
-  std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Actor)> accessibilityConstructor;
-  std::unique_ptr<Dali::Accessibility::Accessible>                       accessibilityObject;
 };
 
 } // namespace Internal
index 556711f..e3701ec 100644 (file)
@@ -97,9 +97,6 @@ void ImageView::OnInitialize()
     return std::unique_ptr<Dali::Accessibility::Accessible>(
       new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::IMAGE));
   });
-
-  //Enable highightability
-  Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
 }
 
 void ImageView::SetImage(const Property::Map& map)
@@ -300,19 +297,34 @@ void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::C
 
   destinationVisual.CreatePropertyMap(destinationMap);
 
-  static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+  static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
     Property::Value* propertyValue = map.Find(index);
     if(propertyValue)
     {
       return propertyValue->Get<Vector4>();
     }
-    return Vector4{};
+    return defaultValue;
+  };
+
+  static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
+    Property::Value* propertyValue = map.Find(index);
+    if(propertyValue)
+    {
+      return propertyValue->Get<float>();
+    }
+    return defaultValue;
   };
 
   Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f);
   Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
-  Vector4 destinationMixColor     = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
-  Vector4 destinationCornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
+  float   sourceBorderlineWidth(0.0f);
+  Vector4 sourceBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
+  float   sourceBorderlineOffset(0.0f);
+  Vector4 destinationMixColor         = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
+  Vector4 destinationCornerRadius     = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
+  float   destinationBorderlineWidth  = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+  Vector4 destinationBorderlineColor  = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+  float   destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
 
   Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source);
   Toolkit::Visual::Base    sourceVisual;
@@ -326,8 +338,11 @@ void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::C
   if(sourceVisual)
   {
     sourceVisual.CreatePropertyMap(sourceMap);
-    sourceMixColor     = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
-    sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
+    sourceMixColor         = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
+    sourceCornerRadius     = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
+    sourceBorderlineWidth  = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+    sourceBorderlineColor  = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+    sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
   }
 
   std::vector<Dali::Property>                              properties;
@@ -348,6 +363,21 @@ void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::C
     properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::CORNER_RADIUS));
     values.push_back(std::make_pair(sourceCornerRadius, destinationCornerRadius));
   }
+  if(sourceBorderlineWidth != destinationBorderlineWidth)
+  {
+    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
+    values.push_back(std::make_pair(sourceBorderlineWidth, destinationBorderlineWidth));
+  }
+  if(sourceBorderlineColor != destinationBorderlineColor)
+  {
+    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
+    values.push_back(std::make_pair(sourceBorderlineColor, destinationBorderlineColor));
+  }
+  if(sourceBorderlineOffset != destinationBorderlineOffset)
+  {
+    properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
+    values.push_back(std::make_pair(sourceBorderlineOffset, destinationBorderlineOffset));
+  }
 
   for(uint32_t i = 0; i < properties.size(); ++i)
   {
index 48dfaad..1006307 100644 (file)
@@ -683,9 +683,8 @@ double ProgressBar::AccessibleImpl::GetMinimum()
 
 double ProgressBar::AccessibleImpl::GetCurrent()
 {
-  auto p = Toolkit::ProgressBar::DownCast(Self());
-  return p.GetProperty(Toolkit::ProgressBar::Property::PROGRESS_VALUE)
-    .Get<float>();
+  auto self = Toolkit::ProgressBar::DownCast(Self());
+  return self.GetProperty(Toolkit::ProgressBar::Property::PROGRESS_VALUE).Get<float>();
 }
 
 double ProgressBar::AccessibleImpl::GetMaximum()
@@ -696,10 +695,12 @@ double ProgressBar::AccessibleImpl::GetMaximum()
 bool ProgressBar::AccessibleImpl::SetCurrent(double current)
 {
   if(current < GetMinimum() || current > GetMaximum())
+  {
     return false;
-  auto p = Toolkit::ProgressBar::DownCast(Self());
-  p.SetProperty(Toolkit::ProgressBar::Property::PROGRESS_VALUE,
-                static_cast<float>(current));
+  }
+
+  auto self = Toolkit::ProgressBar::DownCast(Self());
+  self.SetProperty(Toolkit::ProgressBar::Property::PROGRESS_VALUE, static_cast<float>(current));
   return true;
 }
 
index fcf0b91..1da4297 100644 (file)
@@ -863,42 +863,49 @@ Toolkit::ScrollBar ScrollBar::New(Toolkit::ScrollBar::Direction direction)
 
 double ScrollBar::AccessibleImpl::GetMinimum()
 {
-  auto   p                = Toolkit::ScrollBar::DownCast(Self());
-  Handle scrollableHandle = GetImpl(p).mScrollableObject.GetHandle();
-  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(p).mPropertyMinScrollPosition) : 0.0f;
+  auto self = Toolkit::ScrollBar::DownCast(Self());
+  Handle scrollableHandle = GetImpl(self).mScrollableObject.GetHandle();
+  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(self).mPropertyMinScrollPosition) : 0.0f;
 }
 
 double ScrollBar::AccessibleImpl::GetCurrent()
 {
-  auto   p                = Toolkit::ScrollBar::DownCast(Self());
-  Handle scrollableHandle = GetImpl(p).mScrollableObject.GetHandle();
-  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(p).mPropertyScrollPosition) : 0.0f;
+  auto self = Toolkit::ScrollBar::DownCast(Self());
+  Handle scrollableHandle = GetImpl(self).mScrollableObject.GetHandle();
+  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(self).mPropertyScrollPosition) : 0.0f;
 }
 
 double ScrollBar::AccessibleImpl::GetMaximum()
 {
-  auto   p                = Toolkit::ScrollBar::DownCast(Self());
-  Handle scrollableHandle = GetImpl(p).mScrollableObject.GetHandle();
-  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(p).mPropertyMaxScrollPosition) : 1.0f;
+  auto self = Toolkit::ScrollBar::DownCast(Self());
+  Handle scrollableHandle = GetImpl(self).mScrollableObject.GetHandle();
+  return scrollableHandle ? scrollableHandle.GetCurrentProperty<float>(GetImpl(self).mPropertyMaxScrollPosition) : 1.0f;
 }
 
 bool ScrollBar::AccessibleImpl::SetCurrent(double current)
 {
   if(current < GetMinimum() || current > GetMaximum())
+  {
     return false;
+  }
 
-  auto value_before = GetCurrent();
+  auto valueBefore = GetCurrent();
 
-  auto   p                = Toolkit::ScrollBar::DownCast(Self());
-  Handle scrollableHandle = GetImpl(p).mScrollableObject.GetHandle();
+  auto self = Toolkit::ScrollBar::DownCast(Self());
+  Handle scrollableHandle = GetImpl(self).mScrollableObject.GetHandle();
   if(!scrollableHandle)
+  {
     return false;
-  scrollableHandle.SetProperty(GetImpl(p).mPropertyScrollPosition, static_cast<float>(current));
+  }
 
-  auto value_after = GetCurrent();
+  scrollableHandle.SetProperty(GetImpl(self).mPropertyScrollPosition, static_cast<float>(current));
 
-  if((current != value_before) && (value_before == value_after))
+  auto valueAfter = GetCurrent();
+
+  if((current != valueBefore) && (valueBefore == valueAfter))
+  {
     return false;
+  }
 
   return true;
 }
index fdbbbd9..8cac5ed 100644 (file)
@@ -1413,20 +1413,20 @@ Property::Value Slider::GetProperty(BaseObject* object, Property::Index property
 
 double Slider::AccessibleImpl::GetMinimum()
 {
-  auto p = Toolkit::Slider::DownCast(Self());
-  return p.GetProperty(Toolkit::Slider::Property::LOWER_BOUND).Get<float>();
+  auto self = Toolkit::Slider::DownCast(Self());
+  return self.GetProperty(Toolkit::Slider::Property::LOWER_BOUND).Get<float>();
 }
 
 double Slider::AccessibleImpl::GetCurrent()
 {
-  auto p = Toolkit::Slider::DownCast(Self());
-  return p.GetProperty(Toolkit::Slider::Property::VALUE).Get<float>();
+  auto self = Toolkit::Slider::DownCast(Self());
+  return self.GetProperty(Toolkit::Slider::Property::VALUE).Get<float>();
 }
 
 double Slider::AccessibleImpl::GetMaximum()
 {
-  auto p = Toolkit::Slider::DownCast(Self());
-  return p.GetProperty(Toolkit::Slider::Property::UPPER_BOUND).Get<float>();
+  auto self = Toolkit::Slider::DownCast(Self());
+  return self.GetProperty(Toolkit::Slider::Property::UPPER_BOUND).Get<float>();
 }
 
 bool Slider::AccessibleImpl::SetCurrent(double current)
@@ -1434,19 +1434,19 @@ bool Slider::AccessibleImpl::SetCurrent(double current)
   if(current < GetMinimum() || current > GetMaximum())
     return false;
 
-  auto  p    = Toolkit::Slider::DownCast(Self());
-  auto& impl = Toolkit::GetImpl(p);
+  auto self = Toolkit::Slider::DownCast(Self());
+  auto& impl = Toolkit::GetImpl(self);
 
-  const float prev = p.GetProperty<float>(Toolkit::Slider::Property::VALUE);
+  const float prev = self.GetProperty<float>(Toolkit::Slider::Property::VALUE);
   float       next = static_cast<float>(current);
 
   if(fabsf(next - prev) < Math::MACHINE_EPSILON_0)
   {
     // do nothing
   }
-  else if(p.GetProperty<bool>(Toolkit::Slider::Property::SNAP_TO_MARKS))
+  else if(self.GetProperty<bool>(Toolkit::Slider::Property::SNAP_TO_MARKS))
   {
-    auto marks = p.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS);
+    auto marks = self.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS);
 
     int prevIdx;
     if(impl.MarkReached(impl.MapValuePercentage(prev), prevIdx))
@@ -1455,7 +1455,9 @@ bool Slider::AccessibleImpl::SetCurrent(double current)
       nextIdx += (next > prev) ? 1 : -1;
 
       if(nextIdx < 0 || nextIdx >= static_cast<int>(marks.Count()))
+      {
         return false;
+      }
 
       next = marks[nextIdx].Get<float>();
     }
@@ -1477,13 +1479,15 @@ bool Slider::AccessibleImpl::SetCurrent(double current)
 
 double Slider::AccessibleImpl::GetMinimumIncrement()
 {
-  auto p = Toolkit::Slider::DownCast(Self());
+  auto self = Toolkit::Slider::DownCast(Self());
 
-  bool  hasMarks  = !p.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS).Empty();
-  float tolerance = p.GetProperty<float>(Toolkit::Slider::Property::MARK_TOLERANCE);
+  bool  hasMarks  = !self.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS).Empty();
+  float tolerance = self.GetProperty<float>(Toolkit::Slider::Property::MARK_TOLERANCE);
 
   if(!hasMarks || fabsf(tolerance) < 0.01)
+  {
     return 0.0; // let screen-reader choose the increment
+  }
 
   return Math::MACHINE_EPSILON_10000 + tolerance * (GetMaximum() - GetMinimum());
 }
index db7096a..f74a28d 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/adaptor-framework/adaptor.h>
@@ -149,11 +148,16 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "primaryCursorPo
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "grabHandleColor",                      VECTOR4,   GRAB_HANDLE_COLOR                   )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "enableGrabHandlePopup",                BOOLEAN,   ENABLE_GRAB_HANDLE_POPUP            )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "inputMethodSettings",                  MAP,       INPUT_METHOD_SETTINGS               )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "inputFilter",                          MAP,       INPUT_FILTER                        )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "ellipsis",                             BOOLEAN,   ELLIPSIS                            )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextEditor, "ellipsisPosition",                     INTEGER,   ELLIPSIS_POSITION                   )
 
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged",        SIGNAL_TEXT_CHANGED       )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged",  SIGNAL_INPUT_STYLE_CHANGED)
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "maxLengthReached",   SIGNAL_MAX_LENGTH_REACHED )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "anchorClicked",      SIGNAL_ANCHOR_CLICKED     )
+DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputFiltered",      SIGNAL_INPUT_FILTERED     )
+
 
 DALI_TYPE_REGISTRATION_END()
 // clang-format on
@@ -695,7 +699,7 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr
       }
       case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        impl.mController->SetMatchSystemLanguageDirection(value.Get<bool>());
+        impl.mController->SetMatchLayoutDirection(value.Get<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
         break;
       }
       case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
@@ -801,6 +805,33 @@ void TextEditor::SetProperty(BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::DevelTextEditor::Property::INPUT_FILTER:
+      {
+        const Property::Map* map = value.GetMap();
+        if(map)
+        {
+          impl.mController->SetInputFilterOption(*map);
+        }
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::ELLIPSIS:
+      {
+        const bool ellipsis = value.Get<bool>();
+        DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p ELLIPSIS %d\n", impl.mController.Get(), ellipsis);
+
+        impl.mController->SetTextElideEnabled(ellipsis);
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION:
+      {
+        DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast<DevelText::EllipsisPosition::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
+        if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType))
+        {
+          DALI_LOG_INFO(gLogFilter, Debug::General, "TextEditor %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType);
+          impl.mController->SetEllipsisPosition(ellipsisPositionType);
+        }
+        break;
+      }
     } // switch
   }   // texteditor
 }
@@ -1107,7 +1138,7 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde
       }
       case Toolkit::DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        value = impl.mController->IsMatchSystemLanguageDirection();
+        value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS;
         break;
       }
       case Toolkit::DevelTextEditor::Property::MAX_LENGTH:
@@ -1174,6 +1205,23 @@ Property::Value TextEditor::GetProperty(BaseObject* object, Property::Index inde
         value = map;
         break;
       }
+      case Toolkit::DevelTextEditor::Property::INPUT_FILTER:
+      {
+        Property::Map map;
+        impl.mController->GetInputFilterOption(map);
+        value = map;
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::ELLIPSIS:
+      {
+        value = impl.mController->IsTextElideEnabled();
+        break;
+      }
+      case Toolkit::DevelTextEditor::Property::ELLIPSIS_POSITION:
+      {
+        value = impl.mController->GetEllipsisPosition();
+        break;
+      }
     } //switch
   }
 
@@ -1248,7 +1296,12 @@ DevelTextEditor::AnchorClickedSignalType& TextEditor::AnchorClickedSignal()
   return mAnchorClickedSignal;
 }
 
-Text::ControllerPtr TextEditor::getController()
+DevelTextEditor::InputFilteredSignalType& TextEditor::InputFilteredSignal()
+{
+  return mInputFilteredSignal;
+}
+
+Text::ControllerPtr TextEditor::GetTextController()
 {
   return mController;
 }
@@ -1284,6 +1337,14 @@ bool TextEditor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface*
       editorImpl.AnchorClickedSignal().Connect(tracker, functor);
     }
   }
+  else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_FILTERED))
+  {
+    if(editor)
+    {
+      Internal::TextEditor& editorImpl(GetImpl(editor));
+      editorImpl.InputFilteredSignal().Connect(tracker, functor);
+    }
+  }
   else
   {
     // signalName does not match any signal
@@ -1344,6 +1405,8 @@ void TextEditor::OnInitialize()
   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
   mController->SetLayoutDirection(layoutDirection);
 
+  self.LayoutDirectionChangedSignal().Connect(this, &TextEditor::OnLayoutDirectionChanged);
+
   // Forward input events to controller
   EnableGestureDetection(static_cast<GestureType::Value>(GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS));
   GetTapGestureDetector().SetMaximumTapsRequired(2);
@@ -1469,15 +1532,8 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container)
   Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom));
 
   // Support Right-To-Left of padding
-  Dali::LayoutDirection::Type layoutDirection;
-  if(mController->IsMatchSystemLanguageDirection())
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(self).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+
   if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
   {
     std::swap(padding.start, padding.end);
@@ -1781,11 +1837,11 @@ void TextEditor::TextDeleted(unsigned int position, unsigned int length, const s
   }
 }
 
-void TextEditor::CaretMoved(unsigned int position)
+void TextEditor::CursorMoved(unsigned int position)
 {
   if(Accessibility::IsUp())
   {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextCaretMoved(position);
+    Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(position);
   }
 }
 
@@ -1874,6 +1930,12 @@ void TextEditor::AnchorClicked(const std::string& href)
   mAnchorClickedSignal.Emit(handle, href.c_str(), href.length());
 }
 
+void TextEditor::InputFiltered(Toolkit::InputFilter::Property::Type type)
+{
+  Dali::Toolkit::TextEditor handle(GetOwner());
+  mInputFilteredSignal.Emit(handle, type);
+}
+
 void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
 {
   if(actor)
@@ -1911,6 +1973,18 @@ Uint32Pair TextEditor::GetTextSelectionRange() const
   return range;
 }
 
+void TextEditor::GetControlBackgroundColor(Vector4& color) const
+{
+  Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
+  Property::Map*  resultMap = propValue.GetMap();
+
+  Property::Value* colorValue = nullptr;
+  if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
+  {
+    colorValue->Get(color);
+  }
+}
+
 void TextEditor::UpdateScrollBar()
 {
   using namespace Dali;
@@ -2122,6 +2196,11 @@ void TextEditor::SetEditable(bool editable)
   }
 }
 
+void TextEditor::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
+{
+  mController->ChangedLayoutDirection();
+}
+
 TextEditor::TextEditor()
 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
   mAnimationPeriod(0.0f, 0.0f),
@@ -2151,61 +2230,63 @@ TextEditor::~TextEditor()
 
 std::string TextEditor::AccessibleImpl::GetName()
 {
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  return slf.GetProperty(Toolkit::TextEditor::Property::TEXT)
-    .Get<std::string>();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  return self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
 }
 
-std::string TextEditor::AccessibleImpl::GetText(size_t startOffset,
-                                                size_t endOffset)
+std::string TextEditor::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
 {
   if(endOffset <= startOffset)
+  {
     return {};
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
 
-  if(startOffset > txt.size() || endOffset > txt.size())
+  if(startOffset > text.size() || endOffset > text.size())
+  {
     return {};
+  }
 
-  return txt.substr(startOffset, endOffset - startOffset);
+  return text.substr(startOffset, endOffset - startOffset);
 }
 
 size_t TextEditor::AccessibleImpl::GetCharacterCount()
 {
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
 
-  return txt.size();
+  return text.size();
 }
 
-size_t TextEditor::AccessibleImpl::GetCaretOffset()
+size_t TextEditor::AccessibleImpl::GetCursorOffset()
 {
   auto slf = Toolkit::TextEditor::DownCast(Self());
-  return Dali::Toolkit::GetImpl(slf).getController()->GetCursorPosition();
+  return Dali::Toolkit::GetImpl(slf).GetTextController()->GetCursorPosition();
 }
 
-bool TextEditor::AccessibleImpl::SetCaretOffset(size_t offset)
+bool TextEditor::AccessibleImpl::SetCursorOffset(size_t offset)
 {
   auto slf = Toolkit::TextEditor::DownCast(Self());
   auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
   if(offset > txt.size())
+  {
     return false;
+  }
 
   auto& slfImpl = Dali::Toolkit::GetImpl(slf);
-  slfImpl.getController()->ResetCursorPosition(offset);
+  slfImpl.GetTextController()->ResetCursorPosition(offset);
   slfImpl.RequestTextRelayout();
+
   return true;
 }
 
-Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(
-  size_t offset, Dali::Accessibility::TextBoundary boundary)
+Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset( size_t offset, Dali::Accessibility::TextBoundary boundary)
 {
-  auto slf      = Toolkit::TextEditor::DownCast(Self());
-  auto txt      = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  auto txt_size = txt.size();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  auto textSize = text.size();
 
   auto range = Dali::Accessibility::Range{};
 
@@ -2213,62 +2294,78 @@ Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(
   {
     case Dali::Accessibility::TextBoundary::CHARACTER:
     {
-      if(offset < txt_size)
+      if(offset < textSize)
       {
-        range.content     = txt[offset];
+        range.content     = text[offset];
         range.startOffset = offset;
         range.endOffset   = offset + 1;
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::WORD:
     case Dali::Accessibility::TextBoundary::LINE:
     {
-      auto txt_c_string = txt.c_str();
-      auto breaks       = std::vector<char>(txt_size, 0);
+      auto textString = text.c_str();
+      auto breaks = std::vector<char>(textSize, 0);
+
       if(boundary == Dali::Accessibility::TextBoundary::WORD)
-        Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
       else
-        Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
+
       auto index   = 0u;
       auto counter = 0u;
-      while(index < txt_size && counter <= offset)
+      while(index < textSize && counter <= offset)
       {
         auto start = index;
         if(breaks[index])
         {
           while(breaks[index])
+          {
             index++;
+          }
           counter++;
         }
         else
         {
           if(boundary == Dali::Accessibility::TextBoundary::WORD)
+          {
             index++;
+          }
           if(boundary == Dali::Accessibility::TextBoundary::LINE)
+          {
             counter++;
+          }
         }
+
         if((counter > 0) && ((counter - 1) == offset))
         {
-          range.content     = txt.substr(start, index - start + 1);
+          range.content     = text.substr(start, index - start + 1);
           range.startOffset = start;
           range.endOffset   = index + 1;
         }
+
         if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
           index++;
+        }
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::SENTENCE:
     {
-      /* not supported by efl */
+      /* not supported by default */
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::PARAGRAPH:
     {
       /* Paragraph is not supported by libunibreak library */
+      break;
     }
-    break;
     default:
       break;
   }
@@ -2276,87 +2373,90 @@ Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(
   return range;
 }
 
-Dali::Accessibility::Range
-TextEditor::AccessibleImpl::GetSelection(size_t selectionNum)
+Dali::Accessibility::Range TextEditor::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return {};
+  }
 
-  auto        slf  = Toolkit::TextEditor::DownCast(Self());
-  auto        ctrl = Dali::Toolkit::GetImpl(slf).getController();
-  std::string ret;
-  ctrl->RetrieveSelection(ret);
-  auto r = ctrl->GetSelectionIndexes();
+  auto self  = Toolkit::TextEditor::DownCast(Self());
+  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+  std::string value{};
+  controller->RetrieveSelection(value);
+  auto indices = controller->GetSelectionIndexes();
 
-  return {static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret};
+  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
 }
 
-bool TextEditor::AccessibleImpl::RemoveSelection(size_t selectionNum)
+bool TextEditor::AccessibleImpl::RemoveSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(0, 0);
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
   return true;
 }
 
-bool TextEditor::AccessibleImpl::SetSelection(size_t selectionNum,
-                                              size_t startOffset,
-                                              size_t endOffset)
+bool TextEditor::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(startOffset,
-                                                            endOffset);
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
   return true;
 }
 
-bool TextEditor::AccessibleImpl::CopyText(size_t startPosition,
-                                          size_t endPosition)
+bool TextEditor::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
 
   return true;
 }
 
-bool TextEditor::AccessibleImpl::CutText(size_t startPosition,
-                                         size_t endPosition)
+bool TextEditor::AccessibleImpl::CutText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
 
-  slf.SetProperty(Toolkit::TextEditor::Property::TEXT,
-                  txt.substr(0, startPosition) + txt.substr(endPosition));
+  self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
 
-bool TextEditor::AccessibleImpl::DeleteText(size_t startPosition,
-                                            size_t endPosition)
+bool TextEditor::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
 
-  slf.SetProperty(Toolkit::TextEditor::Property::TEXT,
-                  txt.substr(0, startPosition) + txt.substr(endPosition));
+  self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
@@ -2365,12 +2465,12 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates()
 {
   using namespace Dali::Accessibility;
 
-  auto states              = DevelControl::AccessibleImpl::CalculateStates();
+  auto states = DevelControl::AccessibleImpl::CalculateStates();
   states[State::EDITABLE]  = true;
   states[State::FOCUSABLE] = true;
 
   Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(self == focusControl)
+  if(mSelf == focusControl)
   {
     states[State::FOCUSED] = true;
   }
@@ -2378,23 +2478,22 @@ Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates()
   return states;
 }
 
-bool TextEditor::AccessibleImpl::InsertText(size_t      startPosition,
-                                            std::string text)
+bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, std::string text)
 {
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  auto insertedText = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
 
-  txt.insert(startPosition, text);
+  insertedText.insert(startPosition, text);
 
-  slf.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(txt));
+  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(insertedText));
 
   return true;
 }
 
 bool TextEditor::AccessibleImpl::SetTextContents(std::string newContents)
 {
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  slf.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(newContents));
+  auto self = Toolkit::TextEditor::DownCast(Self());
+  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(newContents));
   return true;
 }
 
index 0286da2..6b6c377 100644 (file)
@@ -93,6 +93,11 @@ public:
   DevelTextEditor::AnchorClickedSignalType& AnchorClickedSignal();
 
   /**
+   * @copydoc Dali::Toollkit::TextEditor::InputFilteredSignal()
+   */
+  DevelTextEditor::InputFilteredSignalType& InputFilteredSignal();
+
+  /**
    * 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.
@@ -104,6 +109,13 @@ public:
   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
 
   /**
+   * @brief Gets text controller
+   *
+   * @return The text controller
+   */
+  Text::ControllerPtr GetTextController();
+
+  /**
    * @copydoc TextEditor::TextChangedSignal()
    */
   Toolkit::TextEditor::TextChangedSignalType& TextChangedSignal();
@@ -204,9 +216,9 @@ private: // From Control
   void TextDeleted(unsigned int position, unsigned int length, const std::string& content) override;
 
   /**
-   * @copydoc Text::EditableControlInterface::CaretMoved()
+   * @copydoc Text::EditableControlInterface::CursorMoved()
    */
-  void CaretMoved(unsigned int position) override;
+  void CursorMoved(unsigned int position) override;
 
   /**
    * @copydoc Text::EditableControlInterface::TextChanged()
@@ -228,6 +240,16 @@ private: // From Control
    */
   void AddDecoration(Actor& actor, bool needsClipping) override;
 
+  /**
+   * @copydoc Text::EditableControlInterface::InputFiltered()
+   */
+  void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
+
+  /**
+   * @copydoc Text::EditableControlInterface::GetControlBackgroundColor()
+   */
+  void GetControlBackgroundColor(Vector4& color) const override;
+
   // From SelectableControlInterface
 public:
   /**
@@ -291,8 +313,6 @@ public:
    */
   void AnchorClicked(const std::string& href) override;
 
-  Text::ControllerPtr getController();
-
 private: // Implementation
   /**
    * @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
@@ -362,6 +382,13 @@ private: // Implementation
   void OnScrollIndicatorAnimationFinished(Animation& animation);
 
   /**
+  * @brief Callback function for when the layout is changed.
+  * @param[in] actor The actor whose layoutDirection is changed.
+  * @param[in] type  The layoutDirection.
+  */
+  void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
+
+  /**
    * Construct a new TextEditor.
    */
   TextEditor();
@@ -398,6 +425,7 @@ private: // Data
   Toolkit::TextEditor::ScrollStateChangedSignalType    mScrollStateChangedSignal;
   Toolkit::DevelTextEditor::MaxLengthReachedSignalType mMaxLengthReachedSignal;
   Toolkit::DevelTextEditor::AnchorClickedSignalType    mAnchorClickedSignal;
+  Toolkit::DevelTextEditor::InputFilteredSignalType    mInputFilteredSignal;
 
   InputMethodContext            mInputMethodContext;
   Text::ControllerPtr           mController;
@@ -426,27 +454,89 @@ private: // Data
   bool  mScrollStarted : 1;
   bool  mTextChanged : 1; ///< If true, emits TextChangedSignal in next OnRelayout().
 
+  /**
+   * @brief This structure is to connect TextEditor with Accessible functions.
+   */
   struct AccessibleImpl : public DevelControl::AccessibleImpl,
                           public virtual Dali::Accessibility::Text,
                           public virtual Dali::Accessibility::EditableText
   {
     using DevelControl::AccessibleImpl::AccessibleImpl;
 
-    std::string           GetName() override;
-    std::string           GetText(size_t startOffset, size_t endOffset) override;
-    size_t                GetCharacterCount() override;
-    size_t                GetCaretOffset() override;
-    bool                  SetCaretOffset(size_t offset) override;
-    Accessibility::Range  GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) override;
-    Accessibility::Range  GetSelection(size_t selectionNum) override;
-    bool                  RemoveSelection(size_t selectionNum) override;
-    bool                  SetSelection(size_t selectionNum, size_t startOffset, size_t endOffset) override;
-    bool                  CopyText(size_t startPosition, size_t endPosition) override;
-    bool                  CutText(size_t startPosition, size_t endPosition) override;
+    /**
+     * @copydoc Dali::Accessibility::Accessible::GetName()
+     */
+    std::string GetName() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetText()
+     */
+    std::string GetText(size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+     */
+    size_t GetCharacterCount() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+     */
+    size_t GetCursorOffset() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+     */
+    bool SetCursorOffset(size_t offset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+     */
+    Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+     */
+    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::RemoveSelection()
+     */
+    bool RemoveSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+     */
+    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::CopyText()
+     */
+    bool CopyText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::CutText()
+     */
+    bool CutText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Accessible::GetStates()
+     */
     Accessibility::States CalculateStates() override;
-    bool                  InsertText(size_t startPosition, std::string text) override;
-    bool                  SetTextContents(std::string newContents) override;
-    bool                  DeleteText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::InsertText()
+     */
+    bool InsertText(size_t startPosition, std::string text) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::SetTextContents()
+     */
+    bool SetTextContents(std::string newContents) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::DeleteText()
+     */
+    bool DeleteText(size_t startPosition, size_t endPosition) override;
   };
 };
 
index 4e5cd9c..2cce4d2 100644 (file)
@@ -21,7 +21,6 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/adaptor-framework/key-devel.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/debug.h>
@@ -138,11 +137,14 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "enableEditing",
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "fontSizeScale",                    FLOAT,     FONT_SIZE_SCALE                     )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "primaryCursorPosition",            INTEGER,   PRIMARY_CURSOR_POSITION             )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "grabHandleColor",                  VECTOR4,   GRAB_HANDLE_COLOR                   )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "inputFilter",                      MAP,       INPUT_FILTER                        )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextField, "ellipsisPosition",                 INTEGER,   ELLIPSIS_POSITION                   )
 
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "textChanged",       SIGNAL_TEXT_CHANGED       )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "maxLengthReached",  SIGNAL_MAX_LENGTH_REACHED )
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED)
 DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "anchorClicked",     SIGNAL_ANCHOR_CLICKED     )
+DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputFiltered",     SIGNAL_INPUT_FILTERED     )
 
 DALI_TYPE_REGISTRATION_END()
 // clang-format on
@@ -694,7 +696,7 @@ void TextField::SetProperty(BaseObject* object, Property::Index index, const Pro
       }
       case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        impl.mController->SetMatchSystemLanguageDirection(value.Get<bool>());
+        impl.mController->SetMatchLayoutDirection(value.Get<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
         break;
       }
       case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
@@ -765,6 +767,25 @@ void TextField::SetProperty(BaseObject* object, Property::Index index, const Pro
         impl.RequestTextRelayout();
         break;
       }
+      case Toolkit::DevelTextField::Property::INPUT_FILTER:
+      {
+        const Property::Map* map = value.GetMap();
+        if(map)
+        {
+          impl.mController->SetInputFilterOption(*map);
+        }
+        break;
+      }
+      case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION:
+      {
+        DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast<DevelText::EllipsisPosition::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
+        if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType))
+        {
+          DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType);
+          impl.mController->SetEllipsisPosition(ellipsisPositionType);
+        }
+        break;
+      }
     } // switch
   }   // textfield
 }
@@ -1070,7 +1091,7 @@ Property::Value TextField::GetProperty(BaseObject* object, Property::Index index
       }
       case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        value = impl.mController->IsMatchSystemLanguageDirection();
+        value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS;
         break;
       }
       case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
@@ -1120,6 +1141,18 @@ Property::Value TextField::GetProperty(BaseObject* object, Property::Index index
         value = impl.mDecorator->GetHandleColor();
         break;
       }
+      case Toolkit::DevelTextField::Property::INPUT_FILTER:
+      {
+        Property::Map map;
+        impl.mController->GetInputFilterOption(map);
+        value = map;
+        break;
+      }
+      case Toolkit::DevelTextField::Property::ELLIPSIS_POSITION:
+      {
+        value = impl.mController->GetEllipsisPosition();
+        break;
+      }
     } //switch
   }
 
@@ -1204,6 +1237,14 @@ bool TextField::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface*
       fieldImpl.AnchorClickedSignal().Connect(tracker, functor);
     }
   }
+  else if(0 == strcmp(signalName.c_str(), SIGNAL_INPUT_FILTERED))
+  {
+    if(field)
+    {
+      Internal::TextField& fieldImpl(GetImpl(field));
+      fieldImpl.InputFilteredSignal().Connect(tracker, functor);
+    }
+  }
   else
   {
     // signalName does not match any signal
@@ -1233,6 +1274,11 @@ DevelTextField::AnchorClickedSignalType& TextField::AnchorClickedSignal()
   return mAnchorClickedSignal;
 }
 
+DevelTextField::InputFilteredSignalType& TextField::InputFilteredSignal()
+{
+  return mInputFilteredSignal;
+}
+
 void TextField::OnInitialize()
 {
   Actor self = Self();
@@ -1270,6 +1316,8 @@ void TextField::OnInitialize()
   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
   mController->SetLayoutDirection(layoutDirection);
 
+  self.LayoutDirectionChangedSignal().Connect(this, &TextField::OnLayoutDirectionChanged);
+
   // Forward input events to controller
   EnableGestureDetection(static_cast<GestureType::Value>(GestureType::TAP | GestureType::PAN | GestureType::LONG_PRESS));
   GetTapGestureDetector().SetMaximumTapsRequired(2);
@@ -1382,15 +1430,8 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
   Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom));
 
   // Support Right-To-Left of padding
-  Dali::LayoutDirection::Type layoutDirection;
-  if(mController->IsMatchSystemLanguageDirection())
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(self).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(self.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+
   if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
   {
     std::swap(padding.start, padding.end);
@@ -1454,7 +1495,7 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
   }
 }
 
-Text::ControllerPtr TextField::getController()
+Text::ControllerPtr TextField::GetTextController()
 {
   return mController;
 }
@@ -1715,11 +1756,11 @@ void TextField::TextDeleted(unsigned int position, unsigned int length, const st
   }
 }
 
-void TextField::CaretMoved(unsigned int position)
+void TextField::CursorMoved(unsigned int position)
 {
   if(Accessibility::IsUp())
   {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextCaretMoved(position);
+    Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(position);
   }
 }
 
@@ -1804,6 +1845,12 @@ void TextField::AnchorClicked(const std::string& href)
   mAnchorClickedSignal.Emit(handle, href.c_str(), href.length());
 }
 
+void TextField::InputFiltered(Toolkit::InputFilter::Property::Type type)
+{
+  Dali::Toolkit::TextField handle(GetOwner());
+  mInputFilteredSignal.Emit(handle, type);
+}
+
 void TextField::AddDecoration(Actor& actor, bool needsClipping)
 {
   if(actor)
@@ -1822,6 +1869,18 @@ void TextField::AddDecoration(Actor& actor, bool needsClipping)
   }
 }
 
+void TextField::GetControlBackgroundColor(Vector4& color) const
+{
+  Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
+  Property::Map*  resultMap = propValue.GetMap();
+
+  Property::Value* colorValue = nullptr;
+  if(resultMap && (colorValue = resultMap->Find(ColorVisual::Property::MIX_COLOR)))
+  {
+    colorValue->Get(color);
+  }
+}
+
 void TextField::OnSceneConnect(Dali::Actor actor)
 {
   if(mHasBeenStaged)
@@ -1907,6 +1966,11 @@ bool TextField::OnTouched(Actor actor, const TouchEvent& touch)
   return false;
 }
 
+void TextField::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
+{
+  mController->ChangedLayoutDirection();
+}
+
 void TextField::OnIdleSignal()
 {
   // Emits the change of input style signals.
@@ -1939,60 +2003,64 @@ TextField::~TextField()
 
 std::string TextField::AccessibleImpl::GetName()
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  return slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 }
 
-std::string TextField::AccessibleImpl::GetText(size_t startOffset,
-                                               size_t endOffset)
+std::string TextField::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
 {
   if(endOffset <= startOffset)
+  {
     return {};
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  if(startOffset > txt.size() || endOffset > txt.size())
+  if(startOffset > text.size() || endOffset > text.size())
+  {
     return {};
+  }
 
-  return txt.substr(startOffset, endOffset - startOffset);
+  return text.substr(startOffset, endOffset - startOffset);
 }
 
 size_t TextField::AccessibleImpl::GetCharacterCount()
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  return txt.size();
+  return text.size();
 }
 
-size_t TextField::AccessibleImpl::GetCaretOffset()
+size_t TextField::AccessibleImpl::GetCursorOffset()
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  return Dali::Toolkit::GetImpl(slf).getController()->GetCursorPosition();
+  auto self = Toolkit::TextField::DownCast(Self());
+  return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
 }
 
-bool TextField::AccessibleImpl::SetCaretOffset(size_t offset)
+bool TextField::AccessibleImpl::SetCursorOffset(size_t offset)
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  if(offset > txt.size())
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  if(offset > text.size())
+  {
     return false;
+  }
+
+  auto& selfImpl = Dali::Toolkit::GetImpl(self);
+  selfImpl.GetTextController()->ResetCursorPosition(offset);
+  selfImpl.RequestTextRelayout();
 
-  auto& slfImpl = Dali::Toolkit::GetImpl(slf);
-  slfImpl.getController()->ResetCursorPosition(offset);
-  slfImpl.RequestTextRelayout();
   return true;
 }
 
 Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   size_t offset, Dali::Accessibility::TextBoundary boundary)
 {
-  auto slf      = Toolkit::TextField::DownCast(Self());
-  auto txt      = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  auto txt_size = txt.size();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto textSize = text.size();
 
   auto range = Dali::Accessibility::Range{};
 
@@ -2000,62 +2068,78 @@ Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   {
     case Dali::Accessibility::TextBoundary::CHARACTER:
     {
-      if(offset < txt_size)
+      if(offset < textSize)
       {
-        range.content     = txt[offset];
+        range.content     = text[offset];
         range.startOffset = offset;
         range.endOffset   = offset + 1;
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::WORD:
     case Dali::Accessibility::TextBoundary::LINE:
     {
-      auto txt_c_string = txt.c_str();
-      auto breaks       = std::vector<char>(txt_size, 0);
+      auto textString = text.c_str();
+      auto breaks = std::vector<char>(textSize, 0);
+
       if(boundary == Dali::Accessibility::TextBoundary::WORD)
-        Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
       else
-        Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
+
       auto index   = 0u;
       auto counter = 0u;
-      while(index < txt_size && counter <= offset)
+      while(index < textSize && counter <= offset)
       {
         auto start = index;
         if(breaks[index])
         {
           while(breaks[index])
+          {
             index++;
+          }
           counter++;
         }
         else
         {
           if(boundary == Dali::Accessibility::TextBoundary::WORD)
+          {
             index++;
+          }
           if(boundary == Dali::Accessibility::TextBoundary::LINE)
+          {
             counter++;
+          }
         }
+
         if((counter > 0) && ((counter - 1) == offset))
         {
-          range.content     = txt.substr(start, index - start + 1);
+          range.content     = text.substr(start, index - start + 1);
           range.startOffset = start;
           range.endOffset   = index + 1;
         }
+
         if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
           index++;
+        }
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::SENTENCE:
     {
-      /* not supported by efl */
+      /* not supported by default */
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::PARAGRAPH:
     {
       /* Paragraph is not supported by libunibreak library */
+      break;
     }
-    break;
     default:
       break;
   }
@@ -2063,87 +2147,90 @@ Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
   return range;
 }
 
-Dali::Accessibility::Range
-TextField::AccessibleImpl::GetSelection(size_t selectionNum)
+Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return {};
+  }
 
-  auto        slf  = Toolkit::TextField::DownCast(Self());
-  auto        ctrl = Dali::Toolkit::GetImpl(slf).getController();
-  std::string ret;
-  ctrl->RetrieveSelection(ret);
-  auto r = ctrl->GetSelectionIndexes();
+  auto self  = Toolkit::TextField::DownCast(Self());
+  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+  std::string value{};
+  controller->RetrieveSelection(value);
+  auto indices = controller->GetSelectionIndexes();
 
-  return {static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret};
+  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
 }
 
-bool TextField::AccessibleImpl::RemoveSelection(size_t selectionNum)
+bool TextField::AccessibleImpl::RemoveSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(0, 0);
+  auto self = Toolkit::TextField::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
   return true;
 }
 
-bool TextField::AccessibleImpl::SetSelection(size_t selectionNum,
-                                             size_t startOffset,
-                                             size_t endOffset)
+bool TextField::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(startOffset,
-                                                            endOffset);
+  auto self = Toolkit::TextField::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
   return true;
 }
 
-bool TextField::AccessibleImpl::CopyText(size_t startPosition,
-                                         size_t endPosition)
+bool TextField::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
 
   return true;
 }
 
-bool TextField::AccessibleImpl::CutText(size_t startPosition,
-                                        size_t endPosition)
+bool TextField::AccessibleImpl::CutText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  Dali::Toolkit::GetImpl(slf).getController()->CopyStringToClipboard(txt.substr(startPosition, endPosition - startPosition));
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  Dali::Toolkit::GetImpl(self).GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
 
-  slf.SetProperty(Toolkit::TextField::Property::TEXT,
-                  txt.substr(0, startPosition) + txt.substr(endPosition));
+  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
 
-bool TextField::AccessibleImpl::DeleteText(size_t startPosition,
-                                           size_t endPosition)
+bool TextField::AccessibleImpl::DeleteText(size_t startPosition, size_t endPosition)
 {
   if(endPosition <= startPosition)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  slf.SetProperty(Toolkit::TextField::Property::TEXT,
-                  txt.substr(0, startPosition) + txt.substr(endPosition));
+  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
 
   return true;
 }
@@ -2158,7 +2245,7 @@ Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
   states[State::FOCUSABLE] = true;
 
   Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(self == focusControl)
+  if(mSelf == focusControl)
   {
     states[State::FOCUSED] = true;
   }
@@ -2166,23 +2253,22 @@ Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
   return states;
 }
 
-bool TextField::AccessibleImpl::InsertText(size_t startPosition,
-                                            std::string text)
+bool TextField::AccessibleImpl::InsertText(size_t startPosition, std::string text)
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  auto txt = slf.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextField::DownCast(Self());
+  auto insertedText = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  txt.insert(startPosition, text);
+  insertedText.insert(startPosition, text);
 
-  slf.SetProperty(Toolkit::TextField::Property::TEXT, std::move(txt));
+  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(insertedText));
 
   return true;
 }
 
 bool TextField::AccessibleImpl::SetTextContents(std::string newContents)
 {
-  auto slf = Toolkit::TextField::DownCast(Self());
-  slf.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
+  auto self = Toolkit::TextField::DownCast(Self());
+  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
   return true;
 }
 
index c76f05a..85d50ef 100644 (file)
@@ -90,6 +90,13 @@ public:
   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
 
   /**
+   * @brief Gets text controller
+   *
+   * @return The text controller
+   */
+  Text::ControllerPtr GetTextController();
+
+  /**
    * @copydoc TextField::TextChangedSignal()
    */
   Toolkit::TextField::TextChangedSignalType& TextChangedSignal();
@@ -109,7 +116,10 @@ public:
    */
   DevelTextField::AnchorClickedSignalType& AnchorClickedSignal();
 
-  Text::ControllerPtr getController();
+  /**
+   * @copydoc TextField::InputFilteredSignal()
+   */
+  DevelTextField::InputFilteredSignalType& InputFilteredSignal();
 
 private: // From Control
   /**
@@ -197,9 +207,9 @@ private: // From Control
   void TextDeleted(unsigned int position, unsigned int length, const std::string& content) override;
 
   /**
-   * @copydoc Text::EditableControlInterface::CaretMoved()
+   * @copydoc Text::EditableControlInterface::CursorMoved()
    */
-  void CaretMoved(unsigned int position) override;
+  void CursorMoved(unsigned int position) override;
 
   /**
    * @copydoc Text::EditableControlInterface::TextChanged()
@@ -221,6 +231,16 @@ private: // From Control
    */
   void AddDecoration(Actor& actor, bool needsClipping) override;
 
+  /**
+   * @copydoc Text::EditableControlInterface::InputFiltered()
+   */
+  void InputFiltered(Toolkit::InputFilter::Property::Type type) override;
+
+  /**
+   * @copydoc Text::EditableControlInterface::GetControlBackgroundColor()
+   */
+  void GetControlBackgroundColor(Vector4& color) const override;
+
   // From SelectableControlInterface
 public:
   /**
@@ -318,6 +338,13 @@ private: // Implementation
   void EmitTextChangedSignal();
 
   /**
+   * @brief Callback function for when the layout is changed.
+   * @param[in] actor The actor whose layoutDirection is changed.
+   * @param[in] type  The layoutDirection.
+   */
+  void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
+
+  /**
    * Construct a new TextField.
    */
   TextField();
@@ -347,18 +374,13 @@ private: // Implementation
   // Connection needed to re-render text, when a Text Field returns to the scene.
   void OnSceneConnect(Dali::Actor actor);
 
-public: // For UTC only
-  Text::ControllerPtr GetTextController()
-  {
-    return mController;
-  }
-
 private: // Data
   // Signals
   Toolkit::TextField::TextChangedSignalType        mTextChangedSignal;
   Toolkit::TextField::MaxLengthReachedSignalType   mMaxLengthReachedSignal;
   Toolkit::TextField::InputStyleChangedSignalType  mInputStyleChangedSignal;
   Toolkit::DevelTextField::AnchorClickedSignalType mAnchorClickedSignal;
+  Toolkit::DevelTextField::InputFilteredSignalType mInputFilteredSignal;
 
   InputMethodContext       mInputMethodContext;
   Text::ControllerPtr      mController;
@@ -380,27 +402,89 @@ private: // Data
   bool  mTextChanged : 1; ///< If true, emits TextChangedSignal in next OnRelayout().
 
 protected:
+  /**
+   * @brief This structure is to connect TextField with Accessible functions.
+   */
   struct AccessibleImpl : public DevelControl::AccessibleImpl,
                           public virtual Dali::Accessibility::Text,
                           public virtual Dali::Accessibility::EditableText
   {
     using DevelControl::AccessibleImpl::AccessibleImpl;
 
-    std::string           GetName() override;
-    std::string           GetText(size_t startOffset, size_t endOffset) override;
-    size_t                GetCharacterCount() override;
-    size_t                GetCaretOffset() override;
-    bool                  SetCaretOffset(size_t offset) override;
-    Accessibility::Range  GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) override;
-    Accessibility::Range  GetSelection(size_t selectionNum) override;
-    bool                  RemoveSelection(size_t selectionNum) override;
-    bool                  SetSelection(size_t selectionNum, size_t startOffset, size_t endOffset) override;
-    bool                  CopyText(size_t startPosition, size_t endPosition) override;
-    bool                  CutText(size_t startPosition, size_t endPosition) override;
+    /**
+     * @copydoc Dali::Accessibility::Accessible::GetName()
+     */
+    std::string GetName() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetText()
+     */
+    std::string GetText(size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+     */
+    size_t GetCharacterCount() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+     */
+    size_t GetCursorOffset() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+     */
+    bool SetCursorOffset(size_t offset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+     */
+    Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+     */
+    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::RemoveSelection()
+     */
+    bool RemoveSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+     */
+    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::CopyText()
+     */
+    bool CopyText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::CutText()
+     */
+    bool CutText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Accessible::GetStates()
+     */
     Accessibility::States CalculateStates() override;
-    bool                  InsertText(size_t startPosition, std::string text) override;
-    bool                  SetTextContents(std::string newContents) override;
-    bool                  DeleteText(size_t startPosition, size_t endPosition) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::InsertText()
+     */
+    bool InsertText(size_t startPosition, std::string text) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::SetTextContents()
+     */
+    bool SetTextContents(std::string newContents) override;
+
+    /**
+     * @copydoc Dali::Accessibility::EditableText::DeleteText()
+     */
+    bool DeleteText(size_t startPosition, size_t endPosition) override;
   };
 };
 
index 52f9c29..263b879 100644 (file)
@@ -21,7 +21,6 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/adaptor-framework/image-loading.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/object/property-helper-devel.h>
 #include <dali/integration-api/debug.h>
@@ -48,6 +47,7 @@
 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 
+// DEVEL INCLUDES
 #include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
 
 using namespace Dali::Toolkit::Text;
@@ -134,6 +134,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "textFit",
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "minLineSize",                  FLOAT,   MIN_LINE_SIZE                  )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "renderingBackend",             INTEGER, RENDERING_BACKEND              )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "fontSizeScale",                FLOAT,   FONT_SIZE_SCALE                )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "ellipsisPosition",             INTEGER, ELLIPSIS_POSITION              )
 
 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, TextLabel, "textColor",      Color::BLACK,     TEXT_COLOR   )
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION(Toolkit,    TextLabel, "textColorRed",   TEXT_COLOR_RED,   TEXT_COLOR, 0)
@@ -457,7 +458,7 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
       }
       case Toolkit::DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        impl.mController->SetMatchSystemLanguageDirection(value.Get<bool>());
+        impl.mController->SetMatchLayoutDirection(value.Get<bool>() ? DevelText::MatchLayoutDirection::LOCALE : DevelText::MatchLayoutDirection::CONTENTS);
         break;
       }
       case Toolkit::DevelTextLabel::Property::TEXT_FIT:
@@ -482,6 +483,16 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
         }
         break;
       }
+      case Toolkit::DevelTextLabel::Property::ELLIPSIS_POSITION:
+      {
+        DevelText::EllipsisPosition::Type ellipsisPositionType(static_cast<DevelText::EllipsisPosition::Type>(-1)); // Set to invalid value to ensure a valid mode does get set
+        if(GetEllipsisPositionTypeEnumeration(value, ellipsisPositionType))
+        {
+          DALI_LOG_INFO(gLogFilter, Debug::General, "TextLabel %p EllipsisPosition::Type %d\n", impl.mController.Get(), ellipsisPositionType);
+          impl.mController->SetEllipsisPosition(ellipsisPositionType);
+        }
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -495,7 +506,7 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
   }
 }
 
-Text::ControllerPtr TextLabel::getController()
+Text::ControllerPtr TextLabel::GetTextController()
 {
   return mController;
 }
@@ -688,7 +699,7 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index
       }
       case Toolkit::DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
       {
-        value = impl.mController->IsMatchSystemLanguageDirection();
+        value = impl.mController->GetMatchLayoutDirection() != DevelText::MatchLayoutDirection::CONTENTS;
         break;
       }
       case Toolkit::DevelTextLabel::Property::TEXT_FIT:
@@ -718,6 +729,11 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index
         value = impl.mController->GetFontSizeScale();
         break;
       }
+      case Toolkit::DevelTextLabel::Property::ELLIPSIS_POSITION:
+      {
+        value = impl.mController->GetEllipsisPosition();
+        break;
+      }
     }
   }
 
@@ -786,6 +802,8 @@ void TextLabel::OnInitialize()
   Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(stage.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
   mController->SetLayoutDirection(layoutDirection);
 
+  self.LayoutDirectionChangedSignal().Connect(this, &TextLabel::OnLayoutDirectionChanged);
+
   // Forward input events to controller
   EnableGestureDetection(static_cast<GestureType::Value>(GestureType::TAP));
   GetTapGestureDetector().SetMaximumTapsRequired(1);
@@ -899,8 +917,10 @@ void TextLabel::OnRelayout(const Vector2& size, RelayoutContainer& container)
 {
   DALI_LOG_INFO(gLogFilter, Debug::General, "TextLabel::OnRelayout\n");
 
+  Actor self = Self();
+
   Extents padding;
-  padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+  padding = self.GetProperty<Extents>(Toolkit::Control::Property::PADDING);
 
   Vector2 contentSize(size.x - (padding.start + padding.end), size.y - (padding.top + padding.bottom));
 
@@ -911,15 +931,8 @@ void TextLabel::OnRelayout(const Vector2& size, RelayoutContainer& container)
   }
 
   // Support Right-To-Left
-  Dali::LayoutDirection::Type layoutDirection;
-  if(mController->IsMatchSystemLanguageDirection())
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(Self()).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(self);
+
   const Text::Controller::UpdateTextType updateTextType = mController->Relayout(contentSize, layoutDirection);
 
   if((Text::Controller::NONE_UPDATED != (Text::Controller::MODEL_UPDATED & updateTextType)) || mTextUpdateNeeded)
@@ -1048,6 +1061,11 @@ void TextLabel::ScrollingFinished()
   RequestTextRelayout();
 }
 
+void TextLabel::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
+{
+  mController->ChangedLayoutDirection();
+}
+
 TextLabel::TextLabel()
 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
   mRenderingBackend(DEFAULT_RENDERING_BACKEND),
@@ -1061,8 +1079,8 @@ TextLabel::~TextLabel()
 
 std::string TextLabel::AccessibleImpl::GetNameRaw()
 {
-  auto slf = Toolkit::TextLabel::DownCast(Self());
-  return slf.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  return self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
 }
 
 Property::Index TextLabel::AccessibleImpl::GetNamePropertyIndex()
@@ -1070,47 +1088,47 @@ Property::Index TextLabel::AccessibleImpl::GetNamePropertyIndex()
   return Toolkit::TextLabel::Property::TEXT;
 }
 
-std::string TextLabel::AccessibleImpl::GetText(size_t startOffset,
-                                               size_t endOffset)
+std::string TextLabel::AccessibleImpl::GetText(size_t startOffset, size_t endOffset)
 {
   if(endOffset <= startOffset)
+  {
     return {};
+  }
 
-  auto slf = Toolkit::TextLabel::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
 
-  if(startOffset > txt.size() || endOffset > txt.size())
+  if(startOffset > text.size() || endOffset > text.size())
+  {
     return {};
+  }
 
-  return txt.substr(startOffset, endOffset - startOffset);
+  return text.substr(startOffset, endOffset - startOffset);
 }
 
 size_t TextLabel::AccessibleImpl::GetCharacterCount()
 {
-  auto slf = Toolkit::TextLabel::DownCast(Self());
-  auto txt =
-    slf.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
 
-  return txt.size();
+  return text.size();
 }
 
-size_t TextLabel::AccessibleImpl::GetCaretOffset()
+size_t TextLabel::AccessibleImpl::GetCursorOffset()
 {
   return {};
 }
 
-bool TextLabel::AccessibleImpl::SetCaretOffset(size_t offset)
+bool TextLabel::AccessibleImpl::SetCursorOffset(size_t offset)
 {
   return {};
 }
 
-Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(
-  size_t offset, Dali::Accessibility::TextBoundary boundary)
+Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary)
 {
-  auto slf      = Toolkit::TextLabel::DownCast(Self());
-  auto txt      = slf.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
-  auto txt_size = txt.size();
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  auto textSize = text.size();
 
   auto range = Dali::Accessibility::Range{};
 
@@ -1118,62 +1136,78 @@ Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(
   {
     case Dali::Accessibility::TextBoundary::CHARACTER:
     {
-      if(offset < txt_size)
+      if(offset < textSize)
       {
-        range.content     = txt[offset];
+        range.content     = text[offset];
         range.startOffset = offset;
         range.endOffset   = offset + 1;
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::WORD:
     case Dali::Accessibility::TextBoundary::LINE:
     {
-      auto txt_c_string = txt.c_str();
-      auto breaks       = std::vector<char>(txt_size, 0);
+      auto textString = text.c_str();
+      auto breaks = std::vector<char>(textSize, 0);
+
       if(boundary == Dali::Accessibility::TextBoundary::WORD)
-        Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
       else
-        Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t*)txt_c_string, txt_size, "", breaks.data());
-      auto index   = 0u;
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
+      }
+
+      auto index = 0u;
       auto counter = 0u;
-      while(index < txt_size && counter <= offset)
+      while(index < textSize && counter <= offset)
       {
         auto start = index;
         if(breaks[index])
         {
           while(breaks[index])
+          {
             index++;
+          }
           counter++;
         }
         else
         {
           if(boundary == Dali::Accessibility::TextBoundary::WORD)
+          {
             index++;
+          }
           if(boundary == Dali::Accessibility::TextBoundary::LINE)
+          {
             counter++;
+          }
         }
+
         if((counter > 0) && ((counter - 1) == offset))
         {
-          range.content     = txt.substr(start, index - start + 1);
+          range.content     = text.substr(start, index - start + 1);
           range.startOffset = start;
           range.endOffset   = index + 1;
         }
+
         if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
           index++;
+        }
       }
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::SENTENCE:
     {
-      /* not supported by efl */
+      /* not supported by default */
+      break;
     }
-    break;
     case Dali::Accessibility::TextBoundary::PARAGRAPH:
     {
       /* Paragraph is not supported by libunibreak library */
+      break;
     }
-    break;
     default:
       break;
   }
@@ -1181,44 +1215,46 @@ Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(
   return range;
 }
 
-Dali::Accessibility::Range
-TextLabel::AccessibleImpl::GetSelection(size_t selectionNum)
+Dali::Accessibility::Range TextLabel::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return {};
+  }
 
-  auto        slf  = Toolkit::TextLabel::DownCast(Self());
-  auto        ctrl = Dali::Toolkit::GetImpl(slf).getController();
-  std::string ret;
-  ctrl->RetrieveSelection(ret);
-  auto r = ctrl->GetSelectionIndexes();
+  auto self  = Toolkit::TextLabel::DownCast(Self());
+  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
+  std::string value{};
+  controller->RetrieveSelection(value);
+  auto indices = controller->GetSelectionIndexes();
 
-  return {static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret};
+  return {static_cast<size_t>(indices.first), static_cast<size_t>(indices.second), value};
 }
 
-bool TextLabel::AccessibleImpl::RemoveSelection(size_t selectionNum)
+bool TextLabel::AccessibleImpl::RemoveSelection(size_t selectionIndex)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(0, 0);
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
   return true;
 }
 
-bool TextLabel::AccessibleImpl::SetSelection(size_t selectionNum,
-                                             size_t startOffset,
-                                             size_t endOffset)
+bool TextLabel::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
 {
   // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionNum > 0)
+  if(selectionIndex > 0)
+  {
     return false;
+  }
 
-  auto slf = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(slf).getController()->SetSelection(startOffset,
-                                                            endOffset);
+  auto self = Toolkit::TextLabel::DownCast(Self());
+  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
   return true;
 }
 
index a204be6..01e003b 100644 (file)
@@ -86,7 +86,12 @@ public:
    */
   static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
 
-  Text::ControllerPtr getController();
+  /**
+   * @brief Gets text controller
+   *
+   * @return The text controller
+   */
+  Text::ControllerPtr GetTextController();
 
 private: // From Control
   /**
@@ -177,6 +182,13 @@ private:
     return mTextScroller;
   }
 
+  /**
+   * @brief Callback function for when the layout is changed.
+   * @param[in] actor The actor whose layoutDirection is changed.
+   * @param[in] type  The layoutDirection.
+   */
+  void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
+
 private: // Data
   Text::ControllerPtr   mController;
   Text::TextScrollerPtr mTextScroller;
@@ -190,21 +202,63 @@ private: // Data
   bool mTextUpdateNeeded : 1;
 
 protected:
+  /**
+   * @brief This structure is to connect TextLabel with Accessible functions.
+   */
   struct AccessibleImpl : public DevelControl::AccessibleImpl,
                           public virtual Dali::Accessibility::Text
   {
     using DevelControl::AccessibleImpl::AccessibleImpl;
 
-    std::string          GetText(size_t startOffset, size_t endOffset) override;
-    size_t               GetCharacterCount() override;
-    size_t               GetCaretOffset() override;
-    bool                 SetCaretOffset(size_t offset) override;
+    /**
+     * @copydoc Dali::Accessibility::Text::GetText()
+     */
+    std::string GetText(size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+     */
+    size_t GetCharacterCount() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+     */
+    size_t GetCursorOffset() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+     */
+    bool SetCursorOffset(size_t offset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+     */
     Accessibility::Range GetTextAtOffset(size_t offset, Accessibility::TextBoundary boundary) override;
-    Accessibility::Range GetSelection(size_t selectionNum) override;
-    bool                 RemoveSelection(size_t selectionNum) override;
-    bool                 SetSelection(size_t selectionNum, size_t startOffset, size_t endOffset) override;
-    std::string          GetNameRaw() override;
-    Property::Index      GetNamePropertyIndex() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+     */
+    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::RemoveSelection()
+     */
+    bool RemoveSelection(size_t selectionIndex) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+     */
+    bool SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetNameRaw()
+     */
+    std::string GetNameRaw() override;
+
+    /**
+     * @copydoc Dali::Accessibility::Text::GetNamePropertyIndex()
+     */
+    Property::Index GetNamePropertyIndex() override;
   };
 };
 
index bf85d8d..170495c 100755 (executable)
@@ -52,6 +52,7 @@
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/public-api/image-loader/image.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 
 namespace Dali
 {
@@ -87,28 +88,9 @@ DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "pageZoomFactor",          FLOAT,
 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "textZoomFactor",          FLOAT,   TEXT_ZOOM_FACTOR          )
 DALI_PROPERTY_REGISTRATION(Toolkit, WebView, "loadProgressPercentage",  FLOAT,   LOAD_PROGRESS_PERCENTAGE  )
 
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadStarted",         PAGE_LOAD_STARTED_SIGNAL         )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadInProgress",      PAGE_LOAD_IN_PROGRESS_SIGNAL     )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadFinished",        PAGE_LOAD_FINISHED_SIGNAL        )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "pageLoadError",           PAGE_LOAD_ERROR_SIGNAL           )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "scrollEdgeReached",       SCROLL_EDGE_REACHED_SIGNAL       )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "urlChanged",              URL_CHANGED_SIGNAL               )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "formRepostDecision",      FORM_REPOST_DECISION_SIGNAL      )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "frameRendered",           FRAME_RENDERED_SIGNAL            )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "requestInterceptor",      REQUEST_INTERCEPTOR_SIGNAL       )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "consoleMessage",          CONSOLE_MESSAGE_SIGNAL           )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "responsePolicyDecided",   POLICY_DECISION                  )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "certificateConfirm",      CERTIFICATE_CONFIRM_SIGNAL       )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "sslCertificateChanged",   SSL_CERTIFICATE_CHANGED_SIGNAL   )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "httpAuthRequest",         HTTP_AUTH_REQUEST_SIGNAL         )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "contextMenuCustomized",   CONTEXT_MENU_CUSTOMIZED_SIGNAL   )
-DALI_SIGNAL_REGISTRATION(Toolkit, WebView, "contextMenuItemSelected", CONTEXT_MENU_ITEM_SELECTED_SIGNAL)
-
 DALI_TYPE_REGISTRATION_END()
 // clang-format on
 
-const std::string kEmptyString;
-
 } // namespace
 
 #define GET_ENUM_STRING(structName, inputExp) \
@@ -119,16 +101,11 @@ const std::string kEmptyString;
 
 WebView::WebView(const std::string& locale, const std::string& timezoneId)
 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
-  mUrl(),
   mVisual(),
   mWebViewSize(Stage::GetCurrent().GetSize()),
   mWebEngine(),
-  mPageLoadStartedSignal(),
-  mPageLoadFinishedSignal(),
-  mPageLoadErrorSignal(),
-  mUrlChangedSignal(),
   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
-  mVideoHoleEnabled(true),
+  mVideoHoleEnabled(false),
   mMouseEventsEnabled(true),
   mKeyEventsEnabled(true),
   mScreenshotCapturedCallback(nullptr)
@@ -144,16 +121,11 @@ WebView::WebView(const std::string& locale, const std::string& timezoneId)
 
 WebView::WebView(uint32_t argc, char** argv)
 : Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)),
-  mUrl(),
   mVisual(),
   mWebViewSize(Stage::GetCurrent().GetSize()),
   mWebEngine(),
-  mPageLoadStartedSignal(),
-  mPageLoadFinishedSignal(),
-  mPageLoadErrorSignal(),
-  mUrlChangedSignal(),
   mWebViewArea(0, 0, mWebViewSize.width, mWebViewSize.height),
-  mVideoHoleEnabled(true),
+  mVideoHoleEnabled(false),
   mMouseEventsEnabled(true),
   mKeyEventsEnabled(true),
   mScreenshotCapturedCallback(nullptr)
@@ -176,6 +148,7 @@ WebView::~WebView()
 {
   if(mWebEngine)
   {
+    mWebEngine.FrameRenderedSignal().Disconnect(this, &WebView::OnFrameRendered);
     mWebEngine.Destroy();
   }
 }
@@ -226,23 +199,7 @@ void WebView::OnInitialize()
 
   if(mWebEngine)
   {
-    mWebEngine.PageLoadStartedSignal().Connect(this, &WebView::OnPageLoadStarted);
-    mWebEngine.PageLoadInProgressSignal().Connect(this, &WebView::OnPageLoadInProgress);
-    mWebEngine.PageLoadFinishedSignal().Connect(this, &WebView::OnPageLoadFinished);
-    mWebEngine.PageLoadErrorSignal().Connect(this, &WebView::OnPageLoadError);
-    mWebEngine.ScrollEdgeReachedSignal().Connect(this, &WebView::OnScrollEdgeReached);
-    mWebEngine.UrlChangedSignal().Connect(this, &WebView::OnUrlChanged);
-    mWebEngine.FormRepostDecisionSignal().Connect(this, &WebView::OnFormRepostDecision);
     mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnFrameRendered);
-    mWebEngine.RequestInterceptorSignal().Connect(this, &WebView::OnInterceptRequest);
-    mWebEngine.ConsoleMessageSignal().Connect(this, &WebView::OnConsoleMessage);
-    mWebEngine.ResponsePolicyDecisionSignal().Connect(this, &WebView::OnResponsePolicyDecided);
-    mWebEngine.CertificateConfirmSignal().Connect(this, &WebView::OnCertificateConfirm);
-    mWebEngine.SslCertificateChangedSignal().Connect(this, &WebView::OnSslCertificateChanged);
-    mWebEngine.HttpAuthHandlerSignal().Connect(this, &WebView::OnHttpAuthenticationRequest);
-    mWebEngine.ContextMenuCustomizedSignal().Connect(this, &WebView::OnContextMenuCustomized);
-    mWebEngine.ContextMenuItemSelectedSignal().Connect(this, &WebView::OnContextMenuItemSelected);
-
     mWebContext         = std::unique_ptr<Dali::Toolkit::WebContext>(new WebContext(mWebEngine.GetContext()));
     mWebCookieManager   = std::unique_ptr<Dali::Toolkit::WebCookieManager>(new WebCookieManager(mWebEngine.GetCookieManager()));
     mWebSettings        = std::unique_ptr<Dali::Toolkit::WebSettings>(new WebSettings(mWebEngine.GetSettings()));
@@ -283,26 +240,14 @@ Dali::Toolkit::ImageView WebView::GetFavicon() const
 
 void WebView::LoadUrl(const std::string& url)
 {
-  mUrl = url;
   if(mWebEngine)
   {
-    Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
-    const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
-    mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
-      {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
-       {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
-
-    if(mVisual)
+    if(!mVisual)
     {
-      // Clean up previously registered visual and add new one.
-      DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
-      mWebEngine.LoadUrl(url);
+      mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnInitialFrameRendered);
     }
 
-    if(mVideoHoleEnabled)
-    {
-      EnableBlendMode(false);
-    }
+    mWebEngine.LoadUrl(url);
   }
 }
 
@@ -310,22 +255,12 @@ void WebView::LoadHtmlString(const std::string& htmlString)
 {
   if(mWebEngine)
   {
-    Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
-    const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
-    mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
-      {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
-       {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
-
-    if(mVisual)
+    if(!mVisual)
     {
-      DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
-      mWebEngine.LoadHtmlString(htmlString);
+      mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnInitialFrameRendered);
     }
 
-    if(mVideoHoleEnabled)
-    {
-      EnableBlendMode(false);
-    }
+    mWebEngine.LoadHtmlString(htmlString);
   }
 }
 
@@ -334,24 +269,12 @@ bool WebView::LoadHtmlStringOverrideCurrentEntry(const std::string& html, const
   if(!mWebEngine)
     return false;
 
-  Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
-  const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
-  mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
-    {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
-     {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
-
-  bool result = false;
-  if(mVisual)
+  if(!mVisual)
   {
-    DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
-    result = mWebEngine.LoadHtmlStringOverrideCurrentEntry(html, basicUri, unreachableUrl);
+    mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnInitialFrameRendered);
   }
 
-  if(mVideoHoleEnabled)
-  {
-    EnableBlendMode(false);
-  }
-  return result;
+  return mWebEngine.LoadHtmlStringOverrideCurrentEntry(html, basicUri, unreachableUrl);
 }
 
 bool WebView::LoadContents(const std::string& contents, uint32_t contentSize, const std::string& mimeType, const std::string& encoding, const std::string& baseUri)
@@ -359,24 +282,12 @@ bool WebView::LoadContents(const std::string& contents, uint32_t contentSize, co
   if(!mWebEngine)
     return false;
 
-  Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
-  const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
-  mVisual                          = Toolkit::VisualFactory::Get().CreateVisual(
-    {{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE},
-     {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
-
-  bool result = false;
-  if(mVisual)
+  if(!mVisual)
   {
-    DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
-    result = mWebEngine.LoadContents(contents, contentSize, mimeType, encoding, baseUri);
+    mWebEngine.FrameRenderedSignal().Connect(this, &WebView::OnInitialFrameRendered);
   }
 
-  if(mVideoHoleEnabled)
-  {
-    EnableBlendMode(false);
-  }
-  return result;
+  return mWebEngine.LoadContents(contents, contentSize, mimeType, encoding, baseUri);
 }
 
 void WebView::Reload()
@@ -656,6 +567,14 @@ void WebView::RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::Geolo
   }
 }
 
+void WebView::SetTtsFocus(bool focused)
+{
+  if(mWebEngine && !HasKeyInputFocus())
+  {
+    mWebEngine.SetFocus(focused);
+  }
+}
+
 void WebView::UpdateDisplayArea(Dali::PropertyNotification& /*source*/)
 {
   if(!mWebEngine)
@@ -716,161 +635,157 @@ Dali::Toolkit::ImageView WebView::CreateImageView(Dali::PixelData pixel) const
     return Dali::Toolkit::ImageView();
   }
 
-  std::string              url       = Dali::Toolkit::Image::GenerateUrl(pixel);
-  Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url);
+  Dali::Toolkit::ImageUrl url       = Dali::Toolkit::Image::GenerateUrl(pixel);
+  Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url.GetUrl());
   imageView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixel.GetWidth(), pixel.GetHeight()));
   return imageView;
 }
 
-Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadStartedSignal()
-{
-  return mPageLoadStartedSignal;
-}
-
-Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadInProgressSignal()
-{
-  return mPageLoadInProgressSignal;
-}
-
-Dali::Toolkit::WebView::WebViewPageLoadSignalType& WebView::PageLoadFinishedSignal()
-{
-  return mPageLoadFinishedSignal;
-}
-
-Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& WebView::PageLoadErrorSignal()
-{
-  return mPageLoadErrorSignal;
-}
-
-Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType& WebView::ScrollEdgeReachedSignal()
-{
-  return mScrollEdgeReachedSignal;
-}
-
-Dali::Toolkit::WebView::WebViewUrlChangedSignalType& WebView::UrlChangedSignal()
-{
-  return mUrlChangedSignal;
-}
-
-Dali::Toolkit::WebView::WebViewFormRepostDecisionSignalType& WebView::FormRepostDecisionSignal()
+void WebView::RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return mFormRepostDecisionSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterPageLoadStartedCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewFrameRenderedSignalType& WebView::FrameRenderedSignal()
+void WebView::RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return mFrameRenderedSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterPageLoadInProgressCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewRequestInterceptorSignalType& WebView::RequestInterceptorSignal()
+void WebView::RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback)
 {
-  return mRequestInterceptorSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterPageLoadFinishedCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewConsoleMessageSignalType& WebView::ConsoleMessageSignal()
+void WebView::RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback)
 {
-  return mConsoleMessageSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterPageLoadErrorCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType& WebView::ResponsePolicyDecisionSignal()
+void WebView::RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback)
 {
-  return mResponsePolicyDecisionSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterScrollEdgeReachedCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewCertificateSignalType& WebView::CertificateConfirmSignal()
+void WebView::RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback)
 {
-  return mCertificateConfirmSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterUrlChangedCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewCertificateSignalType& WebView::SslCertificateChangedSignal()
+void WebView::RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback)
 {
-  return mSslCertificateChangedSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterFormRepostDecidedCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewHttpAuthHandlerSignalType& WebView::HttpAuthHandlerSignal()
+void WebView::RegisterFrameRenderedCallback(Dali::WebEnginePlugin::WebEngineFrameRenderedCallback callback)
 {
-  return mHttpAuthHandlerSignal;
+  mFrameRenderedCallback = callback;
 }
 
-Dali::Toolkit::WebView::WebViewContextMenuCustomizedSignalType& WebView::ContextMenuCustomizedSignal()
+void WebView::RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback)
 {
-  return mContextMenuCustomizedSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterRequestInterceptorCallback(callback);
+  }
 }
 
-Dali::Toolkit::WebView::WebViewContextMenuItemSelectedSignalType& WebView::ContextMenuItemSelectedSignal()
+void WebView::RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback)
 {
-  return mContextMenuItemSelectedSignal;
+  if(mWebEngine)
+  {
+    mWebEngine.RegisterConsoleMessageReceivedCallback(callback);
+  }
 }
 
-void WebView::OnPageLoadStarted(const std::string& url)
+void WebView::RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback)
 {
-  if(!mPageLoadStartedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mPageLoadStartedSignal.Emit(handle, url);
+    mWebEngine.RegisterResponsePolicyDecidedCallback(callback);
   }
 }
 
-void WebView::OnPageLoadInProgress(const std::string& url)
+void WebView::RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  if(!mPageLoadInProgressSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mPageLoadInProgressSignal.Emit(handle, url);
+    mWebEngine.RegisterCertificateConfirmedCallback(callback);
   }
 }
 
-void WebView::OnPageLoadFinished(const std::string& url)
+void WebView::RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback)
 {
-  if(!mPageLoadFinishedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mPageLoadFinishedSignal.Emit(handle, url);
+    mWebEngine.RegisterSslCertificateChangedCallback(callback);
   }
 }
 
-void WebView::OnPageLoadError(std::shared_ptr<Dali::WebEngineLoadError> error)
+void WebView::RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback)
 {
-  if(!mPageLoadErrorSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mPageLoadErrorSignal.Emit(handle, std::move(error));
+    mWebEngine.RegisterHttpAuthHandlerCallback(callback);
   }
 }
 
-void WebView::OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge)
+void WebView::RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback)
 {
-  if(!mScrollEdgeReachedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mScrollEdgeReachedSignal.Emit(handle, edge);
+    mWebEngine.RegisterContextMenuShownCallback(callback);
   }
 }
 
-void WebView::OnUrlChanged(const std::string& url)
+void WebView::RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback)
 {
-  if(!mUrlChangedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mUrlChangedSignal.Emit(handle, url);
+    mWebEngine.RegisterContextMenuHiddenCallback(callback);
   }
 }
 
-void WebView::OnFormRepostDecision(std::shared_ptr<Dali::WebEngineFormRepostDecision> decision)
+void WebView::OnFrameRendered()
 {
-  if(!mFormRepostDecisionSignal.Empty())
+  if(mFrameRenderedCallback)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mFormRepostDecisionSignal.Emit(handle, std::move(decision));
+    mFrameRenderedCallback();
   }
 }
 
-void WebView::OnFrameRendered()
+void WebView::OnInitialFrameRendered()
 {
-  if(!mFrameRenderedSignal.Empty())
+  mWebEngine.FrameRenderedSignal().Disconnect(this, &WebView::OnInitialFrameRendered);
+
+  Texture           texture        = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
+  const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
+  mVisual                          = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
+
+  if(mVisual)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mFrameRenderedSignal.Emit(handle);
+    DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
+    EnableBlendMode(!mVideoHoleEnabled);
   }
 }
 
@@ -891,167 +806,72 @@ void WebView::OnScreenshotCaptured(Dali::PixelData pixel)
   }
 }
 
-void WebView::OnInterceptRequest(std::shared_ptr<Dali::WebEngineRequestInterceptor> interceptor)
+void WebView::OnSceneConnection(int depth)
 {
-  if(!mRequestInterceptorSignal.Empty())
-  {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mRequestInterceptorSignal.Emit(handle, std::move(interceptor));
-  }
+  Control::OnSceneConnection(depth);
+  EnableBlendMode(!mVideoHoleEnabled);
 }
 
-void WebView::OnConsoleMessage(std::shared_ptr<Dali::WebEngineConsoleMessage> message)
+bool WebView::OnTouchEvent(Actor actor, const Dali::TouchEvent& touch)
 {
-  if(!mConsoleMessageSignal.Empty())
-  {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mConsoleMessageSignal.Emit(handle, std::move(message));
-  }
-}
+  bool result = false;
 
-void WebView::OnResponsePolicyDecided(std::shared_ptr<Dali::WebEnginePolicyDecision> decision)
-{
-  if(!mResponsePolicyDecisionSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mResponsePolicyDecisionSignal.Emit(handle, std::move(decision));
+    result = mWebEngine.SendTouchEvent(touch);
   }
+  return result;
 }
 
-void WebView::OnCertificateConfirm(std::shared_ptr<Dali::WebEngineCertificate> certificate)
+bool WebView::OnKeyEvent(const Dali::KeyEvent& event)
 {
-  if(!mCertificateConfirmSignal.Empty())
-  {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mCertificateConfirmSignal.Emit(handle, std::move(certificate));
-  }
-}
+  bool result = false;
 
-void WebView::OnSslCertificateChanged(std::shared_ptr<Dali::WebEngineCertificate> certificate)
-{
-  if(!mSslCertificateChangedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mSslCertificateChangedSignal.Emit(handle, std::move(certificate));
+    result = mWebEngine.SendKeyEvent(event);
   }
+  return result;
 }
 
-void WebView::OnHttpAuthenticationRequest(std::shared_ptr<Dali::WebEngineHttpAuthHandler> handler)
+bool WebView::OnHoverEvent(Actor actor, const Dali::HoverEvent& hover)
 {
-  if(!mHttpAuthHandlerSignal.Empty())
+  bool result = false;
+  if(mWebEngine && mMouseEventsEnabled)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mHttpAuthHandlerSignal.Emit(handle, std::move(handler));
+    result = mWebEngine.SendHoverEvent(hover);
   }
+  return result;
 }
 
-void WebView::OnContextMenuCustomized(std::shared_ptr<Dali::WebEngineContextMenu> menu)
+bool WebView::OnWheelEvent(Actor actor, const Dali::WheelEvent& wheel)
 {
-  if(!mContextMenuCustomizedSignal.Empty())
+  bool result = false;
+  if(mWebEngine && mMouseEventsEnabled)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mContextMenuCustomizedSignal.Emit(handle, std::move(menu));
+    result = mWebEngine.SendWheelEvent(wheel);
   }
+  return result;
 }
 
-void WebView::OnContextMenuItemSelected(std::shared_ptr<Dali::WebEngineContextMenuItem> item)
+void WebView::OnKeyInputFocusGained()
 {
-  if(!mContextMenuItemSelectedSignal.Empty())
+  if(mWebEngine)
   {
-    Dali::Toolkit::WebView handle(GetOwner());
-    mContextMenuItemSelectedSignal.Emit(handle, std::move(item));
+    mWebEngine.SetFocus(true);
   }
+
+  EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
 }
 
-bool WebView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
+void WebView::OnKeyInputFocusLost()
 {
-  Dali::BaseHandle handle(object);
-
-  bool             connected = false;
-  Toolkit::WebView webView   = Toolkit::WebView::DownCast(handle);
-
-  if(0 == strcmp(signalName.c_str(), PAGE_LOAD_STARTED_SIGNAL))
-  {
-    webView.PageLoadStartedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_IN_PROGRESS_SIGNAL))
-  {
-    webView.PageLoadInProgressSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_FINISHED_SIGNAL))
-  {
-    webView.PageLoadFinishedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), PAGE_LOAD_ERROR_SIGNAL))
-  {
-    webView.PageLoadErrorSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), SCROLL_EDGE_REACHED_SIGNAL))
-  {
-    webView.ScrollEdgeReachedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), URL_CHANGED_SIGNAL))
-  {
-    webView.UrlChangedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), FORM_REPOST_DECISION_SIGNAL))
-  {
-    webView.FormRepostDecisionSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), FRAME_RENDERED_SIGNAL))
-  {
-    webView.FrameRenderedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), REQUEST_INTERCEPTOR_SIGNAL))
-  {
-    webView.RequestInterceptorSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), CONSOLE_MESSAGE_SIGNAL))
-  {
-    webView.ConsoleMessageSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), POLICY_DECISION))
-  {
-    webView.ResponsePolicyDecisionSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), CERTIFICATE_CONFIRM_SIGNAL))
-  {
-    webView.CertificateConfirmSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), SSL_CERTIFICATE_CHANGED_SIGNAL))
-  {
-    webView.SslCertificateChangedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), HTTP_AUTH_REQUEST_SIGNAL))
-  {
-    webView.HttpAuthHandlerSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), CONTEXT_MENU_CUSTOMIZED_SIGNAL))
-  {
-    webView.ContextMenuCustomizedSignal().Connect(tracker, functor);
-    connected = true;
-  }
-  else if(0 == strcmp(signalName.c_str(), CONTEXT_MENU_ITEM_SELECTED_SIGNAL))
+  if(mWebEngine)
   {
-    webView.ContextMenuItemSelectedSignal().Connect(tracker, functor);
-    connected = true;
+    mWebEngine.SetFocus(false);
   }
 
-  return connected;
+  EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
 }
 
 Vector3 WebView::GetNaturalSize()
@@ -1066,13 +886,6 @@ Vector3 WebView::GetNaturalSize()
   return Vector3(mWebViewSize);
 }
 
-void WebView::OnSceneConnection(int depth)
-{
-  Control::OnSceneConnection(depth);
-
-  EnableBlendMode(!mVideoHoleEnabled);
-}
-
 void WebView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
 {
   Toolkit::WebView webView = Toolkit::WebView::DownCast(Dali::BaseHandle(object));
@@ -1209,7 +1022,7 @@ Property::Value WebView::GetProperty(BaseObject* object, Property::Index propert
     {
       case Toolkit::WebView::Property::URL:
       {
-        value = impl.mUrl;
+        value = impl.GetUrl();
         break;
       }
       case Toolkit::WebView::Property::USER_AGENT:
@@ -1280,68 +1093,6 @@ Property::Value WebView::GetProperty(BaseObject* object, Property::Index propert
   return value;
 }
 
-bool WebView::OnTouchEvent(Actor actor, const Dali::TouchEvent& touch)
-{
-  bool result = false;
-
-  if(mWebEngine)
-  {
-    result = mWebEngine.SendTouchEvent(touch);
-  }
-  return result;
-}
-
-bool WebView::OnKeyEvent(const Dali::KeyEvent& event)
-{
-  bool result = false;
-
-  if(mWebEngine)
-  {
-    result = mWebEngine.SendKeyEvent(event);
-  }
-  return result;
-}
-
-bool WebView::OnHoverEvent(Actor actor, const Dali::HoverEvent& hover)
-{
-  bool result = false;
-  if(mWebEngine && mMouseEventsEnabled)
-  {
-    result = mWebEngine.SendHoverEvent(hover);
-  }
-  return result;
-}
-
-bool WebView::OnWheelEvent(Actor actor, const Dali::WheelEvent& wheel)
-{
-  bool result = false;
-  if(mWebEngine && mMouseEventsEnabled)
-  {
-    result = mWebEngine.SendWheelEvent(wheel);
-  }
-  return result;
-}
-
-void WebView::OnKeyInputFocusGained()
-{
-  if(mWebEngine)
-  {
-    mWebEngine.SetFocus(true);
-  }
-
-  EmitKeyInputFocusSignal(true); // Calls back into the Control hence done last.
-}
-
-void WebView::OnKeyInputFocusLost()
-{
-  if(mWebEngine)
-  {
-    mWebEngine.SetFocus(false);
-  }
-
-  EmitKeyInputFocusSignal(false); // Calls back into the Control hence done last.
-}
-
 void WebView::SetScrollPosition(int32_t x, int32_t y)
 {
   if(mWebEngine)
@@ -1367,7 +1118,7 @@ Dali::Vector2 WebView::GetContentSize() const
 
 std::string WebView::GetTitle() const
 {
-  return mWebEngine ? mWebEngine.GetTitle() : kEmptyString;
+  return mWebEngine ? mWebEngine.GetTitle() : std::string();
 }
 
 void WebView::SetDocumentBackgroundColor(Dali::Vector4 color)
@@ -1404,12 +1155,17 @@ void WebView::EnableCursorByClient(bool enabled)
 
 std::string WebView::GetSelectedText() const
 {
-  return mWebEngine ? mWebEngine.GetSelectedText() : kEmptyString;
+  return mWebEngine ? mWebEngine.GetSelectedText() : std::string();
+}
+
+std::string WebView::GetUrl() const
+{
+  return mWebEngine ? mWebEngine.GetUrl() : std::string();
 }
 
-const std::string& WebView::GetUserAgent() const
+std::string WebView::GetUserAgent() const
 {
-  return mWebEngine ? mWebEngine.GetUserAgent() : kEmptyString;
+  return mWebEngine ? mWebEngine.GetUserAgent() : std::string();
 }
 
 void WebView::SetUserAgent(const std::string& userAgent)
index a5cefa4..c2d6742 100755 (executable)
@@ -205,12 +205,12 @@ public:
   /**
    * @copydoc Dali::Toolkit::WebView::EvaluateJavaScript()
    */
-  void EvaluateJavaScript(const std::string& script, std::function<void(const std::string&)> resultHandler);
+  void EvaluateJavaScript(const std::string& script, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback resultHandler);
 
   /**
    * @copydoc Dali::Toolkit::WebView::AddJavaScriptMessageHandler()
    */
-  void AddJavaScriptMessageHandler(const std::string& exposedObjectName, std::function<void(const std::string&)> handler);
+  void AddJavaScriptMessageHandler(const std::string& exposedObjectName, Dali::WebEnginePlugin::JavaScriptMessageHandlerCallback handler);
 
   /**
    * @copydoc Dali::Toolkit::WebView::RegisterJavaScriptAlertCallback()
@@ -308,84 +308,89 @@ public:
   void RegisterGeolocationPermissionCallback(Dali::WebEnginePlugin::GeolocationPermissionCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::PageLoadStartedSignal()
+   * @copydoc Dali::Toolkit::WebView::SetTtsFocus()
    */
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType& PageLoadStartedSignal();
+  void SetTtsFocus(bool focused);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::PageLoadInProgressSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterPageLoadStartedCallback()
    */
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType& PageLoadInProgressSignal();
+  void RegisterPageLoadStartedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::PageLoadFinishedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterPageLoadInProgressCallback()
    */
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType& PageLoadFinishedSignal();
+  void RegisterPageLoadInProgressCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::PageLoadErrorSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterPageLoadFinishedCallback()
    */
-  Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType& PageLoadErrorSignal();
+  void RegisterPageLoadFinishedCallback(Dali::WebEnginePlugin::WebEnginePageLoadCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::ScrollEdgeReachedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterPageLoadErrorCallback()
    */
-  Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType& ScrollEdgeReachedSignal();
+  void RegisterPageLoadErrorCallback(Dali::WebEnginePlugin::WebEnginePageLoadErrorCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::UrlChangedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterScrollEdgeReachedCallback()
    */
-  Dali::Toolkit::WebView::WebViewUrlChangedSignalType& UrlChangedSignal();
+  void RegisterScrollEdgeReachedCallback(Dali::WebEnginePlugin::WebEngineScrollEdgeReachedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::FormRepostDecisionSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterUrlChangedCallback()
    */
-  Dali::Toolkit::WebView::WebViewFormRepostDecisionSignalType& FormRepostDecisionSignal();
+  void RegisterUrlChangedCallback(Dali::WebEnginePlugin::WebEngineUrlChangedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::FrameRenderedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterFormRepostDecidedCallback()
    */
-  Dali::Toolkit::WebView::WebViewFrameRenderedSignalType& FrameRenderedSignal();
+  void RegisterFormRepostDecidedCallback(Dali::WebEnginePlugin::WebEngineFormRepostDecidedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::RequestInterceptorSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterFrameRenderedCallback()
    */
-  Dali::Toolkit::WebView::WebViewRequestInterceptorSignalType& RequestInterceptorSignal();
+  void RegisterFrameRenderedCallback(Dali::WebEnginePlugin::WebEngineFrameRenderedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::ConsoleMessageSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterRequestInterceptorCallback()
    */
-  Dali::Toolkit::WebView::WebViewConsoleMessageSignalType& ConsoleMessageSignal();
+  void RegisterRequestInterceptorCallback(Dali::WebEnginePlugin::WebEngineRequestInterceptorCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::ResponsePolicyDecisionSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterConsoleMessageReceivedCallback()
    */
-  Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
+  void RegisterConsoleMessageReceivedCallback(Dali::WebEnginePlugin::WebEngineConsoleMessageReceivedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::CertificateConfirmSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterResponsePolicyDecidedCallback()
    */
-  Dali::Toolkit::WebView::WebViewCertificateSignalType& CertificateConfirmSignal();
+  void RegisterResponsePolicyDecidedCallback(Dali::WebEnginePlugin::WebEngineResponsePolicyDecidedCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::SslCertificateChangedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterCertificateConfirmedCallback()
    */
-  Dali::Toolkit::WebView::WebViewCertificateSignalType& SslCertificateChangedSignal();
+  void RegisterCertificateConfirmedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::HttpAuthHandlerSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterSslCertificateChangedCallback()
    */
-  Dali::Toolkit::WebView::WebViewHttpAuthHandlerSignalType& HttpAuthHandlerSignal();
+  void RegisterSslCertificateChangedCallback(Dali::WebEnginePlugin::WebEngineCertificateCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::ContextMenuCustomizedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterHttpAuthHandlerCallback()
    */
-  Dali::Toolkit::WebView::WebViewContextMenuCustomizedSignalType& ContextMenuCustomizedSignal();
+  void RegisterHttpAuthHandlerCallback(Dali::WebEnginePlugin::WebEngineHttpAuthHandlerCallback callback);
 
   /**
-   * @copydoc Dali::Toolkit::WebView::ContextMenuItemSelectedSignal()
+   * @copydoc Dali::Toolkit::WebView::RegisterContextMenuShownCallback()
    */
-  Dali::Toolkit::WebView::WebViewContextMenuItemSelectedSignalType& ContextMenuItemSelectedSignal();
+  void RegisterContextMenuShownCallback(Dali::WebEnginePlugin::WebEngineContextMenuShownCallback callback);
+
+  /**
+   * @copydoc Dali::Toolkit::WebView::RegisterContextMenuHiddenCallback()
+   */
+  void RegisterContextMenuHiddenCallback(Dali::WebEnginePlugin::WebEngineContextMenuHiddenCallback callback);
 
 public: // Properties
   /**
@@ -406,17 +411,6 @@ public: // Properties
    */
   static Dali::Property::Value GetProperty(Dali::BaseObject* object, Dali::Property::Index propertyIndex);
 
-  /**
-   * 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 c
-   */
-  static bool DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
-
 private: // From Control
   /**
    * @copydoc Toolkit::Control::OnInitialize()
@@ -522,10 +516,16 @@ private:
   std::string GetSelectedText() const;
 
   /**
+   * @brief Get url of web page.
+   * @return The string of url
+   */
+  std::string GetUrl() const;
+
+  /**
    * @brief Get user agent string.
    * @return The string value of user agent
    */
-  const std::string& GetUserAgent() const;
+  std::string GetUserAgent() const;
 
   /**
    * @brief Set user agent string.
@@ -611,43 +611,6 @@ private:
   Dali::Toolkit::ImageView CreateImageView(Dali::PixelData pixel) const;
 
   /**
-   * @brief Callback function to be called when page load started.
-   * @param[in] url The url currently being loaded
-   */
-  void OnPageLoadStarted(const std::string& url);
-
-  /**
-   * @brief Callback function to be called when page is loading in progress.
-   * @param[in] url The url currently being loaded
-   */
-  void OnPageLoadInProgress(const std::string& url);
-
-  /**
-   * @brief Callback function to be called when page load finished.
-   * @param[in] url The url currently being loaded
-   */
-  void OnPageLoadFinished(const std::string& url);
-
-  /**
-   * @brief Callback function to be called when there is an error in page loading.
-   * @param[in] url The url currently being loaded
-   * @param[in] errorCode The error code
-   */
-  void OnPageLoadError(std::shared_ptr<Dali::WebEngineLoadError> error);
-
-  /**
-   * @brief Callback function to be called when scroll edge is reached.
-   * @param[in] edge The scroll edge reached.
-   */
-  void OnScrollEdgeReached(Dali::WebEnginePlugin::ScrollEdge edge);
-
-  /**
-   * @brief Callback function to be called when url is changed.
-   * @param[in] url The url currently being loaded
-   */
-  void OnUrlChanged(const std::string& url);
-
-  /**
    * @brief Signal occurs when the Web View has been touched.
    * @param[in] actor The Actor Touched
    * @param[in] touch The Touch Data.
@@ -672,15 +635,14 @@ private:
   bool OnWheelEvent(Actor actor, const Dali::WheelEvent& wheel);
 
   /**
-   * @brief Callback function to be called when form repost decision need be checked.
-   * @param[in] decision The new decision for form repost
+   * @brief Callback function to be called when frame is rendered.
    */
-  void OnFormRepostDecision(std::shared_ptr<Dali::WebEngineFormRepostDecision> decision);
+  void OnFrameRendered();
 
   /**
-   * @brief Callback function to be called when frame is rendered.
+   * @brief Callback function to be called when frame is rendered. This is to check initial buffer is ready.
    */
-  void OnFrameRendered();
+  void OnInitialFrameRendered();
 
   /**
    * @brief Callback function to be called when visibility is changed.
@@ -696,77 +658,11 @@ private:
    */
   void OnScreenshotCaptured(Dali::PixelData pixel);
 
-  /**
-   * @brief Callback function to be called when http request need be intercepted.
-   * @param [in] request The http request interceptor.
-   */
-  void OnInterceptRequest(std::shared_ptr<Dali::WebEngineRequestInterceptor> interceptor);
-
-  /**
-   * @brief Callback function to be called when console message will be logged.
-   * @param[in] message The message logged.
-   */
-  void OnConsoleMessage(std::shared_ptr<Dali::WebEngineConsoleMessage> message);
-
-  /**
-   * @brief Callback function to be called when response policy need be decided.
-   * @param[in] decision The policy decided.
-   */
-  void OnResponsePolicyDecided(std::shared_ptr<Dali::WebEnginePolicyDecision> decision);
-
-  /**
-   * @brief Callback function to be called when certificate need be confirmed.
-   * @param[in] certificate The certificate policy decision.
-   */
-  void OnCertificateConfirm(std::shared_ptr<Dali::WebEngineCertificate> certificate);
-
-  /**
-   * @brief Callback function to be called when ssl certificate is changed.
-   * @param[in] certificate The certificate information received.
-   */
-  void OnSslCertificateChanged(std::shared_ptr<Dali::WebEngineCertificate> certificate);
-
-  /**
-   * @brief Callback function to be called when http authentication need be confirmed.
-   * @param[in] handler The handler for http authentication
-   */
-  void OnHttpAuthenticationRequest(std::shared_ptr<Dali::WebEngineHttpAuthHandler> handler);
-
-  /**
-   * @brief Callback function to be called when context menu would be customized.
-   * @param[in] e The scroll edge reached.
-   */
-  void OnContextMenuCustomized(std::shared_ptr<Dali::WebEngineContextMenu> menu);
-
-  /**
-   * @brief Callback function to be called when context menu item is selected.
-   * @param[in] url The url currently being loaded
-   */
-  void OnContextMenuItemSelected(std::shared_ptr<Dali::WebEngineContextMenuItem> item);
-
 private:
-  std::string                 mUrl;
   Dali::Toolkit::Visual::Base mVisual;
   Dali::Size                  mWebViewSize;
   Dali::WebEngine             mWebEngine;
 
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType                mPageLoadStartedSignal;
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType                mPageLoadInProgressSignal;
-  Dali::Toolkit::WebView::WebViewPageLoadSignalType                mPageLoadFinishedSignal;
-  Dali::Toolkit::WebView::WebViewPageLoadErrorSignalType           mPageLoadErrorSignal;
-  Dali::Toolkit::WebView::WebViewUrlChangedSignalType              mUrlChangedSignal;
-  Dali::Toolkit::WebView::WebViewScrollEdgeReachedSignalType       mScrollEdgeReachedSignal;
-  Dali::Toolkit::WebView::WebViewFormRepostDecisionSignalType      mFormRepostDecisionSignal;
-  Dali::Toolkit::WebView::WebViewFrameRenderedSignalType           mFrameRenderedSignal;
-  Dali::Toolkit::WebView::WebViewRequestInterceptorSignalType      mRequestInterceptorSignal;
-  Dali::Toolkit::WebView::WebViewConsoleMessageSignalType          mConsoleMessageSignal;
-  Dali::Toolkit::WebView::WebViewResponsePolicyDecisionSignalType  mResponsePolicyDecisionSignal;
-  Dali::Toolkit::WebView::WebViewCertificateSignalType             mCertificateConfirmSignal;
-  Dali::Toolkit::WebView::WebViewCertificateSignalType             mSslCertificateChangedSignal;
-  Dali::Toolkit::WebView::WebViewHttpAuthHandlerSignalType         mHttpAuthHandlerSignal;
-  Dali::Toolkit::WebView::WebViewContextMenuCustomizedSignalType   mContextMenuCustomizedSignal;
-  Dali::Toolkit::WebView::WebViewContextMenuItemSelectedSignalType mContextMenuItemSelectedSignal;
-
   std::unique_ptr<Dali::Toolkit::WebContext>         mWebContext;
   std::unique_ptr<Dali::Toolkit::WebCookieManager>   mWebCookieManager;
   std::unique_ptr<Dali::Toolkit::WebSettings>        mWebSettings;
@@ -781,6 +677,7 @@ private:
   bool                       mKeyEventsEnabled;
 
   Dali::Toolkit::WebView::WebViewScreenshotCapturedCallback mScreenshotCapturedCallback;
+  Dali::WebEnginePlugin::WebEngineFrameRenderedCallback     mFrameRenderedCallback;
 };
 
 } // namespace Internal
index 41d9978..a661176 100644 (file)
@@ -124,6 +124,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/image-loader/atlas-packer.cpp
    ${toolkit_src_dir}/image-loader/image-atlas-impl.cpp
    ${toolkit_src_dir}/image-loader/image-load-thread.cpp
+   ${toolkit_src_dir}/image-loader/image-url-impl.cpp
    ${toolkit_src_dir}/styling/style-manager-impl.cpp
    ${toolkit_src_dir}/text/bidirectional-support.cpp
    ${toolkit_src_dir}/text/character-set-conversion.cpp
@@ -141,6 +142,7 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
+   ${toolkit_src_dir}/text/input-filter.cpp
    ${toolkit_src_dir}/text/property-string-parser.cpp
    ${toolkit_src_dir}/text/segmentation.cpp
    ${toolkit_src_dir}/text/shaper.cpp
index 8dadb11..b10ff63 100644 (file)
@@ -127,7 +127,8 @@ KeyboardFocusManager::KeyboardFocusManager()
   mAlwaysShowIndicator(ALWAYS_SHOW),
   mFocusGroupLoopEnabled(false),
   mIsWaitingKeyboardFocusChangeCommit(false),
-  mClearFocusOnTouch(true)
+  mClearFocusOnTouch(true),
+  mEnableDefaultAlgorithm(false)
 {
   // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
 
@@ -497,7 +498,7 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
         nextFocusableActor                  = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
         mIsWaitingKeyboardFocusChangeCommit = false;
       }
-      else
+      else if(mEnableDefaultAlgorithm)
       {
         // We should find it among the actors nearby.
         nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction);
@@ -878,7 +879,15 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       {
         // "Tab" key changes the focus group in the forward direction and
         // "Shift-Tab" key changes it in the backward direction.
-        DoMoveFocusToNextFocusGroup(!event.IsShiftModifier());
+        if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
+        {
+          // If the focus group is not changed, Move the focus towards right, "Shift-Tap" key moves the focus towards left.
+          if(!MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::LEFT : Toolkit::Control::KeyboardFocus::RIGHT))
+          {
+            // If the focus is not moved, Move the focus towards down, "Shift-Tap" key moves the focus towards up.
+            MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::UP : Toolkit::Control::KeyboardFocus::DOWN);
+          }
+        }
       }
 
       isFocusStartableKey = true;
@@ -1076,6 +1085,16 @@ bool KeyboardFocusManager::IsFocusIndicatorEnabled() const
   return (mEnableFocusIndicator == ENABLE);
 }
 
+void KeyboardFocusManager::EnableDefaultAlgorithm(bool enable)
+{
+  mEnableDefaultAlgorithm = enable;
+}
+
+bool KeyboardFocusManager::IsDefaultAlgorithmEnabled() const
+{
+  return mEnableDefaultAlgorithm;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 07bf86f..8212a79 100644 (file)
@@ -152,6 +152,16 @@ public:
    */
   bool IsFocusIndicatorEnabled() const;
 
+  /**
+   * @copydoc Toolkit::DevelKeyboardFocusManager::EnableDefaultAlgorithm
+   */
+  void EnableDefaultAlgorithm(bool enable);
+
+  /**
+   * @copydoc Toolkit::DevelKeyboardFocusManager::IsDefaultAlgorithmEnabled
+   */
+  bool IsDefaultAlgorithmEnabled() const;
+
 public:
   /**
    * @copydoc Toolkit::KeyboardFocusManager::PreFocusChangeSignal()
@@ -332,6 +342,8 @@ private:
   bool mIsWaitingKeyboardFocusChangeCommit : 1; /// A flag to indicate PreFocusChangeSignal emitted but the proposed focus actor is not commited by the application yet.
 
   bool mClearFocusOnTouch : 1; ///< Whether clear focus on touch.
+
+  bool mEnableDefaultAlgorithm : 1; ///< Whether use default algorithm focus
 };
 
 } // namespace Internal
index 92b29a6..74e8f58 100644 (file)
@@ -140,8 +140,9 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
       textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
     }
     borderlineOpacity *= borderlineColor.a;
+    return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
   }
-  return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+  return mix(textureColor, borderlineColor, borderlineOpacity);
 }
 #endif
 
@@ -238,13 +239,13 @@ mediump float calculateBlurOpacity()
 
 void main()
 {
-  lowp vec4 targetColor = vec4(mixColor, 1.0) * uColor;
+  lowp vec4 targetColor = vec4(mixColor, 1.0);
 
 #if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
-    OUT_COLOR = targetColor;
+    OUT_COLOR = targetColor * uColor;
     return;
   }
   PreprocessPotential();
@@ -253,7 +254,7 @@ void main()
 #if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
   targetColor = convertBorderlineColor(targetColor);
 #endif
-  OUT_COLOR = targetColor;
+  OUT_COLOR = targetColor * uColor;
 
 #if IS_REQUIRED_BLUR
   mediump float opacity = calculateBlurOpacity();
index 9c897b4..f859a24 100644 (file)
@@ -139,8 +139,9 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
       textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
     }
     borderlineOpacity *= borderlineColor.a;
+    return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
   }
-  return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+  return mix(textureColor, borderlineColor, borderlineOpacity);
 }
 #endif
 
@@ -169,16 +170,16 @@ mediump float calculateCornerOpacity()
 void main()
 {
 #if RADIAL
-  lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0) * uColor;
+  lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0);
 #else
-  lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0) * uColor;
+  lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0);
 #endif
 
 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
-    OUT_COLOR = textureColor;
+    OUT_COLOR = textureColor * uColor;
     return;
   }
   PreprocessPotential();
@@ -187,7 +188,7 @@ void main()
 #if IS_REQUIRED_BORDERLINE
   textureColor = convertBorderlineColor(textureColor);
 #endif
-  OUT_COLOR = textureColor;
+  OUT_COLOR = textureColor * uColor;
 
 #if IS_REQUIRED_ROUNDED_CORNER
   mediump float opacity = calculateCornerOpacity();
index b0dcfec..0bba311 100644 (file)
@@ -150,19 +150,22 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
     mediump float tCornerRadius = -gCenterPosition;
     mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
     mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
+    lowp vec3 BorderlineColorRGB = borderlineColor.xyz;
+    BorderlineColorRGB *= mix(1.0, borderlineColor.a, preMultipliedAlpha);
     if(potential > MaxTexturelinePotential)
     {
       // potential is out of texture range. use borderline color instead of texture
-      textureColor = vec4(borderlineColor.xyz, 0.0);
+      textureColor = vec4(BorderlineColorRGB, 0.0);
     }
     else if(potential > MinTexturelinePotential)
     {
       // potential is in texture range
-      textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+      textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
     }
     borderlineOpacity *= borderlineColor.a;
+    return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
   }
-  return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+  return mix(textureColor, borderlineColor, borderlineOpacity);
 }
 #endif
 
@@ -199,13 +202,13 @@ void main()
   mediump vec2 texCoord = vTexCoord;
 #endif
 
-  lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );
+  lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 );
 
 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
   // skip most potential calculate for performance
   if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
   {
-    OUT_COLOR = textureColor;
+    OUT_COLOR = textureColor * uColor;
     return;
   }
   PreprocessPotential();
@@ -214,7 +217,7 @@ void main()
 #if IS_REQUIRED_BORDERLINE
   textureColor = convertBorderlineColor(textureColor);
 #endif
-  OUT_COLOR = textureColor;
+  OUT_COLOR = textureColor * uColor;
 
 #if IS_REQUIRED_ROUNDED_CORNER
   mediump float opacity = calculateCornerOpacity();
diff --git a/dali-toolkit/internal/image-loader/image-url-impl.cpp b/dali-toolkit/internal/image-loader/image-url-impl.cpp
new file mode 100644 (file)
index 0000000..055738f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021 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/image-loader/texture-manager.h>
+#include <dali-toolkit/internal/image-loader/image-url-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+ImageUrl::ImageUrl(Texture& texture)
+: mUrl("")
+{
+  mUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
+}
+
+ImageUrl::~ImageUrl()
+{
+  Dali::Toolkit::TextureManager::RemoveTexture(mUrl);
+}
+
+ImageUrlPtr ImageUrl::New(Texture& texture)
+{
+  ImageUrlPtr imageUrlPtr = new ImageUrl(texture);
+  return imageUrlPtr;
+}
+
+const std::string& ImageUrl::GetUrl() const
+{
+  return mUrl;
+}
+
+} // End of namespace Internal
+
+} // End of namespace Toolkit
+
+} // End of namespace Dali
diff --git a/dali-toolkit/internal/image-loader/image-url-impl.h b/dali-toolkit/internal/image-loader/image-url-impl.h
new file mode 100644 (file)
index 0000000..45981b2
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef DALI_TOOLKIT_INTERNAL_IMAGE_URL_H
+#define DALI_TOOLKIT_INTERNAL_IMAGE_URL_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/image-loader/image-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class ImageUrl;
+using ImageUrlPtr = IntrusivePtr<ImageUrl>;
+
+class ImageUrl : public BaseObject
+{
+public:
+  /**
+   * @brief Constructor.
+   */
+  ImageUrl(Texture& texture);
+
+  /**
+   * @copydoc Dali::Toolkit::ImageUrl::New
+   */
+  static ImageUrlPtr New(Texture& texture);
+
+  /**
+   * @copydoc Dali::Toolkit::ImageUrl::GetUrl
+   */
+  const std::string& GetUrl() const;
+
+protected:
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ImageUrl();
+
+private:
+  // Undefined
+  ImageUrl(const ImageUrl&);
+
+  // Undefined
+  ImageUrl& operator=(const ImageUrl& rhs);
+
+private:
+  std::string mUrl;
+};
+
+} // namespace Internal
+} // namespace Toolkit
+
+// Helpers for public-api forwarding methods
+
+inline Toolkit::Internal::ImageUrl& GetImpl(Dali::Toolkit::ImageUrl& imageUrl)
+{
+  DALI_ASSERT_ALWAYS(imageUrl && "ImageUrl handle is empty");
+
+  BaseObject& handle = imageUrl.GetBaseObject();
+
+  return static_cast<Toolkit::Internal::ImageUrl&>(handle);
+}
+
+inline const Toolkit::Internal::ImageUrl& GetImpl(const Dali::Toolkit::ImageUrl& imageUrl)
+{
+  DALI_ASSERT_ALWAYS(imageUrl && "ImageUrl handle is empty");
+
+  const BaseObject& handle = imageUrl.GetBaseObject();
+
+  return static_cast<const Toolkit::Internal::ImageUrl&>(handle);
+}
+
+} // End of namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_IMAGE_URL_H
index 63a8017..bffc7ef 100644 (file)
@@ -32,10 +32,12 @@ namespace Text
  */
 struct BidirectionalLineInfoRun
 {
-  CharacterRun       characterRun;       ///< The initial character index within the whole text and the number of characters of the run.
-  CharacterIndex*    visualToLogicalMap; ///< Pointer to the visual to logical map table.
-  CharacterDirection direction : 1;      ///< Direction of the first character of the paragraph.
-  bool               isIdentity : 1;     ///< Whether the map is the identity.
+  CharacterRun       characterRun;                  ///< The initial character index within the whole text and the number of characters of the run. In case the line is splitted by MIDDLE Ellipsis, this for the first half of line.
+  CharacterIndex*    visualToLogicalMap;            ///< Pointer to the visual to logical map table. In case the line is splitted by MIDDLE Ellipsis, this for the first half of line.
+  CharacterRun       characterRunForSecondHalfLine; ///< The initial character index within the whole text and the number of characters of the run for the second half of line.
+  CharacterIndex*    visualToLogicalMapSecondHalf;  ///< Pointer to the visual to logical map table for the second half of line.
+  CharacterDirection direction : 1;                 ///< Direction of the first character of the paragraph.
+  bool               isIdentity : 1;                ///< Whether the map is the identity.
 };
 
 } // namespace Text
index da8f961..9bf27f8 100644 (file)
@@ -34,7 +34,7 @@ void SetBidirectionalInfo(const Vector<Character>&               text,
                           CharacterIndex                         startIndex,
                           Length                                 numberOfCharacters,
                           Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
-                          bool                                   matchSystemLanguageDirection,
+                          bool                                   matchLayoutDirection,
                           Dali::LayoutDirection::Type            layoutDirection)
 {
   // Find where to insert the new paragraphs.
@@ -113,7 +113,7 @@ void SetBidirectionalInfo(const Vector<Character>&               text,
         // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run.
         bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo(textBuffer + bidirectionalRun.characterRun.characterIndex,
                                                                                   bidirectionalRun.characterRun.numberOfCharacters,
-                                                                                  matchSystemLanguageDirection,
+                                                                                  matchLayoutDirection,
                                                                                   layoutDirection);
 
         bidirectionalRun.direction = bidirectionalSupport.GetParagraphDirection(bidirectionalRun.bidirectionalInfoIndex);
@@ -147,6 +147,8 @@ void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo
                  BidirectionalLineRunIndex            bidiLineIndex,
                  CharacterIndex                       startIndex,
                  Length                               numberOfCharacters,
+                 CharacterIndex                       startIndexInSecondHalfLine,
+                 Length                               numberOfCharactersInSecondHalfLine,
                  CharacterDirection                   direction)
 {
   // Handle to the bidirectional info module in text-abstraction.
@@ -159,11 +161,16 @@ void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo
   lineInfoRun.direction                       = direction;
   lineInfoRun.isIdentity                      = true;
 
+  lineInfoRun.characterRunForSecondHalfLine.characterIndex     = startIndexInSecondHalfLine;
+  lineInfoRun.characterRunForSecondHalfLine.numberOfCharacters = numberOfCharactersInSecondHalfLine;
+
   // Allocate space for the conversion maps.
   // The memory is freed after the visual to logical to visual conversion tables are built in the logical model.
   lineInfoRun.visualToLogicalMap = reinterpret_cast<CharacterIndex*>(malloc(numberOfCharacters * sizeof(CharacterIndex)));
 
-  if(nullptr != lineInfoRun.visualToLogicalMap)
+  lineInfoRun.visualToLogicalMapSecondHalf = reinterpret_cast<CharacterIndex*>(malloc(numberOfCharactersInSecondHalfLine * sizeof(CharacterIndex)));
+
+  if(nullptr != lineInfoRun.visualToLogicalMap && nullptr != lineInfoRun.visualToLogicalMapSecondHalf)
   {
     // Reorders the line.
     bidirectionalSupport.Reorder(bidirectionalParagraphInfo.bidirectionalInfoIndex,
@@ -171,6 +178,11 @@ void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo
                                  lineInfoRun.characterRun.numberOfCharacters,
                                  lineInfoRun.visualToLogicalMap);
 
+    bidirectionalSupport.Reorder(bidirectionalParagraphInfo.bidirectionalInfoIndex,
+                                 lineInfoRun.characterRunForSecondHalfLine.characterIndex - bidirectionalParagraphInfo.characterRun.characterIndex,
+                                 lineInfoRun.characterRunForSecondHalfLine.numberOfCharacters,
+                                 lineInfoRun.visualToLogicalMapSecondHalf);
+
     // For those LTR lines inside a bidirectional paragraph.
     // It will save to relayout the line after reordering.
     for(unsigned int i = 0; i < numberOfCharacters; ++i)
@@ -181,6 +193,15 @@ void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo
         break;
       }
     }
+
+    for(unsigned int i = 0; i < numberOfCharactersInSecondHalfLine; ++i)
+    {
+      if(i != *(lineInfoRun.visualToLogicalMapSecondHalf + i))
+      {
+        lineInfoRun.isIdentity = false;
+        break;
+      }
+    }
   }
 
   // Push the run into the vector.
index 46c368e..054f50d 100644 (file)
@@ -43,8 +43,8 @@ namespace Text
  * @param[in] startIndex The character from where the bidirectional info is set.
  * @param[in] numberOfCharacters The number of characters.
  * @param[out] bidirectionalInfo Vector with the bidirectional infor for each paragraph.
- * @param[in] matchSystemLanguageDirection Whether match for system language direction or not.
- * @param[in] layoutDirection The direction of the system language.
+ * @param[in] matchLayoutDirection Whether match for layout direction or not.
+ * @param[in] layoutDirection The direction of the layout.
  */
 void SetBidirectionalInfo(const Vector<Character>&               text,
                           const Vector<ScriptRun>&               scripts,
@@ -52,8 +52,8 @@ void SetBidirectionalInfo(const Vector<Character>&               text,
                           CharacterIndex                         startIndex,
                           Length                                 numberOfCharacters,
                           Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
-                          bool                                   matchSystemLanguageDirection = false,
-                          Dali::LayoutDirection::Type            layoutDirection              = LayoutDirection::LEFT_TO_RIGHT);
+                          bool                                   matchLayoutDirection = false,
+                          Dali::LayoutDirection::Type            layoutDirection      = LayoutDirection::LEFT_TO_RIGHT);
 
 /**
  * @brief Sets the visual to logical map table for a given line.
@@ -63,6 +63,8 @@ void SetBidirectionalInfo(const Vector<Character>&               text,
  * @param[in] bidiLineIndex Index to the line's bidirectional info.
  * @param[in] startIndex The character from where the bidirectional info is set.
  * @param[in] numberOfCharacters The number of characters.
+ * @param[in] startIndexInSecondHalfLine The character from where the bidirectional info is set for the second half of line..
+ * @param[in] numberOfCharactersInSecondHalfLine The number of characters for the second half of line..
  * @param[in] direction The direction of the line.
  */
 void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo,
@@ -70,6 +72,8 @@ void ReorderLine(const BidirectionalParagraphInfoRun& bidirectionalParagraphInfo
                  BidirectionalLineRunIndex            bidiLineIndex,
                  CharacterIndex                       startIndex,
                  Length                               numberOfCharacters,
+                 CharacterIndex                       startIndexInSecondHalfLine,
+                 Length                               numberOfCharactersInSecondHalfLine,
                  CharacterDirection                   direction);
 
 /**
diff --git a/dali-toolkit/internal/text/input-filter.cpp b/dali-toolkit/internal/text/input-filter.cpp
new file mode 100644 (file)
index 0000000..eafcfe7
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2021 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/text/hidden-text.h>
+#include <dali-toolkit/internal/text/input-filter.h>
+
+// INTERNAL INCLUDES
+
+using namespace Dali::Toolkit;
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+const char* const PROPERTY_ACCEPTED = "accepted";
+const char* const PROPERTY_REJECTED = "rejected";
+
+InputFilter::InputFilter()
+: mAccepted(""),
+  mRejected("")
+{
+}
+
+void InputFilter::SetProperties(const Property::Map& map)
+{
+  const Property::Map::SizeType count = map.Count();
+
+  for(Property::Map::SizeType position = 0; position < count; ++position)
+  {
+    KeyValuePair     keyValue = map.GetKeyValue(position);
+    Property::Key&   key      = keyValue.first;
+    Property::Value& value    = keyValue.second;
+
+    if(key == Toolkit::InputFilter::Property::ACCEPTED || key == PROPERTY_ACCEPTED)
+    {
+      value.Get(mAccepted);
+    }
+    else if(key == Toolkit::InputFilter::Property::REJECTED || key == PROPERTY_REJECTED)
+    {
+      value.Get(mRejected);
+    }
+  }
+}
+
+void InputFilter::GetProperties(Property::Map& map)
+{
+  map[Toolkit::InputFilter::Property::ACCEPTED] = mAccepted.c_str();
+  map[Toolkit::InputFilter::Property::REJECTED] = mRejected.c_str();
+}
+
+bool InputFilter::Contains(Toolkit::InputFilter::Property::Type type, std::string source)
+{
+  bool       match = false;
+  std::regex pattern;
+
+  if(type == Toolkit::InputFilter::Property::ACCEPTED)
+  {
+    if(mAccepted.empty())
+    {
+      return true;
+    }
+    pattern = mAccepted;
+  }
+  else if(type == Toolkit::InputFilter::Property::REJECTED)
+  {
+    if(mRejected.empty())
+    {
+      return false;
+    }
+    pattern = mRejected;
+  }
+
+  match = std::regex_match(source, pattern);
+
+  return match;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/input-filter.h b/dali-toolkit/internal/text/input-filter.h
new file mode 100644 (file)
index 0000000..6de0132
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef DALI_INPUT_FILTER_H
+#define DALI_INPUT_FILTER_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/property-map.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/text-controls/input-filter-properties.h>
+#include <regex>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * Class to handle the input text filtering
+ */
+class InputFilter : public ConnectionTracker
+{
+public:
+  /**
+   * @brief Constructor
+   */
+  InputFilter();
+
+public: // Intended for internal use
+  /**
+   * @brief Used to set options of input filter.
+   * @param[in] map The property map describing the option.
+   */
+  void SetProperties(const Property::Map& map);
+
+  /**
+   * @brief Retrieve property map of input filter options.
+   * @param[out] map The input filter option.
+   */
+  void GetProperties(Property::Map& map);
+
+  /**
+   * @brief Check if the source is contained in regex.
+   * @param[in] type ACCEPTED or REJECTED
+   * @param[in] source The original text.
+   * @return @e true if the source is contained in regex, otherwise returns @e false.
+   */
+  bool Contains(Toolkit::InputFilter::Property::Type type, std::string source);
+
+private:
+  std::string mAccepted;
+  std::string mRejected;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_INPUT_FILTER_H
index 25f83d1..077b598 100644 (file)
@@ -75,7 +75,13 @@ struct LineLayout
     previousAdvance{0.f},
     length{0.f},
     whiteSpaceLengthEndOfLine{0.f},
-    direction{LTR}
+    direction{LTR},
+    isSplitToTwoHalves(false),
+    glyphIndexInSecondHalfLine{0u},
+    characterIndexInSecondHalfLine{0u},
+    numberOfGlyphsInSecondHalfLine{0u},
+    numberOfCharactersInSecondHalfLine{0u}
+
   {
   }
 
@@ -85,13 +91,18 @@ struct LineLayout
 
   void Clear()
   {
-    glyphIndex         = 0u;
-    characterIndex     = 0u;
-    numberOfGlyphs     = 0u;
-    numberOfCharacters = 0u;
-    ascender           = -MAX_FLOAT;
-    descender          = MAX_FLOAT;
-    direction          = LTR;
+    glyphIndex                         = 0u;
+    characterIndex                     = 0u;
+    numberOfGlyphs                     = 0u;
+    numberOfCharacters                 = 0u;
+    ascender                           = -MAX_FLOAT;
+    descender                          = MAX_FLOAT;
+    direction                          = LTR;
+    isSplitToTwoHalves                 = false;
+    glyphIndexInSecondHalfLine         = 0u;
+    characterIndexInSecondHalfLine     = 0u;
+    numberOfGlyphsInSecondHalfLine     = 0u;
+    numberOfCharactersInSecondHalfLine = 0u;
   }
 
   GlyphIndex         glyphIndex;                ///< Index of the first glyph to be laid-out.
@@ -106,6 +117,12 @@ struct LineLayout
   float              length;                    ///< The current length of the line.
   float              whiteSpaceLengthEndOfLine; ///< The length of the white spaces at the end of the line.
   CharacterDirection direction;
+
+  bool           isSplitToTwoHalves;                 ///< Whether the second half is defined.
+  GlyphIndex     glyphIndexInSecondHalfLine;         ///< Index of the first glyph to be laid-out for the second half of line.
+  CharacterIndex characterIndexInSecondHalfLine;     ///< Index of the first character to be laid-out for the second half of line.
+  Length         numberOfGlyphsInSecondHalfLine;     ///< The number of glyph which fit in one line for the second half of line.
+  Length         numberOfCharactersInSecondHalfLine; ///< The number of characters which fit in one line for the second half of line.
 };
 
 struct LayoutBidiParameters
@@ -175,9 +192,11 @@ struct Engine::Impl
    *
    * @param[in,out] lineLayout The line layout.
    * @param[in] tmpLineLayout A temporary line layout.
+   * @param[in] isShifted Whether to shift first glyph and character indices.
    */
   void MergeLineLayout(LineLayout&       lineLayout,
-                       const LineLayout& tmpLineLayout)
+                       const LineLayout& tmpLineLayout,
+                       bool              isShifted)
   {
     lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
     lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
@@ -193,6 +212,19 @@ struct Engine::Impl
 
     // Sets the minimum descender.
     lineLayout.descender = std::min(lineLayout.descender, tmpLineLayout.descender);
+
+    // To handle cases START in ellipsis position when want to shift first glyph to let width fit.
+    if(isShifted)
+    {
+      lineLayout.glyphIndex     = tmpLineLayout.glyphIndex;
+      lineLayout.characterIndex = tmpLineLayout.characterIndex;
+    }
+
+    lineLayout.isSplitToTwoHalves                 = tmpLineLayout.isSplitToTwoHalves;
+    lineLayout.glyphIndexInSecondHalfLine         = tmpLineLayout.glyphIndexInSecondHalfLine;
+    lineLayout.characterIndexInSecondHalfLine     = tmpLineLayout.characterIndexInSecondHalfLine;
+    lineLayout.numberOfGlyphsInSecondHalfLine     = tmpLineLayout.numberOfGlyphsInSecondHalfLine;
+    lineLayout.numberOfCharactersInSecondHalfLine = tmpLineLayout.numberOfCharactersInSecondHalfLine;
   }
 
   void LayoutRightToLeft(const Parameters&               parameters,
@@ -200,6 +232,11 @@ struct Engine::Impl
                          float&                          length,
                          float&                          whiteSpaceLengthEndOfLine)
   {
+    // Travers characters in line then draw it form right to left by mapping index using visualToLogicalMap.
+    // When the line is spllited by MIDDLE ellipsis then travers the second half of line "characterRunForSecondHalfLine"
+    // then the first half of line "characterRun",
+    // Otherwise travers whole characters in"characterRun".
+
     const Character* const  textBuffer               = parameters.textModel->mLogicalModel->mText.Begin();
     const Length* const     charactersPerGlyphBuffer = parameters.textModel->mVisualModel->mCharactersPerGlyph.Begin();
     const GlyphInfo* const  glyphsBuffer             = parameters.textModel->mVisualModel->mGlyphs.Begin();
@@ -209,21 +246,62 @@ struct Engine::Impl
     const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
 
     CharacterIndex characterLogicalIndex = 0u;
-    CharacterIndex characterVisualIndex  = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
+    CharacterIndex characterVisualIndex  = 0u;
+
+    // If there are characters in the second half of Line then the first visual index mapped from visualToLogicalMapSecondHalf
+    // Otherwise maps the first visual index from visualToLogicalMap.
+    // This is to initialize the first visual index.
+    if(bidirectionalLineInfo.characterRunForSecondHalfLine.numberOfCharacters > 0u)
+    {
+      characterVisualIndex = bidirectionalLineInfo.characterRunForSecondHalfLine.characterIndex + *(bidirectionalLineInfo.visualToLogicalMapSecondHalf + characterLogicalIndex);
+    }
+    else
+    {
+      characterVisualIndex = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
+    }
+
+    bool extendedToSecondHalf = false; // Whether the logical index is extended to second half
 
     if(RTL == bidirectionalLineInfo.direction)
     {
-      while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+      // If there are characters in the second half of Line.
+      if(bidirectionalLineInfo.characterRunForSecondHalfLine.numberOfCharacters > 0u)
       {
-        const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
+        // Keep adding the WhiteSpaces to the whiteSpaceLengthEndOfLine
+        while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+        {
+          const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
 
-        whiteSpaceLengthEndOfLine += glyphInfo.advance;
+          whiteSpaceLengthEndOfLine += glyphInfo.advance;
 
-        ++characterLogicalIndex;
-        characterVisualIndex = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
+          ++characterLogicalIndex;
+          characterVisualIndex = bidirectionalLineInfo.characterRunForSecondHalfLine.characterIndex + *(bidirectionalLineInfo.visualToLogicalMapSecondHalf + characterLogicalIndex);
+        }
+      }
+
+      // If all characters in the second half of Line are WhiteSpaces.
+      // then continue adding the WhiteSpaces from the first hel of Line.
+      // Also this is valid when the line was not splitted.
+      if(characterLogicalIndex == bidirectionalLineInfo.characterRunForSecondHalfLine.numberOfCharacters)
+      {
+        extendedToSecondHalf  = true; // Whether the logical index is extended to second half
+        characterLogicalIndex = 0u;
+        characterVisualIndex  = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
+
+        // Keep adding the WhiteSpaces to the whiteSpaceLengthEndOfLine
+        while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+        {
+          const GlyphInfo& glyphInfo = *(glyphsBuffer + *(charactersToGlyphsBuffer + characterVisualIndex));
+
+          whiteSpaceLengthEndOfLine += glyphInfo.advance;
+
+          ++characterLogicalIndex;
+          characterVisualIndex = bidirectionalLineInfo.characterRun.characterIndex + *(bidirectionalLineInfo.visualToLogicalMap + characterLogicalIndex);
+        }
       }
     }
 
+    // Here's the first index of character is not WhiteSpace
     const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
 
     // Check whether the first glyph comes from a character that is shaped in multiple glyphs.
@@ -241,6 +319,70 @@ struct Engine::Impl
     float penX = -glyphMetrics.xBearing + mCursorWidth + outlineWidth;
 
     // Traverses the characters of the right to left paragraph.
+    // Continue in the second half of line, because in it the first index of character that is not WhiteSpace.
+    if(!extendedToSecondHalf &&
+       bidirectionalLineInfo.characterRunForSecondHalfLine.numberOfCharacters > 0u)
+    {
+      for(; characterLogicalIndex < bidirectionalLineInfo.characterRunForSecondHalfLine.numberOfCharacters;)
+      {
+        // Convert the character in the logical order into the character in the visual order.
+        const CharacterIndex characterVisualIndex = bidirectionalLineInfo.characterRunForSecondHalfLine.characterIndex + *(bidirectionalLineInfo.visualToLogicalMapSecondHalf + characterLogicalIndex);
+        const bool           isWhiteSpace         = TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex));
+
+        const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
+
+        // Check whether this glyph comes from a character that is shaped in multiple glyphs.
+        const Length numberOfGLyphsInGroup = GetNumberOfGlyphsOfGroup(glyphIndex,
+                                                                      lastGlyphOfParagraphPlusOne,
+                                                                      charactersPerGlyphBuffer);
+
+        characterLogicalIndex += *(charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u);
+
+        GlyphMetrics glyphMetrics;
+        GetGlyphsMetrics(glyphIndex,
+                         numberOfGLyphsInGroup,
+                         glyphMetrics,
+                         glyphsBuffer,
+                         mMetrics);
+
+        if(isWhiteSpace)
+        {
+          // If glyph is WhiteSpace then:
+          // For RTL it is whitespace but not at endOfLine. Use "advance" to accumulate length and shift penX.
+          // the endOfLine in RTL was the headOfLine for layouting.
+          // But for LTR added it to the endOfLine and use "advance" to accumulate length.
+          if(RTL == bidirectionalLineInfo.direction)
+          {
+            length += glyphMetrics.advance;
+          }
+          else
+          {
+            whiteSpaceLengthEndOfLine += glyphMetrics.advance;
+          }
+          penX += glyphMetrics.advance;
+        }
+        else
+        {
+          // If glyph is not whiteSpace then:
+          // Reset endOfLine for LTR because there is a non-whiteSpace so the tail of line is not whiteSpaces
+          // Use "advance" and "interGlyphExtraAdvance" to shift penX.
+          // Set length to the maximum possible length, of the current glyph "xBearing" and "width" are shifted penX to length greater than current lenght.
+          // Otherwise the current length is maximum.
+          if(LTR == bidirectionalLineInfo.direction)
+          {
+            whiteSpaceLengthEndOfLine = 0.f;
+          }
+          length = std::max(length, penX + glyphMetrics.xBearing + glyphMetrics.width);
+          penX += (glyphMetrics.advance + parameters.interGlyphExtraAdvance);
+        }
+      }
+    }
+
+    // Continue traversing in the first half of line or in the whole line.
+    // If the second half of line was extended then continue from logical index in the first half of line
+    // Also this is valid when the line was not splitted and there were WhiteSpace.
+    // Otherwise start from first logical index in line.
+    characterLogicalIndex = extendedToSecondHalf ? characterLogicalIndex : 0u;
     for(; characterLogicalIndex < bidirectionalLineInfo.characterRun.numberOfCharacters;)
     {
       // Convert the character in the logical order into the character in the visual order.
@@ -265,6 +407,10 @@ struct Engine::Impl
 
       if(isWhiteSpace)
       {
+        // If glyph is WhiteSpace then:
+        // For RTL it is whitespace but not at endOfLine. Use "advance" to accumulate length and shift penX.
+        // the endOfLine in RTL was the headOfLine for layouting.
+        // But for LTR added it to the endOfLine and use "advance" to accumulate length.
         if(RTL == bidirectionalLineInfo.direction)
         {
           length += glyphMetrics.advance;
@@ -277,6 +423,11 @@ struct Engine::Impl
       }
       else
       {
+        // If glyph is not whiteSpace then:
+        // Reset endOfLine for LTR because there is a non-whiteSpace so the tail of line is not whiteSpaces
+        // Use "advance" and "interGlyphExtraAdvance" to shift penX.
+        // Set length to the maximum possible length, of the current glyph "xBearing" and "width" are shifted penX to length greater than current lenght.
+        // Otherwise the current length is maximum.
         if(LTR == bidirectionalLineInfo.direction)
         {
           whiteSpaceLengthEndOfLine = 0.f;
@@ -291,7 +442,8 @@ struct Engine::Impl
                          LayoutBidiParameters& bidiParameters,
                          const LineLayout&     currentLineLayout,
                          LineLayout&           lineLayout,
-                         bool                  breakInCharacters)
+                         bool                  breakInCharacters,
+                         bool                  enforceEllipsisInSingleLine)
   {
     const Length* const charactersPerGlyphBuffer = parameters.textModel->mVisualModel->mCharactersPerGlyph.Begin();
 
@@ -312,6 +464,8 @@ struct Engine::Impl
                   bidiParameters.bidiLineIndex,
                   lineLayout.characterIndex,
                   lineLayout.numberOfCharacters,
+                  lineLayout.characterIndexInSecondHalfLine,
+                  lineLayout.numberOfCharactersInSecondHalfLine,
                   bidiParameters.paragraphDirection);
 
       // Recalculate the length of the line and update the layout.
@@ -329,7 +483,7 @@ struct Engine::Impl
         lineLayout.whiteSpaceLengthEndOfLine = whiteSpaceLengthEndOfLine;
         if(!Equals(length, lineLayout.length))
         {
-          const bool isMultiline = mLayout == MULTI_LINE_BOX;
+          const bool isMultiline = (!enforceEllipsisInSingleLine) && (mLayout == MULTI_LINE_BOX);
 
           if(isMultiline && (length > parameters.boundingBox.width))
           {
@@ -403,6 +557,8 @@ struct Engine::Impl
                 bidiParameters.bidiLineIndex,
                 lineLayout.characterIndex,
                 lineLayout.numberOfCharacters,
+                lineLayout.characterIndexInSecondHalfLine,
+                lineLayout.numberOfCharactersInSecondHalfLine,
                 bidiParameters.paragraphDirection);
 
     const BidirectionalLineInfoRun& bidirectionalLineInfo = *(bidirectionalLinesInfo.Begin() + bidiParameters.bidiLineIndex);
@@ -430,11 +586,15 @@ struct Engine::Impl
    * @param[] bidiParameters Bidirectional info for the current line.
    * @param[out] lineLayout The line layout.
    * @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
+   * @param[in] ellipsisPosition Where is the location the text elide
    */
-  void GetLineLayoutForBox(const Parameters&     parameters,
-                           LayoutBidiParameters& bidiParameters,
-                           LineLayout&           lineLayout,
-                           bool                  completelyFill)
+  void GetLineLayoutForBox(const Parameters&                 parameters,
+                           LayoutBidiParameters&             bidiParameters,
+                           LineLayout&                       lineLayout,
+                           bool                              completelyFill,
+                           DevelText::EllipsisPosition::Type ellipsisPosition,
+                           bool                              enforceEllipsisInSingleLine,
+                           bool                              elideTextEnabled)
   {
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n");
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  initial glyph index : %d\n", lineLayout.glyphIndex);
@@ -448,13 +608,15 @@ struct Engine::Impl
     const float  outlineWidth        = static_cast<float>(parameters.textModel->GetOutlineWidth());
     const Length totalNumberOfGlyphs = parameters.textModel->mVisualModel->mGlyphs.Count();
 
-    const bool isMultiline   = mLayout == MULTI_LINE_BOX;
+    const bool isMultiline   = !enforceEllipsisInSingleLine && (mLayout == MULTI_LINE_BOX);
     const bool isWordLaidOut = parameters.textModel->mLineWrapMode == Text::LineWrap::WORD ||
                                (parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
                                (parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED);
     const bool isHyphenMode = parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION;
     const bool isMixedMode  = parameters.textModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED;
 
+    const bool isSplitToTwoHalves = elideTextEnabled && !isMultiline && ellipsisPosition == DevelText::EllipsisPosition::MIDDLE;
+
     // The last glyph to be laid-out.
     const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
 
@@ -467,6 +629,11 @@ struct Engine::Impl
                                                                   lastGlyphOfParagraphPlusOne,
                                                                   charactersPerGlyphBuffer);
 
+    float targetWidth    = parameters.boundingBox.width;
+    float widthFirstHalf = ((ellipsisPosition != DevelText::EllipsisPosition::MIDDLE) ? targetWidth : targetWidth - std::floor(targetWidth / 2));
+
+    bool isSecondHalf = false;
+
     GlyphMetrics glyphMetrics;
     GetGlyphsMetrics(lineLayout.glyphIndex,
                      numberOfGLyphsInGroup,
@@ -534,11 +701,22 @@ struct Engine::Impl
       // Get the line break info for the current character.
       const LineBreakInfo lineBreakInfo = hasCharacters ? *(lineBreakInfoBuffer + characterLastIndex) : TextAbstraction::LINE_NO_BREAK;
 
-      // Increase the number of characters.
-      tmpLineLayout.numberOfCharacters += charactersPerGlyph;
+      if(isSecondHalf)
+      {
+        // Increase the number of characters.
+        tmpLineLayout.numberOfCharactersInSecondHalfLine += charactersPerGlyph;
+
+        // Increase the number of glyphs.
+        tmpLineLayout.numberOfGlyphsInSecondHalfLine += numberOfGLyphsInGroup;
+      }
+      else
+      {
+        // Increase the number of characters.
+        tmpLineLayout.numberOfCharacters += charactersPerGlyph;
 
-      // Increase the number of glyphs.
-      tmpLineLayout.numberOfGlyphs += numberOfGLyphsInGroup;
+        // Increase the number of glyphs.
+        tmpLineLayout.numberOfGlyphs += numberOfGLyphsInGroup;
+      }
 
       // Check whether is a white space.
       const Character character    = *(textBuffer + characterFirstIndex);
@@ -568,9 +746,94 @@ struct Engine::Impl
         tmpLineLayout.whiteSpaceLengthEndOfLine = 0.f;
       }
 
+      if(isSplitToTwoHalves && (!isSecondHalf) &&
+         (tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > widthFirstHalf))
+      {
+        tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
+        tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
+
+        tmpLineLayout.numberOfCharactersInSecondHalfLine += charactersPerGlyph;
+        tmpLineLayout.numberOfGlyphsInSecondHalfLine += numberOfGLyphsInGroup;
+
+        tmpLineLayout.glyphIndexInSecondHalfLine     = tmpLineLayout.glyphIndex + tmpLineLayout.numberOfGlyphs;
+        tmpLineLayout.characterIndexInSecondHalfLine = tmpLineLayout.characterIndex + tmpLineLayout.numberOfCharacters;
+
+        tmpLineLayout.isSplitToTwoHalves = isSecondHalf = true;
+      }
       // Check if the accumulated length fits in the width of the box.
-      if((completelyFill || isMultiline) && !isWhiteSpace &&
-         (tmpLineLayout.length > parameters.boundingBox.width))
+      if((ellipsisPosition == DevelText::EllipsisPosition::START ||
+          (ellipsisPosition == DevelText::EllipsisPosition::MIDDLE && isSecondHalf)) &&
+         completelyFill && !isMultiline &&
+         (tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth))
+      {
+        GlyphIndex glyphIndexToRemove = isSecondHalf ? tmpLineLayout.glyphIndexInSecondHalfLine : tmpLineLayout.glyphIndex;
+
+        while(tmpLineLayout.length + tmpLineLayout.whiteSpaceLengthEndOfLine > targetWidth && glyphIndexToRemove < glyphIndex)
+        {
+          GlyphMetrics glyphMetrics;
+          GetGlyphsMetrics(glyphIndexToRemove,
+                           numberOfGLyphsInGroup,
+                           glyphMetrics,
+                           glyphsBuffer,
+                           mMetrics);
+
+          const Length numberOfGLyphsInGroup = GetNumberOfGlyphsOfGroup(glyphIndexToRemove,
+                                                                        lastGlyphOfParagraphPlusOne,
+                                                                        charactersPerGlyphBuffer);
+
+          const Length         charactersPerGlyph  = *(charactersPerGlyphBuffer + glyphIndexToRemove + numberOfGLyphsInGroup - 1u);
+          const bool           hasCharacters       = charactersPerGlyph > 0u;
+          const CharacterIndex characterFirstIndex = *(glyphsToCharactersBuffer + glyphIndexToRemove);
+          const CharacterIndex characterLastIndex  = characterFirstIndex + (hasCharacters ? charactersPerGlyph - 1u : 0u);
+
+          // Check whether is a white space.
+          const Character character                = *(textBuffer + characterFirstIndex);
+          const bool      isRemovedGlyphWhiteSpace = TextAbstraction::IsWhiteSpace(character);
+
+          if(isSecondHalf)
+          {
+            // Decrease the number of characters for SecondHalf.
+            tmpLineLayout.numberOfCharactersInSecondHalfLine -= charactersPerGlyph;
+
+            // Decrease the number of glyphs for SecondHalf.
+            tmpLineLayout.numberOfGlyphsInSecondHalfLine -= numberOfGLyphsInGroup;
+          }
+          else
+          {
+            // Decrease the number of characters.
+            tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
+
+            // Decrease the number of glyphs.
+            tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
+          }
+
+          if(isRemovedGlyphWhiteSpace)
+          {
+            tmpLineLayout.penX -= glyphMetrics.advance;
+            tmpLineLayout.length -= glyphMetrics.advance;
+          }
+          else
+          {
+            tmpLineLayout.penX -= (glyphMetrics.advance + parameters.interGlyphExtraAdvance);
+            tmpLineLayout.length -= (std::min(glyphMetrics.advance + parameters.interGlyphExtraAdvance, glyphMetrics.xBearing + glyphMetrics.width));
+          }
+
+          if(isSecondHalf)
+          {
+            tmpLineLayout.glyphIndexInSecondHalfLine += numberOfGLyphsInGroup;
+            tmpLineLayout.characterIndexInSecondHalfLine = characterLastIndex + 1u;
+            glyphIndexToRemove                           = tmpLineLayout.glyphIndexInSecondHalfLine;
+          }
+          else
+          {
+            tmpLineLayout.glyphIndex += numberOfGLyphsInGroup;
+            tmpLineLayout.characterIndex = characterLastIndex + 1u;
+            glyphIndexToRemove           = tmpLineLayout.glyphIndex;
+          }
+        }
+      }
+      else if((completelyFill || isMultiline) &&
+              (tmpLineLayout.length > targetWidth))
       {
         // Current word does not fit in the box's width.
         if(((oneHyphenLaidOut && isHyphenMode) ||
@@ -586,10 +849,18 @@ struct Engine::Impl
           DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  Break the word by character\n");
 
           // The word doesn't fit in the control's width. It needs to be split by character.
-          if(tmpLineLayout.numberOfGlyphs > 0u)
+          if(tmpLineLayout.numberOfGlyphs + tmpLineLayout.numberOfGlyphsInSecondHalfLine > 0u)
           {
-            tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
-            tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
+            if(isSecondHalf)
+            {
+              tmpLineLayout.numberOfCharactersInSecondHalfLine -= charactersPerGlyph;
+              tmpLineLayout.numberOfGlyphsInSecondHalfLine -= numberOfGLyphsInGroup;
+            }
+            else
+            {
+              tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
+              tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
+            }
 
             tmpLineLayout.penX                      = previousTmpPenX;
             tmpLineLayout.previousAdvance           = previousTmpAdvance;
@@ -597,8 +868,17 @@ struct Engine::Impl
             tmpLineLayout.whiteSpaceLengthEndOfLine = previousTmpWhiteSpaceLengthEndOfLine;
           }
 
-          // Add part of the word to the line layout.
-          MergeLineLayout(lineLayout, tmpLineLayout);
+          if(ellipsisPosition == DevelText::EllipsisPosition::START && !isMultiline)
+          {
+            // Add part of the word to the line layout and shift the first glyph.
+            MergeLineLayout(lineLayout, tmpLineLayout, true);
+          }
+          else if(ellipsisPosition != DevelText::EllipsisPosition::START ||
+                  (ellipsisPosition == DevelText::EllipsisPosition::START && (!completelyFill)))
+          {
+            // Add part of the word to the line layout.
+            MergeLineLayout(lineLayout, tmpLineLayout, false);
+          }
         }
         else
         {
@@ -614,7 +894,8 @@ struct Engine::Impl
                             bidiParameters,
                             lineLayout,
                             lineLayout,
-                            true);
+                            true,
+                            enforceEllipsisInSingleLine);
         }
 
         return;
@@ -625,8 +906,17 @@ struct Engine::Impl
       {
         LineLayout currentLineLayout = lineLayout;
         oneHyphenLaidOut             = false;
-        // Must break the line. Update the line layout and return.
-        MergeLineLayout(lineLayout, tmpLineLayout);
+
+        if(ellipsisPosition == DevelText::EllipsisPosition::START && !isMultiline)
+        {
+          // Must break the line. Update the line layout, shift the first glyph and return.
+          MergeLineLayout(lineLayout, tmpLineLayout, true);
+        }
+        else
+        {
+          // Must break the line. Update the line layout and return.
+          MergeLineLayout(lineLayout, tmpLineLayout, false);
+        }
 
         // Reorder the RTL line.
         if(bidiParameters.isBidirectional)
@@ -635,7 +925,8 @@ struct Engine::Impl
                             bidiParameters,
                             currentLineLayout,
                             lineLayout,
-                            false);
+                            false,
+                            enforceEllipsisInSingleLine);
         }
 
         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  Must break\n");
@@ -653,7 +944,7 @@ struct Engine::Impl
 
         // Current glyph is the last one of the current word.
         // Add the temporal layout to the current one.
-        MergeLineLayout(lineLayout, tmpLineLayout);
+        MergeLineLayout(lineLayout, tmpLineLayout, false);
 
         tmpLineLayout.Clear();
       }
@@ -670,7 +961,7 @@ struct Engine::Impl
 
         mMetrics->GetGlyphMetrics(&hyphenGlyph, 1);
 
-        if((tmpLineLayout.length + hyphenGlyph.width) <= parameters.boundingBox.width)
+        if((tmpLineLayout.length + hyphenGlyph.width) <= targetWidth)
         {
           hyphenIndex      = glyphIndex;
           oneHyphenLaidOut = true;
@@ -679,7 +970,7 @@ struct Engine::Impl
 
           // Current glyph is the last one of the current word hyphen.
           // Add the temporal layout to the current one.
-          MergeLineLayout(lineLayout, tmpLineLayout);
+          MergeLineLayout(lineLayout, tmpLineLayout, false);
 
           tmpLineLayout.Clear();
         }
@@ -691,31 +982,54 @@ struct Engine::Impl
     DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n");
   }
 
-  void SetGlyphPositions(const GlyphInfo* const glyphsBuffer,
-                         Length                 numberOfGlyphs,
-                         float                  outlineWidth,
-                         float                  interGlyphExtraAdvance,
-                         Vector2*               glyphPositionsBuffer)
+  void SetGlyphPositions(const Parameters& layoutParameters,
+                         Vector2*          glyphPositionsBuffer,
+                         const LineLayout& layout)
   {
     // Traverse the glyphs and set the positions.
 
+    const GlyphInfo* const glyphsBuffer           = layoutParameters.textModel->mVisualModel->mGlyphs.Begin();
+    const float            outlineWidth           = static_cast<float>(layoutParameters.textModel->GetOutlineWidth());
+    const Length           numberOfGlyphs         = layout.numberOfGlyphs;
+    const float            interGlyphExtraAdvance = layoutParameters.interGlyphExtraAdvance;
+
+    const GlyphIndex startIndexForGlyph          = layout.glyphIndex;
+    const GlyphIndex startIndexForGlyphPositions = startIndexForGlyph - layoutParameters.startGlyphIndex;
+
     // 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.
-
-    const GlyphInfo& glyph = *glyphsBuffer;
-    float            penX  = -glyph.xBearing + mCursorWidth + outlineWidth;
+    const GlyphInfo& glyph = *(glyphsBuffer + startIndexForGlyph);
+    float            penX  = -glyph.xBearing + mCursorWidth + outlineWidth; //
 
     for(GlyphIndex i = 0u; i < numberOfGlyphs; ++i)
     {
-      const GlyphInfo& glyph    = *(glyphsBuffer + i);
-      Vector2&         position = *(glyphPositionsBuffer + i);
+      const GlyphInfo& glyph    = *(glyphsBuffer + startIndexForGlyph + i);
+      Vector2&         position = *(glyphPositionsBuffer + startIndexForGlyphPositions + i);
 
       position.x = penX + glyph.xBearing;
       position.y = -glyph.yBearing;
 
       penX += (glyph.advance + interGlyphExtraAdvance);
     }
+
+    if(layout.isSplitToTwoHalves)
+    {
+      const GlyphIndex startIndexForGlyphInSecondHalf         = layout.glyphIndexInSecondHalfLine;
+      const Length     numberOfGlyphsInSecondHalfLine         = layout.numberOfGlyphsInSecondHalfLine;
+      const GlyphIndex startIndexForGlyphPositionsnSecondHalf = layout.glyphIndexInSecondHalfLine - layoutParameters.startGlyphIndex;
+
+      for(GlyphIndex i = 0u; i < numberOfGlyphsInSecondHalfLine; ++i)
+      {
+        const GlyphInfo& glyph    = *(glyphsBuffer + startIndexForGlyphInSecondHalf + i);
+        Vector2&         position = *(glyphPositionsBuffer + startIndexForGlyphPositionsnSecondHalf + i);
+
+        position.x = penX + glyph.xBearing;
+        position.y = -glyph.yBearing;
+
+        penX += (glyph.advance + interGlyphExtraAdvance);
+      }
+    }
   }
 
   void SetGlyphPositions(const Parameters&     layoutParameters,
@@ -730,22 +1044,49 @@ struct Engine::Impl
     const Length* const             glyphsPerCharacterBuffer = layoutParameters.textModel->mVisualModel->mGlyphsPerCharacter.Begin();
 
     CharacterIndex characterLogicalIndex = 0u;
-    CharacterIndex characterVisualIndex  = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
+    CharacterIndex characterVisualIndex  = bidiLine.characterRunForSecondHalfLine.characterIndex + *(bidiLine.visualToLogicalMapSecondHalf + characterLogicalIndex);
+    bool           extendedToSecondHalf  = false; // Whether the logical index is extended to second half
 
     float penX = 0.f;
-    while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+
+    if(layout.isSplitToTwoHalves)
     {
-      const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
-      const GlyphInfo& glyph      = *(glyphsBuffer + glyphIndex);
+      while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+      {
+        const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
+        const GlyphInfo& glyph      = *(glyphsBuffer + glyphIndex);
 
-      Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
-      position.x        = penX;
-      position.y        = -glyph.yBearing;
+        Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
+        position.x        = penX;
+        position.y        = -glyph.yBearing;
 
-      penX += glyph.advance;
+        penX += glyph.advance;
 
-      ++characterLogicalIndex;
-      characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
+        ++characterLogicalIndex;
+        characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
+      }
+    }
+
+    if(characterLogicalIndex == bidiLine.characterRunForSecondHalfLine.numberOfCharacters)
+    {
+      extendedToSecondHalf  = true;
+      characterLogicalIndex = 0u;
+      characterVisualIndex  = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
+
+      while(TextAbstraction::IsWhiteSpace(*(textBuffer + characterVisualIndex)))
+      {
+        const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
+        const GlyphInfo& glyph      = *(glyphsBuffer + glyphIndex);
+
+        Vector2& position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
+        position.x        = penX;
+        position.y        = -glyph.yBearing;
+
+        penX += glyph.advance;
+
+        ++characterLogicalIndex;
+        characterVisualIndex = bidiLine.characterRun.characterIndex + *(bidiLine.visualToLogicalMap + characterLogicalIndex);
+      }
     }
 
     const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex);
@@ -754,6 +1095,36 @@ struct Engine::Impl
     penX += -glyph.xBearing;
 
     // Traverses the characters of the right to left paragraph.
+    if(layout.isSplitToTwoHalves && !extendedToSecondHalf)
+    {
+      for(; characterLogicalIndex < bidiLine.characterRunForSecondHalfLine.numberOfCharacters;
+          ++characterLogicalIndex)
+      {
+        // Convert the character in the logical order into the character in the visual order.
+        const CharacterIndex characterVisualIndex = bidiLine.characterRunForSecondHalfLine.characterIndex + *(bidiLine.visualToLogicalMapSecondHalf + characterLogicalIndex);
+
+        // Get the number of glyphs of the character.
+        const Length numberOfGlyphs = *(glyphsPerCharacterBuffer + characterVisualIndex);
+
+        for(GlyphIndex index = 0u; index < numberOfGlyphs; ++index)
+        {
+          // Convert the character in the visual order into the glyph in the visual order.
+          const GlyphIndex glyphIndex = *(charactersToGlyphsBuffer + characterVisualIndex) + index;
+
+          DALI_ASSERT_DEBUG(glyphIndex < layoutParameters.textModel->mVisualModel->mGlyphs.Count());
+
+          const GlyphInfo& glyph    = *(glyphsBuffer + glyphIndex);
+          Vector2&         position = *(glyphPositionsBuffer + glyphIndex - layoutParameters.startGlyphIndex);
+
+          position.x = penX + glyph.xBearing;
+          position.y = -glyph.yBearing;
+
+          penX += (glyph.advance + layoutParameters.interGlyphExtraAdvance);
+        }
+      }
+    }
+
+    characterLogicalIndex = extendedToSecondHalf ? characterLogicalIndex : 0u;
     for(; characterLogicalIndex < bidiLine.characterRun.numberOfCharacters;
         ++characterLogicalIndex)
     {
@@ -825,22 +1196,25 @@ struct Engine::Impl
    * @param[in] penY The vertical layout position.
    * @param[in] currentParagraphDirection The current paragraph's direction.
    * @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
+   * @param[in] ellipsisPosition Where is the location the text elide
    *
    * return Whether the line is ellipsized.
    */
-  bool EllipsisLine(const Parameters&     layoutParameters,
-                    LayoutBidiParameters& layoutBidiParameters,
-                    const LineLayout&     layout,
-                    Size&                 layoutSize,
-                    LineRun*              linesBuffer,
-                    Vector2*              glyphPositionsBuffer,
-                    Length&               numberOfLines,
-                    float                 penY,
-                    bool&                 isAutoScrollEnabled)
+  bool EllipsisLine(const Parameters&                 layoutParameters,
+                    LayoutBidiParameters&             layoutBidiParameters,
+                    const LineLayout&                 layout,
+                    Size&                             layoutSize,
+                    LineRun*                          linesBuffer,
+                    Vector2*                          glyphPositionsBuffer,
+                    Length&                           numberOfLines,
+                    float                             penY,
+                    bool&                             isAutoScrollEnabled,
+                    DevelText::EllipsisPosition::Type ellipsisPosition,
+                    bool                              enforceEllipsisInSingleLine)
   {
-    const bool ellipsis = isAutoScrollEnabled ? (penY - layout.descender > layoutParameters.boundingBox.height) : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width)));
-
-    if(ellipsis)
+    const bool ellipsis    = enforceEllipsisInSingleLine || (isAutoScrollEnabled ? (penY - layout.descender > layoutParameters.boundingBox.height) : ((penY - layout.descender > layoutParameters.boundingBox.height) || ((mLayout == SINGLE_LINE_BOX) && (layout.length > layoutParameters.boundingBox.width))));
+    const bool isMultiline = !enforceEllipsisInSingleLine && (mLayout == MULTI_LINE_BOX);
+    if(ellipsis && (ellipsisPosition == DevelText::EllipsisPosition::END || !isMultiline))
     {
       isAutoScrollEnabled = false;
       // Do not layout more lines if ellipsis is enabled.
@@ -854,7 +1228,6 @@ struct Engine::Impl
       {
         // Get the last line and layout it again with the 'completelyFill' flag to true.
         lineRun = linesBuffer + (numberOfLines - 1u);
-
         penY -= layout.ascender - lineRun->descender + lineRun->lineSpacing;
 
         ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex;
@@ -866,6 +1239,7 @@ struct Engine::Impl
 
         lineRun->glyphRun.glyphIndex = 0u;
         ellipsisLayout.glyphIndex    = 0u;
+        lineRun->isSplitToTwoHalves  = false;
 
         ++numberOfLines;
       }
@@ -873,8 +1247,16 @@ struct Engine::Impl
       GetLineLayoutForBox(layoutParameters,
                           layoutBidiParameters,
                           ellipsisLayout,
+                          true,
+                          ellipsisPosition,
+                          enforceEllipsisInSingleLine,
                           true);
 
+      if(ellipsisPosition == DevelText::EllipsisPosition::START && !isMultiline)
+      {
+        lineRun->glyphRun.glyphIndex = ellipsisLayout.glyphIndex;
+      }
+
       lineRun->glyphRun.numberOfGlyphs         = ellipsisLayout.numberOfGlyphs;
       lineRun->characterRun.characterIndex     = ellipsisLayout.characterIndex;
       lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
@@ -884,15 +1266,18 @@ struct Engine::Impl
       lineRun->descender                       = ellipsisLayout.descender;
       lineRun->ellipsis                        = true;
 
+      lineRun->isSplitToTwoHalves                               = ellipsisLayout.isSplitToTwoHalves;
+      lineRun->glyphRunSecondHalf.glyphIndex                    = ellipsisLayout.glyphIndexInSecondHalfLine;
+      lineRun->glyphRunSecondHalf.numberOfGlyphs                = ellipsisLayout.numberOfGlyphsInSecondHalfLine;
+      lineRun->characterRunForSecondHalfLine.characterIndex     = ellipsisLayout.characterIndexInSecondHalfLine;
+      lineRun->characterRunForSecondHalfLine.numberOfCharacters = ellipsisLayout.numberOfCharactersInSecondHalfLine;
+
       layoutSize.width = layoutParameters.boundingBox.width;
       if(layoutSize.height < Math::MACHINE_EPSILON_1000)
       {
         layoutSize.height += (lineRun->ascender + -lineRun->descender) + lineRun->lineSpacing;
       }
 
-      const GlyphInfo* const glyphsBuffer = layoutParameters.textModel->mVisualModel->mGlyphs.Begin();
-      const float            outlineWidth = static_cast<float>(layoutParameters.textModel->GetOutlineWidth());
-
       const Vector<BidirectionalLineInfoRun>& bidirectionalLinesInfo = layoutParameters.textModel->mLogicalModel->mBidirectionalLineInfo;
 
       if(layoutBidiParameters.isBidirectional)
@@ -904,8 +1289,14 @@ struct Engine::Impl
             ++it, ++layoutBidiParameters.bidiLineIndex)
         {
           const BidirectionalLineInfoRun& run = *it;
-
-          if(ellipsisLayout.characterIndex == run.characterRun.characterIndex)
+          //To handle case when the laid characters exist in next line.
+          //More than one BidirectionalLineInfoRun could start with same character.
+          //When need to check also numberOfCharacters in line.
+          //Note: This fixed the incorrect view of extra spaces of RTL as in Arabic then view ellipsis glyph
+          if(ellipsisLayout.characterIndex == run.characterRun.characterIndex &&
+             ellipsisLayout.numberOfCharacters == run.characterRun.numberOfCharacters &&
+             ellipsisLayout.characterIndexInSecondHalfLine == run.characterRunForSecondHalfLine.characterIndex &&
+             ellipsisLayout.numberOfCharactersInSecondHalfLine == run.characterRunForSecondHalfLine.numberOfCharacters)
           {
             // Found where to insert the bidi line info.
             break;
@@ -928,11 +1319,9 @@ struct Engine::Impl
       else
       {
         lineRun->direction = LTR;
-        SetGlyphPositions(glyphsBuffer + lineRun->glyphRun.glyphIndex,
-                          ellipsisLayout.numberOfGlyphs,
-                          outlineWidth,
-                          layoutParameters.interGlyphExtraAdvance,
-                          glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex);
+        SetGlyphPositions(layoutParameters,
+                          glyphPositionsBuffer,
+                          ellipsisLayout);
       }
     }
 
@@ -968,6 +1357,12 @@ struct Engine::Impl
     lineRun.width                           = layout.length;
     lineRun.extraLength                     = std::ceil(layout.whiteSpaceLengthEndOfLine);
 
+    lineRun.isSplitToTwoHalves                               = layout.isSplitToTwoHalves;
+    lineRun.glyphRunSecondHalf.glyphIndex                    = layout.glyphIndexInSecondHalfLine;
+    lineRun.glyphRunSecondHalf.numberOfGlyphs                = layout.numberOfGlyphsInSecondHalfLine;
+    lineRun.characterRunForSecondHalfLine.characterIndex     = layout.characterIndexInSecondHalfLine;
+    lineRun.characterRunForSecondHalfLine.numberOfCharacters = layout.numberOfCharactersInSecondHalfLine;
+
     // Rounds upward to avoid a non integer size.
     lineRun.width = std::ceil(lineRun.width);
 
@@ -1095,10 +1490,11 @@ struct Engine::Impl
     }
   }
 
-  bool LayoutText(Parameters& layoutParameters,
-                  Size&       layoutSize,
-                  bool        elideTextEnabled,
-                  bool&       isAutoScrollEnabled)
+  bool LayoutText(Parameters&                       layoutParameters,
+                  Size&                             layoutSize,
+                  bool                              elideTextEnabled,
+                  bool&                             isAutoScrollEnabled,
+                  DevelText::EllipsisPosition::Type ellipsisPosition)
   {
     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);
@@ -1106,6 +1502,12 @@ struct Engine::Impl
     layoutParameters.textModel->mVisualModel->mHyphen.glyph.Clear();
     layoutParameters.textModel->mVisualModel->mHyphen.index.Clear();
 
+    //Reset indices of ElidedGlyphs
+    layoutParameters.textModel->mVisualModel->SetStartIndexOfElidedGlyphs(0u);
+    layoutParameters.textModel->mVisualModel->SetEndIndexOfElidedGlyphs(layoutParameters.textModel->GetNumberOfGlyphs() - 1u);
+    layoutParameters.textModel->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
+    layoutParameters.textModel->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
+
     Vector<LineRun>& lines = layoutParameters.textModel->mVisualModel->mLines;
 
     if(0u == layoutParameters.numberOfGlyphs)
@@ -1202,8 +1604,9 @@ struct Engine::Impl
       linesBuffer = lines.Begin();
     }
 
-    float penY = CalculateLineOffset(lines,
+    float penY            = CalculateLineOffset(lines,
                                      layoutParameters.startLineIndex);
+    bool  anyLineIsEliped = false;
     for(GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne;)
     {
       layoutBidiParameters.Clear();
@@ -1272,7 +1675,10 @@ struct Engine::Impl
       GetLineLayoutForBox(layoutParameters,
                           layoutBidiParameters,
                           layout,
-                          false);
+                          false,
+                          ellipsisPosition,
+                          false,
+                          elideTextEnabled);
 
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "           glyph index %d\n", layout.glyphIndex);
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "       character index %d\n", layout.characterIndex);
@@ -1280,7 +1686,7 @@ struct Engine::Impl
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "  number of characters %d\n", layout.numberOfCharacters);
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "                length %f\n", layout.length);
 
-      if(0u == layout.numberOfGlyphs)
+      if(0u == layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine)
       {
         // The width is too small and no characters are laid-out.
         DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--LayoutText width too small!\n\n");
@@ -1313,11 +1719,29 @@ struct Engine::Impl
                                 glyphPositionsBuffer,
                                 numberOfLines,
                                 penY,
-                                isAutoScrollEnabled);
+                                isAutoScrollEnabled,
+                                ellipsisPosition,
+                                false);
       }
 
-      if(ellipsis)
+      if(ellipsis && ((ellipsisPosition == DevelText::EllipsisPosition::END) || (numberOfLines == 1u)))
       {
+        const bool isMultiline = mLayout == MULTI_LINE_BOX;
+        if(isMultiline && ellipsisPosition != DevelText::EllipsisPosition::END)
+        {
+          ellipsis = EllipsisLine(layoutParameters,
+                                  layoutBidiParameters,
+                                  layout,
+                                  layoutSize,
+                                  linesBuffer,
+                                  glyphPositionsBuffer,
+                                  numberOfLines,
+                                  penY,
+                                  isAutoScrollEnabled,
+                                  ellipsisPosition,
+                                  true);
+        }
+
         //clear hyphen from ellipsis line
         const Length* hyphenIndices = layoutParameters.textModel->mVisualModel->mHyphen.index.Begin();
         Length        hyphensCount  = layoutParameters.textModel->mVisualModel->mHyphen.glyph.Size();
@@ -1334,8 +1758,11 @@ struct Engine::Impl
       }
       else
       {
+        //In START location of ellipsis whether to shift lines or not.
+        anyLineIsEliped |= ellipsis;
+
         // Whether the last line has been laid-out.
-        const bool isLastLine = index + layout.numberOfGlyphs == totalNumberOfGlyphs;
+        const bool isLastLine = index + (layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine) == totalNumberOfGlyphs;
 
         if(numberOfLines == linesCapacity)
         {
@@ -1355,7 +1782,7 @@ struct Engine::Impl
                          numberOfLines,
                          isLastLine);
 
-        const GlyphIndex nextIndex = index + layout.numberOfGlyphs;
+        const GlyphIndex nextIndex = index + layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine;
 
         if((nextIndex == totalNumberOfGlyphs) &&
            layoutParameters.isLastNewParagraph &&
@@ -1375,16 +1802,13 @@ struct Engine::Impl
           }
 
           UpdateTextLayout(layoutParameters,
-                           layout.characterIndex + layout.numberOfCharacters,
-                           index + layout.numberOfGlyphs,
+                           layout.characterIndex + (layout.numberOfCharacters + layout.numberOfCharactersInSecondHalfLine),
+                           index + (layout.numberOfGlyphs + layout.numberOfGlyphsInSecondHalfLine),
                            layoutSize,
                            linesBuffer,
                            numberOfLines);
         } // whether to add a last line.
 
-        const GlyphInfo* const glyphsBuffer = layoutParameters.textModel->mVisualModel->mGlyphs.Begin();
-        const float            outlineWidth = static_cast<float>(layoutParameters.textModel->GetOutlineWidth());
-
         const BidirectionalLineInfoRun* const bidirectionalLineInfo = (layoutBidiParameters.isBidirectional && !bidirectionalLinesInfo.Empty()) ? &bidirectionalLinesInfo[layoutBidiParameters.bidiLineIndex] : nullptr;
 
         if((nullptr != bidirectionalLineInfo) &&
@@ -1399,11 +1823,9 @@ struct Engine::Impl
         else
         {
           // Sets the positions of the glyphs.
-          SetGlyphPositions(glyphsBuffer + index,
-                            layout.numberOfGlyphs,
-                            outlineWidth,
-                            layoutParameters.interGlyphExtraAdvance,
-                            glyphPositionsBuffer + index - layoutParameters.startGlyphIndex);
+          SetGlyphPositions(layoutParameters,
+                            glyphPositionsBuffer,
+                            layout);
         }
 
         // Updates the vertical pen's position.
@@ -1421,6 +1843,52 @@ struct Engine::Impl
       } // no ellipsis
     }   // end for() traversing glyphs.
 
+    //Shift lines to up if ellipsis and multilines and set ellipsis of first line to true
+    if(anyLineIsEliped && numberOfLines > 1u)
+    {
+      if(ellipsisPosition == DevelText::EllipsisPosition::START)
+      {
+        Length lineIndex = 0;
+        while(lineIndex < numberOfLines && layoutParameters.boundingBox.height < layoutSize.height)
+        {
+          LineRun& delLine = linesBuffer[lineIndex];
+          delLine.ellipsis = true;
+
+          layoutSize.height -= (delLine.ascender + -delLine.descender) + delLine.lineSpacing;
+          for(Length lineIndex = 0; lineIndex < numberOfLines - 1; lineIndex++)
+          {
+            linesBuffer[lineIndex]          = linesBuffer[lineIndex + 1];
+            linesBuffer[lineIndex].ellipsis = false;
+          }
+          numberOfLines--;
+          lineIndex++;
+        }
+        linesBuffer[0u].ellipsis = true;
+      }
+      else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+      {
+        Length middleLineIndex   = (numberOfLines) / 2u;
+        Length ellipsisLineIndex = 0u;
+        while(1u < numberOfLines && 0u < middleLineIndex && layoutParameters.boundingBox.height < layoutSize.height)
+        {
+          LineRun& delLine = linesBuffer[middleLineIndex];
+          delLine.ellipsis = true;
+
+          layoutSize.height -= (delLine.ascender + -delLine.descender) + delLine.lineSpacing;
+          for(Length lineIndex = middleLineIndex; lineIndex < numberOfLines - 1; lineIndex++)
+          {
+            linesBuffer[lineIndex]          = linesBuffer[lineIndex + 1];
+            linesBuffer[lineIndex].ellipsis = false;
+          }
+          numberOfLines--;
+          ellipsisLineIndex = middleLineIndex > 0u ? middleLineIndex - 1u : 0u;
+          middleLineIndex   = (numberOfLines) / 2u;
+        }
+
+        linesBuffer[ellipsisLineIndex].ellipsis = true;
+      }
+    }
+
     if(updateCurrentBuffer)
     {
       glyphPositions.Insert(glyphPositions.Begin() + layoutParameters.startGlyphIndex,
@@ -1474,7 +1942,7 @@ struct Engine::Impl
              Vector<LineRun>&                lines,
              float&                          alignmentOffset,
              Dali::LayoutDirection::Type     layoutDirection,
-             bool                            matchSystemLanguageDirection)
+             bool                            matchLayoutDirection)
   {
     const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
 
@@ -1510,7 +1978,7 @@ struct Engine::Impl
                                    horizontalAlignment,
                                    line,
                                    layoutDirection,
-                                   matchSystemLanguageDirection);
+                                   matchLayoutDirection);
 
       // Updates the alignment offset.
       alignmentOffset = std::min(alignmentOffset, line.alignmentOffset);
@@ -1521,7 +1989,7 @@ struct Engine::Impl
                                     HorizontalAlignment::Type   horizontalAlignment,
                                     LineRun&                    line,
                                     Dali::LayoutDirection::Type layoutDirection,
-                                    bool                        matchSystemLanguageDirection)
+                                    bool                        matchLayoutDirection)
   {
     line.alignmentOffset = 0.f;
     const bool isLineRTL = RTL == line.direction;
@@ -1532,7 +2000,7 @@ struct Engine::Impl
     float lineLength  = line.width;
 
     // match align for system language direction
-    if(matchSystemLanguageDirection)
+    if(matchLayoutDirection)
     {
       // Swap the alignment type if the line is right to left.
       isLayoutRTL = layoutDirection == LayoutDirection::RIGHT_TO_LEFT;
@@ -1662,15 +2130,17 @@ int Engine::GetCursorWidth() const
   return static_cast<int>(mImpl->mCursorWidth);
 }
 
-bool Engine::LayoutText(Parameters& layoutParameters,
-                        Size&       layoutSize,
-                        bool        elideTextEnabled,
-                        bool&       isAutoScrollEnabled)
+bool Engine::LayoutText(Parameters&                       layoutParameters,
+                        Size&                             layoutSize,
+                        bool                              elideTextEnabled,
+                        bool&                             isAutoScrollEnabled,
+                        DevelText::EllipsisPosition::Type ellipsisPosition)
 {
   return mImpl->LayoutText(layoutParameters,
                            layoutSize,
                            elideTextEnabled,
-                           isAutoScrollEnabled);
+                           isAutoScrollEnabled,
+                           ellipsisPosition);
 }
 
 void Engine::Align(const Size&                     size,
@@ -1680,7 +2150,7 @@ void Engine::Align(const Size&                     size,
                    Vector<LineRun>&                lines,
                    float&                          alignmentOffset,
                    Dali::LayoutDirection::Type     layoutDirection,
-                   bool                            matchSystemLanguageDirection)
+                   bool                            matchLayoutDirection)
 {
   mImpl->Align(size,
                startIndex,
@@ -1689,7 +2159,7 @@ void Engine::Align(const Size&                     size,
                lines,
                alignmentOffset,
                layoutDirection,
-               matchSystemLanguageDirection);
+               matchLayoutDirection);
 }
 
 void Engine::SetDefaultLineSpacing(float lineSpacing)
index 28e987c..e11c549 100644 (file)
@@ -28,6 +28,9 @@
 #include <dali-toolkit/internal/text/metrics.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 
+//DEVEL INCLUDE
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -104,13 +107,15 @@ public:
    * @param[out] layoutSize The size of the text after it has been laid-out.
    * @param[in] elideTextEnabled Whether the text elide is enabled.
    * @param[in,out] isAutoScrollEnabled If the isAutoScrollEnabled is true and the height of the text exceeds the boundaries of the control the text is elided and the isAutoScrollEnabled is set to false to disable the autoscroll
+   * @param[in] ellipsisPosition The location of the text ellipsis
    *
    * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character.
    */
-  bool LayoutText(Parameters& layoutParameters,
-                  Size&       layoutSize,
-                  bool        elideTextEnabled,
-                  bool&       isAutoScrollEnabled);
+  bool LayoutText(Parameters&                       layoutParameters,
+                  Size&                             layoutSize,
+                  bool                              elideTextEnabled,
+                  bool&                             isAutoScrollEnabled,
+                  DevelText::EllipsisPosition::Type ellipsisPosition);
 
   /**
    * @brief Aligns the laid out lines.
@@ -121,8 +126,8 @@ public:
    * @param[in] horizontalAlignment The horizontal alignment.
    * @param[in,out] lines The laid-out lines.
    * @param[out] alignmentOffset The alignment offset.
-   * @param[in] layoutDirection The direction of the system language.
-   * @param[in] matchSystemLanguageDirection Whether match align for system language direction or not.
+   * @param[in] layoutDirection The direction of the layout.
+   * @param[in] matchLayoutDirection Whether match align for layout direction or not.
    */
   void Align(const Size&                     size,
              CharacterIndex                  startIndex,
@@ -131,7 +136,7 @@ public:
              Vector<LineRun>&                lines,
              float&                          alignmentOffset,
              Dali::LayoutDirection::Type     layoutDirection,
-             bool                            matchSystemLanguageDirection);
+             bool                            matchLayoutDirection);
 
   /**
    * @brief Sets the default line spacing.
index f4d13e0..ff826e6 100644 (file)
@@ -33,16 +33,19 @@ namespace Text
  */
 struct LineRun
 {
-  GlyphRun           glyphRun;        ///< The initial glyph index and the number of glyphs of the run.
-  CharacterRun       characterRun;    ///< The initial character index and the number of characters of the run.
-  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.
-  float              lineSpacing;     ///< The line's spacing
-  CharacterDirection direction : 1;   ///< Direction of the first character of the paragraph.
-  bool               ellipsis : 1;    ///< Wheter ellipsis is added to the line.
+  GlyphRun           glyphRun;                      ///< The initial glyph index and the number of glyphs of the run.
+  CharacterRun       characterRun;                  ///< The initial character index and the number of characters of the run.
+  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.
+  float              lineSpacing;                   ///< The line's spacing
+  CharacterDirection direction : 1;                 ///< Direction of the first character of the paragraph.
+  bool               ellipsis : 1;                  ///< Wheter ellipsis is added to the line.
+  bool               isSplitToTwoHalves;            ///< Whether the second half is defined. When split line to two halves to set Ellipsis in the MIDDLE of line. The second half is the second part of line after Ellipsis.
+  GlyphRun           glyphRunSecondHalf;            ///< The initial glyph index and the number of glyphs of the run for the second half of line.
+  CharacterRun       characterRunForSecondHalfLine; ///< The initial character index and the number of characters of the run for the second half of line.
 };
 
 } // namespace Text
index 1023dc4..ef80844 100644 (file)
@@ -46,7 +46,7 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT
 const float    ZERO(0.0f);
 const float    HALF(0.5f);
 const float    ONE(1.0f);
-const uint32_t DOUBLE_PIXEL_PADDING = 4u;//Padding will be added twice to Atlas
+const uint32_t DOUBLE_PIXEL_PADDING = 4u; //Padding will be added twice to Atlas
 const uint16_t NO_OUTLINE           = 0u;
 } // namespace
 
@@ -249,13 +249,12 @@ struct AtlasRenderer::Impl
           // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas
 
           // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice.
-          uint32_t default_width = defaultTextAtlasSize.width;
+          uint32_t default_width  = defaultTextAtlasSize.width;
           uint32_t default_height = defaultTextAtlasSize.height;
 
-          while (
+          while(
             (blockSize.mNeededBlockWidth >= (default_width - (DOUBLE_PIXEL_PADDING + 1u)) ||
-             blockSize.mNeededBlockHeight >= (default_height - (DOUBLE_PIXEL_PADDING + 1u)))
-            &&
+             blockSize.mNeededBlockHeight >= (default_height - (DOUBLE_PIXEL_PADDING + 1u))) &&
             (default_width < maximumTextAtlasSize.width &&
              default_height < maximumTextAtlasSize.height))
           {
@@ -433,6 +432,11 @@ struct AtlasRenderer::Impl
     const Length*    hyphenIndices = view.GetHyphenIndices();
     const Length     hyphensCount  = view.GetHyphensCount();
 
+    // Elided text info. Indices according to elided text.
+    const auto startIndexOfGlyphs              = view.GetStartIndexOfElidedGlyphs();
+    const auto firstMiddleIndexOfElidedGlyphs  = view.GetFirstMiddleIndexOfElidedGlyphs();
+    const auto secondMiddleIndexOfElidedGlyphs = view.GetSecondMiddleIndexOfElidedGlyphs();
+
     const bool useDefaultColor = (NULL == colorsBuffer);
 
     // Get the underline runs.
@@ -466,13 +470,23 @@ struct AtlasRenderer::Impl
     uint32_t               hyphenIndex = 0;
 
     //For septated underlined chunks. (this is for Markup case)
-    uint32_t underlineChunkId = 0u; // give id for each chunk.
-    bool     isPreUnderlined = false; // status of underlined for previous glyph.
+    uint32_t underlineChunkId = 0u;    // give id for each chunk.
+    bool     isPreUnderlined  = false; // status of underlined for previous glyph.
+
+    //Skip hyphenIndices less than startIndexOfGlyphs or between two middle of elided text
+    if(hyphenIndices)
+    {
+      while((hyphenIndex < hyphensCount) && (hyphenIndices[hyphenIndex] < startIndexOfGlyphs ||
+                                             (hyphenIndices[hyphenIndex] > firstMiddleIndexOfElidedGlyphs && hyphenIndices[hyphenIndex] < secondMiddleIndexOfElidedGlyphs)))
+      {
+        ++hyphenIndex;
+      }
+    }
 
     for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
     {
       GlyphInfo glyph;
-      bool      addHyphen = ((hyphenIndex < hyphensCount) && hyphenIndices && (i == hyphenIndices[hyphenIndex]));
+      bool      addHyphen = ((hyphenIndex < hyphensCount) && hyphenIndices && ((i + startIndexOfGlyphs) == hyphenIndices[hyphenIndex]));
       if(addHyphen && hyphens)
       {
         glyph = hyphens[hyphenIndex];
@@ -601,10 +615,9 @@ struct AtlasRenderer::Impl
                        0u);
         }
 
-
         //The new underlined chunk. Add new id if they are not consecutive indices (this is for Markup case)
         // Examples: "Hello <u>World</u> Hello <u>World</u>", "<u>World</u> Hello <u>World</u>", "<u>   World</u> Hello <u>World</u>"
-        if( isPreUnderlined && (isPreUnderlined != isGlyphUnderlined))
+        if(isPreUnderlined && (isPreUnderlined != isGlyphUnderlined))
         {
           underlineChunkId++;
         }
@@ -871,7 +884,7 @@ struct AtlasRenderer::Impl
       extent.mUnderlinePosition  = underlinePosition;
       extent.mUnderlineThickness = underlineThickness;
       extent.mMeshRecordIndex    = index;
-      extent.mUnderlineChunkId = underlineChunkId;
+      extent.mUnderlineChunkId   = underlineChunkId;
       extents.PushBack(extent);
     }
   }
index 17a5c61..cea2a19 100644 (file)
@@ -539,6 +539,24 @@ ViewModel* Typesetter::GetViewModel()
   return mModel;
 }
 
+Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Pixel::Format pixelFormat)
+{
+  Devel::PixelBuffer imageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+
+  if(Pixel::RGBA8888 == pixelFormat)
+  {
+    const unsigned int bufferSizeInt  = bufferWidth * bufferHeight;
+    const unsigned int bufferSizeChar = 4u * bufferSizeInt;
+    memset(imageBuffer.GetBuffer(), 0u, bufferSizeChar);
+  }
+  else
+  {
+    memset(imageBuffer.GetBuffer(), 0, bufferWidth * bufferHeight);
+  }
+
+  return imageBuffer;
+}
+
 PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat)
 {
   // @todo. This initial implementation for a TextLabel has only one visible page.
@@ -630,14 +648,16 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
   const unsigned int bufferSizeInt  = bufferWidth * bufferHeight;
   const unsigned int bufferSizeChar = 4u * bufferSizeInt;
 
-  Length numberOfGlyphs = mModel->GetNumberOfGlyphs();
+  //Elided text in ellipsis at START could start on index greater than 0
+  auto startIndexOfGlyphs = mModel->GetStartIndexOfElidedGlyphs();
+  auto endIndexOfGlyphs   = mModel->GetEndIndexOfElidedGlyphs();
 
   Devel::PixelBuffer imageBuffer;
 
   if(RENDER_MASK == behaviour)
   {
     // Generate the image buffer as an alpha mask for color glyphs.
-    imageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+    imageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_MASK, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
   }
   else if(RENDER_NO_TEXT == behaviour)
   {
@@ -648,7 +668,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
   else
   {
     // Generate the image buffer for the text with no style.
-    imageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+    imageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_NONE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
   }
 
   if((RENDER_NO_STYLES != behaviour) && (RENDER_MASK != behaviour))
@@ -658,7 +678,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
     if(outlineWidth != 0u)
     {
       // Create the image buffer for outline
-      Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+      Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
 
       // Combine the two buffers
       imageBuffer = CombineImageBuffer(imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight);
@@ -671,7 +691,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
     if(fabsf(shadowOffset.x) > Math::MACHINE_EPSILON_1 || fabsf(shadowOffset.y) > Math::MACHINE_EPSILON_1)
     {
       // Create the image buffer for shadow
-      Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+      Devel::PixelBuffer shadowImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_SHADOW, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
 
       // Check whether it will be a soft shadow
       const float& blurRadius = mModel->GetShadowBlurRadius();
@@ -690,7 +710,7 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
     if(underlineEnabled)
     {
       // Create the image buffer for underline
-      Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+      Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
 
       // Combine the two buffers
       imageBuffer = CombineImageBuffer(imageBuffer, underlineImageBuffer, bufferWidth, bufferHeight);
@@ -705,11 +725,11 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect
 
       if(backgroundEnabled)
       {
-        backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+        backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
       }
       else
       {
-        backgroundImageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+        backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat);
       }
 
       if(backgroundMarkupSet)
@@ -737,7 +757,6 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
   // Retrieve lines, glyphs, positions and colors from the view model.
   const Length            modelNumberOfLines = mModel->GetNumberOfLines();
   const LineRun* const    modelLinesBuffer   = mModel->GetLines();
-  const Length            numberOfGlyphs     = mModel->GetNumberOfGlyphs();
   const GlyphInfo* const  glyphsBuffer       = mModel->GetGlyphs();
   const Vector2* const    positionBuffer     = mModel->GetLayout();
   const Vector4* const    colorsBuffer       = mModel->GetColors();
@@ -746,6 +765,13 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
   const Length*           hyphenIndices      = mModel->GetHyphenIndices();
   const Length            hyphensCount       = mModel->GetHyphensCount();
 
+  // Elided text info. Indices according to elided text and Ellipsis position.
+  const auto startIndexOfGlyphs              = mModel->GetStartIndexOfElidedGlyphs();
+  const auto endIndexOfGlyphs                = mModel->GetEndIndexOfElidedGlyphs();
+  const auto firstMiddleIndexOfElidedGlyphs  = mModel->GetFirstMiddleIndexOfElidedGlyphs();
+  const auto secondMiddleIndexOfElidedGlyphs = mModel->GetSecondMiddleIndexOfElidedGlyphs();
+  const auto ellipsisPosition                = mModel->GetEllipsisPosition();
+
   // Whether to use the default color.
   const bool     useDefaultColor = (NULL == colorsBuffer);
   const Vector4& defaultColor    = mModel->GetDefaultColor();
@@ -755,20 +781,9 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
   glyphData.verticalOffset   = verticalOffset;
   glyphData.width            = bufferWidth;
   glyphData.height           = bufferHeight;
-  glyphData.bitmapBuffer     = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+  glyphData.bitmapBuffer     = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat);
   glyphData.horizontalOffset = 0;
 
-  if(Pixel::RGBA8888 == pixelFormat)
-  {
-    const unsigned int bufferSizeInt  = bufferWidth * bufferHeight;
-    const unsigned int bufferSizeChar = 4u * bufferSizeInt;
-    memset(glyphData.bitmapBuffer.GetBuffer(), 0u, bufferSizeChar);
-  }
-  else
-  {
-    memset(glyphData.bitmapBuffer.GetBuffer(), 0, bufferWidth * bufferHeight);
-  }
-
   // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs.
   TextAbstraction::FontClient fontClient  = TextAbstraction::FontClient::Get();
   Length                      hyphenIndex = 0;
@@ -839,8 +854,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
     bool  addHyphen       = false;
 
     // Traverses the glyphs of the line.
-    const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs);
-    for(GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex)
+    const GlyphIndex startGlyphIndex = std::max(line.glyphRun.glyphIndex, startIndexOfGlyphs);
+    GlyphIndex       endGlyphIndex   = (line.isSplitToTwoHalves ? line.glyphRunSecondHalf.glyphIndex + line.glyphRunSecondHalf.numberOfGlyphs : line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs) - 1u;
+    endGlyphIndex                    = std::min(endGlyphIndex, endIndexOfGlyphs);
+
+    for(GlyphIndex glyphIndex = startGlyphIndex; glyphIndex <= endGlyphIndex; ++glyphIndex)
     {
       if(glyphIndex < fromGlyphIndex || glyphIndex > toGlyphIndex)
       {
@@ -848,6 +866,25 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
         continue;
       }
 
+      //To handle START case of ellipsis, the first glyph has been shifted
+      //glyphIndex represent indices in whole glyphs but elidedGlyphIndex represents indices in elided Glyphs
+      GlyphIndex elidedGlyphIndex = glyphIndex - startIndexOfGlyphs;
+
+      //To handle MIDDLE case of ellipsis, the first glyph in the second half of line has been shifted and skip the removed glyph from middle.
+      if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+      {
+        if(glyphIndex > firstMiddleIndexOfElidedGlyphs &&
+           glyphIndex < secondMiddleIndexOfElidedGlyphs)
+        {
+          // Ignore any glyph that removed for MIDDLE ellipsis
+          continue;
+        }
+        if(glyphIndex >= secondMiddleIndexOfElidedGlyphs)
+        {
+          elidedGlyphIndex -= (secondMiddleIndexOfElidedGlyphs - firstMiddleIndexOfElidedGlyphs - 1u);
+        }
+      }
+
       // Retrieve the glyph's info.
       const GlyphInfo* glyphInfo;
 
@@ -858,7 +895,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
       }
       else
       {
-        glyphInfo = glyphsBuffer + glyphIndex;
+        glyphInfo = glyphsBuffer + elidedGlyphIndex;
       }
 
       if((glyphInfo->width < Math::MACHINE_EPSILON_1000) ||
@@ -879,11 +916,11 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth,
       } // underline
 
       // Retrieves the glyph's position.
-      Vector2 position = *(positionBuffer + glyphIndex);
+      Vector2 position = *(positionBuffer + elidedGlyphIndex);
 
       if(addHyphen)
       {
-        GlyphInfo tempInfo = *(glyphsBuffer + glyphIndex);
+        GlyphInfo tempInfo = *(glyphsBuffer + elidedGlyphIndex);
         position.x         = position.x + tempInfo.advance - tempInfo.xBearing + glyphInfo->xBearing;
         position.y         = -glyphInfo->yBearing;
       }
index c9cd4cc..ee57e29 100644 (file)
@@ -123,7 +123,7 @@ private:
   Typesetter& operator=(const Typesetter& handle);
 
   /**
-   * @brief Create the image buffer for the given range of the glyphs in the given style.
+   * @brief Create & draw the image buffer for the given range of the glyphs in the given style.
    *
    * Does the following operations:
    * - Retrieves the data buffers from the text model.
@@ -145,6 +145,19 @@ private:
   Devel::PixelBuffer CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Typesetter::Style style, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset, TextAbstraction::GlyphIndex fromGlyphIndex, TextAbstraction::GlyphIndex toGlyphIndex);
 
   /**
+   * @brief Create an initialized image buffer.
+   *
+   * Creates the pixel data used to generate the final image with the given size.
+   *
+   * @param[in] bufferWidth The width of the image buffer.
+   * @param[in] bufferHeight The height of the image buffer.
+   * @param[in] pixelFormat The format of the pixel in the image that the text is rendered as (i.e. either Pixel::BGRA8888 or Pixel::L8).
+   *
+   * @return An image buffer.
+   */
+  Devel::PixelBuffer CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Pixel::Format pixelFormat);
+
+  /**
    * @brief Combine the two RGBA image buffers together.
    *
    * The top layer buffer will blend over the bottom layer buffer:
index 4ad0b14..35c0a87 100644 (file)
@@ -35,7 +35,11 @@ ViewModel::ViewModel(const ModelInterface* const model)
 : mModel(model),
   mElidedGlyphs(),
   mElidedLayout(),
-  mIsTextElided(false)
+  mIsTextElided(false),
+  mStartIndexOfElidedGlyphs(0u),
+  mEndIndexOfElidedGlyphs(0u),
+  mFirstMiddleIndexOfElidedGlyphs(0u),
+  mSecondMiddleIndexOfElidedGlyphs(0u)
 {
 }
 
@@ -73,6 +77,11 @@ DevelText::VerticalLineAlignment::Type ViewModel::GetVerticalLineAlignment() con
   return mModel->GetVerticalLineAlignment();
 }
 
+DevelText::EllipsisPosition::Type ViewModel::GetEllipsisPosition() const
+{
+  return mModel->GetEllipsisPosition();
+}
+
 bool ViewModel::IsTextElideEnabled() const
 {
   return mModel->IsTextElideEnabled();
@@ -112,6 +121,46 @@ Length ViewModel::GetNumberOfGlyphs() const
   return 0u;
 }
 
+GlyphIndex ViewModel::GetStartIndexOfElidedGlyphs() const
+{
+  if(mIsTextElided && mModel->IsTextElideEnabled())
+  {
+    return mStartIndexOfElidedGlyphs;
+  }
+
+  return mModel->GetStartIndexOfElidedGlyphs();
+}
+
+GlyphIndex ViewModel::GetEndIndexOfElidedGlyphs() const
+{
+  if(mIsTextElided && mModel->IsTextElideEnabled())
+  {
+    return mEndIndexOfElidedGlyphs;
+  }
+
+  return mModel->GetEndIndexOfElidedGlyphs();
+}
+
+GlyphIndex ViewModel::GetFirstMiddleIndexOfElidedGlyphs() const
+{
+  if(mIsTextElided && mModel->IsTextElideEnabled())
+  {
+    return mFirstMiddleIndexOfElidedGlyphs;
+  }
+
+  return mModel->GetFirstMiddleIndexOfElidedGlyphs();
+}
+
+GlyphIndex ViewModel::GetSecondMiddleIndexOfElidedGlyphs() const
+{
+  if(mIsTextElided && mModel->IsTextElideEnabled())
+  {
+    return mSecondMiddleIndexOfElidedGlyphs;
+  }
+
+  return mModel->GetSecondMiddleIndexOfElidedGlyphs();
+}
+
 const GlyphInfo* const ViewModel::GetGlyphs() const
 {
   if(mIsTextElided && mModel->IsTextElideEnabled())
@@ -252,157 +301,283 @@ Length ViewModel::GetHyphensCount() const
 
 void ViewModel::ElideGlyphs()
 {
-  mIsTextElided = false;
+  mIsTextElided             = false;
+  mStartIndexOfElidedGlyphs = mFirstMiddleIndexOfElidedGlyphs = mSecondMiddleIndexOfElidedGlyphs = 0;
+  mEndIndexOfElidedGlyphs                                                                        = mModel->GetNumberOfGlyphs() - 1u;
+
+  auto ellipsisPosition = GetEllipsisPosition();
 
-  if(mModel->IsTextElideEnabled())
+  if(IsTextElideEnabled())
   {
     const Length numberOfLines = mModel->GetNumberOfLines();
     if(0u != numberOfLines)
     {
       const LineRun* const lines = mModel->GetLines();
 
-      const LineRun& lastLine              = *(lines + (numberOfLines - 1u));
-      const Length   numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs;
+      //Get line of ellipsis
+      const LineRun* ellipsisLine     = nullptr;
+      const LineRun* ellipsisNextLine = nullptr;
 
-      if(lastLine.ellipsis && (0u != numberOfLaidOutGlyphs))
+      for(Length lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
       {
-        mIsTextElided                          = true;
-        TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+        const LineRun* line = (lines + lineIndex);
+        if(line->ellipsis)
+        {
+          ellipsisLine = line;
+          if(lineIndex < numberOfLines - 1u)
+          {
+            ellipsisNextLine = (lines + lineIndex + 1u);
+          }
+          break;
+        }
+      }
 
-        const GlyphInfo* const glyphs    = mModel->GetGlyphs();
-        const Vector2* const   positions = mModel->GetLayout();
+      // Check if there is a line contains Ellipsis.
+      // Then find total number of glyphs and total number of laid out glyphs.
+      // Check where to set Ellipsis glyph in line.
+      // Determine index of Ellipsis glyph and how many glyphs should be replaced by Ellipsis glyph, according to width of Ellipsis glyph.
+      if(ellipsisLine != nullptr)
+      {
+        // Total number of glyphs.
+        const Length numberOfGlyphs = mModel->GetNumberOfGlyphs();
+        // Total number of laid out glyphs.
+        Length numberOfActualLaidOutGlyphs = 0u;
 
-        // Copy the glyphs to be elided.
-        mElidedGlyphs.Resize(numberOfLaidOutGlyphs);
-        mElidedLayout.Resize(numberOfLaidOutGlyphs);
+        // Accumulate laid out glyphs for each line to find total number of laid out glyphs.
+        for(Length lineIndex = 0u; lineIndex < numberOfLines; lineIndex++)
+        {
+          numberOfActualLaidOutGlyphs += lines[lineIndex].glyphRun.numberOfGlyphs + lines[lineIndex].glyphRunSecondHalf.numberOfGlyphs;
+        }
 
-        GlyphInfo* elidedGlyphsBuffer    = mElidedGlyphs.Begin();
-        Vector2*   elidedPositionsBuffer = mElidedLayout.Begin();
+        // Make sure there are laid out glyphs.
+        if(0u != numberOfActualLaidOutGlyphs)
+        {
+          // There are elided glyphs.
+          mIsTextElided                          = true;
+          TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
 
-        memcpy(elidedGlyphsBuffer, glyphs, numberOfLaidOutGlyphs * sizeof(GlyphInfo));
-        memcpy(elidedPositionsBuffer, positions, numberOfLaidOutGlyphs * sizeof(Vector2));
+          // Retrieve the whole glyphs and their positions.
+          const GlyphInfo* const glyphs    = mModel->GetGlyphs();
+          const Vector2* const   positions = mModel->GetLayout();
 
-        const Size& controlSize = mModel->GetControlSize();
+          // Copy the glyphs to be elided.
+          mElidedGlyphs.Resize(numberOfGlyphs);
+          mElidedLayout.Resize(numberOfGlyphs);
+          GlyphInfo* elidedGlyphsBuffer    = mElidedGlyphs.Begin();
+          Vector2*   elidedPositionsBuffer = mElidedLayout.Begin();
 
-        if((1u == numberOfLines) &&
-           (lastLine.ascender - lastLine.descender > controlSize.height))
-        {
-          // Get the first glyph which is going to be replaced and the ellipsis glyph.
-          GlyphInfo&       glyphToRemove = *elidedGlyphsBuffer;
-          const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId));
+          memcpy(elidedGlyphsBuffer, glyphs, numberOfGlyphs * sizeof(GlyphInfo));
+          memcpy(elidedPositionsBuffer, positions, numberOfGlyphs * sizeof(Vector2));
 
-          // Change the 'x' and 'y' position of the ellipsis glyph.
-          Vector2& position = *elidedPositionsBuffer;
+          const Size& controlSize = mModel->GetControlSize();
 
-          position.x = ellipsisGlyph.xBearing;
-          position.y = -lastLine.ascender + controlSize.height - ellipsisGlyph.yBearing;
+          // Set index where to set Ellipsis according to the selected position of Ellipsis.
+          // Start with this index to replace its glyph by Ellipsis, if the width  is not enough, then remove more glyphs.
+          GlyphIndex startIndexOfEllipsis = 0u;
+          if(ellipsisPosition == DevelText::EllipsisPosition::START)
+          {
+            // It's the fisrt glyph in line.
+            startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex;
+          }
+          else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+          {
+            // It's the second middle of the line in case the line split to two halves.
+            // Otherwise it's It's the last glyph in line (line before all removed lines).
+            startIndexOfEllipsis = ellipsisLine->isSplitToTwoHalves ? (ellipsisLine->glyphRunSecondHalf.glyphIndex) : (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u);
+          }
+          else // DevelText::EllipsisPosition::END
+          {
+            // It's the last glyph in line.
+            startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u;
+          }
 
-          // Replace the glyph by the ellipsis glyph and resize the buffers.
-          glyphToRemove = ellipsisGlyph;
+          // When the hight is not enough then show one glyph and that should be the first laid out glyph.
+          if((1u == numberOfLines) &&
+             (ellipsisLine->ascender - ellipsisLine->descender > controlSize.height))
+          {
+            // Replace the first glyph with ellipsis glyph
+            auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;
 
-          mElidedGlyphs.Resize(1u);
-          mElidedLayout.Resize(1u);
+            // Regardless where the location of ellipsis,in-case the hight of line is greater than control's height
+            // then replace the first glyph with ellipsis glyph.
 
-          return;
-        }
+            // Get the first glyph which is going to be replaced and the ellipsis glyph.
+            GlyphInfo&       glyphToRemove = *(elidedGlyphsBuffer + indexOfFirstGlyph);
+            const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId));
 
-        // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
-        float firstPenX   = 0.f; // Used if rtl text is elided.
-        float penY        = 0.f;
-        bool  firstPenSet = false;
+            // Change the 'x' and 'y' position of the ellipsis glyph.
+            Vector2& position = *(elidedPositionsBuffer + indexOfFirstGlyph);
 
-        // Add the ellipsis glyph.
-        bool       inserted              = false;
-        float      removedGlypsWidth     = 0.f;
-        Length     numberOfRemovedGlyphs = 0u;
-        GlyphIndex index                 = numberOfLaidOutGlyphs - 1u;
+            position.x = ellipsisGlyph.xBearing;
+            position.y = -ellipsisLine->ascender + controlSize.height - ellipsisGlyph.yBearing;
 
-        // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
-        while(!inserted)
-        {
-          const GlyphInfo& glyphToRemove = *(elidedGlyphsBuffer + index);
+            // Replace the glyph by the ellipsis glyph and resize the buffers.
+            glyphToRemove = ellipsisGlyph;
 
-          if(0u != glyphToRemove.fontId)
-          {
-            // i.e. The font id of the glyph shaped from the '\n' character is zero.
+            mElidedGlyphs.Resize(1u);
+            mElidedLayout.Resize(1u);
 
-            // Need to reshape the glyph as the font may be different in size.
-            const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId));
+            mEndIndexOfElidedGlyphs = mStartIndexOfElidedGlyphs = mFirstMiddleIndexOfElidedGlyphs = mSecondMiddleIndexOfElidedGlyphs = indexOfFirstGlyph;
+
+            return;
+          }
+
+          // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
+          float firstPenX   = 0.f; // Used if rtl text is elided.
+          float penY        = 0.f;
+          bool  firstPenSet = false;
+
+          // Add the ellipsis glyph.
+          bool       inserted              = false;
+          float      removedGlypsWidth     = 0.f;
+          Length     numberOfRemovedGlyphs = 0u;
+          GlyphIndex indexOfEllipsis       = startIndexOfEllipsis;
+
+          // Tail Mode: start by the end of line.
+          bool isTailMode = (ellipsisPosition == DevelText::EllipsisPosition::END) ||
+                            (ellipsisPosition == DevelText::EllipsisPosition::MIDDLE && numberOfLines != 1u);
 
-            if(!firstPenSet || EqualsZero(glyphToRemove.advance))
+          // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
+          while(!inserted)
+          {
+            const GlyphInfo& glyphToRemove = *(elidedGlyphsBuffer + indexOfEllipsis);
+
+            if(0u != glyphToRemove.fontId)
             {
-              const Vector2& position = *(elidedPositionsBuffer + index);
+              // i.e. The font id of the glyph shaped from the '\n' character is zero.
 
-              // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
-              penY = position.y + glyphToRemove.yBearing;
+              // Need to reshape the glyph as the font may be different in size.
+              const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph(fontClient.GetPointSize(glyphToRemove.fontId));
 
-              // Calculates the first penX which will be used if rtl text is elided.
-              firstPenX = position.x - glyphToRemove.xBearing;
-              if(firstPenX < -ellipsisGlyph.xBearing)
+              if(!firstPenSet)
               {
-                // Avoids to exceed the bounding box when rtl text is elided.
-                firstPenX = -ellipsisGlyph.xBearing;
-              }
+                const Vector2& position = *(elidedPositionsBuffer + indexOfEllipsis);
 
-              removedGlypsWidth = -ellipsisGlyph.xBearing;
+                // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
+                penY = position.y + glyphToRemove.yBearing;
+
+                // Calculates the first penX which will be used if rtl text is elided.
+                firstPenX = position.x - glyphToRemove.xBearing;
+                if(firstPenX < -ellipsisGlyph.xBearing)
+                {
+                  // Avoids to exceed the bounding box when rtl text is elided.
+                  firstPenX = -ellipsisGlyph.xBearing;
+                }
+
+                removedGlypsWidth = -ellipsisGlyph.xBearing;
 
-              if(!EqualsZero(firstPenX))
-              {
                 firstPenSet = true;
               }
-            }
 
-            removedGlypsWidth += std::min(glyphToRemove.advance, (glyphToRemove.xBearing + glyphToRemove.width));
+              removedGlypsWidth += std::min(glyphToRemove.advance, (glyphToRemove.xBearing + glyphToRemove.width));
 
-            // Calculate the width of the ellipsis glyph and check if it fits.
-            const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
+              // Calculate the width of the ellipsis glyph and check if it fits.
+              const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
 
-            // If it is the last glyph to remove, add the ellipsis glyph without checking its width.
-            if((ellipsisGlyphWidth < removedGlypsWidth) || (index == 0u))
-            {
-              GlyphInfo& glyphInfo = *(elidedGlyphsBuffer + index);
-              Vector2&   position  = *(elidedPositionsBuffer + index);
-              position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f;
+              // If it is the last glyph to remove, add the ellipsis glyph without checking its width.
+              if((ellipsisGlyphWidth < removedGlypsWidth) || (isTailMode ? (indexOfEllipsis == 0u) : (indexOfEllipsis == numberOfGlyphs - 1u)))
+              {
+                GlyphInfo& glyphInfo = *(elidedGlyphsBuffer + indexOfEllipsis);
+                Vector2&   position  = *(elidedPositionsBuffer + indexOfEllipsis);
+                position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f;
 
-              // Replace the glyph by the ellipsis glyph.
-              glyphInfo = ellipsisGlyph;
+                // Replace the glyph by the ellipsis glyph.
+                glyphInfo = ellipsisGlyph;
 
-              // Change the 'x' and 'y' position of the ellipsis glyph.
-              if(position.x > firstPenX)
-              {
-                position.x = firstPenX;
-                if(ellipsisGlyphWidth < removedGlypsWidth)
+                // Change the 'x' and 'y' position of the ellipsis glyph.
+                if(position.x > firstPenX)
                 {
-                  position.x += removedGlypsWidth - ellipsisGlyphWidth;
+                  position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
                 }
-              }
 
-              position.x += ellipsisGlyph.xBearing;
-              position.y = penY - ellipsisGlyph.yBearing;
+                position.x += ellipsisGlyph.xBearing;
+                position.y = penY - ellipsisGlyph.yBearing;
 
-              inserted = true;
+                inserted = true;
+              }
             }
-          }
 
-          if(!inserted)
+            if(!inserted)
+            {
+              if(!isTailMode && indexOfEllipsis < numberOfGlyphs - 1u)
+              {
+                // Tail Mode: remove glyphs from startIndexOfEllipsis then decrement indexOfEllipsis, until arrive to index zero.
+                ++indexOfEllipsis;
+              }
+              else if(isTailMode && indexOfEllipsis > 0u)
+              {
+                // Not Tail Mode: remove glyphs from startIndexOfEllipsis then increase indexOfEllipsis, until arrive to last index (numberOfGlyphs - 1u).
+                --indexOfEllipsis;
+              }
+              else
+              {
+                // No space for the ellipsis.
+                inserted = true;
+              }
+              ++numberOfRemovedGlyphs;
+            }
+          } // while( !inserted )
+
+          //Reduce size, shift glyphs and start from ellipsis glyph
+          Length numberOfElidedGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
+          mElidedGlyphs.Resize(numberOfElidedGlyphs);
+          mElidedLayout.Resize(numberOfElidedGlyphs);
+
+          if(ellipsisPosition == DevelText::EllipsisPosition::START)
           {
-            if(index > 0u)
+            // 'Shifts' glyphs after ellipsis glyph and 'Removes' before ellipsis glyph
+            memcpy(elidedGlyphsBuffer, elidedGlyphsBuffer + indexOfEllipsis, numberOfElidedGlyphs * sizeof(GlyphInfo));
+            memcpy(elidedPositionsBuffer, elidedPositionsBuffer + indexOfEllipsis, numberOfElidedGlyphs * sizeof(Vector2));
+
+            mStartIndexOfElidedGlyphs = mFirstMiddleIndexOfElidedGlyphs = mSecondMiddleIndexOfElidedGlyphs = indexOfEllipsis;
+          }
+          else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+          {
+            // 'Shifts and connects' glyphs before and after ellipsis glyph and 'Removes' in-between.
+            bool isOnlySecondHalf = false;
+
+            if(isTailMode)
+            {
+              mFirstMiddleIndexOfElidedGlyphs = indexOfEllipsis;
+              if(ellipsisNextLine != nullptr)
+              {
+                mSecondMiddleIndexOfElidedGlyphs = ellipsisNextLine->glyphRun.glyphIndex;
+              }
+              else
+              {
+                mEndIndexOfElidedGlyphs = mSecondMiddleIndexOfElidedGlyphs = mFirstMiddleIndexOfElidedGlyphs;
+              }
+            }
+            else
             {
-              --index;
+              mFirstMiddleIndexOfElidedGlyphs  = (ellipsisLine->glyphRun.numberOfGlyphs > 0u) ? (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u) : (ellipsisLine->glyphRun.glyphIndex);
+              mSecondMiddleIndexOfElidedGlyphs = indexOfEllipsis;
+              isOnlySecondHalf                 = ellipsisLine->glyphRun.numberOfGlyphs == 0u && ellipsisLine->glyphRunSecondHalf.numberOfGlyphs > 0u;
+            }
+
+            if(isOnlySecondHalf)
+            {
+              Length numberOfSecondHalfGlyphs = numberOfElidedGlyphs - mFirstMiddleIndexOfElidedGlyphs;
+
+              //Copy elided glyphs after the ellipsis glyph.
+              memcpy(elidedGlyphsBuffer + mFirstMiddleIndexOfElidedGlyphs, elidedGlyphsBuffer + mSecondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
+              memcpy(elidedPositionsBuffer + mFirstMiddleIndexOfElidedGlyphs, elidedPositionsBuffer + mSecondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
             }
             else
             {
-              // No space for the ellipsis.
-              inserted = true;
+              Length numberOfSecondHalfGlyphs = numberOfElidedGlyphs - mFirstMiddleIndexOfElidedGlyphs + 1u;
+
+              //Copy elided glyphs after the ellipsis glyph.
+              memcpy(elidedGlyphsBuffer + mFirstMiddleIndexOfElidedGlyphs + 1u, elidedGlyphsBuffer + mSecondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
+              memcpy(elidedPositionsBuffer + mFirstMiddleIndexOfElidedGlyphs + 1u, elidedPositionsBuffer + mSecondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
             }
-            ++numberOfRemovedGlyphs;
           }
-        } // while( !inserted )
-
-        // 'Removes' all the glyphs after the ellipsis glyph.
-        const Length numberOfGlyphs = numberOfLaidOutGlyphs - numberOfRemovedGlyphs;
-        mElidedGlyphs.Resize(numberOfGlyphs);
-        mElidedLayout.Resize(numberOfGlyphs);
+          else // DevelText::EllipsisPosition::END
+          {
+            // 'Removes' all the glyphs after the ellipsis glyph.
+            mEndIndexOfElidedGlyphs = indexOfEllipsis;
+          }
+        }
       }
     }
   }
index e51a075..fd83b62 100644 (file)
@@ -81,11 +81,16 @@ public:
   Text::VerticalAlignment::Type GetVerticalAlignment() const override;
 
   /**
- * @copydoc ModelInterface::GetVerticalLineAlignment()
- */
 * @copydoc ModelInterface::GetVerticalLineAlignment()
 */
   DevelText::VerticalLineAlignment::Type GetVerticalLineAlignment() const override;
 
   /**
+  * @copydoc ModelInterface::GetEllipsisPosition()
+  */
+  DevelText::EllipsisPosition::Type GetEllipsisPosition() const override;
+
+  /**
    * @copydoc ModelInterface::IsTextElideEnabled()
    */
   bool IsTextElideEnabled() const override;
@@ -116,6 +121,26 @@ public:
   Length GetNumberOfGlyphs() const override;
 
   /**
+   * @copydoc ModelInterface::GetStartIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetStartIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetEndIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetEndIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetFirstMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetSecondMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const override;
+
+  /**
    * @copydoc ModelInterface::GetGlyphs()
    */
   const GlyphInfo* const GetGlyphs() const override;
@@ -236,20 +261,26 @@ public:
   Length GetHyphensCount() const override;
 
   /**
-   * @brief Does the text elide.
+   * @brief Does the text elide at the end, start or middle of text according to ellipsis position
    *
    * It stores a copy of the visible glyphs and removes as many glyphs as needed
-   * from the last visible line to add the ellipsis glyph.
+   * from the last visible line to add the ellipsis glyph in END case,
+   * from the first visible line to add the ellipsis glyph in START case,
+   * between the first and last visible lines to add the ellipsis glyph.
    *
    * It stores as well a copy of the positions for each visible glyph.
    */
   void ElideGlyphs();
 
 private:
-  const ModelInterface* const mModel;            ///< Pointer to the text's model.
-  Vector<GlyphInfo>           mElidedGlyphs;     ///< Stores the glyphs of the elided text.
-  Vector<Vector2>             mElidedLayout;     ///< Stores the positions of each glyph of the elided text.
-  bool                        mIsTextElided : 1; ///< Whether the text has been elided.
+  const ModelInterface* const mModel;                           ///< Pointer to the text's model.
+  Vector<GlyphInfo>           mElidedGlyphs;                    ///< Stores the glyphs of the elided text.
+  Vector<Vector2>             mElidedLayout;                    ///< Stores the positions of each glyph of the elided text.
+  bool                        mIsTextElided : 1;                ///< Whether the text has been elided.
+  GlyphIndex                  mStartIndexOfElidedGlyphs;        ///< The start index of elided glyphs.
+  GlyphIndex                  mEndIndexOfElidedGlyphs;          ///< The end index of elided glyphs.
+  GlyphIndex                  mFirstMiddleIndexOfElidedGlyphs;  ///< The first end index of elided glyphs, index before ellipsis of middle.
+  GlyphIndex                  mSecondMiddleIndexOfElidedGlyphs; ///< The second end index of elided glyphs, index of ellipsis of middle.
 };
 
 } // namespace Text
index c17c820..15805c8 100644 (file)
@@ -247,12 +247,36 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE
       DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
       if(!controller.IsEditable()) return false;
 
-      if(!keyString.empty())
+      std::string refinedKey = keyString;
+      if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
+      {
+        bool accepted = false;
+        bool rejected = false;
+        accepted      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::ACCEPTED, keyString);
+        rejected      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::REJECTED, keyString);
+
+        if(!accepted)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the accepted filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
+        }
+        if(rejected)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the rejected filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
+        }
+      }
+
+      if(!refinedKey.empty())
       {
         // InputMethodContext is no longer handling key-events
         controller.mImpl->ClearPreEditFlag();
 
-        controller.InsertText(keyString, COMMIT);
+        controller.InsertText(refinedKey, COMMIT);
 
         textChanged = true;
 
index 29f6ba3..995a800 100644 (file)
@@ -124,7 +124,7 @@ bool ControllerImplEventHandler::ProcessInputEvents(Controller::Impl& impl)
 
     if(nullptr != impl.mEditableControlInterface)
     {
-      impl.mEditableControlInterface->CaretMoved(eventData->mPrimaryCursorPosition);
+      impl.mEditableControlInterface->CursorMoved(eventData->mPrimaryCursorPosition);
     }
 
     if(eventData->mUpdateCursorHookPosition)
index b8b6f31..279f23b 100644 (file)
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-run-container.h>
 #include <dali-toolkit/internal/text/text-selection-handle-controller.h>
 
-#include <dali-toolkit/internal/text/text-enumerations-impl.h>
-
 using namespace Dali;
 
 namespace
@@ -60,6 +60,14 @@ struct BackgroundMesh
   Vector<unsigned short>   mIndices;  ///< container of indices
 };
 
+// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
+// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+const float         BRIGHTNESS_THRESHOLD = 0.179f;
+const float         CONSTANT_R           = 0.2126f;
+const float         CONSTANT_G           = 0.7152f;
+const float         CONSTANT_B           = 0.0722f;
+const Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
+const Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
 const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
 const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
@@ -789,7 +797,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
                          startIndex,
                          requestedNumberOfCharacters,
                          bidirectionalInfo,
-                         mModel->mMatchSystemLanguageDirection,
+                         (mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
                          mLayoutDirection);
 
     if(0u != bidirectionalInfo.Count())
@@ -915,7 +923,23 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
           backgroundColorRun.color                           = textColor;
           mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
 
-          Vector4          backgroundColor = mModel->mVisualModel->GetBackgroundColor();
+          Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor();
+          if(backgroundColor.a == 0) // There is no text background color.
+          {
+            // Try use the control's background color.
+            if(nullptr != mEditableControlInterface)
+            {
+              mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+              if(backgroundColor.a == 0) // There is no control background color.
+              {
+                // Determines black or white color according to text color.
+                // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+                float L         = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
+                backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
+              }
+            }
+          }
+
           Vector<ColorRun> colorRuns;
           colorRuns.Resize(1u);
           ColorRun& colorRun                       = *(colorRuns.Begin());
@@ -1713,7 +1737,7 @@ void Controller::Impl::GetCursorPosition(CharacterIndex logical,
     cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
 
     bool isRTL = false;
-    if(mModel->mMatchSystemLanguageDirection)
+    if(mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS)
     {
       isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
     }
@@ -2082,8 +2106,10 @@ Actor Controller::Impl::CreateBackgroundActor()
 
       // Get the background color of the character.
       // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
-      const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i);
-      const Vector4&   backgroundColor      = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+      const bool       isMarkupBackground       = mView.IsMarkupBackgroundColorSet();
+      const ColorIndex backgroundColorIndex     = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u;
+      const bool       isDefaultBackgroundColor = (0u == backgroundColorIndex);
+      const Vector4&   backgroundColor          = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
 
       mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
       Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
index 9f637d3..f6681bd 100644 (file)
@@ -338,6 +338,7 @@ struct Controller::Impl
     mOperationsPending(NO_OPERATION),
     mMaximumNumberOfCharacters(50u),
     mHiddenInput(NULL),
+    mInputFilter(nullptr),
     mRecalculateNaturalSize(true),
     mMarkupProcessorEnabled(false),
     mClipboardHideEnabled(true),
@@ -354,7 +355,8 @@ struct Controller::Impl
     mTextFitMaxSize(DEFAULT_TEXTFIT_MAX),
     mTextFitStepSize(DEFAULT_TEXTFIT_STEP),
     mTextFitEnabled(false),
-    mFontSizeScale(DEFAULT_FONT_SIZE_SCALE)
+    mFontSizeScale(DEFAULT_FONT_SIZE_SCALE),
+    mIsLayoutDirectionChanged(false)
   {
     mModel = Model::New();
 
@@ -386,7 +388,6 @@ struct Controller::Impl
   ~Impl()
   {
     delete mHiddenInput;
-
     delete mFontDefaults;
     delete mUnderlineDefaults;
     delete mShadowDefaults;
@@ -793,29 +794,30 @@ private:
   void CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns);
 
 public:
-  ControlInterface*           mControlInterface;           ///< Reference to the text controller.
-  EditableControlInterface*   mEditableControlInterface;   ///< Reference to the editable text controller.
-  SelectableControlInterface* mSelectableControlInterface; ///< Reference to the selectable text controller.
-  AnchorControlInterface*     mAnchorControlInterface;     ///< Reference to the anchor controller.
-  ModelPtr                    mModel;                      ///< Pointer to the text's model.
-  FontDefaults*               mFontDefaults;               ///< Avoid allocating this when the user does not specify a font.
-  UnderlineDefaults*          mUnderlineDefaults;          ///< Avoid allocating this when the user does not specify underline parameters.
-  ShadowDefaults*             mShadowDefaults;             ///< Avoid allocating this when the user does not specify shadow parameters.
-  EmbossDefaults*             mEmbossDefaults;             ///< Avoid allocating this when the user does not specify emboss parameters.
-  OutlineDefaults*            mOutlineDefaults;            ///< Avoid allocating this when the user does not specify outline parameters.
-  EventData*                  mEventData;                  ///< Avoid allocating everything for text input until EnableTextInput().
-  TextAbstraction::FontClient mFontClient;                 ///< Handle to the font client.
-  Clipboard                   mClipboard;                  ///< Handle to the system clipboard
-  View                        mView;                       ///< The view interface to the rendering back-end.
-  MetricsPtr                  mMetrics;                    ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
-  Layout::Engine              mLayoutEngine;               ///< The layout engine.
-  Vector<ModifyEvent>         mModifyEvents;               ///< Temporary stores the text set until the next relayout.
-  Vector4                     mTextColor;                  ///< The regular text color
-  TextUpdateInfo              mTextUpdateInfo;             ///< Info of the characters updated.
-  OperationsMask              mOperationsPending;          ///< Operations pending to be done to layout the text.
-  Length                      mMaximumNumberOfCharacters;  ///< Maximum number of characters that can be inserted.
-  HiddenText*                 mHiddenInput;                ///< Avoid allocating this when the user does not specify hidden input mode.
-  Vector2                     mTextFitContentSize;         ///< Size of Text fit content
+  ControlInterface*            mControlInterface;           ///< Reference to the text controller.
+  EditableControlInterface*    mEditableControlInterface;   ///< Reference to the editable text controller.
+  SelectableControlInterface*  mSelectableControlInterface; ///< Reference to the selectable text controller.
+  AnchorControlInterface*      mAnchorControlInterface;     ///< Reference to the anchor controller.
+  ModelPtr                     mModel;                      ///< Pointer to the text's model.
+  FontDefaults*                mFontDefaults;               ///< Avoid allocating this when the user does not specify a font.
+  UnderlineDefaults*           mUnderlineDefaults;          ///< Avoid allocating this when the user does not specify underline parameters.
+  ShadowDefaults*              mShadowDefaults;             ///< Avoid allocating this when the user does not specify shadow parameters.
+  EmbossDefaults*              mEmbossDefaults;             ///< Avoid allocating this when the user does not specify emboss parameters.
+  OutlineDefaults*             mOutlineDefaults;            ///< Avoid allocating this when the user does not specify outline parameters.
+  EventData*                   mEventData;                  ///< Avoid allocating everything for text input until EnableTextInput().
+  TextAbstraction::FontClient  mFontClient;                 ///< Handle to the font client.
+  Clipboard                    mClipboard;                  ///< Handle to the system clipboard
+  View                         mView;                       ///< The view interface to the rendering back-end.
+  MetricsPtr                   mMetrics;                    ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
+  Layout::Engine               mLayoutEngine;               ///< The layout engine.
+  Vector<ModifyEvent>          mModifyEvents;               ///< Temporary stores the text set until the next relayout.
+  Vector4                      mTextColor;                  ///< The regular text color
+  TextUpdateInfo               mTextUpdateInfo;             ///< Info of the characters updated.
+  OperationsMask               mOperationsPending;          ///< Operations pending to be done to layout the text.
+  Length                       mMaximumNumberOfCharacters;  ///< Maximum number of characters that can be inserted.
+  HiddenText*                  mHiddenInput;                ///< Avoid allocating this when the user does not specify hidden input mode.
+  std::unique_ptr<InputFilter> mInputFilter;                ///< Avoid allocating this when the user does not specify input filter mode.
+  Vector2                      mTextFitContentSize;         ///< Size of Text fit content
 
   bool               mRecalculateNaturalSize : 1; ///< Whether the natural size needs to be recalculated.
   bool               mMarkupProcessorEnabled : 1; ///< Whether the mark-up procesor is enabled.
@@ -833,11 +835,12 @@ public:
 
   Shader mShaderBackground; ///< The shader for text background.
 
-  float mTextFitMinSize;     ///< Minimum Font Size for text fit. Default 10
-  float mTextFitMaxSize;     ///< Maximum Font Size for text fit. Default 100
-  float mTextFitStepSize;    ///< Step Size for font intervalse. Default 1
-  bool  mTextFitEnabled : 1; ///< Whether the text's fit is enabled.
-  float mFontSizeScale;      ///< Scale value for Font Size. Default 1.0
+  float mTextFitMinSize;               ///< Minimum Font Size for text fit. Default 10
+  float mTextFitMaxSize;               ///< Maximum Font Size for text fit. Default 100
+  float mTextFitStepSize;              ///< Step Size for font intervalse. Default 1
+  bool  mTextFitEnabled : 1;           ///< Whether the text's fit is enabled.
+  float mFontSizeScale;                ///< Scale value for Font Size. Default 1.0
+  bool  mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
 
 private:
   friend ControllerImplEventHandler;
index 062153d..4c71934 100644 (file)
@@ -384,7 +384,7 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll
     textUpdateInfo.mCharacterIndex     = 0u;
   }
 
-  if(model->mMatchSystemLanguageDirection && impl.mLayoutDirection != layoutDirection)
+  if(impl.mLayoutDirection != layoutDirection)
   {
     // Clear the update info. This info will be set the next time the text is updated.
     textUpdateInfo.mClearAll = true;
@@ -394,6 +394,7 @@ Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controll
                                                     GET_GLYPH_METRICS |
                                                     SHAPE_TEXT |
                                                     UPDATE_DIRECTION |
+                                                    ALIGN |
                                                     LAYOUT |
                                                     BIDI_INFO |
                                                     REORDER);
@@ -543,6 +544,7 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size
 
     // Update the ellipsis
     bool elideTextEnabled = impl.mModel->mElideEnabled;
+    auto ellipsisPosition = impl.mModel->mEllipsisPosition;
 
     if(NULL != impl.mEventData)
     {
@@ -569,7 +571,8 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size
     viewUpdated               = impl.mLayoutEngine.LayoutText(layoutParameters,
                                                 newLayoutSize,
                                                 elideTextEnabled,
-                                                isAutoScrollEnabled);
+                                                isAutoScrollEnabled,
+                                                ellipsisPosition);
     impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
 
     viewUpdated = viewUpdated || (newLayoutSize != layoutSize);
@@ -622,7 +625,7 @@ bool Controller::Relayouter::DoRelayout(Controller& controller, const Size& size
                              lines,
                              impl.mModel->mAlignmentOffset,
                              impl.mLayoutDirection,
-                             impl.mModel->mMatchSystemLanguageDirection);
+                             (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
 
     viewUpdated = true;
   }
index a863317..304276c 100644 (file)
@@ -19,6 +19,8 @@
 #include <dali-toolkit/internal/text/text-controller.h>
 
 // EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/integration-api/debug.h>
 #include <memory.h>
 #include <cmath>
@@ -382,14 +384,19 @@ void Controller::SetIgnoreSpacesAfterText(bool ignore)
   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
 }
 
-bool Controller::IsMatchSystemLanguageDirection() const
+void Controller::ChangedLayoutDirection()
 {
-  return mImpl->mModel->mMatchSystemLanguageDirection;
+  mImpl->mIsLayoutDirectionChanged = true;
 }
 
-void Controller::SetMatchSystemLanguageDirection(bool match)
+void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
 {
-  mImpl->mModel->mMatchSystemLanguageDirection = match;
+  mImpl->mModel->mMatchLayoutDirection = type;
+}
+
+DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
+{
+  return mImpl->mModel->mMatchLayoutDirection;
 }
 
 void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
@@ -397,6 +404,19 @@ void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
   mImpl->mLayoutDirection = layoutDirection;
 }
 
+Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
+{
+  if(mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
+     (mImpl->mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mImpl->mIsLayoutDirectionChanged))
+  {
+    return static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(actor).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+  }
+  else
+  {
+    return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+  }
+}
+
 bool Controller::IsShowingRealText() const
 {
   return mImpl->IsShowingRealText();
@@ -439,6 +459,7 @@ Text::LineWrap::Mode Controller::GetLineWrapMode() const
 void Controller::SetTextElideEnabled(bool enabled)
 {
   mImpl->mModel->mElideEnabled = enabled;
+  mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
 }
 
 bool Controller::IsTextElideEnabled() const
@@ -1618,6 +1639,23 @@ void Controller::GetHiddenInputOption(Property::Map& options)
   }
 }
 
+void Controller::SetInputFilterOption(const Property::Map& options)
+{
+  if(!mImpl->mInputFilter)
+  {
+    mImpl->mInputFilter = std::unique_ptr<InputFilter>(new InputFilter());
+  }
+  mImpl->mInputFilter->SetProperties(options);
+}
+
+void Controller::GetInputFilterOption(Property::Map& options)
+{
+  if(NULL != mImpl->mInputFilter)
+  {
+    mImpl->mInputFilter->GetProperties(options);
+  }
+}
+
 void Controller::SetPlaceholderProperty(const Property::Map& map)
 {
   PlaceholderHandler::SetPlaceholderProperty(*this, map);
@@ -1682,6 +1720,17 @@ void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignm
   mImpl->mModel->mVerticalLineAlignment = alignment;
 }
 
+Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
+{
+  return mImpl->mModel->GetEllipsisPosition();
+}
+
+void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
+{
+  mImpl->mModel->mEllipsisPosition = ellipsisPosition;
+  mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
+}
+
 // public : Relayout.
 
 Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
index aaa3a66..73f132b 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/hidden-text.h>
+#include <dali-toolkit/internal/text/input-filter.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-model-interface.h>
@@ -1386,6 +1387,16 @@ public: // Queries & retrieves.
   void GetHiddenInputOption(Property::Map& options);
 
   /**
+   * @brief Used to set the input filter option
+   */
+  void SetInputFilterOption(const Property::Map& options);
+
+  /**
+   * @brief Used to get the input filter option
+   */
+  void GetInputFilterOption(Property::Map& options);
+
+  /**
    * @brief Sets the Placeholder Properties.
    *
    * @param[in] map The placeholder property map
@@ -1418,6 +1429,18 @@ public: // Queries & retrieves.
   void SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment);
 
   /**
+   * @brief Retrieves ellipsis position
+   * @return The ellipsis position
+   */
+  Toolkit::DevelText::EllipsisPosition::Type GetEllipsisPosition() const;
+
+  /**
+   * @brief Sets ellipsis position
+   * @param[in] ellipsisPosition The ellipsis position for the text
+   */
+  void SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition);
+
+  /**
    * @brief Retrieves ignoreSpaceAfterText value from model
    * @return The value of ignoreSpaceAfterText
    */
@@ -1430,24 +1453,36 @@ public: // Queries & retrieves.
   void SetIgnoreSpacesAfterText(bool ignore);
 
   /**
-   * @brief Retrieves matchSystemLanguageDirection value from model
-   * @return The value of matchSystemLanguageDirection
+   * @brief Sets SetMatchLayoutDirection value to model
+   * @param[in] match The value of matchLayoutDirection for the text
    */
-  bool IsMatchSystemLanguageDirection() const;
+  void SetMatchLayoutDirection(DevelText::MatchLayoutDirection type);
 
   /**
-   * @brief Sets matchSystemLanguageDirection value to model
-   * @param[in] match The value of matchSystemLanguageDirection for the text
+   * @brief Retrieves matchLayoutDirection value from model
+   * @return The value of matchLayoutDirection
    */
-  void SetMatchSystemLanguageDirection(bool match);
+  DevelText::MatchLayoutDirection GetMatchLayoutDirection() const;
 
   /**
-   * @brief Sets layoutDirection value
-   * @param[in] layoutDirection The value of system language direction
+   * @brief Sets layoutDirection type value.
+   * @param[in] layoutDirection The value of the layout direction type.
    */
   void SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection);
 
   /**
+   * @brief Gets layoutDirection type value.
+   * @param[in] actor The actor which will get the layout direction type.
+   * @return The value of the layout direction type.
+   */
+  Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
+
+  /**
+   * @brief Sets the layout direction changed.
+   */
+  void ChangedLayoutDirection();
+
+  /**
    * @brief Retrieves if showing real text or not.
    * @return The value of showing real text.
    */
index 4bd0de0..d62101e 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/input-style.h>
+#include <dali-toolkit/public-api/controls/text-controls/input-filter-properties.h>
 
 namespace Dali
 {
@@ -55,11 +56,11 @@ public:
   /**
    * @brief Called to signal that caret (cursor position) has been moved.
    */
-  virtual void CaretMoved(unsigned int position) = 0;
+  virtual void CursorMoved(unsigned int position) = 0;
 
   /**
    * @brief Called to signal that text has been inserted or deleted.
-   * 
+   *
    * @param[in] immediate If true, it immediately emits the signal, if false, only emits once the signal when OnRelayout() is called next time.
    */
   virtual void TextChanged(bool immediate) = 0;
@@ -77,6 +78,13 @@ public:
   virtual void InputStyleChanged(InputStyle::Mask inputStyleMask) = 0;
 
   /**
+   * @brief Called when the character to be inserted is filtered by the input filter.
+   *
+   * @param[in] type The filter type is ACCEPTED or REJECTED.
+   */
+  virtual void InputFiltered(Toolkit::InputFilter::Property::Type type) = 0;
+
+  /**
    * @brief Add a decoration.
    *
    * @param[in] decoration The actor displaying a decoration.
@@ -85,6 +93,13 @@ public:
   virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
 
   /**
+   * @brief Gets the color of the control.
+   *
+   * @param[out] The color of the control.
+   */
+  virtual void GetControlBackgroundColor(Vector4& color) const = 0;
+
+  /**
    * @brief Editable status (on/off).
    *
    * @return true if it can be edit, else false.
index 11ff5c6..ebb567d 100644 (file)
@@ -48,6 +48,13 @@ DALI_ENUM_TO_STRING_TABLE_BEGIN(LINE_WRAP_MODE)
   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Text::LineWrap, WORD)
   DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::Text::LineWrap, CHARACTER)
 DALI_ENUM_TO_STRING_TABLE_END(LINE_WRAP_MODE)
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN(ELLIPSIS_POSITION_TYPE)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::DevelText::EllipsisPosition, END)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::DevelText::EllipsisPosition, START)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::DevelText::EllipsisPosition, MIDDLE)
+DALI_ENUM_TO_STRING_TABLE_END(ELLIPSIS_POSITION_TYPE)
+
 } // namespace
 
 bool GetHorizontalAlignmentEnumeration(const Property::Value& propertyValue, Toolkit::Text::HorizontalAlignment::Type& alignment)
@@ -79,6 +86,11 @@ const char* GetVerticalAlignmentString(const Toolkit::Text::VerticalAlignment::T
                                                                                      VERTICAL_ALIGNMENT_TYPE_TABLE_COUNT);
 }
 
+bool GetEllipsisPositionTypeEnumeration(const Property::Value& propertyValue, Toolkit::DevelText::EllipsisPosition::Type& ellipsisPositionType)
+{
+  return Scripting::GetEnumerationProperty(propertyValue, ELLIPSIS_POSITION_TYPE_TABLE, ELLIPSIS_POSITION_TYPE_TABLE_COUNT, ellipsisPositionType);
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index bb72e98..af71f7d 100644 (file)
@@ -24,6 +24,8 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 
+// DEVEL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 namespace Dali
 {
 namespace Toolkit
@@ -68,6 +70,14 @@ const char* GetHorizontalAlignmentString(const Toolkit::Text::HorizontalAlignmen
  */
 const char* GetVerticalAlignmentString(const Toolkit::Text::VerticalAlignment::Type& alignment);
 
+/**
+ * @brief Get the ellipsis-location-type from the provided property value.
+ * @param[in] propertyValue The source value (which can be a Property::INTEGER or Property::STRING type)
+ * @param[out] ellipsisPositionType The resulting ellipsisPositionType from the given source
+ * @return true if the resulting ellipsisPositionType has been updated
+ */
+bool GetEllipsisPositionTypeEnumeration(const Property::Value& propertyValue, Toolkit::DevelText::EllipsisPosition::Type& ellipsisPositionType);
+
 } // namespace Text
 
 } // namespace Toolkit
index 928c3f0..d9520f1 100644 (file)
@@ -90,6 +90,13 @@ public:
   virtual DevelText::VerticalLineAlignment::Type GetVerticalLineAlignment() const = 0;
 
   /**
+   * @brief Retrieves ellipsis position for text.
+   *
+   * @return The ellipsis position.
+   */
+  virtual DevelText::EllipsisPosition::Type GetEllipsisPosition() const = 0;
+
+  /**
    * @brief Whether the text elide property is enabled.
    *
    * @return @e true if the text elide property is enabled, @e false otherwise.
@@ -132,6 +139,34 @@ public:
   virtual Length GetNumberOfGlyphs() const = 0;
 
   /**
+   * @brief Retrieves the start index of laid-out glyphs.
+   *
+   * @return The start index of laid-out glyphs.
+   */
+  virtual GlyphIndex GetStartIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the end index of laid-out glyphs.
+   *
+   * @return The end index of laid-out glyphs.
+   */
+  virtual GlyphIndex GetEndIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the first middle index of elided glyphs, index before ellipsis of middle.
+   *
+   * @return The first middle index of elided glyphs, index before ellipsis of middle.
+   */
+  virtual GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the second middle index of elided glyphs, index of ellipsis of middle.
+   *
+   * @return The second middle index of elided glyphs, index of ellipsis of middle.
+   */
+  virtual GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const = 0;
+
+  /**
    * @brief Retrieves the laid-out glyphs.
    *
    * @return A pointer to the vector with the laid-out glyphs.
index 3868979..4c3e3f0 100644 (file)
@@ -67,6 +67,11 @@ DevelText::VerticalLineAlignment::Type Model::GetVerticalLineAlignment() const
   return mVerticalLineAlignment;
 }
 
+DevelText::EllipsisPosition::Type Model::GetEllipsisPosition() const
+{
+  return mEllipsisPosition;
+}
+
 bool Model::IsTextElideEnabled() const
 {
   return mElideEnabled;
@@ -97,6 +102,26 @@ Length Model::GetNumberOfGlyphs() const
   return mVisualModel->mGlyphs.Count();
 }
 
+GlyphIndex Model::GetStartIndexOfElidedGlyphs() const
+{
+  return mVisualModel->GetStartIndexOfElidedGlyphs();
+}
+
+GlyphIndex Model::GetEndIndexOfElidedGlyphs() const
+{
+  return mVisualModel->GetEndIndexOfElidedGlyphs();
+}
+
+GlyphIndex Model::GetFirstMiddleIndexOfElidedGlyphs() const
+{
+  return mVisualModel->GetFirstMiddleIndexOfElidedGlyphs();
+}
+
+GlyphIndex Model::GetSecondMiddleIndexOfElidedGlyphs() const
+{
+  return mVisualModel->GetSecondMiddleIndexOfElidedGlyphs();
+}
+
 const GlyphInfo* const Model::GetGlyphs() const
 {
   return mVisualModel->mGlyphs.Begin();
@@ -129,7 +154,7 @@ const ColorIndex* const Model::GetBackgroundColorIndices() const
 
 bool const Model::IsMarkupBackgroundColorSet() const
 {
-  return (mVisualModel->mBackgroundColorIndices.Count() > 0);
+  return (mVisualModel->mBackgroundColors.Count() > 0);
 }
 
 const Vector4& Model::GetDefaultColor() const
@@ -229,14 +254,18 @@ Model::Model()
   mAlignmentOffset(0.0f),
   mElideEnabled(false),
   mIgnoreSpacesAfterText(true),
-  mMatchSystemLanguageDirection(true)
+  mMatchLayoutDirection(DevelText::MatchLayoutDirection::INHERIT),
+  mEllipsisPosition(DevelText::EllipsisPosition::END)
 {
   mLogicalModel = LogicalModel::New();
   mVisualModel  = VisualModel::New();
 
   // Check environment variable for DALI_MATCH_SYSTEM_LANGUAGE_DIRECTION
-  auto match                    = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_MATCH_SYSTEM_LANGUAGE_DIRECTION);
-  mMatchSystemLanguageDirection = match ? (std::atoi(match) == 0 ? false : true) : mMatchSystemLanguageDirection;
+  auto match = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_MATCH_SYSTEM_LANGUAGE_DIRECTION);
+  if(match && (std::atoi(match) == 0))
+  {
+    mMatchLayoutDirection = DevelText::MatchLayoutDirection::CONTENTS;
+  }
 }
 
 Model::~Model()
index 751f230..280b63d 100644 (file)
@@ -83,6 +83,11 @@ public:
   DevelText::VerticalLineAlignment::Type GetVerticalLineAlignment() const override;
 
   /**
+   * @copydoc ModelInterface::GetEllipsisPosition()
+   */
+  DevelText::EllipsisPosition::Type GetEllipsisPosition() const override;
+
+  /**
    * @copydoc ModelInterface::IsTextElideEnabled()
    */
   bool IsTextElideEnabled() const override;
@@ -113,6 +118,26 @@ public:
   Length GetNumberOfGlyphs() const override;
 
   /**
+   * @copydoc ModelInterface::GetStartIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetStartIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetEndIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetEndIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetFirstMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc ModelInterface::GetSecondMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const override;
+
+  /**
    * @copydoc ModelInterface::GetGlyphs()
    */
   const GlyphInfo* const GetGlyphs() const override;
@@ -257,16 +282,17 @@ public:
    * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
    * Typically this will have a negative value with scrolling occurs.
    */
-  Vector2                                mScrollPosition;                   ///< The text is offset by this position when scrolling.
-  Vector2                                mScrollPositionLast;               ///< The last offset value of mScrollPosition
-  HorizontalAlignment::Type              mHorizontalAlignment;              ///< The layout's horizontal alignment.
-  VerticalAlignment::Type                mVerticalAlignment;                ///< The layout's vertical alignment.
-  DevelText::VerticalLineAlignment::Type mVerticalLineAlignment;            ///< The layout's vertical line alignment.
-  Text::LineWrap::Mode                   mLineWrapMode;                     ///< The text wrap mode
-  float                                  mAlignmentOffset;                  ///< The alignment offset.
-  bool                                   mElideEnabled : 1;                 ///< Whether the text's elide is enabled.
-  bool                                   mIgnoreSpacesAfterText : 1;        ///< Whether ignoring spaces after text or not. Default is true.
-  bool                                   mMatchSystemLanguageDirection : 1; ///< Whether match align for system language direction or not. Default is false.
+  Vector2                                mScrollPosition;            ///< The text is offset by this position when scrolling.
+  Vector2                                mScrollPositionLast;        ///< The last offset value of mScrollPosition
+  HorizontalAlignment::Type              mHorizontalAlignment;       ///< The layout's horizontal alignment.
+  VerticalAlignment::Type                mVerticalAlignment;         ///< The layout's vertical alignment.
+  DevelText::VerticalLineAlignment::Type mVerticalLineAlignment;     ///< The layout's vertical line alignment.
+  Text::LineWrap::Mode                   mLineWrapMode;              ///< The text wrap mode
+  float                                  mAlignmentOffset;           ///< The alignment offset.
+  bool                                   mElideEnabled : 1;          ///< Whether the text's elide is enabled.
+  bool                                   mIgnoreSpacesAfterText : 1; ///< Whether ignoring spaces after text or not. Default is true.
+  DevelText::MatchLayoutDirection        mMatchLayoutDirection;      ///< Whether to match text alignment with layout direction or not.
+  DevelText::EllipsisPosition::Type      mEllipsisPosition;          ///< Where is the location the text elide
 };
 
 } // namespace Text
index ee4c306..24994bf 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
 #include <dali-toolkit/internal/text/text-definitions.h>
 
 namespace Dali
@@ -223,6 +224,48 @@ public:
    * @return The width of the outline.
    */
   virtual uint16_t GetOutlineWidth() const = 0;
+
+  /**
+   * @brief Retrieves ellipsis position for text.
+   *
+   * @return The ellipsis position.
+   */
+  virtual DevelText::EllipsisPosition::Type GetEllipsisPosition() const = 0;
+
+  /**
+   * @brief Whether the text elide property is enabled.
+   *
+   * @return @e true if the text elide property is enabled, @e false otherwise.
+   */
+  virtual bool IsTextElideEnabled() const = 0;
+
+  /**
+   * @brief Retrieves the start index of laid-out glyphs.
+   *
+   * @return The start index of laid-out glyphs.
+   */
+  virtual GlyphIndex GetStartIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the end index of laid-out glyphs.
+   *
+   * @return The end index of laid-out glyphs.
+   */
+  virtual GlyphIndex GetEndIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the first middle index of elided glyphs, index before ellipsis of middle.
+   *
+   * @return The first middle index of elided glyphs, index before ellipsis of middle.
+   */
+  virtual GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const = 0;
+
+  /**
+   * @brief Retrieves the second middle index of elided glyphs, index of ellipsis of middle.
+   *
+   * @return The second middle index of elided glyphs, index of ellipsis of middle.
+   */
+  virtual GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const = 0;
 };
 
 } // namespace Text
index 74a83f5..f8a2722 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/text-abstraction/font-client.h>
 #include <dali/public-api/math/vector2.h>
+#include <memory.h>
 
 namespace Dali
 {
@@ -95,30 +96,77 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
                        GlyphIndex glyphIndex,
                        Length     numberOfGlyphs) const
 {
-  Length numberOfLaidOutGlyphs = 0u;
+  Length numberOfLaidOutGlyphs       = 0u;
+  Length numberOfActualLaidOutGlyphs = 0u;
 
   if(mImpl->mVisualModel)
   {
+    bool                              textElided       = false;
+    DevelText::EllipsisPosition::Type ellipsisPosition = GetEllipsisPosition();
+
+    //Reset indices of ElidedGlyphs
+    mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(0u);
+    mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(numberOfGlyphs);
+    mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(0u);
+    mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(0u);
+
     // If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'.
     // Check the last laid out line to know if the layout engine elided some text.
 
     const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
     if(numberOfLines > 0u)
     {
-      const LineRun& lastLine = *(mImpl->mVisualModel->mLines.Begin() + (numberOfLines - 1u));
+      const LineRun* const lines = mImpl->mVisualModel->mLines.Begin();
+
+      //Get line of ellipsis
+      const LineRun* ellipsisLine     = nullptr;
+      const LineRun* ellipsisNextLine = nullptr;
+      bool           hasEllipsis      = false;
+      for(Length lineIndex = 0; lineIndex < numberOfLines; lineIndex++)
+      {
+        const LineRun* line = (lines + lineIndex);
+        if(line->ellipsis)
+        {
+          ellipsisLine = line;
+          hasEllipsis  = true;
+          if(lineIndex < numberOfLines - 1u)
+          {
+            ellipsisNextLine = (lines + lineIndex + 1u);
+          }
+          break;
+        }
+      }
 
       // If ellipsis is enabled, calculate the number of laid out glyphs.
       // Otherwise use the given number of glyphs.
-      if(lastLine.ellipsis)
+      if(hasEllipsis)
       {
-        numberOfLaidOutGlyphs = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs;
+        textElided            = true;
+        numberOfLaidOutGlyphs = numberOfGlyphs;
+
+        if(ellipsisPosition == DevelText::EllipsisPosition::START)
+        {
+          numberOfActualLaidOutGlyphs = numberOfGlyphs - ellipsisLine->glyphRun.glyphIndex;
+        }
+        else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+        {
+          numberOfActualLaidOutGlyphs = 0u;
+          for(Length lineIndex = 0u; lineIndex < numberOfLines; lineIndex++)
+          {
+            numberOfActualLaidOutGlyphs += lines[lineIndex].glyphRun.numberOfGlyphs + lines[lineIndex].glyphRunSecondHalf.numberOfGlyphs;
+          }
+        }
+        else // DevelText::EllipsisPosition::END
+        {
+          numberOfActualLaidOutGlyphs = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs;
+        }
       }
       else
       {
-        numberOfLaidOutGlyphs = numberOfGlyphs;
+        numberOfActualLaidOutGlyphs = numberOfLaidOutGlyphs = numberOfGlyphs;
       }
 
-      if(0u < numberOfLaidOutGlyphs)
+      if(0u < numberOfActualLaidOutGlyphs)
       {
         // Retrieve from the visual model the glyphs and positions.
         mImpl->mVisualModel->GetGlyphs(glyphs,
@@ -131,11 +179,11 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
 
         // 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;
+        LineIndex firstLineIndex = 0u;
+        Length    numberOfLines  = 0u;
         mImpl->mVisualModel->GetNumberOfLines(glyphIndex,
                                               numberOfLaidOutGlyphs,
-                                              firstLine,
+                                              firstLineIndex,
                                               numberOfLines);
 
         Vector<LineRun> lines;
@@ -147,11 +195,11 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
                                                   numberOfLaidOutGlyphs);
 
         // Get the first line for the given glyph range.
-        LineIndex lineIndex = firstLine;
+        LineIndex lineIndex = firstLineIndex;
         LineRun*  line      = lineBuffer + lineIndex;
 
         // Index of the last glyph of the line.
-        GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
+        GlyphIndex lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u;
 
         // Add the alignment offset to the glyph's position.
 
@@ -175,37 +223,76 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
               line          = lineBuffer + lineIndex;
               minLineOffset = std::min(minLineOffset, line->alignmentOffset);
 
-              lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
+              lastGlyphIndexOfLine = (line->isSplitToTwoHalves ? line->glyphRunSecondHalf.glyphIndex + line->glyphRunSecondHalf.numberOfGlyphs : line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs) - 1u;
 
               penY += line->ascender;
             }
           }
         }
 
+        // Set index where to set Ellipsis according to the selected position of Ellipsis.
+        // Start with this index to replace its glyph by Ellipsis, if the width  is not enough, then remove more glyphs.
+        GlyphIndex startIndexOfEllipsis = 0u;
+        if(hasEllipsis)
+        {
+          if(ellipsisPosition == DevelText::EllipsisPosition::START)
+          {
+            // It's the fisrt glyph in line.
+            startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex;
+          }
+          else if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+          {
+            // It's the second middle of the line in case the line split to two halves.
+            // Otherwise it's It's the last glyph in line (line before all removed lines).
+            startIndexOfEllipsis = ellipsisLine->isSplitToTwoHalves ? (ellipsisLine->glyphRunSecondHalf.glyphIndex) : (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u);
+          }
+          else // DevelText::EllipsisPosition::END
+          {
+            // It's the last glyph in line.
+            startIndexOfEllipsis = ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u;
+          }
+        }
+
         if(1u == numberOfLaidOutGlyphs)
         {
           // not a point try to do ellipsis with only one laid out character.
+
           return numberOfLaidOutGlyphs;
         }
 
-        if(lastLine.ellipsis)
+        if(textElided)
         {
+          const LineRun& elidedLine = *ellipsisLine;
+
           if((1u == numberOfLines) &&
-             (lastLine.ascender - lastLine.descender > mImpl->mVisualModel->mControlSize.height))
+             (elidedLine.ascender - elidedLine.descender > mImpl->mVisualModel->mControlSize.height))
           {
+            // Replace the first glyph with ellipsis glyph
+            auto indexOfFirstGlyph = (ellipsisPosition == DevelText::EllipsisPosition::START) ? startIndexOfEllipsis : 0u;
+
+            // Regardless where the location of ellipsis,in-case the hight of line is greater than control's height
+            // then replace the first glyph with ellipsis glyph.
+
             // Get the first glyph which is going to be replaced and the ellipsis glyph.
-            GlyphInfo&       glyphInfo     = *glyphs;
+            GlyphInfo&       glyphInfo     = *(glyphs + indexOfFirstGlyph);
             const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph(mImpl->mFontClient.GetPointSize(glyphInfo.fontId));
 
             // Change the 'x' and 'y' position of the ellipsis glyph.
-            Vector2& position = *glyphPositions;
+            Vector2& position = *(glyphPositions + indexOfFirstGlyph);
             position.x        = ellipsisGlyph.xBearing;
             position.y        = mImpl->mVisualModel->mControlSize.height - ellipsisGlyph.yBearing;
 
             // Replace the glyph by the ellipsis glyph.
             glyphInfo = ellipsisGlyph;
 
-            return 1u;
+            mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfFirstGlyph);
+            mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfFirstGlyph);
+            mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(indexOfFirstGlyph);
+            mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(indexOfFirstGlyph);
+
+            numberOfLaidOutGlyphs = 1u;
+
+            return numberOfLaidOutGlyphs;
           }
 
           // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
@@ -217,12 +304,16 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
           bool       inserted              = false;
           float      removedGlypsWidth     = 0.f;
           Length     numberOfRemovedGlyphs = 0u;
-          GlyphIndex index                 = numberOfLaidOutGlyphs - 1u;
+          GlyphIndex indexOfEllipsis       = startIndexOfEllipsis;
+
+          // Tail Mode: start by the end of line.
+          const bool isTailMode = ellipsisPosition == DevelText::EllipsisPosition::END ||
+                                  (ellipsisPosition == DevelText::EllipsisPosition::MIDDLE && numberOfLines != 1u);
 
           // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
           while(!inserted)
           {
-            const GlyphInfo& glyphToRemove = *(glyphs + index);
+            const GlyphInfo& glyphToRemove = *(glyphs + indexOfEllipsis);
 
             if(0u != glyphToRemove.fontId)
             {
@@ -233,7 +324,7 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
 
               if(!firstPenSet)
               {
-                const Vector2& position = *(glyphPositions + index);
+                const Vector2& position = *(glyphPositions + indexOfEllipsis);
 
                 // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
                 penY = position.y + glyphToRemove.yBearing;
@@ -255,10 +346,10 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
 
               // Calculate the width of the ellipsis glyph and check if it fits.
               const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
-              if(ellipsisGlyphWidth < removedGlypsWidth)
+              if((ellipsisGlyphWidth < removedGlypsWidth) || (isTailMode ? (indexOfEllipsis == 0u) : (indexOfEllipsis == numberOfGlyphs - 1u)))
               {
-                GlyphInfo& glyphInfo = *(glyphs + index);
-                Vector2&   position  = *(glyphPositions + index);
+                GlyphInfo& glyphInfo = *(glyphs + indexOfEllipsis);
+                Vector2&   position  = *(glyphPositions + indexOfEllipsis);
                 position.x -= (0.f > glyphInfo.xBearing) ? glyphInfo.xBearing : 0.f;
 
                 // Replace the glyph by the ellipsis glyph.
@@ -280,9 +371,15 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
 
             if(!inserted)
             {
-              if(index > 0u)
+              if(isTailMode && indexOfEllipsis > 0u)
               {
-                --index;
+                // Tail Mode: remove glyphs from startIndexOfEllipsis then decrement indexOfEllipsis, until arrive to index zero.
+                --indexOfEllipsis;
+              }
+              else if(!isTailMode && indexOfEllipsis < numberOfLaidOutGlyphs - 1u)
+              {
+                // Not Tail Mode: remove glyphs from startIndexOfEllipsis then increase indexOfEllipsis, until arrive to last index (numberOfGlyphs - 1u).
+                ++indexOfEllipsis;
               }
               else
               {
@@ -294,7 +391,99 @@ Length View::GetGlyphs(GlyphInfo* glyphs,
           }
 
           // 'Removes' all the glyphs after the ellipsis glyph.
-          numberOfLaidOutGlyphs -= numberOfRemovedGlyphs;
+          if(ellipsisPosition == DevelText::EllipsisPosition::MIDDLE)
+          {
+            //Reduce size, shift glyphs and start from ellipsis glyph
+            numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
+
+            GlyphIndex firstMiddleIndexOfElidedGlyphs  = 0u;
+            GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u;
+
+            bool isOnlySecondHalf = false;
+            if(isTailMode)
+            {
+              // Multi-lines case with MIDDLE
+              // In case the Ellipsis in the end of line,
+              // then this index will be the firstMiddleIndex.
+              // The secondMiddleIndex will be the fisrt index in next line.
+              // But in case there is no line after Ellipsis's line then secondMiddleIndex and endIndex equal firstMiddle
+              // Example:
+              // A: are laid out glyphs in line has Ellipsis in the end.
+              // N: are laid out glyphs in lines after removed lines.
+              // R: are removed glyphs.
+              // L: are removed glyphs when removed lines.
+              // AAAAAAAAAAAA...RRR    => Here's the firstMiddleIndex (First index after last A)
+              // LLLLLLLLLLLLLLL
+              // LLLLLLLLLLLLLLL
+              // NNNNNNNNNNNNNN        => Here's the secondMiddleIndex (First N)
+              // NNNNNNNNNN
+
+              firstMiddleIndexOfElidedGlyphs = indexOfEllipsis;
+              if(ellipsisNextLine != nullptr)
+              {
+                secondMiddleIndexOfElidedGlyphs = ellipsisNextLine->glyphRun.glyphIndex;
+              }
+              else
+              {
+                secondMiddleIndexOfElidedGlyphs = firstMiddleIndexOfElidedGlyphs;
+                mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs);
+              }
+            }
+            else
+            {
+              // Single line case with MIDDLE
+              // In case the Ellipsis in the middle of line,
+              // Then the last index in first half will be firstMiddleIndex.
+              // And the indexOfEllipsis will be secondMiddleIndex, which is the first index in second half.
+              // Example:
+              // A: are laid out glyphs in first half of line.
+              // N: are laid out glyphs in second half of line.
+              // R: are removed glyphs.
+              // L: re removed glyphs when layouting text
+              // AAAAAAALLLLLLLLLLLRRR...NNNNN
+              // firstMiddleIndex (index of last A)
+              // secondMiddleIndex (index before first N)
+
+              firstMiddleIndexOfElidedGlyphs  = (ellipsisLine->glyphRun.numberOfGlyphs > 0u) ? (ellipsisLine->glyphRun.glyphIndex + ellipsisLine->glyphRun.numberOfGlyphs - 1u) : (ellipsisLine->glyphRun.glyphIndex);
+              secondMiddleIndexOfElidedGlyphs = indexOfEllipsis;
+              isOnlySecondHalf                = ellipsisLine->glyphRun.numberOfGlyphs == 0u && ellipsisLine->glyphRunSecondHalf.numberOfGlyphs > 0u;
+            }
+
+            mImpl->mVisualModel->SetFirstMiddleIndexOfElidedGlyphs(firstMiddleIndexOfElidedGlyphs);
+            mImpl->mVisualModel->SetSecondMiddleIndexOfElidedGlyphs(secondMiddleIndexOfElidedGlyphs);
+
+            // The number of shifted glyphs and shifting positions will be different according to Single-line or Multi-lines.
+            // isOnlySecondHalf will be true when MIDDLE Ellipsis glyph in single line.
+            if(isOnlySecondHalf)
+            {
+              Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs;
+
+              //Copy elided glyphs after the ellipsis glyph.
+              memcpy(glyphs + firstMiddleIndexOfElidedGlyphs, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
+              memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
+            }
+            else
+            {
+              Length numberOfSecondHalfGlyphs = numberOfLaidOutGlyphs - firstMiddleIndexOfElidedGlyphs + 1u;
+
+              //Copy elided glyphs after the ellipsis glyph.
+              memcpy(glyphs + firstMiddleIndexOfElidedGlyphs + 1u, glyphs + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(GlyphInfo));
+              memcpy(glyphPositions + firstMiddleIndexOfElidedGlyphs + 1u, glyphPositions + secondMiddleIndexOfElidedGlyphs, numberOfSecondHalfGlyphs * sizeof(Vector2));
+            }
+          }
+          else if(ellipsisPosition == DevelText::EllipsisPosition::START)
+          {
+            numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
+            //Copy elided glyphs after the ellipsis glyph.
+            memcpy(glyphs, glyphs + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(GlyphInfo));
+            memcpy(glyphPositions, glyphPositions + startIndexOfEllipsis + numberOfRemovedGlyphs, numberOfLaidOutGlyphs * sizeof(Vector2));
+            mImpl->mVisualModel->SetStartIndexOfElidedGlyphs(indexOfEllipsis);
+          }
+          else // DevelText::EllipsisPosition::END
+          {
+            numberOfLaidOutGlyphs = numberOfActualLaidOutGlyphs - numberOfRemovedGlyphs;
+            mImpl->mVisualModel->SetEndIndexOfElidedGlyphs(indexOfEllipsis);
+          }
         }
       }
     }
@@ -347,7 +536,7 @@ bool const View::IsMarkupBackgroundColorSet() const
 {
   if(mImpl->mVisualModel)
   {
-    return (mImpl->mVisualModel->mBackgroundColorIndices.Count() > 0);
+    return (mImpl->mVisualModel->mBackgroundColors.Count() > 0);
   }
 
   return false;
@@ -476,6 +665,83 @@ uint16_t View::GetOutlineWidth() const
   return 0u;
 }
 
+DevelText::EllipsisPosition::Type View::GetEllipsisPosition() const
+{
+  DevelText::EllipsisPosition::Type ellipsisPosition = DevelText::EllipsisPosition::END;
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model = *mImpl->mVisualModel;
+    ellipsisPosition         = model.GetEllipsisPosition();
+  }
+
+  return ellipsisPosition;
+}
+
+bool View::IsTextElideEnabled() const
+{
+  bool isTextElideEnabled = false;
+
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model = *mImpl->mVisualModel;
+    isTextElideEnabled       = model.IsTextElideEnabled();
+  }
+
+  return isTextElideEnabled;
+}
+
+GlyphIndex View::GetStartIndexOfElidedGlyphs() const
+{
+  GlyphIndex startIndexOfElidedGlyphs = 0u;
+
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model = *mImpl->mVisualModel;
+    startIndexOfElidedGlyphs = model.GetStartIndexOfElidedGlyphs();
+  }
+
+  return startIndexOfElidedGlyphs;
+}
+
+GlyphIndex View::GetEndIndexOfElidedGlyphs() const
+{
+  GlyphIndex endIndexOfElidedGlyphs = 0u;
+
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model = *mImpl->mVisualModel;
+    endIndexOfElidedGlyphs   = model.GetEndIndexOfElidedGlyphs();
+  }
+
+  return endIndexOfElidedGlyphs;
+}
+
+GlyphIndex View::GetFirstMiddleIndexOfElidedGlyphs() const
+{
+  GlyphIndex firstMiddleIndexOfElidedGlyphs = 0u;
+
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model       = *mImpl->mVisualModel;
+    firstMiddleIndexOfElidedGlyphs = model.GetFirstMiddleIndexOfElidedGlyphs();
+  }
+
+  return firstMiddleIndexOfElidedGlyphs;
+}
+
+GlyphIndex View::GetSecondMiddleIndexOfElidedGlyphs() const
+{
+  GlyphIndex secondMiddleIndexOfElidedGlyphs = 0u;
+
+  if(mImpl->mVisualModel)
+  {
+    const VisualModel& model        = *mImpl->mVisualModel;
+    secondMiddleIndexOfElidedGlyphs = model.GetSecondMiddleIndexOfElidedGlyphs();
+  }
+
+  return secondMiddleIndexOfElidedGlyphs;
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 7c61275..62324e8 100644 (file)
@@ -167,6 +167,36 @@ public:
    */
   uint16_t GetOutlineWidth() const override;
 
+  /**
+  * @copydoc Dali::Toolkit::Text::ViewInterface::GetEllipsisPosition()
+  */
+  DevelText::EllipsisPosition::Type GetEllipsisPosition() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::IsTextElideEnabled()
+   */
+  bool IsTextElideEnabled() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetStartIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetStartIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetEndIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetEndIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetFirstMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetSecondMiddleIndexOfElidedGlyphs()
+   */
+  GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const override;
+
 private:
   // Undefined
   View(const View& handle);
index 7edb428..5fa3843 100644 (file)
@@ -230,6 +230,12 @@ void VisualModel::GetNumberOfLines(GlyphIndex glyphIndex,
       firstLineFound = true;
       ++numberOfLines;
     }
+    else if((line.glyphRunSecondHalf.glyphIndex + line.glyphRunSecondHalf.numberOfGlyphs > glyphIndex) &&
+            (lastGlyphIndex > line.glyphRunSecondHalf.glyphIndex))
+    {
+      firstLineFound = true;
+      ++numberOfLines;
+    }
     else if(lastGlyphIndex <= line.glyphRun.glyphIndex)
     {
       // nothing else to do.
@@ -389,6 +395,36 @@ void VisualModel::SetMarkupProcessorEnabled(bool enabled)
   mMarkupProcessorEnabled = enabled;
 }
 
+void VisualModel::SetTextElideEnabled(bool enabled)
+{
+  mTextElideEnabled = enabled;
+}
+
+void VisualModel::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
+{
+  mEllipsisPosition = ellipsisPosition;
+}
+
+void VisualModel::SetStartIndexOfElidedGlyphs(GlyphIndex startIndexOfElidedGlyphs)
+{
+  mStartIndexOfElidedGlyphs = startIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetEndIndexOfElidedGlyphs(GlyphIndex endIndexOfElidedGlyphs)
+{
+  mEndIndexOfElidedGlyphs = endIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetFirstMiddleIndexOfElidedGlyphs(GlyphIndex firstMiddleIndexOfElidedGlyphs)
+{
+  mFirstMiddleIndexOfElidedGlyphs = firstMiddleIndexOfElidedGlyphs;
+}
+
+void VisualModel::SetSecondMiddleIndexOfElidedGlyphs(GlyphIndex secondMiddleIndexOfElidedGlyphs)
+{
+  mSecondMiddleIndexOfElidedGlyphs = secondMiddleIndexOfElidedGlyphs;
+}
+
 const Vector4& VisualModel::GetTextColor() const
 {
   return mTextColor;
@@ -449,6 +485,36 @@ bool VisualModel::IsMarkupProcessorEnabled() const
   return mMarkupProcessorEnabled;
 }
 
+bool VisualModel::IsTextElideEnabled() const
+{
+  return mTextElideEnabled;
+}
+
+Toolkit::DevelText::EllipsisPosition::Type VisualModel::GetEllipsisPosition() const
+{
+  return mEllipsisPosition;
+}
+
+GlyphIndex VisualModel::GetStartIndexOfElidedGlyphs() const
+{
+  return mStartIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetEndIndexOfElidedGlyphs() const
+{
+  return mEndIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetFirstMiddleIndexOfElidedGlyphs() const
+{
+  return mFirstMiddleIndexOfElidedGlyphs;
+}
+
+GlyphIndex VisualModel::GetSecondMiddleIndexOfElidedGlyphs() const
+{
+  return mSecondMiddleIndexOfElidedGlyphs;
+}
+
 Length VisualModel::GetNumberOfUnderlineRuns() const
 {
   return mUnderlineRuns.Count();
@@ -484,10 +550,17 @@ VisualModel::VisualModel()
   mNaturalSize(),
   mLayoutSize(),
   mCachedLineIndex(0u),
+  mEllipsisPosition(DevelText::EllipsisPosition::END),
+  mStartIndexOfElidedGlyphs(0u),
+  mEndIndexOfElidedGlyphs(0u),
+  mFirstMiddleIndexOfElidedGlyphs(0u),
+  mSecondMiddleIndexOfElidedGlyphs(0u),
+  mTextElideEnabled(false),
   mUnderlineEnabled(false),
   mUnderlineColorSet(false),
   mBackgroundEnabled(false),
   mMarkupProcessorEnabled(false)
+
 {
 }
 
index c355c3c..359b695 100644 (file)
@@ -29,6 +29,9 @@
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/line-run.h>
 
+// DEVEL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -374,6 +377,89 @@ public:
    */
   bool IsMarkupProcessorEnabled() const;
 
+  /**
+   * @brief Sets ellipsis position
+   * @param[in] ellipsisPosition The ellipsis position for the text
+   */
+  void SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition);
+
+  /**
+   * @brief Retrieves ellipsis position for text.
+   *
+   * @return The ellipsis position.
+   */
+  Toolkit::DevelText::EllipsisPosition::Type GetEllipsisPosition() const;
+
+  /**
+   * @brief Enable or disable the text elide.
+   *
+   * @param[in] enabled Whether to enable the text elide.
+   */
+  void SetTextElideEnabled(bool enabled);
+
+  /**
+   * @brief Whether the text elide property is enabled.
+   *
+   * @return @e true if the text elide property is enabled, @e false otherwise.
+   */
+  bool IsTextElideEnabled() const;
+
+  /**
+   * @brief Sets the start index of laid-out glyphs.
+   *
+   * @param[in] startIndexOfElidedGlyphs The start index of laid-out glyphs.
+   */
+  void SetStartIndexOfElidedGlyphs(GlyphIndex startIndexOfElidedGlyphs);
+
+  /**
+   * @brief Sets the end index of elided glyphs.
+   *
+   * @param[in] endIndexOfElidedGlyphs The end index of elided glyphs.
+   */
+  void SetEndIndexOfElidedGlyphs(GlyphIndex endIndexOfElidedGlyphs);
+
+  /**
+   * @brief Sets the first middle index of elided glyphs, index before ellipsis of middle.
+   *
+   * @param[in] firstMiddleIndexOfElidedGlyphs The first middle index of elided glyphs, index before ellipsis of middle.
+   */
+  void SetFirstMiddleIndexOfElidedGlyphs(GlyphIndex firstMiddleIndexOfElidedGlyphs);
+
+  /**
+   * @brief Sets the second middle index of elided glyphs, index of ellipsis of middle.
+   *
+   * @param[in] secondMiddleIndexOfElidedGlyphs The second middle index of elided glyphs, index of ellipsis of middle.
+   */
+  void SetSecondMiddleIndexOfElidedGlyphs(GlyphIndex secondMiddleIndexOfElidedGlyphs);
+
+  /**
+   * @brief Retrieves the start index of laid-out glyphs.
+   *
+   * @return The start index of laid-out glyphs.
+   */
+  GlyphIndex GetStartIndexOfElidedGlyphs() const;
+
+  /**
+   * @brief Retrieves the end index of laid-out glyphs.
+   *
+   * @return The end index of laid-out glyphs.
+   */
+  GlyphIndex GetEndIndexOfElidedGlyphs() const;
+
+  /**
+   * @brief Retrieves the first middle index of elided glyphs, index before ellipsis of middle.
+   *
+   * @return The first middle index of elided glyphs, index before ellipsis of middle.
+   */
+  GlyphIndex GetFirstMiddleIndexOfElidedGlyphs() const;
+
+  /**
+   * @brief Retrieves the second middle index of elided glyphs, index of ellipsis of middle.
+   *
+   * @return The second middle index of elided glyphs, index of ellipsis of middle.
+   */
+  GlyphIndex GetSecondMiddleIndexOfElidedGlyphs() const;
+
 protected:
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -424,12 +510,19 @@ private:
   // Caches to increase performance in some consecutive operations.
   LineIndex mCachedLineIndex; ///< Used to increase performance in consecutive calls to GetLineOfGlyph() or GetLineOfCharacter() with consecutive glyphs or characters.
 
+  DevelText::EllipsisPosition::Type mEllipsisPosition;                ///< Where is the location the text elide
+  GlyphIndex                        mStartIndexOfElidedGlyphs;        ///< The start index of elided glyphs.
+  GlyphIndex                        mEndIndexOfElidedGlyphs;          ///< The end index of elided glyphs.
+  GlyphIndex                        mFirstMiddleIndexOfElidedGlyphs;  ///< The first end index of elided glyphs, index before ellipsis of middle.
+  GlyphIndex                        mSecondMiddleIndexOfElidedGlyphs; ///< The first end index of elided glyphs, index of ellipsis of middle.
+  bool                              mTextElideEnabled : 1;            ///< Whether the text's elide is enabled.
+
 public:
-  bool mUnderlineEnabled : 1;  ///< Underline enabled flag
-  bool mUnderlineColorSet : 1; ///< Has the underline color been explicitly set?
-  bool mBackgroundEnabled : 1; ///< Background enabled flag
-  bool mMarkupProcessorEnabled : 1; ///< Markup-processor enabled flag
-  HyphenInfo mHyphen; ///< Contains hyphen glyph info & the character index to draw hyphen after.
+  bool       mUnderlineEnabled : 1;       ///< Underline enabled flag
+  bool       mUnderlineColorSet : 1;      ///< Has the underline color been explicitly set?
+  bool       mBackgroundEnabled : 1;      ///< Background enabled flag
+  bool       mMarkupProcessorEnabled : 1; ///< Markup-processor enabled flag
+  HyphenInfo mHyphen;                     ///< Contains hyphen glyph info & the character index to draw hyphen after.
 };
 
 } // namespace Text
index 30edc3e..33bee66 100644 (file)
@@ -87,17 +87,20 @@ void Fade::OnPlay()
   Property::Map startPropertyMap;
   Property::Map finishPropertyMap;
 
+  float targetOpacity                              = GetWorldColor(targetControl).a;
+  targetControl[Dali::Actor::Property::COLOR_MODE] = Dali::ColorMode::USE_OWN_COLOR;
+
   if(IsAppearingTransition())
   {
     initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, 0.0f);
-    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
-    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity * targetOpacity);
+    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetOpacity);
   }
   else
   {
-    initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
-    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
-    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
+    initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetOpacity);
+    startPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetOpacity);
+    finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity * targetOpacity);
   }
 
   SetInitialPropertyMap(initialPropertyMap);
index 870ac09..19ecb5c 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/devel-api/images/pixel-data-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 #include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
@@ -474,15 +473,7 @@ void TextVisual::UpdateRenderer()
     return;
   }
 
-  Dali::LayoutDirection::Type layoutDirection;
-  if(mController->IsMatchSystemLanguageDirection())
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(DevelWindow::Get(control).GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-  else
-  {
-    layoutDirection = static_cast<Dali::LayoutDirection::Type>(control.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
+  Dali::LayoutDirection::Type layoutDirection = mController->GetLayoutDirection(control);
 
   const Text::Controller::UpdateTextType updateTextType = mController->Relayout(relayoutSize, layoutDirection);
 
index a449997..b225d8d 100644 (file)
@@ -519,6 +519,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 void TextureManager::Remove(const TextureManager::TextureId textureId, TextureUploadObserver* observer)
 {
   int textureInfoIndex = GetCacheIndexFromId(textureId);
+
   if(textureInfoIndex != INVALID_INDEX)
   {
     TextureInfo& textureInfo(mTextureInfoContainer[textureInfoIndex]);
@@ -660,6 +661,7 @@ std::string TextureManager::AddExternalTexture(TextureSet& textureSet)
   info.textureId  = GenerateUniqueTextureId();
   info.textureSet = textureSet;
   mExternalTextures.emplace_back(info);
+
   return VisualUrl::CreateTextureUrl(std::to_string(info.textureId));
 }
 
@@ -668,10 +670,9 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
   if(url.size() > 0u)
   {
     // get the location from the Url
-    VisualUrl parseUrl(url);
-    if(VisualUrl::TEXTURE == parseUrl.GetProtocolType())
+    if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(url))
     {
-      std::string location = parseUrl.GetLocation();
+      std::string location = VisualUrl::GetLocation(url);
       if(location.size() > 0u)
       {
         TextureId  id  = std::stoi(location);
@@ -681,7 +682,10 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
           if(iter->textureId == id)
           {
             auto textureSet = iter->textureSet;
-            mExternalTextures.erase(iter);
+            if(--(iter->referenceCount) <= 0)
+            {
+              mExternalTextures.erase(iter);
+            }
             return textureSet;
           }
         }
@@ -691,6 +695,26 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
   return TextureSet();
 }
 
+void TextureManager::UseExternalTexture(const VisualUrl& url)
+{
+  if(VisualUrl::TEXTURE == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId id = std::stoi(location);
+      for(auto&& elem : mExternalTextures)
+      {
+        if(elem.textureId == id)
+        {
+          elem.referenceCount++;
+          return;
+        }
+      }
+    }
+  }
+}
+
 void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
 {
   // make sure an observer doesn't observe the same object twice
index 089ae92..c9618a9 100644 (file)
@@ -403,6 +403,12 @@ public:
   TextureSet RemoveExternalTexture(const std::string& url);
 
   /**
+   * @brief Notify that external textures are used.
+   * @param[in] url The URL of the texture to use.
+   */
+  void UseExternalTexture(const VisualUrl& url);
+
+  /**
    * Add an observer to the object.
    * @param[in] observer The observer to add.
    */
@@ -850,6 +856,7 @@ private:
   {
     TextureId  textureId;
     TextureSet textureSet;
+    int16_t    referenceCount{1};
   };
 
 private:
index e498313..1979f78 100644 (file)
 // EXTERNAL HEADERS
 #include <cstring> // for toupper()
 
+// INTERNAL HEADERS
+#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -209,6 +213,14 @@ VisualUrl::VisualUrl(const std::string& url)
       // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine
       mType = ResolveType(url);
     }
+    else
+    {
+      Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+      if(factory)
+      {
+        GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+      }
+    }
   }
 }
 
@@ -217,15 +229,53 @@ VisualUrl::VisualUrl(const VisualUrl& url)
   mType(url.mType),
   mLocation(url.mLocation)
 {
+  if(VisualUrl::TEXTURE == mLocation)
+  {
+    Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+    if(factory)
+    {
+      GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+    }
+  }
+}
+
+VisualUrl::~VisualUrl()
+{
+  if(VisualUrl::TEXTURE == mLocation)
+  {
+    Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+    if(factory)
+    {
+      GetImplementation(factory).GetTextureManager().RemoveExternalTexture(mUrl);
+    }
+  }
 }
 
 VisualUrl& VisualUrl::operator=(const VisualUrl& url)
 {
   if(&url != this)
   {
+    if(VisualUrl::TEXTURE == mLocation)
+    {
+      Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+      if(factory)
+      {
+        GetImplementation(factory).GetTextureManager().RemoveExternalTexture(mUrl);
+      }
+    }
+
     mUrl      = url.mUrl;
     mType     = url.mType;
     mLocation = url.mLocation;
+
+    if(VisualUrl::TEXTURE == mLocation)
+    {
+      Toolkit::VisualFactory factory = Toolkit::VisualFactory::Get();
+      if(factory)
+      {
+        GetImplementation(factory).GetTextureManager().UseExternalTexture(*this);
+      }
+    }
   }
   return *this;
 }
@@ -257,12 +307,7 @@ bool VisualUrl::IsLocalResource() const
 
 std::string VisualUrl::GetLocation() const
 {
-  const auto location = mUrl.find("://");
-  if(std::string::npos != location)
-  {
-    return mUrl.substr(location + 3u); // 3 characters forwards from the start of ://
-  }
-  return mUrl;
+  return GetLocation(mUrl);
 }
 
 std::string VisualUrl::CreateTextureUrl(const std::string& location)
@@ -270,6 +315,22 @@ std::string VisualUrl::CreateTextureUrl(const std::string& location)
   return "dali://" + location;
 }
 
+VisualUrl::ProtocolType VisualUrl::GetProtocolType(const std::string& url)
+{
+  return ResolveLocation(url);
+}
+
+std::string VisualUrl::GetLocation(const std::string& url)
+{
+  const auto location = url.find("://");
+  if(std::string::npos != location)
+  {
+    return url.substr(location + 3u); // 3 characters forwards from the start of ://
+  }
+  return url;
+}
+
+
 } // namespace Internal
 
 } // namespace Toolkit
index 8857184..a772bd1 100644 (file)
@@ -55,8 +55,16 @@ public:
   VisualUrl();
 
   /**
+   * Default Destructor.
+   * Delete an external texture if if protocolType is TEXTURE.
+   */
+  ~VisualUrl();
+
+  /**
    * Constructor.
    * Determines type of visual and whether the url is local or remote
+   * Notify that it is using an external texture if if protocolType is TEXTURE.
+   *
    * @param[in] url The URL to store and resolve
    */
   VisualUrl(const std::string& url);
@@ -114,6 +122,19 @@ public:
    */
   static std::string CreateTextureUrl(const std::string& location);
 
+  /**
+   * Helper to get a ProtocolType from url
+   * @param url the url of the texture
+   * @return the protocol type
+   */
+  static VisualUrl::ProtocolType GetProtocolType(const std::string& url);
+
+  /**
+   * Helper to get a location from url
+   * @param url the location of the texture
+   * @return the location
+   */
+  static std::string GetLocation(const std::string& url);
 private:
   std::string  mUrl;
   Type         mType;
index 414fb07..20fcb02 100755 (executable)
@@ -20,3 +20,5 @@ msgstr "لصق"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "الحافظة"
 
+msgid "slider"
+msgstr ""
index 6581e52..cfd4a80 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Yapışdır"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Mübadilə buferi"
 
+msgid "icon"
+msgstr "Piktoqram"
+
+msgid "slider"
+msgstr "Sürüngəc"
index 52a2d78..4b13de1 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Поставяне"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Системен буфер"
 
+msgid "icon"
+msgstr "Икона"
+
+msgid "slider"
+msgstr "Плъзгач"
index c29c744..a6191a8 100644 (file)
@@ -16,3 +16,8 @@ msgstr "পেস্ট করুন"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "ক্লিপবোর্ড"
 
+msgid "icon"
+msgstr "Icon"
+
+msgid "slider"
+msgstr "স্লাইডার"
index 34c6125..ba85f18 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Enganxar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Porta-retalls"
 
+msgid "slider"
+msgstr "control lliscant"
index c8c68f9..3e4f477 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Vložit"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Schránka"
 
+msgid "slider"
+msgstr "šoupátko"
index 0898d64..fea998c 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Indsæt"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Udklipsholder"
 
+msgid "icon"
+msgstr "Ikon"
+
+msgid "slider"
+msgstr "skyder"
index 3082bbb..f1b0020 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Einfügen"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Zwischenablage"
 
+msgid "slider"
+msgstr ""
index 8f93b05..3ed1056 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Επικόλληση"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Πρόχειρο"
 
+msgid "icon"
+msgstr "Εικονίδιο"
+
+msgid "slider"
+msgstr "Ρυθμιστικό"
index 2579c1c..9945b39 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Paste"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Clipboard"
 
+msgid "icon"
+msgstr "Icon"
+
+msgid "slider"
+msgstr "Slider"
index 2579c1c..9945b39 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Paste"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Clipboard"
 
+msgid "icon"
+msgstr "Icon"
+
+msgid "slider"
+msgstr "Slider"
index 5fed085..b0b516e 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Pegar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Portapapeles"
 
+msgid "icon"
+msgstr "Icono"
+
+msgid "slider"
+msgstr "Controlador deslizante"
index fdb40d8..5e7ec49 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Pegar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Portapapeles"
 
+msgid "icon"
+msgstr "Icono"
+
+msgid "slider"
+msgstr "Controlador deslizante"
index 361b88a..a68fc27 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Kleebi"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Lõikelaud"
 
+msgid "icon"
+msgstr "Ikoon"
+
+msgid "slider"
+msgstr "Liugur"
index 86fe6e5..616c68f 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Itsatsi"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Arbela"
 
+msgid "icon"
+msgstr "Ikonoa"
+
+msgid "slider"
+msgstr "Irristagailua"
index 5e8369b..5ac66a0 100644 (file)
@@ -20,3 +20,5 @@ msgstr "الحاق"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "کلیپ بورد"
 
+msgid "slider"
+msgstr ""
index fd23422..f6c7931 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Liitä"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Leikepöytä"
 
+msgid "slider"
+msgstr "liukusäädin"
index e217eef..dfff479 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Coller"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Presse-papier"
 
+msgid "slider"
+msgstr "curseur"
index 0a8fdd2..7902515 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Coller"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Presse-papier"
 
+msgid "icon"
+msgstr "Icône"
+
+msgid "slider"
+msgstr "Curseur"
index 3e66cbf..4b08c18 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Pegar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Portapapeis"
 
+msgid "slider"
+msgstr "Barra de desprazamento"
index 6c8a251..436f894 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Zalijepi"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Međuspremnik"
 
+msgid "icon"
+msgstr "Ikona"
+
+msgid "slider"
+msgstr "Klizač"
index accab91..367144c 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Beilleszt"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Vágólap"
 
+msgid "slider"
+msgstr "csúszka"
index 9892948..42a66e1 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Տեղադրել"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Գզրոց"
 
+msgid "icon"
+msgstr "Պատկերակ"
+
+msgid "slider"
+msgstr "Սողանիկ"
index bd1952e..fe0b00d 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Líma"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Klippiborð"
 
+msgid "icon"
+msgstr "Tákn"
+
+msgid "slider"
+msgstr "Skyggna"
index f68a4f9..0f578de 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Incolla"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Appunti"
 
+msgid "icon"
+msgstr "Icona"
+
+msgid "slider"
+msgstr "Dispositivo di scorrimento"
index 5dd6d53..28f1b73 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "ჩასმა"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "ბუფერული მეხს."
 
+msgid "icon"
+msgstr "ნიშანი"
+
+msgid "slider"
+msgstr "სლაიდერი"
index 6de1a32..20845c9 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Қою"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Буфер"
 
+msgid "icon"
+msgstr "Белгіше"
+
+msgid "slider"
+msgstr "Сырғытпа"
index 8ecb8d3..dadd773 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "붙여넣기"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "클립보드"
 
+msgid "slider"
+msgstr "슬라이더"
index d403fcc..4163cd3 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Įklijuoti"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Iškarpinė"
 
+msgid "slider"
+msgstr "šliaužiklis"
index 519597b..9698938 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Ielīmēt"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Starpliktuve"
 
+msgid "icon"
+msgstr "Ikona"
+
+msgid "slider"
+msgstr "Slīdnis"
index cc2b51b..ee6fc24 100644 (file)
@@ -16,3 +16,8 @@ msgstr "Буулгах"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Түр санах ой"
 
+msgid "icon"
+msgstr "Дүрс"
+
+msgid "slider"
+msgstr "Slider"
index 0c15456..ae6d545 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Lim inn"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Utklippstavle"
 
+msgid "icon"
+msgstr "Ikon"
+
+msgid "slider"
+msgstr "Glidebryter"
index 48645c4..16e7bd4 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Plakken"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Klembord"
 
+msgid "slider"
+msgstr ""
index c87ec62..b1a99b5 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Wklej"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Schowek"
 
+msgid "slider"
+msgstr "slajder"
index 9c6743a..eb86f8e 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Colar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Área de transferência"
 
+msgid "icon"
+msgstr "Ícone"
+
+msgid "slider"
+msgstr "Controle deslizante"
index e1a21da..b6c820e 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Colar"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Área transferência"
 
+msgid "icon"
+msgstr "Ícone"
+
+msgid "slider"
+msgstr "Cursor de deslocamento"
index 0d78703..4e5278e 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Lipire"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Clipboard"
 
+msgid "icon"
+msgstr "Pictogr."
+
+msgid "slider"
+msgstr "Cursor"
index 8134f66..c7dc38c 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Вставить"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Буфер обмена"
 
+msgid "icon"
+msgstr "Значок"
+
+msgid "slider"
+msgstr "Ползунок"
index 1944646..327899d 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Vložiť"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Schránka"
 
+msgid "icon"
+msgstr "Ikona"
+
+msgid "slider"
+msgstr "Posuvný ovládač"
index 4c8ad23..6de5ccd 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Prilepi"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Odložišče"
 
+msgid "slider"
+msgstr "drsnik"
index 1be1832..d792061 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "Zalepi"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Privremena memorija"
 
+msgid "slider"
+msgstr "клизач"
index 13c587d..573dd6a 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Klistra in"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Urklipp"
 
+msgid "icon"
+msgstr "Ikon"
+
+msgid "slider"
+msgstr "Slider"
index a360194..e116eec 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Yapıştır"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Pano"
 
+msgid "icon"
+msgstr "Simge"
+
+msgid "slider"
+msgstr "Kaydırıcı"
index c41b559..baab2fa 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Вставити"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Буфер обміну"
 
+msgid "icon"
+msgstr "Значок"
+
+msgid "slider"
+msgstr "Слайдер"
index b4bf3be..b663b28 100644 (file)
@@ -20,3 +20,5 @@ msgstr "جوڑ دیں"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "کلپ بورڈ"
 
+msgid "slider"
+msgstr ""
index bcad8b0..bdce823 100755 (executable)
@@ -16,3 +16,8 @@ msgstr "Qo‘shib qo‘yish"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Bufer"
 
+msgid "icon"
+msgstr "Ikoncha"
+
+msgid "slider"
+msgstr "Slider"
index e22211f..5c1e515 100644 (file)
@@ -16,3 +16,5 @@ msgstr "Dán"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "Bộ nhớ tạm"
 
+msgid "slider"
+msgstr "Thanh Trượt"
index b80e9d9..603d05f 100755 (executable)
@@ -16,3 +16,5 @@ msgstr "粘贴"
 msgid "IDS_COM_BODY_CLIPBOARD"
 msgstr "剪贴板"
 
+msgid "slider"
+msgstr "滑块"
diff --git a/dali-toolkit/public-api/controls/text-controls/input-filter-properties.h b/dali-toolkit/public-api/controls/text-controls/input-filter-properties.h
new file mode 100644 (file)
index 0000000..6f9b07f
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef DALI_INPUT_FILTER_PROPERTIES_H
+#define DALI_INPUT_FILTER_PROPERTIES_H
+
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+/**
+ * @addtogroup dali_toolkit_controls_text_controls
+ * @{
+ */
+
+namespace InputFilter
+{
+/**
+ * @brief InputFilter Property.
+ * @SINCE_2_0.33
+ */
+namespace Property
+{
+/**
+ * @brief Enumeration for the type of InputFilter.
+ *
+ * An enum that determines the input filter type of the InputFilter map.
+ * Users can set the ACCEPTED or REJECTED character set, or both.
+ * If both are used, REJECTED has higher priority.
+ * The character set must follow the regular expression rules.
+ * Behaviour can not be guaranteed for incorrect grammars.
+ *
+ * Useful Meta characters:
+ *
+ * | %Meta characters  | Description
+ * |-------------------|------------------------------------------------------------------------------------------------------------|
+ * | \\w               | Matches an alphanumeric character, including "_"; same as [A-Za-z0-9_].                                    |
+ * | \\W               | Matches a non-alphanumeric character, excluding "_"; same as [^A-Za-z0-9_].                                |
+ * | \\s               | Matches a whitespace character, which in ASCII are tab, line feed, form feed, carriage return, and space.  |
+ * | \\S               | Matches anything but a whitespace.                                                                         |
+ * | \\d               | Matches a digit; same as [0-9].                                                                            |
+ * | \\D               | Matches a non-digit; same as [^0-9].                                                                       |
+ *
+ * Example Usage:
+ * @code
+ *   Property::Map filter;
+ *   filter[InputFilter::Property::ACCEPTED] = "[\\d]"; // accept whole digits
+ *   filter[InputFilter::Property::REJECTED] = "[0-5]"; // reject 0, 1, 2, 3, 4, 5
+ *
+ *   field.SetProperty(DevelTextField::Property::INPUT_FILTER, filter); // acceptable inputs are 6, 7, 8, 9
+ * @endcode
+ * @SINCE_2_0.33
+ */
+enum Type
+{
+  /**
+   * @brief The set of characters to be accepted.
+   * @details Name "accepted", type Property::STRING.
+   * @SINCE_2_0.33
+   * @note Available on regex string.
+   */
+  ACCEPTED,
+
+  /**
+   * @brief The set of characters to be rejected.
+   * @details Name "rejected", type Property::STRING.
+   * @SINCE_2_0.33
+   * @note Available on regex string.
+   */
+  REJECTED
+};
+
+} // namespace Property
+
+} // namespace InputFilter
+
+/**
+ * @}
+ */
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_INPUT_FILTER_PROPERTIES_H
index 1010fe1..1ff27f1 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 32;
+const unsigned int TOOLKIT_MICRO_VERSION = 35;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 895bfc7..212dba7 100644 (file)
@@ -28,6 +28,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/controls/video-view/video-view.cpp
   ${public_api_src_dir}/controls/camera-view/camera-view.cpp
   ${public_api_src_dir}/image-loader/image.cpp
+  ${public_api_src_dir}/image-loader/image-url.cpp
   ${public_api_src_dir}/image-loader/async-image-loader.cpp
   ${public_api_src_dir}/image-loader/sync-image-loader.cpp
   ${public_api_src_dir}/styling/style-manager.cpp
@@ -84,6 +85,7 @@ SET( public_api_item_view_header_files
 
 SET( public_api_image_loader_header_files
   ${public_api_src_dir}/image-loader/image.h
+  ${public_api_src_dir}/image-loader/image-url.h
   ${public_api_src_dir}/image-loader/async-image-loader.h
   ${public_api_src_dir}/image-loader/sync-image-loader.h
 )
@@ -114,6 +116,7 @@ SET( public_api_styling_header_files
 
 SET( public_api_text_controls_header_files
   ${public_api_src_dir}/controls/text-controls/hidden-input-properties.h
+  ${public_api_src_dir}/controls/text-controls/input-filter-properties.h
   ${public_api_src_dir}/controls/text-controls/placeholder-properties.h
   ${public_api_src_dir}/controls/text-controls/text-editor.h
   ${public_api_src_dir}/controls/text-controls/text-label.h
diff --git a/dali-toolkit/public-api/image-loader/image-url.cpp b/dali-toolkit/public-api/image-loader/image-url.cpp
new file mode 100644 (file)
index 0000000..65b9601
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021 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/public-api/image-loader/image-url.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/image-loader/image-url-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+ImageUrl::ImageUrl()
+{
+}
+
+ImageUrl::~ImageUrl()
+{
+}
+
+ImageUrl ImageUrl::New(Texture& texture)
+{
+  Toolkit::Internal::ImageUrlPtr internal = Toolkit::Internal::ImageUrl::New(texture);
+  return ImageUrl(internal.Get());
+}
+
+ImageUrl ImageUrl::DownCast(BaseHandle handle)
+{
+  return ImageUrl(dynamic_cast<Toolkit::Internal::ImageUrl*>(handle.GetObjectPtr()));
+}
+
+ImageUrl::ImageUrl(const ImageUrl& rhs) = default;
+
+ImageUrl& ImageUrl::operator=(const ImageUrl& url) = default;
+
+ImageUrl::ImageUrl(ImageUrl&& rhs) = default;
+
+ImageUrl& ImageUrl::operator=(ImageUrl&& rhs) = default;
+
+const std::string& ImageUrl::GetUrl() const
+{
+  return GetImpl(*this).GetUrl();
+}
+
+ImageUrl::ImageUrl(Toolkit::Internal::ImageUrl* internal)
+: BaseHandle(internal)
+{
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/public-api/image-loader/image-url.h b/dali-toolkit/public-api/image-loader/image-url.h
new file mode 100644 (file)
index 0000000..819198b
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef DALI_TOOLKIT_IMAGE_URL_H
+#define DALI_TOOLKIT_IMAGE_URL_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <dali/public-api/rendering/texture.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal DALI_INTERNAL
+{
+class ImageUrl;
+}
+/**
+ * @brief ImageUrl can be used to wrap an external buffer.
+ *
+ * An instance of ImageUrl can be created from Image::GenerateUrl().
+ * Application can get url from ImageUrl.
+ * When application does not use this anymore, the destructor of the ImageUrl is called.
+ * At this time, the buffer is deleted from the texture manager.
+ */
+class DALI_TOOLKIT_API ImageUrl : public BaseHandle
+{
+public:
+  /**
+   * Default Constructor.
+   * Resulting URL is not valid
+   */
+  ImageUrl();
+
+  /**
+   * Destructor
+   */
+  ~ImageUrl();
+
+  /**
+   * @brief Create an initialized ImageUrl.
+   *
+   * @param[in] texture The texture url is got from external buffer.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static ImageUrl New(Texture& texture);
+
+  /**
+   * @brief Downcast an Object handle to ImageUrl handle.
+   *
+   * If handle points to a ImageUrl object the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @param[in] handle to An object.
+   * @return handle to a ImageUrl object or an uninitialized handle.
+   */
+  static ImageUrl DownCast(BaseHandle handle);
+
+  /**
+   * Copy constructor
+   * @param[in] url The url to copy
+   */
+  ImageUrl(const ImageUrl& url);
+
+  /**
+   * Assignment operator
+   * @param[in] url The url to copy
+   */
+  ImageUrl& operator=(const ImageUrl& url);
+
+  /**
+   * @brief Move constructor.
+   * @param[in] rhs A reference to the moved handle
+   */
+  ImageUrl(ImageUrl&& rhs);
+
+  /**
+   * @brief Move assignment operator.
+   * @param[in] rhs A reference to the moved handle
+   * @return A reference to this handle
+   */
+  ImageUrl& operator=(ImageUrl&& rhs);
+
+  /**
+   * Get the url
+   * @return Returns url's string
+   */
+  const std::string& GetUrl() const;
+
+public: // Not intended for application developers
+  /// @cond internal
+  /**
+   * @brief This constructor is used by New() methods.
+   *
+   * @param[in] internal A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL ImageUrl(Toolkit::Internal::ImageUrl* internal);
+  /// @endcond
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif /* DALI_TOOLKIT_IMAGE_URL_H */
index 2dc20c8..b44061e 100644 (file)
@@ -19,6 +19,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/rendering/frame-buffer-devel.h>
@@ -29,30 +30,34 @@ namespace Toolkit
 {
 namespace Image
 {
-std::string GenerateUrl(Dali::FrameBuffer frameBuffer, Pixel::Format pixelFormat, uint32_t width, uint32_t height)
+Dali::Toolkit::ImageUrl GenerateUrl(Dali::FrameBuffer frameBuffer, Pixel::Format pixelFormat, uint32_t width, uint32_t height)
 {
   Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelFormat, width, height);
   frameBuffer.AttachColorTexture(texture, 0u, 0u);
-  return Dali::Toolkit::TextureManager::AddTexture(texture);
+  Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+  return imageUrl;
 }
 
-std::string GenerateUrl(const Dali::FrameBuffer frameBuffer, uint8_t index)
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::FrameBuffer frameBuffer, uint8_t index)
 {
   Texture texture = Dali::DevelFrameBuffer::GetColorTexture(frameBuffer, index);
-  return Dali::Toolkit::TextureManager::AddTexture(texture);
+  Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+  return imageUrl;
 }
 
-std::string GenerateUrl(const Dali::PixelData pixelData)
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData)
 {
   Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
   texture.Upload(pixelData);
-  return Dali::Toolkit::TextureManager::AddTexture(texture);
+  Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+  return imageUrl;
 }
 
-std::string GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource)
+Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource)
 {
   Texture texture = Dali::Texture::New(*nativeImageSource);
-  return Dali::Toolkit::TextureManager::AddTexture(texture);
+  Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture);
+  return imageUrl;
 }
 
 } // namespace Image
index 6fb2816..ad2f56e 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <dali-toolkit/public-api/image-loader/image-url.h>
 
 namespace Dali
 {
@@ -44,9 +45,9 @@ namespace Image
  * @param[in] pixelFormat the pixel format for this frame buffer
  * @param[in] width the width for this frame buffer
  * @param[in] height the height for this frame buffer
- * @return the Url string representing this frame buffer
+ * @return the ImageUrl representing this frame buffer
  */
-DALI_TOOLKIT_API std::string GenerateUrl(const Dali::FrameBuffer frameBuffer, Pixel::Format pixelFormat, uint32_t width, uint32_t height);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::FrameBuffer frameBuffer, Pixel::Format pixelFormat, uint32_t width, uint32_t height);
 
 /**
  * @brief Generate a Url from frame buffer.
@@ -55,27 +56,27 @@ DALI_TOOLKIT_API std::string GenerateUrl(const Dali::FrameBuffer frameBuffer, Pi
  * This method does not check for duplicates, If same frame buffer is entered multiple times, a different URL is returned each time.
  * @param[in] frameBuffer the frame buffer to converted to Url
  * @param[in] index the index of the attached color texture.
- * @return the Url string representing this frame buffer
+ * @return the ImageUrl representing this frame buffer
  */
-DALI_TOOLKIT_API std::string GenerateUrl(const Dali::FrameBuffer frameBuffer, uint8_t index);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::FrameBuffer frameBuffer, uint8_t index);
 
 /**
  * @brief Generate a Url from Pixel data.
  * This Url can be used in visuals to render the pixel data.
  * @note This method does not check for duplicates, If same pixel data is entered multiple times, a different URL is returned each time.
  * @param[in] pixelData the pixel data to converted to Url
- * @return the Url string representing this pixel data
+ * @return the ImageUrl representing this pixel data
  */
-DALI_TOOLKIT_API std::string GenerateUrl(const Dali::PixelData pixelData);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::PixelData pixelData);
 
 /**
  * @brief Generate a Url from native image source.
  * This Url can be used in visuals to render the native image source.
  * @note This method does not check for duplicates, If same native image source is entered multiple times, a different URL is returned each time.
  * @param[in] nativeImageSource the native image source to converted to Url
- * @return the Url string representing this native image source
+ * @return the ImageUrl representing this native image source
  */
-DALI_TOOLKIT_API std::string GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource);
+DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSourcePtr nativeImageSource);
 
 } // namespace Image
 
index 2c852c4..635dc28 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.0.32
+Version:    2.0.35
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT