Merge "Add clockwise and counter clockwise direction type and movefocus" into devel...
authorjoogab yun <joogab.yun@samsung.com>
Mon, 21 Mar 2022 00:57:40 +0000 (00:57 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 21 Mar 2022 00:57:40 +0000 (00:57 +0000)
75 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-DebugRendering.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
dali-toolkit/devel-api/controls/control-accessible.cpp
dali-toolkit/devel-api/controls/control-accessible.h
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/devel-api/controls/control-devel.h
dali-toolkit/devel-api/focus-manager/focus-finder.cpp
dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.cpp
dali-toolkit/devel-api/focus-manager/keyboard-focus-manager-devel.h
dali-toolkit/internal/controls/alignment/alignment-impl.cpp
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp
dali-toolkit/internal/controls/buttons/button-impl.cpp
dali-toolkit/internal/controls/buttons/button-impl.h
dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp
dali-toolkit/internal/controls/buttons/check-box-button-impl.h
dali-toolkit/internal/controls/buttons/push-button-impl.cpp
dali-toolkit/internal/controls/buttons/push-button-impl.h
dali-toolkit/internal/controls/buttons/radio-button-impl.cpp
dali-toolkit/internal/controls/buttons/radio-button-impl.h
dali-toolkit/internal/controls/buttons/toggle-button-impl.cpp
dali-toolkit/internal/controls/buttons/toggle-button-impl.h
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/effects-view/effects-view-impl.cpp
dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp
dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp
dali-toolkit/internal/controls/image-view/image-view-impl.cpp
dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp
dali-toolkit/internal/controls/model3d-view/model3d-view-impl.cpp
dali-toolkit/internal/controls/navigation-view/navigation-view-impl.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp
dali-toolkit/internal/controls/popup/popup-impl.cpp
dali-toolkit/internal/controls/popup/popup-impl.h
dali-toolkit/internal/controls/progress-bar/progress-bar-impl.cpp
dali-toolkit/internal/controls/progress-bar/progress-bar-impl.h
dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp
dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h
dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp
dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp
dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h
dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp
dali-toolkit/internal/controls/scrollable/scrollable-impl.h
dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp
dali-toolkit/internal/controls/slider/slider-impl.cpp
dali-toolkit/internal/controls/slider/slider-impl.h
dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp
dali-toolkit/internal/controls/table-view/table-view-impl.cpp
dali-toolkit/internal/controls/text-controls/common-text-utils.cpp
dali-toolkit/internal/controls/text-controls/common-text-utils.h
dali-toolkit/internal/controls/text-controls/text-anchor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-anchor-impl.h
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/text-controls/text-selection-popup-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h
dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp
dali-toolkit/internal/controls/tool-bar/tool-bar-impl.cpp
dali-toolkit/internal/controls/video-view/video-view-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/dali-toolkit-version.cpp
format [deleted file]
packaging/dali-toolkit.spec

index f75d224..c156b6e 100644 (file)
@@ -11,6 +11,7 @@
 #include <dali-toolkit/devel-api/controls/buttons/toggle-button.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/popup/popup.h>
+#include <dali-toolkit/devel-api/controls/table-view/table-view.h>
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/common/stage.h>
 #include <cstdlib>
@@ -1075,6 +1076,17 @@ int UtcDaliAccessibilityScrollToChildScrollView(void)
   actorB.SetProperty( Dali::Actor::Property::POSITION, positionB );
   scrollView.Add(actorB);
 
+  TableView tableView = TableView::New( 2, 2 ); // 2 by 2 grid.
+  tableView.SetProperty( Actor::Property::SIZE, Vector2(100.0f, 100.0f) );
+  scrollView.Add(tableView);
+
+  PushButton actorC = PushButton::New();
+  actorC.SetProperty( Actor::Property::SIZE, Vector2(50.0f, 50.0f) );
+  tableView.AddChild( actorC, TableView::CellPosition( 0, 0 ) );
+
+  PushButton actorD = PushButton::New();
+  application.GetScene().Add( actorD );
+
   Wait(application);
 
   auto* accessibleParent = dynamic_cast<DevelControl::ControlAccessible*>(Dali::Accessibility::Accessible::Get(scrollView));
@@ -1083,12 +1095,22 @@ int UtcDaliAccessibilityScrollToChildScrollView(void)
   DALI_TEST_CHECK(accessibleA);
   auto* accessibleB = dynamic_cast<DevelControl::ControlAccessible*>(Dali::Accessibility::Accessible::Get(actorB));
   DALI_TEST_CHECK(accessibleB);
+  auto* accessibleC = dynamic_cast<DevelControl::ControlAccessible*>(Dali::Accessibility::Accessible::Get(actorC));
+  DALI_TEST_CHECK(accessibleC);
 
   accessibleA->GrabHighlight(); // == scrollView.ScrollTo(actorA)
   Wait(application);
   accessibleB->GrabHighlight(); // == scrollView.ScrollTo(actorB)
   Wait(application);
 
+  // scrollView is ancestor of actorC
+  // This should work without a crash
+  accessibleC->GrabHighlight(); // == scrollView.ScrollTo(actorC)
+  Wait(application);
+
+  // negative testcase calling ScrollToChild using non-child actor
+  accessibleParent->ScrollToChild(actorD);
+
   Dali::Accessibility::TestEnableSC( false );
   END_TEST;
 }
index 9b733f2..d39b00c 100755 (executable)
@@ -18,9 +18,9 @@
 
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
-#include <dali-toolkit/internal/visuals/wireframe/wireframe-visual.h>
-#include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/text/text-visual.h>
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+#include <dali-toolkit/internal/visuals/wireframe/wireframe-visual.h>
 
 #include <dali-toolkit/dali-toolkit.h>
 
@@ -37,45 +37,49 @@ using namespace Dali::Toolkit;
 
 namespace
 {
-const char* TEST_IMAGE_FILE_NAME  "image_01.jpg";
-const char* TEST_NPATCH_FILE_NAME =  "image_01.9.jpg";
-const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg";
-const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif";
+const char* TEST_IMAGE_FILE_NAME  = "image_01.jpg";
+const char* TEST_NPATCH_FILE_NAME = "image_01.9.jpg";
+const char* TEST_SVG_FILE_NAME    = TEST_RESOURCE_DIR "/svg1.svg";
+const char* TEST_GIF_FILE_NAME    = TEST_RESOURCE_DIR "/anim.gif";
 
-const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+const std::string DEFAULT_FONT_DIR("/resources/fonts");
 
-void TestDebugVisual( Integration::Scene scene,  Visual::Base& visual, Visual::Type actualType, Vector2 expectedNaturalSize )
+void TestDebugVisual(Integration::Scene scene, Visual::Base& visual, DevelVisual::Type actualType, Vector2 expectedNaturalSize)
 {
   {
-    auto& impl = GetImplementation( visual );
-    DALI_TEST_CHECK( &typeid( Toolkit::Internal::WireframeVisual ) == &typeid( impl ) );
+    auto& impl = GetImplementation(visual);
+    DALI_TEST_CHECK(&typeid(Toolkit::Internal::WireframeVisual) == &typeid(impl));
   }
 
   Vector2 naturalSize;
-  visual.GetNaturalSize( naturalSize );
-  DALI_TEST_EQUALS( naturalSize, expectedNaturalSize, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  visual.GetNaturalSize(naturalSize);
+  DALI_TEST_EQUALS(naturalSize, expectedNaturalSize, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
 
   Property::Map propertyMap;
-  visual.CreatePropertyMap( propertyMap );
-  Property::Value* typeValue = propertyMap.Find( Toolkit::Visual::Property::TYPE,  Property::INTEGER );
-  if ( typeValue )
+  visual.CreatePropertyMap(propertyMap);
+  Property::Value* typeValue = propertyMap.Find(Toolkit::Visual::Property::TYPE, Property::INTEGER);
+  if(typeValue)
   {
-    DALI_TEST_CHECK( typeValue->Get<int>() == actualType );
+    DALI_TEST_CHECK(typeValue->Get<int>() == actualType);
   }
 
-  DummyControl actor = DummyControl::New();
+  DummyControl      actor     = DummyControl::New();
   DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
-  dummyImpl.RegisterVisual( Control::CONTROL_PROPERTY_END_INDEX + 1, visual );
-  scene.Add( actor );
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+  scene.Add(actor);
 
-  DALI_TEST_EQUALS( actor.GetRendererCount(), 1, TEST_LOCATION );
-  if( actor.GetRendererCount() > 0 )
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1, TEST_LOCATION);
+  if(actor.GetRendererCount() > 0)
   {
-    Geometry geometry = actor.GetRendererAt( 0 ).GetGeometry();
-    DALI_TEST_CHECK( geometry.GetType() == Geometry::LINES );
+    Geometry geometry = actor.GetRendererAt(0).GetGeometry();
+    DALI_TEST_CHECK(geometry.GetType() == Geometry::LINES);
   }
 }
+void TestDebugVisual(Integration::Scene scene, Visual::Base& visual, Visual::Type actualType, Vector2 expectedNaturalSize)
+{
+  TestDebugVisual(scene, visual, (DevelVisual::Type)actualType, expectedNaturalSize);
 }
+} // namespace
 
 void dali_debug_rendering_startup(void)
 {
@@ -94,57 +98,57 @@ int UtcDaliDebugRenderingGetVisual1(void)
 {
   EnvironmentVariable::SetTestingEnvironmentVariable(true);
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliDebugRenderingGetVisual1:  Request visual with a Property::Map" );
+  tet_infoline("UtcDaliDebugRenderingGetVisual1:  Request visual with a Property::Map");
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
   // Test that color visual is replaced with debug visual
   Property::Map propertyMap1;
-  propertyMap1.Insert(Visual::Property::TYPE,  Visual::COLOR);
-  propertyMap1.Insert(ColorVisual::Property::MIX_COLOR,  Color::BLUE);
+  propertyMap1.Insert(Visual::Property::TYPE, Visual::COLOR);
+  propertyMap1.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
   Visual::Base colorVisual = factory.CreateVisual(propertyMap1);
-  DALI_TEST_CHECK( colorVisual );
-  TestDebugVisual( application.GetScene(),  colorVisual, Visual::COLOR, Vector2::ZERO );
+  DALI_TEST_CHECK(colorVisual);
+  TestDebugVisual(application.GetScene(), colorVisual, Visual::COLOR, Vector2::ZERO);
 
   // Test that border visual is replaced with debug visual
   Property::Map propertyMap2;
-  propertyMap2.Insert(Visual::Property::TYPE,  Visual::BORDER);
-  propertyMap2.Insert(BorderVisual::Property::COLOR,  Color::BLUE);
-  propertyMap2.Insert(BorderVisual::Property::SIZE,  2.f);
+  propertyMap2.Insert(Visual::Property::TYPE, Visual::BORDER);
+  propertyMap2.Insert(BorderVisual::Property::COLOR, Color::BLUE);
+  propertyMap2.Insert(BorderVisual::Property::SIZE, 2.f);
   Visual::Base borderVisual = factory.CreateVisual(propertyMap2);
-  DALI_TEST_CHECK( borderVisual );
-  TestDebugVisual( application.GetScene(),  borderVisual, Visual::BORDER, Vector2::ZERO );
+  DALI_TEST_CHECK(borderVisual);
+  TestDebugVisual(application.GetScene(), borderVisual, Visual::BORDER, Vector2::ZERO);
 
   // Test that gradient visual is replaced with debug visual
   Property::Map propertyMap3;
-  propertyMap3.Insert(Visual::Property::TYPE,  Visual::GRADIENT);
+  propertyMap3.Insert(Visual::Property::TYPE, Visual::GRADIENT);
   Vector2 start(-1.f, -1.f);
   Vector2 end(1.f, 1.f);
   propertyMap3.Insert(GradientVisual::Property::START_POSITION, start);
   propertyMap3.Insert(GradientVisual::Property::END_POSITION, end);
   propertyMap3.Insert(GradientVisual::Property::SPREAD_METHOD, GradientVisual::SpreadMethod::REPEAT);
   Property::Array stopOffsets;
-  stopOffsets.PushBack( 0.2f );
-  stopOffsets.PushBack( 0.8f );
+  stopOffsets.PushBack(0.2f);
+  stopOffsets.PushBack(0.8f);
   propertyMap3.Insert(GradientVisual::Property::STOP_OFFSET, stopOffsets);
   Property::Array stopColors;
-  stopColors.PushBack( Color::RED );
-  stopColors.PushBack( Color::GREEN );
+  stopColors.PushBack(Color::RED);
+  stopColors.PushBack(Color::GREEN);
   propertyMap3.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
   Visual::Base gradientVisual = factory.CreateVisual(propertyMap3);
-  DALI_TEST_CHECK( gradientVisual );
-  TestDebugVisual( application.GetScene(),  gradientVisual, Visual::GRADIENT, Vector2::ZERO );
+  DALI_TEST_CHECK(gradientVisual);
+  TestDebugVisual(application.GetScene(), gradientVisual, Visual::GRADIENT, Vector2::ZERO);
 
   // Test that image visual is replaced with debug visual
   Property::Map propertyMap4;
-  propertyMap4.Insert( Toolkit::Visual::Property::TYPE,  Visual::IMAGE );
-  propertyMap4.Insert( ImageVisual::Property::URL,  TEST_IMAGE_FILE_NAME );
-  propertyMap4.Insert( ImageVisual::Property::DESIRED_WIDTH,  50.f );
-  propertyMap4.Insert( ImageVisual::Property::DESIRED_HEIGHT,  100.f );
-  Visual::Base imageVisual = factory.CreateVisual( propertyMap4 );
-  DALI_TEST_CHECK( imageVisual );
-  TestDebugVisual( application.GetScene(),  imageVisual, Visual::IMAGE, Vector2( 50.f, 100.f ) );
+  propertyMap4.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+  propertyMap4.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+  propertyMap4.Insert(ImageVisual::Property::DESIRED_WIDTH, 50.f);
+  propertyMap4.Insert(ImageVisual::Property::DESIRED_HEIGHT, 100.f);
+  Visual::Base imageVisual = factory.CreateVisual(propertyMap4);
+  DALI_TEST_CHECK(imageVisual);
+  TestDebugVisual(application.GetScene(), imageVisual, Visual::IMAGE, Vector2(50.f, 100.f));
 
   // Test that SVG visual is replaced with debug visual
   // TEST_SVG_FILE:
@@ -152,62 +156,62 @@ int UtcDaliDebugRenderingGetVisual1(void)
   //  <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
   //  </svg>
   Property::Map propertyMap5;
-  propertyMap5.Insert( Toolkit::Visual::Property::TYPE, Visual::SVG );
-  propertyMap5.Insert( ImageVisual::Property::URL,  TEST_SVG_FILE_NAME );
-  Visual::Base svgVisual = factory.CreateVisual( propertyMap5 );
-  DALI_TEST_CHECK( svgVisual );
-  TestDebugVisual( application.GetScene(),  svgVisual, Visual::SVG, Vector2(100.f, 100.f) );
+  propertyMap5.Insert(Toolkit::Visual::Property::TYPE, Visual::SVG);
+  propertyMap5.Insert(ImageVisual::Property::URL, TEST_SVG_FILE_NAME);
+  Visual::Base svgVisual = factory.CreateVisual(propertyMap5);
+  DALI_TEST_CHECK(svgVisual);
+  TestDebugVisual(application.GetScene(), svgVisual, Visual::SVG, Vector2(100.f, 100.f));
 
   // Test that AnimatedImageVisual is replaced with debug visual
   // TEST_GIF_FILE: anim.gif
   // resolution: 50*50, frame count: 4, frame delay: 0.2 second for each frame
   Property::Map propertyMap6;
-  propertyMap6.Insert( Toolkit::Visual::Property::TYPE, Visual::ANIMATED_IMAGE );
-  propertyMap6.Insert( ImageVisual::Property::URL,  TEST_GIF_FILE_NAME );
-  Visual::Base animatedImageVisual = factory.CreateVisual( propertyMap6 );
-  DALI_TEST_CHECK( animatedImageVisual );
-  TestDebugVisual( application.GetScene(),  animatedImageVisual, Visual::ANIMATED_IMAGE, Vector2(50.f, 50.f) );
+  propertyMap6.Insert(Toolkit::Visual::Property::TYPE, Visual::ANIMATED_IMAGE);
+  propertyMap6.Insert(ImageVisual::Property::URL, TEST_GIF_FILE_NAME);
+  Visual::Base animatedImageVisual = factory.CreateVisual(propertyMap6);
+  DALI_TEST_CHECK(animatedImageVisual);
+  TestDebugVisual(application.GetScene(), animatedImageVisual, Visual::ANIMATED_IMAGE, Vector2(50.f, 50.f));
 
   // Test that text visual is replaced with debug visual
 
   // Load some fonts to get the same metrics on different platforms.
   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
-  fontClient.SetDpi( 96u, 96u );
+  fontClient.SetDpi(96u, 96u);
 
-  char* pathNamePtr = get_current_dir_name();
-  const std::string pathName( pathNamePtr );
-  free( pathNamePtr );
+  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/TizenSansRegular.ttf");
 
   Property::Map propertyMap7;
-  propertyMap7.Insert( Toolkit::Visual::Property::TYPE, Visual::TEXT );
-  propertyMap7.Insert( TextVisual::Property::ENABLE_MARKUP, true );
-  propertyMap7.Insert( TextVisual::Property::TEXT, "<font family='TizenSans' size='12'>Hello world</font>" );
-  propertyMap7.Insert( TextVisual::Property::MULTI_LINE, true );
+  propertyMap7.Insert(Toolkit::Visual::Property::TYPE, Visual::TEXT);
+  propertyMap7.Insert(TextVisual::Property::ENABLE_MARKUP, true);
+  propertyMap7.Insert(TextVisual::Property::TEXT, "<font family='TizenSans' size='12'>Hello world</font>");
+  propertyMap7.Insert(TextVisual::Property::MULTI_LINE, true);
 
-  Visual::Base textVisual = factory.CreateVisual( propertyMap7 );
-  DALI_TEST_CHECK( textVisual );
+  Visual::Base textVisual = factory.CreateVisual(propertyMap7);
+  DALI_TEST_CHECK(textVisual);
   {
-    auto&& impl = GetImplementation( textVisual );
-    DALI_TEST_CHECK( &typeid( Toolkit::Internal::WireframeVisual ) == &typeid( impl ) );
+    auto&& impl = GetImplementation(textVisual);
+    DALI_TEST_CHECK(&typeid(Toolkit::Internal::WireframeVisual) == &typeid(impl));
   }
 
   Vector2 naturalSize;
-  textVisual.GetNaturalSize( naturalSize );
-  DALI_TEST_EQUALS( naturalSize, Vector2( 82.f, 20.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  textVisual.GetNaturalSize(naturalSize);
+  DALI_TEST_EQUALS(naturalSize, Vector2(82.f, 20.f), Math::MACHINE_EPSILON_1000, TEST_LOCATION);
 
-  const float height = textVisual.GetHeightForWidth( 40.f );
-  DALI_TEST_EQUALS( height, 60.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  const float height = textVisual.GetHeightForWidth(40.f);
+  DALI_TEST_EQUALS(height, 60.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
 
   // Test that NPatchVisual is replaced with debug visual
   // TEST_NPATCH_FILE_NAME: image_01.9.jpg
   Property::Map propertyMap8;
-  propertyMap8.Insert( Toolkit::Visual::Property::TYPE, Visual::N_PATCH );
-  propertyMap8.Insert( ImageVisual::Property::URL,  TEST_NPATCH_FILE_NAME );
-  Visual::Base nPatchVisual = factory.CreateVisual( propertyMap8 );
-  DALI_TEST_CHECK( nPatchVisual );
-  TestDebugVisual( application.GetScene(),  nPatchVisual, Visual::N_PATCH, Vector2::ZERO );
+  propertyMap8.Insert(Toolkit::Visual::Property::TYPE, Visual::N_PATCH);
+  propertyMap8.Insert(ImageVisual::Property::URL, TEST_NPATCH_FILE_NAME);
+  Visual::Base nPatchVisual = factory.CreateVisual(propertyMap8);
+  DALI_TEST_CHECK(nPatchVisual);
+  TestDebugVisual(application.GetScene(), nPatchVisual, Visual::N_PATCH, Vector2::ZERO);
 
   EnvironmentVariable::SetTestingEnvironmentVariable(false);
   END_TEST;
@@ -217,78 +221,77 @@ int UtcDaliDebugRenderingGetVisual2(void)
 {
   EnvironmentVariable::SetTestingEnvironmentVariable(true);
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliDebugRenderingGetVisual2: Request visual with various parameters" );
+  tet_infoline("UtcDaliDebugRenderingGetVisual2: Request visual with various parameters");
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
   // Test that color visual is replaced with debug visual
   Dali::Property::Map map;
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::COLOR;
-  map[ ColorVisual::Property::MIX_COLOR ] = Color::CYAN;
+  map[Toolkit::Visual::Property::TYPE]  = Visual::COLOR;
+  map[ColorVisual::Property::MIX_COLOR] = Color::CYAN;
 
-  Visual::Base colorVisual = factory.CreateVisual( map);
-  DALI_TEST_CHECK( colorVisual );
-  TestDebugVisual( application.GetScene(),  colorVisual, Visual::COLOR, Vector2::ZERO );
+  Visual::Base colorVisual = factory.CreateVisual(map);
+  DALI_TEST_CHECK(colorVisual);
+  TestDebugVisual(application.GetScene(), colorVisual, Visual::COLOR, Vector2::ZERO);
 
   // Test that border visual is replaced with debug visual
   map.Clear();
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::BORDER;
-  map[ BorderVisual::Property::COLOR  ] = Color::GREEN;
-  map[ BorderVisual::Property::SIZE   ] = 2.f;
-  Visual::Base borderVisual = factory.CreateVisual( map );
-  DALI_TEST_CHECK( borderVisual );
-  TestDebugVisual( application.GetScene(),  borderVisual, Visual::BORDER, Vector2::ZERO );
+  map[Toolkit::Visual::Property::TYPE] = Visual::BORDER;
+  map[BorderVisual::Property::COLOR]   = Color::GREEN;
+  map[BorderVisual::Property::SIZE]    = 2.f;
+  Visual::Base borderVisual            = factory.CreateVisual(map);
+  DALI_TEST_CHECK(borderVisual);
+  TestDebugVisual(application.GetScene(), borderVisual, Visual::BORDER, Vector2::ZERO);
 
   // Test that image visual is replaced with debug visual
   map.Clear();
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::IMAGE;
-  map[ ImageVisual::Property::URL ] = TEST_IMAGE_FILE_NAME;
-  Visual::Base imageVisual = factory.CreateVisual( map );
-  DALI_TEST_CHECK( imageVisual );
-  TestDebugVisual( application.GetScene(),  imageVisual, Visual::IMAGE, Vector2(64.0f, 64.0f /* Broken Image Size */ ));
+  map[Toolkit::Visual::Property::TYPE] = Visual::IMAGE;
+  map[ImageVisual::Property::URL]      = TEST_IMAGE_FILE_NAME;
+  Visual::Base imageVisual             = factory.CreateVisual(map);
+  DALI_TEST_CHECK(imageVisual);
+  TestDebugVisual(application.GetScene(), imageVisual, Visual::IMAGE, Vector2(64.0f, 64.0f /* Broken Image Size */));
 
   // Test that n patch visual is replaced with debug visual
-  Visual::Base nPatchVisual = factory.CreateVisual( TEST_NPATCH_FILE_NAME, ImageDimensions() );
-  DALI_TEST_CHECK( nPatchVisual );
-  TestDebugVisual( application.GetScene(),  nPatchVisual, Visual::N_PATCH, Vector2::ZERO );
+  Visual::Base nPatchVisual = factory.CreateVisual(TEST_NPATCH_FILE_NAME, ImageDimensions());
+  DALI_TEST_CHECK(nPatchVisual);
+  TestDebugVisual(application.GetScene(), nPatchVisual, Visual::N_PATCH, Vector2::ZERO);
 
   EnvironmentVariable::SetTestingEnvironmentVariable(false);
   END_TEST;
 }
 
-
 int UtcDaliDebugRenderingGetVisual3(void)
 {
-  EnvironmentVariable::SetTestingEnvironmentVariable( true );
+  EnvironmentVariable::SetTestingEnvironmentVariable(true);
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliDebugRenderingGetVisual3: Request visual with various parameters" );
+  tet_infoline("UtcDaliDebugRenderingGetVisual3: Request visual with various parameters");
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
   // Test that image visual is replaced with debug visual
   Dali::Property::Map map;
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::IMAGE;
-  map[ ImageVisual::Property::URL ] = TEST_IMAGE_FILE_NAME;
-  Visual::Base imageVisual = factory.CreateVisual( map );
-  DALI_TEST_CHECK( imageVisual );
-  TestDebugVisual( application.GetScene(),  imageVisual, Visual::IMAGE, Vector2(64.0f, 64.0f /* Broken Image Size */ ));
+  map[Toolkit::Visual::Property::TYPE] = Visual::IMAGE;
+  map[ImageVisual::Property::URL]      = TEST_IMAGE_FILE_NAME;
+  Visual::Base imageVisual             = factory.CreateVisual(map);
+  DALI_TEST_CHECK(imageVisual);
+  TestDebugVisual(application.GetScene(), imageVisual, Visual::IMAGE, Vector2(64.0f, 64.0f /* Broken Image Size */));
 
   // Test that image visual with null string don't make visual
   map.Clear();
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::IMAGE;
-  map[ ImageVisual::Property::URL ] = "";
-  Visual::Base emptyVisual = factory.CreateVisual( map );
-  DALI_TEST_CHECK( emptyVisual );
-  TestDebugVisual( application.GetScene(), emptyVisual, Visual::WIREFRAME, Vector2::ZERO);
+  map[Toolkit::Visual::Property::TYPE] = Visual::IMAGE;
+  map[ImageVisual::Property::URL]      = "";
+  Visual::Base emptyVisual             = factory.CreateVisual(map);
+  DALI_TEST_CHECK(emptyVisual);
+  TestDebugVisual(application.GetScene(), emptyVisual, Visual::WIREFRAME, Vector2::ZERO);
 
-  tet_infoline( "Check that GetVisualObject returns the actual WireframeVisual" );
-  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation( emptyVisual ).GetVisualObject();
-  DALI_TEST_CHECK( dynamic_cast< Toolkit::Internal::WireframeVisual* >( &visualImpl ) );
+  tet_infoline("Check that GetVisualObject returns the actual WireframeVisual");
+  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(emptyVisual).GetVisualObject();
+  DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::WireframeVisual*>(&visualImpl));
 
-  tet_infoline( "Compare the returned emptyVisual with the visual implementation, should be the same" );
-  DALI_TEST_CHECK( emptyVisual.GetObjectPtr() == &visualImpl );
+  tet_infoline("Compare the returned emptyVisual with the visual implementation, should be the same");
+  DALI_TEST_CHECK(emptyVisual.GetObjectPtr() == &visualImpl);
 
   // Test that image view with empty property map don't make visual even DebugRendering is enabled.
   map.Clear();
@@ -298,13 +301,13 @@ int UtcDaliDebugRenderingGetVisual3(void)
 
   // Test that image view with empty property value don't make visual even DebugRendering is enabled.
   Property::Value emptyValue;
-  ImageView imageView2 = ImageView::New();
+  ImageView       imageView2 = ImageView::New();
   imageView2.SetProperty(Control::Property::BACKGROUND, emptyValue);
   imageView2.SetProperty(ImageView::Property::IMAGE, emptyValue);
 
   // Test that image view with invalid property value don't make visual even DebugRendering is enabled.
   Property::Value invalidValue(static_cast<int>(3));
-  ImageView imageView3 = ImageView::New();
+  ImageView       imageView3 = ImageView::New();
   imageView3.SetProperty(Control::Property::BACKGROUND, invalidValue);
   imageView3.SetProperty(ImageView::Property::IMAGE, invalidValue);
 
@@ -315,40 +318,89 @@ int UtcDaliDebugRenderingGetVisual3(void)
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_EQUALS( imageView1.GetRendererCount(), 0u, TEST_LOCATION );
-  DALI_TEST_EQUALS( imageView2.GetRendererCount(), 0u, TEST_LOCATION );
-  DALI_TEST_EQUALS( imageView3.GetRendererCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS(imageView1.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(imageView2.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(imageView3.GetRendererCount(), 0u, TEST_LOCATION);
 
   EnvironmentVariable::SetTestingEnvironmentVariable(false);
   END_TEST;
 }
 
+int UtcDaliDebugRenderingGetVisual4(void)
+{
+  EnvironmentVariable::SetTestingEnvironmentVariable(true);
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliDebugRenderingGetVisual4: Request visual with empty URL and empty Array");
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  // Test that image visual with null string don't make visual
+  for(auto type : {DevelVisual::IMAGE, DevelVisual::ANIMATED_IMAGE, DevelVisual::SVG, DevelVisual::N_PATCH, DevelVisual::ANIMATED_VECTOR_IMAGE})
+  {
+    Dali::Property::Map map;
+    map[Toolkit::Visual::Property::TYPE] = type;
+    map[ImageVisual::Property::URL]      = "";
+    Visual::Base emptyVisual             = factory.CreateVisual(map);
+    DALI_TEST_CHECK(emptyVisual);
+    TestDebugVisual(application.GetScene(), emptyVisual, Visual::WIREFRAME, Vector2::ZERO);
+
+    tet_infoline("Check that GetVisualObject returns the actual WireframeVisual");
+    Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(emptyVisual).GetVisualObject();
+    DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::WireframeVisual*>(&visualImpl));
+
+    tet_infoline("Compare the returned emptyVisual with the visual implementation, should be the same");
+    DALI_TEST_CHECK(emptyVisual.GetObjectPtr() == &visualImpl);
+  }
+
+  // Test that image visual with empty array don't make visual
+  for(auto type : {Visual::IMAGE, Visual::ANIMATED_IMAGE})
+  {
+    Dali::Property::Map   map;
+    Dali::Property::Array emptyArray;
+    map[Toolkit::Visual::Property::TYPE] = type;
+    map[ImageVisual::Property::URL]      = emptyArray;
+    Visual::Base emptyVisual             = factory.CreateVisual(map);
+    DALI_TEST_CHECK(emptyVisual);
+    TestDebugVisual(application.GetScene(), emptyVisual, Visual::WIREFRAME, Vector2::ZERO);
+
+    tet_infoline("Check that GetVisualObject returns the actual WireframeVisual");
+    Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(emptyVisual).GetVisualObject();
+    DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::WireframeVisual*>(&visualImpl));
+
+    tet_infoline("Compare the returned emptyVisual with the visual implementation, should be the same");
+    DALI_TEST_CHECK(emptyVisual.GetObjectPtr() == &visualImpl);
+  }
+
+  EnvironmentVariable::SetTestingEnvironmentVariable(false);
+  END_TEST;
+}
 
 int UtcDaliDebugRenderingGetVisualObject01(void)
 {
-  EnvironmentVariable::SetTestingEnvironmentVariable( true );
+  EnvironmentVariable::SetTestingEnvironmentVariable(true);
   ToolkitTestApplication application;
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
-  tet_infoline( "Create a TextVisual when debugging is enabled, thus creating a proxy Wireframe Visual" );
+  tet_infoline("Create a TextVisual when debugging is enabled, thus creating a proxy Wireframe Visual");
 
   Dali::Property::Map map;
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::TEXT;
-  map[ TextVisual::Property::TEXT ] = "Hello";
+  map[Toolkit::Visual::Property::TYPE] = Visual::TEXT;
+  map[TextVisual::Property::TEXT]      = "Hello";
 
-  Visual::Base textVisual = factory.CreateVisual( map);
-  DALI_TEST_CHECK( textVisual );
+  Visual::Base textVisual = factory.CreateVisual(map);
+  DALI_TEST_CHECK(textVisual);
 
-  tet_infoline( "Check that GetVisualObject returns the actual TextVisual" );
-  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation( textVisual ).GetVisualObject();
-  DALI_TEST_CHECK( dynamic_cast< Toolkit::Internal::TextVisual* >( &visualImpl ) );
+  tet_infoline("Check that GetVisualObject returns the actual TextVisual");
+  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(textVisual).GetVisualObject();
+  DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::TextVisual*>(&visualImpl));
 
-  tet_infoline( "Compare the returned TextVisual with the visual implementation, should differ" );
-  DALI_TEST_CHECK( textVisual.GetObjectPtr() != &visualImpl );
+  tet_infoline("Compare the returned TextVisual with the visual implementation, should differ");
+  DALI_TEST_CHECK(textVisual.GetObjectPtr() != &visualImpl);
 
-  EnvironmentVariable::SetTestingEnvironmentVariable( false );
+  EnvironmentVariable::SetTestingEnvironmentVariable(false);
   END_TEST;
 }
 
@@ -357,23 +409,23 @@ int UtcDaliDebugRenderingGetVisualObject02(void)
   ToolkitTestApplication application;
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
-  tet_infoline( "Create a TextVisual without debugging enabled, thus no proxy Wireframe Visual" );
+  tet_infoline("Create a TextVisual without debugging enabled, thus no proxy Wireframe Visual");
 
   Dali::Property::Map map;
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::TEXT;
-  map[ TextVisual::Property::TEXT ] = "Hello";
+  map[Toolkit::Visual::Property::TYPE] = Visual::TEXT;
+  map[TextVisual::Property::TEXT]      = "Hello";
 
-  Visual::Base textVisual = factory.CreateVisual( map);
-  DALI_TEST_CHECK( textVisual );
+  Visual::Base textVisual = factory.CreateVisual(map);
+  DALI_TEST_CHECK(textVisual);
 
-  tet_infoline( "Check that GetVisualObject returns the actual TextVisual" );
-  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation( textVisual ).GetVisualObject();
-  DALI_TEST_CHECK( dynamic_cast< Toolkit::Internal::TextVisual* >( &visualImpl ) );
+  tet_infoline("Check that GetVisualObject returns the actual TextVisual");
+  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(textVisual).GetVisualObject();
+  DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::TextVisual*>(&visualImpl));
 
-  tet_infoline( "Compare the returned TextVisual with the visual implementation, should be the same" );
-  DALI_TEST_CHECK( textVisual.GetObjectPtr() == &visualImpl );
+  tet_infoline("Compare the returned TextVisual with the visual implementation, should be the same");
+  DALI_TEST_CHECK(textVisual.GetObjectPtr() == &visualImpl);
 
   END_TEST;
 }
@@ -383,40 +435,41 @@ int UtcDaliDebugRenderingGetVisualObject03(void)
   ToolkitTestApplication application;
 
   VisualFactory factory = VisualFactory::Get();
-  DALI_TEST_CHECK( factory );
+  DALI_TEST_CHECK(factory);
 
-  tet_infoline( "Create a WireframeVisual without debugging enabled, thus no proxy Wireframe Visual either" );
+  tet_infoline("Create a WireframeVisual without debugging enabled, thus no proxy Wireframe Visual either");
 
   Dali::Property::Map map;
-  map[ Toolkit::Visual::Property::TYPE ] = Visual::WIREFRAME;
+  map[Toolkit::Visual::Property::TYPE] = Visual::WIREFRAME;
 
-  Visual::Base textVisual = factory.CreateVisual( map);
-  DALI_TEST_CHECK( textVisual );
+  Visual::Base textVisual = factory.CreateVisual(map);
+  DALI_TEST_CHECK(textVisual);
 
-  tet_infoline( "Check that GetVisualObject returns the WireframeVisual" );
-  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation( textVisual ).GetVisualObject();
-  DALI_TEST_CHECK( dynamic_cast< Toolkit::Internal::WireframeVisual* >( &visualImpl ) );
+  tet_infoline("Check that GetVisualObject returns the WireframeVisual");
+  Toolkit::Internal::Visual::Base& visualImpl = GetImplementation(textVisual).GetVisualObject();
+  DALI_TEST_CHECK(dynamic_cast<Toolkit::Internal::WireframeVisual*>(&visualImpl));
 
-  tet_infoline( "Compare the returned Visual with the visual implementation, should be the same" );
-  DALI_TEST_CHECK( textVisual.GetObjectPtr() == &visualImpl );
+  tet_infoline("Compare the returned Visual with the visual implementation, should be the same");
+  DALI_TEST_CHECK(textVisual.GetObjectPtr() == &visualImpl);
 
   END_TEST;
 }
 
 int UtcDaliDebugRenderingRenderText(void)
 {
-  EnvironmentVariable::SetTestingEnvironmentVariable( true );
+  EnvironmentVariable::SetTestingEnvironmentVariable(true);
   ToolkitTestApplication application;
-  tet_infoline( "Ensure we can render text when in debug mode" );
+  tet_infoline("Ensure we can render text when in debug mode");
 
   try
   {
-    Toolkit::TextLabel label = TextLabel::New( "Hello" );
-    application.GetScene().Add( label );
-    DALI_TEST_CHECK( true );
-  } catch( ... )
+    Toolkit::TextLabel label = TextLabel::New("Hello");
+    application.GetScene().Add(label);
+    DALI_TEST_CHECK(true);
+  }
+  catch(...)
   {
-    DALI_TEST_CHECK( false );
+    DALI_TEST_CHECK(false);
   }
 
   END_TEST;
index 96b0021..407dade 100644 (file)
@@ -65,6 +65,7 @@ enum class CommandType
   SET_DEPTH_COMPARE_OP    = 1 << 24,
   SET_DEPTH_TEST_ENABLE   = 1 << 25,
   SET_DEPTH_WRITE_ENABLE  = 1 << 26,
+  DRAW_NATIVE             = 1 << 27,
 };
 
 std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op);
@@ -123,7 +124,8 @@ struct DrawCallDescriptor
   {
     DRAW,
     DRAW_INDEXED,
-    DRAW_INDEXED_INDIRECT
+    DRAW_INDEXED_INDIRECT,
+    DRAW_NATIVE
   };
 
   Type type{}; ///< Type of the draw call
@@ -166,6 +168,11 @@ struct DrawCallDescriptor
       uint32_t                  drawCount;
       uint32_t                  stride;
     } drawIndexedIndirect;
+
+    struct
+    {
+      Graphics::DrawNativeInfo drawNativeInfo;
+    } drawNative;
   };
 };
 
@@ -265,6 +272,12 @@ struct Command
         data.bindUniformBuffers = rhs.data.bindUniformBuffers;
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        data.draw.type       = rhs.data.draw.type;
+        data.draw.drawNative = rhs.data.draw.drawNative;
+        break;
+      }
       case CommandType::DRAW:
       {
         data.draw.type = rhs.data.draw.type;
@@ -418,6 +431,12 @@ struct Command
         data.bindPipeline = rhs.data.bindPipeline;
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        data.draw.type       = rhs.data.draw.type;
+        data.draw.drawNative = rhs.data.draw.drawNative;
+        break;
+      }
       case CommandType::DRAW:
       {
         data.draw.type = rhs.data.draw.type;
@@ -800,6 +819,16 @@ public:
     mCallStack.PushCall("ExecuteCommandBuffers", "");
   }
 
+  void DrawNative(const Graphics::DrawNativeInfo* drawInfo)
+  {
+    mCommands.emplace_back();
+    mCommands.back().type         = CommandType::DRAW_NATIVE;
+    auto& cmd                     = mCommands.back().data.draw;
+    cmd.type                      = DrawCallDescriptor::Type::DRAW_NATIVE;
+    cmd.drawNative.drawNativeInfo = *drawInfo;
+    mCallStack.PushCall("DrawNative", "");
+  }
+
   void Draw(
     uint32_t vertexCount,
     uint32_t instanceCount,
index bedce18..6a8eab4 100644 (file)
@@ -693,6 +693,12 @@ void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& com
         BindPipeline(currentPipeline);
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        auto info = &cmd.data.draw.drawNative.drawNativeInfo;
+        CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
+        break;
+      }
       case CommandType::DRAW:
       {
         if(currentPipeline)
index ec95a75..7b08e1a 100644 (file)
@@ -55,11 +55,12 @@ public:
   : mInterfaceVerified(interfaceVerified),
     mCurrentFocusedActor(),
     mProposedActorToFocus(),
-    mDirection(Control::KeyboardFocus::LEFT)
+    mDirection(Control::KeyboardFocus::LEFT),
+    mDeviceName("")
   {
   }
 
-  Actor GetNextFocusableActor(Actor currentFocusedActor, Actor proposedActorToFocus, Control::KeyboardFocus::Direction direction)
+  Actor GetNextFocusableActor(Actor currentFocusedActor, Actor proposedActorToFocus, Control::KeyboardFocus::Direction direction, const std::string& deviceName)
   {
     tet_infoline("Verifying CustomAlgorithm()");
 
@@ -68,6 +69,7 @@ public:
     mCurrentFocusedActor  = currentFocusedActor;
     mProposedActorToFocus = proposedActorToFocus;
     mDirection            = direction;
+    mDeviceName           = deviceName;
 
     return mProposedActorToFocus;
   }
@@ -78,12 +80,14 @@ public:
     mCurrentFocusedActor  = Actor();
     mProposedActorToFocus = Actor();
     mDirection            = Control::KeyboardFocus::LEFT;
+    mDeviceName           = "";
   }
 
   bool&                             mInterfaceVerified;
   Actor                             mCurrentFocusedActor;
   Actor                             mProposedActorToFocus;
   Control::KeyboardFocus::Direction mDirection;
+  std::string mDeviceName;
 };
 
 // Functors to test whether PreFocusChange signal is emitted when the keyboard focus is about to change
@@ -578,17 +582,19 @@ int UtcDaliKeyboardFocusManagerCustomAlgorithmMoveFocus(void)
   preFocusChangeCallback.Reset();
 
   bool            customAlgorithmInterfaceVerified = false;
+  std::string     deviceName                       = "deviceName";
   CustomAlgorithm customAlgorithm(customAlgorithmInterfaceVerified);
   Toolkit::DevelKeyboardFocusManager::SetCustomAlgorithm(manager, customAlgorithm);
 
   // Move the focus towards right
-  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
+  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::RIGHT, deviceName) == false);
 
   // Because no layout control in the stage and the first actor is focused, it should invoke CustomAlgorithm
   DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
   DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == Actor());
   DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
   DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::RIGHT);
+  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
   customAlgorithm.Reset();
 
   // Check that the focus is set on the first actor
@@ -600,13 +606,14 @@ int UtcDaliKeyboardFocusManagerCustomAlgorithmMoveFocus(void)
   focusChangedCallback.Reset();
 
   // Move the focus towards right
-  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == false);
+  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::RIGHT, deviceName) == false);
 
   // Because no layout control in the stage and the first actor is focused, it should invoke CustomAlgorithm
   DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
   DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == first);
   DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
   DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::RIGHT);
+  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
   customAlgorithm.Reset();
 
   // Check that the focus is set on the second actor
@@ -618,13 +625,14 @@ int UtcDaliKeyboardFocusManagerCustomAlgorithmMoveFocus(void)
   focusChangedCallback.Reset();
 
   // Move the focus towards up
-  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == false);
+  DALI_TEST_CHECK(Toolkit::DevelKeyboardFocusManager::MoveFocus(manager, Control::KeyboardFocus::UP, deviceName) == false);
 
   // Because no layout control in the stage and no actor is focused, it should invoke CustomAlgorithm
   DALI_TEST_CHECK(customAlgorithm.mInterfaceVerified);
   DALI_TEST_CHECK(customAlgorithm.mCurrentFocusedActor == second);
   DALI_TEST_CHECK(customAlgorithm.mProposedActorToFocus == Actor());
   DALI_TEST_CHECK(customAlgorithm.mDirection == Control::KeyboardFocus::UP);
+  DALI_TEST_EQUALS(customAlgorithm.mDeviceName, deviceName, TEST_LOCATION );
   customAlgorithm.Reset();
   DALI_TEST_CHECK(!focusChangedCallback.mSignalVerified);
 
@@ -1983,6 +1991,8 @@ int UtcDaliKeyboardFocusManagerEnableDefaultAlgorithm(void)
   // button1 -- button2
   button1.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
   button2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 0.0f));
+  button1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  button2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
 
   // flush the queue and render once
   application.SendNotification();
@@ -2027,13 +2037,31 @@ int UtcDaliKeyboardFocusManagerEnableDefaultAlgorithm(void)
   // 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
+  // Confirm whether focus is moved to button1
   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();
 
+  // Clears focus.
+  manager.ClearFocus();
+  // There is no actor focused.
+  // button1 -- button2
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+
+  // Move the focus towards right, The focus is on the actor closest to the top left of the window.
+  // [button1] -- button2
+  DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+
+  // Confirm whether focus is moved to button1
+  DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+  DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+  DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor());
+  DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
+  focusChangedCallback.Reset();
+
+
   END_TEST;
 }
 
index ae7eff0..9a3da6c 100644 (file)
@@ -66,20 +66,15 @@ static Dali::Actor CreateHighlightIndicatorActor()
 }
 } // unnamed namespace
 
-ControlAccessible::ControlAccessible(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
-: ActorAccessible(self),
-  mIsModal(modal)
+ControlAccessible::ControlAccessible(Dali::Actor self)
+: ActorAccessible(self)
 {
-  auto control = Dali::Toolkit::Control::DownCast(Self());
+  auto control = 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) {
+  self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle& handle, Dali::Property::Index index, Dali::Property::Value value) {
     if(this->Self() != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
     {
       return;
@@ -222,32 +217,22 @@ bool ControlAccessible::IsShowing()
 
 Dali::Accessibility::States ControlAccessible::CalculateStates()
 {
-  Dali::Actor self = 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;
+  using Dali::Accessibility::State;
 
-  if(self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).GetType() == Dali::Property::NONE)
-  {
-    state[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
-  }
-  else
-  {
-    state[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE).Get<bool>();
-  }
+  Dali::Actor self = Self();
+  Dali::Accessibility::States states;
 
-  state[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
-  state[Dali::Accessibility::State::ENABLED]     = true;
-  state[Dali::Accessibility::State::SENSITIVE]   = true;
-  state[Dali::Accessibility::State::VISIBLE]     = self.GetProperty<bool>(Actor::Property::VISIBLE);
+  states[State::FOCUSABLE]     = self.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE);
+  states[State::FOCUSED]       = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
+  states[State::HIGHLIGHTABLE] = self.GetProperty<bool>(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
+  states[State::HIGHLIGHTED]   = GetCurrentlyHighlightedActor() == self;
+  states[State::ENABLED]       = true;
+  states[State::SENSITIVE]     = true;
+  states[State::VISIBLE]       = self.GetProperty<bool>(Actor::Property::VISIBLE);
+  states[State::SHOWING]       = IsShowing();
+  states[State::DEFUNCT]       = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
 
-  if(mIsModal)
-  {
-    state[Dali::Accessibility::State::MODAL] = true;
-  }
-  state[Dali::Accessibility::State::SHOWING] = IsShowing();
-  state[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
-  return state;
+  return states;
 }
 
 Dali::Accessibility::States ControlAccessible::GetStates()
@@ -348,10 +333,10 @@ bool ControlAccessible::GrabHighlight()
   // Clear the old highlight.
   if(oldHighlightedActor)
   {
-    auto oldHighlightObject = dynamic_cast<Dali::Accessibility::Component*>(Internal::Control::Impl::GetAccessibilityObject(oldHighlightedActor));
-    if(oldHighlightObject)
+    auto oldHighlightedObject = Dali::Accessibility::Component::DownCast(Accessible::Get(oldHighlightedActor));
+    if(oldHighlightedObject)
     {
-      oldHighlightObject->ClearHighlight();
+      oldHighlightedObject->ClearHighlight();
     }
   }
 
index 7b0ae78..dd8389a 100644 (file)
@@ -33,10 +33,9 @@ namespace Dali::Toolkit::DevelControl {
 /**
  * @brief Represents the Accessible object for Dali::Toolkit::Control and derived classes
  *
- * You can create a derived class (and register it using SetAccessibilityConstructor)
+ * You can create a derived class (and override Control::CreateAccessibleObject)
  * in order to customize Accessibility for a given control.
  *
- * @see Dali::Toolkit::DevelControl::SetAccessibilityConstructor
  * @see Dali::Accessibility::Accessible
  * @see Dali::Accessibility::Component
  * @see Dali::Accessibility::Collection
@@ -51,8 +50,6 @@ struct DALI_TOOLKIT_API ControlAccessible : public Dali::Accessibility::ActorAcc
 protected:
   Vector2                       mLastPosition{0.0f, 0.0f};
   Dali::WeakHandle<Dali::Actor> mCurrentHighlightActor;
-  bool mIsModal = false;
-  bool mIsRoot = false;
 
   void ScrollToSelf();
 
@@ -73,7 +70,7 @@ protected:
   bool IsShowing();
 
 public:
-  ControlAccessible(Dali::Actor self, Dali::Accessibility::Role role, bool modal = false);
+  ControlAccessible(Dali::Actor self);
 
   /**
    * @copydoc Dali::Accessibility::Accessible::GetName()
index a98cefe..a604433 100644 (file)
@@ -224,11 +224,6 @@ void ClearAccessibilityRelations(Toolkit::Control control)
   GetControlImplementation(control).mAccessibilityRelations.clear();
 }
 
-void SetAccessibilityConstructor(Dali::Actor control, std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Dali::Actor)> constructor)
-{
-  GetControlImplementation(Toolkit::Control::DownCast(control)).mAccessibilityConstructor = constructor;
-}
-
 void AppendAccessibilityAttribute(Toolkit::Control control, const std::string& key, const std::string& value)
 {
   GetControlImplementation(control).AppendAccessibilityAttribute(key, value);
@@ -256,28 +251,22 @@ Dali::Accessibility::ReadingInfoTypes GetAccessibilityReadingInfoType(Toolkit::C
 
 bool ClearAccessibilityHighlight(Toolkit::Control control)
 {
-  auto* accessible = Dali::Accessibility::Component::DownCast(GetControlImplementation(control).GetAccessibilityObject());
-
-  return accessible ? accessible->ClearHighlight() : false;
+  return GetControlImplementation(control).GetAccessibleObject()->ClearHighlight();
 }
 
 bool GrabAccessibilityHighlight(Toolkit::Control control)
 {
-  auto* accessible = Dali::Accessibility::Component::DownCast(GetControlImplementation(control).GetAccessibilityObject());
-
-  return accessible ? accessible->GrabHighlight() : false;
+  return GetControlImplementation(control).GetAccessibleObject()->GrabHighlight();
 }
 
 Dali::Accessibility::States GetAccessibilityStates(Toolkit::Control control)
 {
-  auto* accessible = GetControlImplementation(control).GetAccessibilityObject();
-
-  return accessible->GetStates();
+  return GetControlImplementation(control).GetAccessibleObject()->GetStates();
 }
 
 void NotifyAccessibilityStateChange(Toolkit::Control control, Dali::Accessibility::States states, bool recurse)
 {
-  GetControlImplementation(control).GetAccessibilityObject()->NotifyAccessibilityStateChange(std::move(states), recurse);
+  GetControlImplementation(control).GetAccessibleObject()->NotifyAccessibilityStateChange(std::move(states), recurse);
 }
 
 } // namespace DevelControl
index be9b759..42384a1 100644 (file)
@@ -575,25 +575,6 @@ DALI_TOOLKIT_API Dali::Accessibility::States GetAccessibilityStates(Toolkit::Con
  */
 DALI_TOOLKIT_API void NotifyAccessibilityStateChange(Toolkit::Control control, Dali::Accessibility::States states, bool recurse);
 
-/**
- * The method allows to set specific constructor for creating accessibility structure
- *
- * Thank to this method hierarchy of accessibility objects can be based on internal hierarchy of Actors.
- * It prevents from necessity of keeping two trees synchronized.
- * The method should be called inside OnInitialize method of all classes inheriting from Control.
- *
- * Possible usage can be as follows:
- * @code
- *   SetAccessibilityConstructor( []( Dali::Actor actor ) {
-       return std::unique_ptr< Dali::Accessibility::Accessible >(
-       new ControlAccessible( actor, Dali::Accessibility::Role::DIALOG, true ) );
-      } );
-  * @endcode
-  *
-  * param constructor callback creating Accessible object
-  */
-DALI_TOOLKIT_API void SetAccessibilityConstructor(Dali::Actor control, std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Dali::Actor)> constructor);
-
 } // namespace DevelControl
 
 } // namespace Toolkit
index c52bf57..d338e39 100644 (file)
@@ -385,12 +385,23 @@ Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect,
 Actor GetNearestFocusableActor(Actor rootActor, Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
 {\r
   Actor nearestActor;\r
-  if(!focusedActor || !rootActor)\r
+  if(!rootActor)\r
   {\r
     return nearestActor;\r
   }\r
 \r
-  Rect<float> focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
+  Rect<float> focusedRect;\r
+  if (!focusedActor)\r
+  {\r
+    // If there is no currently focused actor, it is searched based on the upper left corner of the current window.\r
+    Rect<float> rootRect = DevelActor::CalculateScreenExtents(rootActor);\r
+    focusedRect = Rect<float>(rootRect.x, rootRect.y, 0.f, 0.f);\r
+  }\r
+  else\r
+  {\r
+    focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
+  }\r
+\r
 \r
   // initialize the best candidate to something impossible\r
   // (so the first plausible actor will become the best choice)\r
index f320269..a3ed473 100644 (file)
@@ -50,6 +50,11 @@ bool IsDefaultAlgorithmEnabled(KeyboardFocusManager keyboardFocusManager)
   return GetImpl(keyboardFocusManager).IsDefaultAlgorithmEnabled();
 }
 
+bool MoveFocus(KeyboardFocusManager keyboardFocusManager, Control::KeyboardFocus::Direction direction, const std::string& deviceName)
+{
+  return GetImpl(keyboardFocusManager).MoveFocus(direction, deviceName);
+}
+
 } // namespace DevelKeyboardFocusManager
 
 } // namespace Toolkit
index 192c296..b830445 100644 (file)
@@ -54,9 +54,11 @@ public:
    * @param[in] current The current focused actor
    * @param[in] proposed The proposed focused actor
    * @param[in] direction The direction of focus movement
+   * @param[in] deviceName The name of the device where the key event occurred.
    * @return A handle to the next focusable actor
    */
-  virtual Actor GetNextFocusableActor(Actor current, Actor proposed, Control::KeyboardFocus::Direction direction) = 0;
+  virtual Actor GetNextFocusableActor(Actor current, Actor proposed, Control::KeyboardFocus::Direction direction, const std::string& deviceName = "") = 0;
+
 };
 
 /**
@@ -100,6 +102,20 @@ DALI_TOOLKIT_API void EnableDefaultAlgorithm(KeyboardFocusManager keyboardFocusM
  */
 DALI_TOOLKIT_API bool IsDefaultAlgorithmEnabled(KeyboardFocusManager keyboardFocusManager);
 
+/**
+ * @brief Moves the focus to the next focusable actor in the focus
+ * chain in the given direction (according to the focus traversal
+ * order).
+ *
+ * @param[in] keyboardFocusManager The instance of KeyboardFocusManager
+ * @param direction The direction of focus movement
+ * @param deviceName The device name
+ * @return true if the movement was successful
+ * @pre The KeyboardFocusManager has been initialized.
+ */
+DALI_TOOLKIT_API bool MoveFocus(KeyboardFocusManager keyboardFocusManager, Control::KeyboardFocus::Direction direction, const std::string& deviceName);
+
+
 } // namespace DevelKeyboardFocusManager
 
 } // namespace Toolkit
index d9b3b4d..002ab93 100644 (file)
@@ -187,10 +187,7 @@ const Toolkit::Alignment::Padding& Alignment::GetPadding() const
 
 void Alignment::OnInitialize()
 {
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void Alignment::OnRelayout(const Vector2& size, RelayoutContainer& container)
index 5ed17c8..d7e474f 100644 (file)
@@ -217,10 +217,7 @@ void BloomView::OnInitialize()
   // bind properties for / set shader constants to defaults
   SetupProperties();
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::ANIMATION));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::ANIMATION);
 }
 
 void BloomView::OnSizeSet(const Vector3& targetSize)
index 7fb1ab8..6c33e19 100644 (file)
@@ -620,6 +620,11 @@ bool Button::OnAccessibilityActivated()
   return OnKeyboardEnter();
 }
 
+DevelControl::ControlAccessible* Button::CreateAccessibleObject()
+{
+  return new ButtonAccessible(Self());
+}
+
 bool Button::OnTouch(Actor actor, const TouchEvent& touch)
 {
   if(!IsDisabled() && (actor == touch.GetHitActor(0)))
@@ -1303,7 +1308,7 @@ Padding Button::GetForegroundPadding()
   return mForegroundPadding;
 }
 
-std::string Button::AccessibleImpl::GetNameRaw() const
+std::string Button::ButtonAccessible::GetNameRaw() const
 {
   std::string   labelText;
   auto          slf      = Toolkit::Button::DownCast(Self());
@@ -1318,7 +1323,7 @@ std::string Button::AccessibleImpl::GetNameRaw() const
   return labelText;
 }
 
-Property::Index Button::AccessibleImpl::GetNamePropertyIndex()
+Property::Index Button::ButtonAccessible::GetNamePropertyIndex()
 {
   Property::Index label    = Toolkit::Button::Property::LABEL;
   Property::Map   labelMap = Self().GetProperty<Property::Map>(label);
@@ -1333,7 +1338,7 @@ Property::Index Button::AccessibleImpl::GetNamePropertyIndex()
   }
 }
 
-Dali::Accessibility::States Button::AccessibleImpl::CalculateStates()
+Dali::Accessibility::States Button::ButtonAccessible::CalculateStates()
 {
   auto tmp                                    = DevelControl::ControlAccessible::CalculateStates();
   tmp[Dali::Accessibility::State::SELECTABLE] = true;
index 3e36873..cae3dc8 100644 (file)
@@ -322,6 +322,11 @@ protected: // From Control
   bool OnAccessibilityActivated() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Control::OnKeyboardEnter()
    */
   bool OnKeyboardEnter() override;
@@ -535,13 +540,25 @@ private:
   bool mClickActionPerforming; ///< Used to manage signal emissions during action
 
 protected:
-  struct AccessibleImpl : public DevelControl::ControlAccessible
+  class ButtonAccessible : public DevelControl::ControlAccessible
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
-    std::string                 GetNameRaw() const override;
-    Property::Index             GetNamePropertyIndex() override;
+
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::GetNameRaw()
+     */
+    std::string GetNameRaw() const override;
+
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::GetNamePropertyIndex()
+     */
+    Property::Index GetNamePropertyIndex() override;
   };
 };
 
index 98733ea..78a2794 100644 (file)
@@ -77,15 +77,17 @@ void CheckBoxButton::OnInitialize()
 {
   Button::OnInitialize();
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::CHECK_BOX));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::CHECK_BOX);
 }
 
-Dali::Accessibility::States CheckBoxButton::AccessibleImpl::CalculateStates()
+DevelControl::ControlAccessible* CheckBoxButton::CreateAccessibleObject()
 {
-  auto state = Button::AccessibleImpl::CalculateStates();
+  return new CheckBoxButton::CheckBoxButtonAccessible(Self());
+}
+
+Dali::Accessibility::States CheckBoxButton::CheckBoxButtonAccessible::CalculateStates()
+{
+  auto state = Button::ButtonAccessible::CalculateStates();
   auto self = Toolkit::Button::DownCast(Self());
   if(self.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
   {
@@ -97,10 +99,9 @@ Dali::Accessibility::States CheckBoxButton::AccessibleImpl::CalculateStates()
 void CheckBoxButton::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))
+  if((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);
+    GetAccessibleObject()->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
   }
 }
 
index ffae507..c542143 100644 (file)
@@ -63,6 +63,11 @@ private: // From Button
    */
   void OnInitialize() override;
 
+  /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
 private:
   // Undefined
   CheckBoxButton(const CheckBoxButton&);
@@ -71,12 +76,17 @@ private:
   CheckBoxButton& operator=(const CheckBoxButton&);
 
 protected:
-  struct AccessibleImpl : public Button::AccessibleImpl
+  class CheckBoxButtonAccessible : public Button::ButtonAccessible
   {
-    using Button::AccessibleImpl::AccessibleImpl;
+  public:
+    using Button::ButtonAccessible::ButtonAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
   };
+
   void OnStateChange(State newState) override;
 };
 
index 2958766..9ff9531 100644 (file)
@@ -95,10 +95,12 @@ void PushButton::OnInitialize()
   Actor self = Self();
   self.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::PUSH_BUTTON));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::PUSH_BUTTON);
+}
+
+DevelControl::ControlAccessible* PushButton::CreateAccessibleObject()
+{
+  return new PushButtonAccessible(Self());
 }
 
 void PushButton::SetIconAlignment(const PushButton::IconAlignment iconAlignment)
@@ -194,9 +196,9 @@ Property::Value PushButton::GetProperty(BaseObject* object, Property::Index prop
   return value;
 }
 
-Dali::Accessibility::States PushButton::AccessibleImpl::CalculateStates()
+Dali::Accessibility::States PushButton::PushButtonAccessible::CalculateStates()
 {
-  auto state = Button::AccessibleImpl::CalculateStates();
+  auto state = Button::ButtonAccessible::CalculateStates();
   auto self = Toolkit::Button::DownCast(Self());
   state[Dali::Accessibility::State::PRESSED] = self.GetProperty<bool>(Toolkit::Button::Property::SELECTED);
   return state;
@@ -205,14 +207,15 @@ Dali::Accessibility::States PushButton::AccessibleImpl::CalculateStates()
 void PushButton::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))
+  if((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);
+    auto* accessible = GetAccessibleObject();
+
+    accessible->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);
+      accessible->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
     }
   }
 }
index 6300fe2..21a4d01 100644 (file)
@@ -93,6 +93,11 @@ private: // From Button
    */
   void OnInitialize() override;
 
+  /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
 private:
   /**
    * @brief Sets the alignment mode to use to align the icon to the label.
@@ -119,12 +124,17 @@ private:
   IconAlignment mIconAlignment; ///< The alignment of the icon against the label.
 
 protected:
-  struct AccessibleImpl : public Button::AccessibleImpl
+  class PushButtonAccessible : public Button::ButtonAccessible
   {
-    using Button::AccessibleImpl::AccessibleImpl;
+  public:
+    using Button::ButtonAccessible::ButtonAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
   };
+
   void OnStateChange(State newState) override;
 };
 
index 4b4e070..bf35f99 100644 (file)
@@ -71,10 +71,12 @@ void RadioButton::OnInitialize()
 {
   Button::OnInitialize();
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::RADIO_BUTTON));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::RADIO_BUTTON);
+}
+
+DevelControl::ControlAccessible* RadioButton::CreateAccessibleObject()
+{
+  return new RadioButtonAccessible(Self());
 }
 
 bool RadioButton::OnToggleReleased()
@@ -105,16 +107,15 @@ 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))
+  if((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);
+    GetAccessibleObject()->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
   }
 }
 
-Dali::Accessibility::States RadioButton::AccessibleImpl::CalculateStates()
+Dali::Accessibility::States RadioButton::RadioButtonAccessible::CalculateStates()
 {
-  auto state = Button::AccessibleImpl::CalculateStates();
+  auto state = Button::ButtonAccessible::CalculateStates();
   auto self = Toolkit::Button::DownCast(Self());
 
   if(self.GetProperty<bool>(Toolkit::Button::Property::SELECTED))
index b172750..dbe2d35 100644 (file)
@@ -65,6 +65,11 @@ private: // From Button
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Internal::Button::OnStateChange
    */
   void OnStateChange(State newState) override;
@@ -82,10 +87,14 @@ private:
   RadioButton& operator=(const RadioButton& origin);
 
 protected:
-  struct AccessibleImpl : public Button::AccessibleImpl
+  class RadioButtonAccessible : public Button::ButtonAccessible
   {
-    using Button::AccessibleImpl::AccessibleImpl;
+  public:
+    using Button::ButtonAccessible::ButtonAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
   };
 };
index 3010e69..1b6ef02 100644 (file)
@@ -106,10 +106,12 @@ void ToggleButton::OnInitialize()
   Actor self = Self();
   self.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::TOGGLE_BUTTON));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TOGGLE_BUTTON);
+}
+
+DevelControl::ControlAccessible* ToggleButton::CreateAccessibleObject()
+{
+  return new ToggleButtonAccessible(Self());
 }
 
 void ToggleButton::SetProperty(BaseObject* object, Property::Index propertyIndex, const Property::Value& value)
@@ -372,9 +374,9 @@ void ToggleButton::OnPressed()
   RelayoutRequest();
 }
 
-Dali::Accessibility::States ToggleButton::AccessibleImpl::CalculateStates()
+Dali::Accessibility::States ToggleButton::ToggleButtonAccessible::CalculateStates()
 {
-  auto states = Button::AccessibleImpl::CalculateStates();
+  auto states = Button::ButtonAccessible::CalculateStates();
   auto button = Toolkit::ToggleButton::DownCast(Self());
   if(button.GetProperty<int>(Toolkit::ToggleButton::Property::CURRENT_STATE_INDEX))
   {
@@ -383,7 +385,7 @@ Dali::Accessibility::States ToggleButton::AccessibleImpl::CalculateStates()
   return states;
 }
 
-std::string ToggleButton::AccessibleImpl::GetDescriptionRaw() const
+std::string ToggleButton::ToggleButtonAccessible::GetDescriptionRaw() const
 {
   auto button   = Toolkit::ToggleButton::DownCast(Self());
   auto index    = button.GetProperty<int>(Toolkit::ToggleButton::Property::CURRENT_STATE_INDEX);
@@ -392,7 +394,7 @@ std::string ToggleButton::AccessibleImpl::GetDescriptionRaw() const
   return tooltips[index].Get<std::string>();
 }
 
-Property::Index ToggleButton::AccessibleImpl::GetDescriptionPropertyIndex()
+Property::Index ToggleButton::ToggleButtonAccessible::GetDescriptionPropertyIndex()
 {
   return Toolkit::ToggleButton::Property::TOOLTIPS;
 }
@@ -400,11 +402,12 @@ Property::Index ToggleButton::AccessibleImpl::GetDescriptionPropertyIndex()
 void ToggleButton::OnStateChange(State newState)
 {
   // TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
-  if(Dali::Accessibility::IsUp() && (Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
-     && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
+  if((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);
+    auto* accessible = GetAccessibleObject();
+
+    accessible->EmitStateChanged(Dali::Accessibility::State::CHECKED, mCurrentToggleIndex ? 1 : 0, 0);
+    accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
   }
 }
 
index 6629d40..c6652a5 100644 (file)
@@ -128,6 +128,11 @@ private: // From Button
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Internal::Button::OnRelayout
    */
   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
@@ -152,15 +157,29 @@ private:
   std::vector<Toolkit::Visual::Base> mToggleDisabledSelectedVisuals; ///< Save all disabled selected visuals.
   std::vector<std::string>           mToggleTooltips;                ///< Toggle tooltips.
   unsigned int                       mCurrentToggleIndex;            ///< The index of state.
+
 protected:
-  struct AccessibleImpl : public Button::AccessibleImpl
+  class ToggleButtonAccessible : public Button::ButtonAccessible
   {
-    using Button::AccessibleImpl::AccessibleImpl;
+  public:
+    using Button::ButtonAccessible::ButtonAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
-    std::string                 GetDescriptionRaw() const override;
-    Property::Index             GetDescriptionPropertyIndex() override;
+
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::GetDescriptionRaw()
+     */
+    std::string GetDescriptionRaw() const override;
+
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::GetDescriptionPropertyIndex()
+     */
+    Property::Index GetDescriptionPropertyIndex() override;
   };
+
   void OnStateChange(State newState) override;
 };
 
index 6ec6fc9..39253d0 100644 (file)
@@ -97,10 +97,7 @@ void CanvasView::OnInitialize()
   // CanvasView can relayout in the OnImageReady, alternative to a signal would be to have a upcall from the Control to CanvasView
   Dali::Toolkit::Control handle(GetOwner());
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::IMAGE));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::IMAGE);
 
   Adaptor::Get().RegisterProcessor(*this, true);
 }
index 3a154ca..b49f9d0 100644 (file)
@@ -445,6 +445,19 @@ static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
   return rect.width > 0 && rect.height > 0;
 }
 
+Dali::Accessibility::Accessible* ExternalAccessibleGetter(Dali::Actor actor)
+{
+  auto control = Toolkit::Control::DownCast(actor);
+  if (!control)
+  {
+    return nullptr;
+  }
+
+  auto& controlImpl = Toolkit::Internal::GetImplementation(control);
+
+  return controlImpl.GetAccessibleObject();
+}
+
 } // unnamed namespace
 
 // clang-format off
@@ -512,14 +525,7 @@ Control::Impl::Impl(Control& controlImpl)
   mNeedToEmitResourceReady(false),
   mDispatchKeyEvents(true)
 {
-  Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(
-    [](Dali::Actor actor) -> Dali::Accessibility::Accessible* {
-      return Control::Impl::GetAccessibilityObject(actor);
-    });
-
-  mAccessibilityConstructor = [](Dali::Actor actor) -> std::unique_ptr<Dali::Accessibility::Accessible> {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::UNKNOWN));
-  };
+  Dali::Accessibility::Accessible::RegisterExternalAccessibleGetter(&ExternalAccessibleGetter);
 }
 
 Control::Impl::~Impl()
@@ -556,13 +562,7 @@ const Control::Impl& Control::Impl::Get(const Internal::Control& internalControl
 
 void Control::Impl::CheckHighlightedObjectGeometry()
 {
-  auto accessible = dynamic_cast<Dali::Toolkit::DevelControl::ControlAccessible*>(mAccessibilityObject.get());
-  if(!accessible)
-  {
-    DALI_LOG_ERROR("accessible is not a pointer to a DevelControl::ControlAccessible type");
-    return;
-  }
-
+  auto accessible     = GetAccessibleObject();
   auto lastPosition   = accessible->GetLastPosition();
   auto accessibleRect = accessible->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
   auto rect = GetShowingGeometry(accessibleRect, accessible);
@@ -590,7 +590,7 @@ void Control::Impl::CheckHighlightedObjectGeometry()
       // notify AT-clients on outgoing moves only
       if(mAccessibilityLastScreenRelativeMoveType != Dali::Accessibility::ScreenRelativeMoveType::INSIDE)
       {
-        mAccessibilityObject.get()->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
+        accessible->EmitMovedOutOfScreen(mAccessibilityLastScreenRelativeMoveType);
       }
       break;
     }
@@ -1362,7 +1362,7 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         {
           controlImpl.mImpl->mAccessibilityHidden = hidden;
 
-          auto* accessible = controlImpl.mImpl->GetAccessibilityObject();
+          auto* accessible = controlImpl.GetAccessibleObject();
           auto* parent     = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
           if (parent)
           {
@@ -2085,27 +2085,14 @@ void Control::Impl::OnIdleCallback()
   mIdleCallback = nullptr;
 }
 
-Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject()
+Toolkit::DevelControl::ControlAccessible* Control::Impl::GetAccessibleObject()
 {
-  if(!mAccessibilityObject)
+  if(!mAccessibleObject)
   {
-    mAccessibilityObject = mAccessibilityConstructor(mControlImpl.Self());
+    mAccessibleObject.reset(mControlImpl.CreateAccessibleObject());
   }
-  return mAccessibilityObject.get();
-}
 
-Dali::Accessibility::Accessible* Control::Impl::GetAccessibilityObject(Dali::Actor actor)
-{
-  if(actor)
-  {
-    auto control = Dali::Toolkit::Control::DownCast(actor);
-    if(control)
-    {
-      auto controlImpl = static_cast<Internal::Control*>(&control.GetImplementation());
-      return controlImpl->mImpl->GetAccessibilityObject();
-    }
-  }
-  return nullptr;
+  return mAccessibleObject.get();
 }
 
 } // namespace Internal
index 73f87b9..2354a94 100644 (file)
@@ -423,20 +423,9 @@ public:
   void UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
 
   /**
-   * @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
+   * @copydoc Dali::Toolkit::Internal::Control::GetAccessibleObject()
    */
-  static Dali::Accessibility::Accessible* GetAccessibilityObject(Dali::Actor actor);
+  Toolkit::DevelControl::ControlAccessible* GetAccessibleObject();
 
 private:
   /**
@@ -548,8 +537,7 @@ public:
   Dali::Accessibility::Role mAccessibilityRole = Dali::Accessibility::Role::UNKNOWN;
 
   std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> mAccessibilityRelations;
-  std::function<std::unique_ptr<Dali::Accessibility::Accessible>(Actor)>            mAccessibilityConstructor;
-  std::unique_ptr<Dali::Accessibility::Accessible>                                  mAccessibilityObject;
+  std::unique_ptr<Toolkit::DevelControl::ControlAccessible>                         mAccessibleObject;
 
   // Gesture Detection
   PinchGestureDetector     mPinchGestureDetector;
index 0f3e141..5f132c7 100644 (file)
@@ -234,10 +234,7 @@ void EffectsView::OnInitialize()
   mChildrenRoot.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
   self.Add(mChildrenRoot);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void EffectsView::OnSizeSet(const Vector3& targetSize)
index 964afe2..b220445 100644 (file)
@@ -835,10 +835,7 @@ void FlexContainer::OnInitialize()
   self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
   SetAsKeyboardFocusGroup(true);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 } // namespace Internal
index 64d5ecb..31b7c61 100644 (file)
@@ -295,10 +295,7 @@ void GaussianBlurView::OnInitialize()
   mInternalRoot.Add(mVertBlurActor);
   mInternalRoot.Add(mRenderDownsampledCamera);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
index 46c9e11..f769b44 100644 (file)
@@ -94,10 +94,7 @@ void ImageView::OnInitialize()
   Dali::Toolkit::Control handle(GetOwner());
   handle.ResourceReadySignal().Connect(this, &ImageView::OnResourceReady);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::IMAGE));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::IMAGE);
 }
 
 void ImageView::SetImage(const Property::Map& map)
index 6da7915..671551b 100644 (file)
@@ -218,10 +218,7 @@ void Magnifier::Initialize()
   constraint.AddSource(Source(self, Actor::Property::WORLD_SCALE));
   constraint.Apply();
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 Magnifier::~Magnifier()
index b9ee873..1384a15 100644 (file)
@@ -280,10 +280,7 @@ void Model3dView::OnInitialize()
   Shader   shader = Shader::New(SHADER_MODEL3D_VIEW_SIMPLE_SHADER_VERT, SHADER_MODEL3D_VIEW_SIMPLE_SHADER_FRAG);
   mRenderer       = Renderer::New(mesh, shader);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::IMAGE));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::IMAGE);
 }
 
 void Model3dView::LoadGeometry()
index 9eab290..f140e3e 100644 (file)
@@ -70,10 +70,7 @@ Toolkit::NavigationView NavigationView::New()
 
 void NavigationView::OnInitialize()
 {
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void NavigationView::OnSceneConnection(int depth)
index 69369de..a5e9e95 100644 (file)
@@ -414,10 +414,7 @@ void PageTurnView::OnInitialize()
   // enable the pan gesture which is attached to the control
   EnableGestureDetection(GestureType::Value(GestureType::PAN));
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::PAGE_TAB_LIST));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::PAGE_TAB_LIST);
 }
 
 Shader PageTurnView::CreateShader(const Property::Map& shaderMap)
index f811812..f7ebcf4 100644 (file)
@@ -345,9 +345,12 @@ void Popup::OnInitialize()
 
   DevelControl::AppendAccessibilityAttribute(Toolkit::Control::DownCast(self), "sub-role", "Alert");
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(new AccessibleImpl(actor, Dali::Accessibility::Role::DIALOG, true));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::DIALOG);
+}
+
+DevelControl::ControlAccessible* Popup::CreateAccessibleObject()
+{
+  return new PopupAccessible(Self());
 }
 
 Popup::~Popup()
@@ -1994,7 +1997,7 @@ void Popup::SetupTouch()
   }
 }
 
-std::string Popup::AccessibleImpl::GetNameRaw() const
+std::string Popup::PopupAccessible::GetNameRaw() const
 {
   auto        popup = Toolkit::Popup::DownCast(Self());
   std::string title;
@@ -2016,13 +2019,14 @@ std::string Popup::AccessibleImpl::GetNameRaw() const
   return title;
 }
 
-Dali::Accessibility::States Popup::AccessibleImpl::CalculateStates()
+Dali::Accessibility::States Popup::PopupAccessible::CalculateStates()
 {
   auto states       = DevelControl::ControlAccessible::CalculateStates();
   auto popup        = Toolkit::Popup::DownCast(Self());
   auto displayState = popup.GetProperty<std::string>(Toolkit::Popup::Property::DISPLAY_STATE);
 
   states[Dali::Accessibility::State::SHOWING] = (displayState == "SHOWN" || displayState == "SHOWING");
+  states[Dali::Accessibility::State::MODAL]   = true;
 
   return states;
 }
index 50a2fd6..8f4aef0 100644 (file)
@@ -241,11 +241,19 @@ public:
   static Property::Value GetProperty(BaseObject* object, Property::Index propertyIndex);
 
 protected:
-  struct AccessibleImpl : public DevelControl::ControlAccessible
+  class PopupAccessible : public DevelControl::ControlAccessible
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
-    std::string                 GetNameRaw() const override;
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::GetNameRaw()
+     */
+    std::string GetNameRaw() const override;
+
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+     */
     Dali::Accessibility::States CalculateStates() override;
   };
 
@@ -429,6 +437,11 @@ private:
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * Called whenever the popup layout is re-set up.
    * Normally due to a change in contents.
    * Note: This is only done when the popup is shown.
index 1a243a2..f98ece7 100644 (file)
@@ -165,12 +165,14 @@ ProgressBar::~ProgressBar()
 
 void ProgressBar::OnInitialize()
 {
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::PROGRESS_BAR));
-  });
-  //Enable highightability
-  Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+  // Accessibility
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::PROGRESS_BAR);
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+}
+
+DevelControl::ControlAccessible* ProgressBar::CreateAccessibleObject()
+{
+  return new ProgressBarAccessible(Self());
 }
 
 void ProgressBar::OnRelayout(const Vector2& size, RelayoutContainer& container)
@@ -271,7 +273,7 @@ void ProgressBar::SetProgressValue(float value)
     mValueChangedSignal.Emit(self, mProgressValue, mSecondaryProgressValue);
     if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
     {
-      Control::Impl::GetAccessibilityObject(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
+      GetAccessibleObject()->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
     }
     RelayoutRequest();
   }
@@ -676,23 +678,23 @@ void ProgressBar::OnSceneConnection(int depth)
   }
 }
 
-double ProgressBar::AccessibleImpl::GetMinimum() const
+double ProgressBar::ProgressBarAccessible::GetMinimum() const
 {
   return DEFAULT_LOWER_BOUND;
 }
 
-double ProgressBar::AccessibleImpl::GetCurrent() const
+double ProgressBar::ProgressBarAccessible::GetCurrent() const
 {
   auto self = Toolkit::ProgressBar::DownCast(Self());
   return self.GetProperty(Toolkit::ProgressBar::Property::PROGRESS_VALUE).Get<float>();
 }
 
-double ProgressBar::AccessibleImpl::GetMaximum() const
+double ProgressBar::ProgressBarAccessible::GetMaximum() const
 {
   return DEFAULT_UPPER_BOUND;
 }
 
-bool ProgressBar::AccessibleImpl::SetCurrent(double current)
+bool ProgressBar::ProgressBarAccessible::SetCurrent(double current)
 {
   if(current < GetMinimum() || current > GetMaximum())
   {
@@ -704,7 +706,7 @@ bool ProgressBar::AccessibleImpl::SetCurrent(double current)
   return true;
 }
 
-double ProgressBar::AccessibleImpl::GetMinimumIncrement() const
+double ProgressBar::ProgressBarAccessible::GetMinimumIncrement() const
 {
   return 0.0;
 }
index 96540d2..13c9cb3 100644 (file)
@@ -201,6 +201,11 @@ private:
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * Get the range of the valid values the ProgressBar handle can move between
    *
    * @param[in] currentSize The current size of the ProgressBar
@@ -265,15 +270,35 @@ private:
   Property::Map           mSecondaryProgressVisualMap;    ///< To backup visual properties when switching determinate/indeterminate.
 
 protected:
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::Value
+  class ProgressBarAccessible : public DevelControl::ControlAccessible,
+                                public virtual Dali::Accessibility::Value
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimum()
+     */
     double GetMinimum() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetCurrent()
+     */
     double GetCurrent() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMaximum()
+     */
     double GetMaximum() const override;
-    bool   SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::SetCurrent()
+     */
+    bool SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimumIncrement()
+     */
     double GetMinimumIncrement() const override;
   };
 };
index 1fef71b..88fdf6b 100644 (file)
@@ -209,13 +209,17 @@ ScrollBar::~ScrollBar()
 
 void ScrollBar::OnInitialize()
 {
+  auto self = Self();
+
   CreateDefaultIndicatorActor();
-  Self().SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+  self.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
+
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::SCROLL_BAR);
+}
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::SCROLL_BAR));
-  });
+DevelControl::ControlAccessible* ScrollBar::CreateAccessibleObject()
+{
+  return new ScrollBarAccessible(Self());
 }
 
 void ScrollBar::SetScrollPropertySource(Handle handle, Property::Index propertyScrollPosition, Property::Index propertyMinScrollPosition, Property::Index propertyMaxScrollPosition, Property::Index propertyScrollContentSize)
@@ -360,7 +364,7 @@ void ScrollBar::OnScrollPositionIntervalReached(PropertyNotification& source)
     mScrollPositionIntervalReachedSignal.Emit(scrollableHandle.GetCurrentProperty<float>(mPropertyScrollPosition));
     if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
     {
-      Control::Impl::GetAccessibilityObject(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
+      GetAccessibleObject()->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
     }
   }
 }
@@ -861,28 +865,28 @@ Toolkit::ScrollBar ScrollBar::New(Toolkit::ScrollBar::Direction direction)
   return handle;
 }
 
-double ScrollBar::AccessibleImpl::GetMinimum() const
+double ScrollBar::ScrollBarAccessible::GetMinimum() const
 {
   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() const
+double ScrollBar::ScrollBarAccessible::GetCurrent() const
 {
   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() const
+double ScrollBar::ScrollBarAccessible::GetMaximum() const
 {
   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)
+bool ScrollBar::ScrollBarAccessible::SetCurrent(double current)
 {
   if(current < GetMinimum() || current > GetMaximum())
   {
@@ -910,7 +914,7 @@ bool ScrollBar::AccessibleImpl::SetCurrent(double current)
   return true;
 }
 
-double ScrollBar::AccessibleImpl::GetMinimumIncrement() const
+double ScrollBar::ScrollBarAccessible::GetMinimumIncrement() const
 {
   return 1.0;
 }
index 97a7daa..57def7f 100644 (file)
@@ -211,6 +211,11 @@ private: // from Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Control::OnPan
    */
   void OnPan(const PanGesture& gesture) override;
@@ -314,15 +319,35 @@ private:
   bool mIndicatorFirstShow : 1; ///< True if the indicator has never been shown
 
 protected:
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::Value
+  class ScrollBarAccessible : public DevelControl::ControlAccessible,
+                              public virtual Dali::Accessibility::Value
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimum()
+     */
     double GetMinimum() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetCurrent()
+     */
     double GetCurrent() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMaximum()
+     */
     double GetMaximum() const override;
-    bool   SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::SetCurrent()
+     */
+    bool SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimumIncrement()
+     */
     double GetMinimumIncrement() const override;
   };
 };
index e9b58c8..6d6e211 100644 (file)
@@ -367,9 +367,12 @@ void ItemView::OnInitialize()
   // Connect wheel event
   self.WheelEventSignal().Connect(this, &ItemView::OnWheelEvent);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(new AccessibleImpl(actor, Dali::Accessibility::Role::SCROLL_PANE));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::SCROLL_PANE);
+}
+
+DevelControl::ControlAccessible* ItemView::CreateAccessibleObject()
+{
+  return new ItemViewAccessible(Self());
 }
 
 ItemView::~ItemView()
@@ -1345,7 +1348,7 @@ void ItemView::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
   }
 }
 
-bool ItemView::AccessibleImpl::ScrollToChild(Actor child)
+bool ItemView::ItemViewAccessible::ScrollToChild(Actor child)
 {
   auto itemView = Dali::Toolkit::ItemView::DownCast(Self());
   Toolkit::GetImpl(itemView).OnKeyboardFocusChangeCommitted(child);
index 7e3d8c1..b388e22 100644 (file)
@@ -419,6 +419,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Toolkit::Control::OnAccessibilityPan()
    */
   bool OnAccessibilityPan(PanGesture gesture) override;
@@ -434,10 +439,14 @@ private: // From Control
   void OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor) override;
 
 protected:
-  struct AccessibleImpl : public Scrollable::AccessibleImpl
+  class ItemViewAccessible : public Scrollable::ScrollableAccessible
   {
-    using Scrollable::AccessibleImpl::AccessibleImpl;
+  public:
+    using Scrollable::ScrollableAccessible::ScrollableAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::ScrollToChild()
+     */
     bool ScrollToChild(Actor child) override;
   };
 
index 712cb17..0dceb47 100644 (file)
@@ -680,10 +680,12 @@ void ScrollView::OnInitialize()
   // Connect wheel event
   self.WheelEventSignal().Connect(this, &ScrollView::OnWheelEvent);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::SCROLL_PANE));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::SCROLL_PANE);
+}
+
+DevelControl::ControlAccessible* ScrollView::CreateAccessibleObject()
+{
+  return new ScrollViewAccessible(Self());
 }
 
 void ScrollView::OnSceneConnection(int depth)
@@ -1262,7 +1264,7 @@ Toolkit::ScrollView::SnapStartedSignalType& ScrollView::SnapStartedSignal()
   return mSnapStartedSignal;
 }
 
-bool ScrollView::AccessibleImpl::ScrollToChild(Actor child)
+bool ScrollView::ScrollViewAccessible::ScrollToChild(Actor child)
 {
   auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self());
   if(Toolkit::GetImpl(scrollView).FindClosestActor() == child)
@@ -1270,6 +1272,19 @@ bool ScrollView::AccessibleImpl::ScrollToChild(Actor child)
     return false;
   }
 
+  // child can be one of descendants
+  // find direct child of ScrollView to avoid the ASSERT in ScrollTo
+  auto parent = child.GetParent();
+  while (parent && parent != Self())
+  {
+    child = parent;
+    parent = child.GetParent();
+  }
+  if (!parent)
+  {
+    return false;
+  }
+
   // FIXME: ScrollTo does not work (snaps back to original position)
   scrollView.ScrollTo(child, scrollView.GetScrollFlickDuration());
   return true;
index 4061727..d9dddfc 100644 (file)
@@ -661,6 +661,11 @@ private: // private overridden functions from CustomActorImpl and Controls
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc CustomActorImpl::OnSceneConnection()
    */
   void OnSceneConnection(int depth) override;
@@ -841,10 +846,14 @@ private:
   void WrapPosition(Vector2& position) const;
 
 protected:
-  struct AccessibleImpl : public Scrollable::AccessibleImpl
+  class ScrollViewAccessible : public Scrollable::ScrollableAccessible
   {
-    using Scrollable::AccessibleImpl::AccessibleImpl;
+  public:
+    using Scrollable::ScrollableAccessible::ScrollableAccessible;
 
+    /**
+     * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::ScrollToChild()
+     */
     bool ScrollToChild(Actor child) override;
   };
 
index ea3240f..7c12348 100644 (file)
@@ -92,17 +92,19 @@ Scrollable::~Scrollable()
 {
 }
 
-bool Scrollable::AccessibleImpl::IsScrollable() const
+bool Scrollable::ScrollableAccessible::IsScrollable() const
 {
   return true;
 }
 
 void Scrollable::OnInitialize()
 {
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::SCROLL_PANE));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::SCROLL_PANE);
+}
+
+DevelControl::ControlAccessible* Scrollable::CreateAccessibleObject()
+{
+  return new ScrollableAccessible(Self());
 }
 
 bool Scrollable::IsOvershootEnabled() const
index 44d9a33..5e30b86 100644 (file)
@@ -117,10 +117,14 @@ public:
   virtual void SetOvershootSize(const Vector2& size) = 0;
 
 protected: // From Control
-  struct AccessibleImpl : public DevelControl::ControlAccessible
+  class ScrollableAccessible : public DevelControl::ControlAccessible
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
+    /**
+     * @copydoc Dali::Accessibility::Component::IsScrollable()
+     */
     bool IsScrollable() const override;
   };
 
@@ -129,6 +133,11 @@ protected: // From Control
    */
   virtual void OnInitialize() override;
 
+  /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
 private:
   /**
    * Temporary function to override EnableScrollOvershoot functionality for overshoot
index 1197a46..9140b97 100644 (file)
@@ -256,10 +256,7 @@ void ShadowView::OnInitialize()
   blurStrengthConstraint.AddSource(Source(self, mBlurStrengthPropertyIndex));
   blurStrengthConstraint.Apply();
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void ShadowView::OnChildAdd(Actor& child)
index 7e6370d..a48ddbe 100644 (file)
@@ -202,16 +202,17 @@ void Slider::OnInitialize()
   // Size the Slider actor to a default
   self.SetProperty(Actor::Property::SIZE, Vector2(DEFAULT_HIT_REGION.x, DEFAULT_HIT_REGION.y));
 
-  // Set the Slider to be highlightable in Screen Reader mode
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
   // Connect to the touch signal
   self.TouchedSignal().Connect(this, &Slider::OnTouch);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::SLIDER));
-  });
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::SLIDER);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+}
+
+DevelControl::ControlAccessible* Slider::CreateAccessibleObject()
+{
+  return new SliderAccessible(Self());
 }
 
 void Slider::OnRelayout(const Vector2& size, RelayoutContainer& container)
@@ -950,7 +951,7 @@ void Slider::SetValue(float value)
   DisplayValue(mValue, true);
   if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
   {
-    Control::Impl::GetAccessibilityObject(Self())->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
+    GetAccessibleObject()->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
   }
 }
 
@@ -1411,25 +1412,25 @@ Property::Value Slider::GetProperty(BaseObject* object, Property::Index property
   return value;
 }
 
-double Slider::AccessibleImpl::GetMinimum() const
+double Slider::SliderAccessible::GetMinimum() const
 {
   auto self = Toolkit::Slider::DownCast(Self());
   return self.GetProperty(Toolkit::Slider::Property::LOWER_BOUND).Get<float>();
 }
 
-double Slider::AccessibleImpl::GetCurrent() const
+double Slider::SliderAccessible::GetCurrent() const
 {
   auto self = Toolkit::Slider::DownCast(Self());
   return self.GetProperty(Toolkit::Slider::Property::VALUE).Get<float>();
 }
 
-double Slider::AccessibleImpl::GetMaximum() const
+double Slider::SliderAccessible::GetMaximum() const
 {
   auto self = Toolkit::Slider::DownCast(Self());
   return self.GetProperty(Toolkit::Slider::Property::UPPER_BOUND).Get<float>();
 }
 
-bool Slider::AccessibleImpl::SetCurrent(double current)
+bool Slider::SliderAccessible::SetCurrent(double current)
 {
   if(current < GetMinimum() || current > GetMaximum())
     return false;
@@ -1477,7 +1478,7 @@ bool Slider::AccessibleImpl::SetCurrent(double current)
   return true;
 }
 
-double Slider::AccessibleImpl::GetMinimumIncrement() const
+double Slider::SliderAccessible::GetMinimumIncrement() const
 {
   auto self = Toolkit::Slider::DownCast(Self());
 
index 7385953..7bf3e2a 100644 (file)
@@ -319,6 +319,11 @@ private:
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * Hit region touch
    *
    * @param[in] actor The actor the event is raised for
@@ -749,15 +754,35 @@ private:
     mSnapToMarks : 1;  ///< Turn on or off snapping to marks
 
 protected:
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::Value
+  class SliderAccessible : public DevelControl::ControlAccessible,
+                           public virtual Dali::Accessibility::Value
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
 
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimum()
+     */
     double GetMinimum() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetCurrent()
+     */
     double GetCurrent() const override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMaximum()
+     */
     double GetMaximum() const override;
-    bool   SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::SetCurrent()
+     */
+    bool SetCurrent(double) override;
+
+    /**
+     * @copydoc Dali::Accessibility::Value::GetMinimumIncrement()
+     */
     double GetMinimumIncrement() const override;
   };
 };
index ad90105..7ea1492 100644 (file)
@@ -149,10 +149,7 @@ void SuperBlurView::OnInitialize()
 
   mBlurStrengthPropertyIndex = self.RegisterUniqueProperty("blurStrength", 0.f);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
 void SuperBlurView::SetTexture(Texture texture)
index 2426775..2afc0da 100644 (file)
@@ -1119,10 +1119,7 @@ void TableView::OnInitialize()
   self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
   SetAsKeyboardFocusGroup(true);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::TABLE));
-  });
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TABLE);
 }
 
 void TableView::ResizeContainers(unsigned int rows, unsigned int columns)
index 696b44a..833b81b 100644 (file)
  * limitations under the License.
  */
 
+// EXTERNAL INCLUDES
 #include <dali/public-api/actors/layer.h>
 
+// INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/hidden-text.h>
 #include <dali-toolkit/internal/text/text-view.h>
 
 namespace Dali::Toolkit::Internal
@@ -151,4 +156,344 @@ void CommonTextUtils::RenderText(
   }
 }
 
+std::size_t TextControlAccessible::GetCharacterCount() const
+{
+  return GetWholeText().size();
+}
+
+std::size_t TextControlAccessible::GetCursorOffset() const
+{
+  return 0u;
+}
+
+Rect<> TextControlAccessible::GetRangeExtents(std::size_t startOffset, std::size_t endOffset, Accessibility::CoordinateType type)
+{
+  if(!ValidateRange(GetWholeText(), startOffset, endOffset))
+  {
+    return {0, 0, 0, 0};
+  }
+
+  auto rect    = GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
+  auto extents = GetExtents(type);
+
+  rect.x += extents.x;
+  rect.y += extents.y;
+
+  return rect;
+}
+
+Accessibility::Range TextControlAccessible::GetRangeOfSelection(std::size_t selectionIndex) const
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return {};
+  }
+
+  auto indices     = GetTextController()->GetSelectionIndexes();
+  auto startOffset = static_cast<std::size_t>(indices.first);
+  auto endOffset   = static_cast<std::size_t>(indices.second);
+  auto text        = GetText(startOffset, endOffset);
+
+  return {startOffset, endOffset, text};
+}
+
+std::string TextControlAccessible::GetText(std::size_t startOffset, std::size_t endOffset) const
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startOffset, endOffset))
+  {
+    return {};
+  }
+
+  if(IsHiddenInput())
+  {
+    std::uint32_t substituteCharacterUtf32 = GetSubstituteCharacter();
+    std::string   substituteCharacterUtf8;
+    std::string   substituteText;
+
+    Toolkit::Text::Utf32ToUtf8(&substituteCharacterUtf32, 1, substituteCharacterUtf8);
+
+    while(substituteText.length() < endOffset - startOffset)
+    {
+      substituteText.append(substituteCharacterUtf8);
+    }
+
+    return substituteText;
+  }
+
+  return text.substr(startOffset, endOffset - startOffset);
+}
+
+Accessibility::Range TextControlAccessible::GetTextAtOffset(std::size_t offset, Accessibility::TextBoundary boundary) const
+{
+  Accessibility::Range range{};
+
+  if(IsHiddenInput())
+  {
+    // Returning empty object, as there is no possibility to parse the textfield
+    // when its content is hidden.
+    return range;
+  }
+
+  auto text     = GetWholeText();
+  auto textSize = text.size();
+
+  switch(boundary)
+  {
+    case Dali::Accessibility::TextBoundary::CHARACTER:
+    {
+      if(offset < textSize)
+      {
+        range.content     = text[offset];
+        range.startOffset = offset;
+        range.endOffset   = offset + 1;
+      }
+      break;
+    }
+
+    case Dali::Accessibility::TextBoundary::WORD:
+    case Dali::Accessibility::TextBoundary::LINE:
+    {
+      std::vector<char> breaks(textSize, '\0');
+
+      if(boundary == Dali::Accessibility::TextBoundary::WORD)
+      {
+        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(text.c_str()), textSize, "", breaks.data());
+      }
+      else
+      {
+        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(text.c_str()), textSize, "", breaks.data());
+      }
+
+      std::size_t index   = 0u;
+      std::size_t counter = 0u;
+
+      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     = text.substr(start, index - start + 1);
+          range.startOffset = start;
+          range.endOffset   = index + 1;
+        }
+
+        if(boundary == Dali::Accessibility::TextBoundary::LINE)
+        {
+          index++;
+        }
+      }
+      break;
+    }
+
+    case Dali::Accessibility::TextBoundary::SENTENCE: // Not supported by default
+    case Dali::Accessibility::TextBoundary::PARAGRAPH: // Not supported by libunibreak library
+    default:
+    {
+      break;
+    }
+  }
+
+  return range;
+}
+
+bool TextControlAccessible::RemoveSelection(std::size_t selectionIndex)
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return false;
+  }
+
+  GetTextController()->SetSelection(0, 0);
+
+  return true;
+}
+
+bool TextControlAccessible::SetCursorOffset(std::size_t offset)
+{
+  return false;
+}
+
+bool TextControlAccessible::SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset)
+{
+  // Since DALi supports only one selection, indices other than 0 are ignored
+  if(selectionIndex > 0)
+  {
+    return false;
+  }
+
+  // Lack of ValidateRange() is intentional
+
+  GetTextController()->SetSelection(startOffset, endOffset);
+
+  return true;
+}
+
+Accessibility::Hyperlink* TextControlAccessible::GetLink(std::int32_t linkIndex) const
+{
+  if(linkIndex < 0 || linkIndex >= GetLinkCount())
+  {
+    return nullptr;
+  }
+
+  auto anchor = GetTextAnchors()[linkIndex];
+
+  return Accessibility::Hyperlink::DownCast(Accessibility::Accessible::Get(anchor));
+}
+
+std::int32_t TextControlAccessible::GetLinkCount() const
+{
+  return static_cast<std::int32_t>(GetTextAnchors().size());
+}
+
+std::int32_t TextControlAccessible::GetLinkIndex(std::int32_t characterOffset) const
+{
+  return GetTextController()->GetAnchorIndex(static_cast<std::size_t>(characterOffset));
+}
+
+std::string TextControlAccessible::GetWholeText() const
+{
+  std::string text;
+
+  GetTextController()->GetText(text);
+
+  return text;
+}
+
+std::uint32_t TextControlAccessible::GetSubstituteCharacter() const
+{
+  return Toolkit::Text::STAR;
+}
+
+bool TextControlAccessible::IsHiddenInput() const
+{
+  return false;
+}
+
+bool TextControlAccessible::ValidateRange(const std::string& string, std::size_t begin, std::size_t end)
+{
+  auto size = string.size();
+
+  if(end <= begin || begin >= size || end > size)
+  {
+    return false;
+  }
+
+  // TODO: Check whether the range [begin, end) describes a valid substring:
+  // 1. It does not break multi-byte UTF-8 sequences.
+  // 2. It does not break graphemes (compound emojis, glyphs with combining characters etc.).
+
+  return true;
+}
+
+Accessibility::States EditableTextControlAccessible::CalculateStates()
+{
+  using Dali::Accessibility::State;
+
+  auto states       = DevelControl::ControlAccessible::CalculateStates();
+  auto focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
+
+  states[State::EDITABLE]  = true;
+  states[State::FOCUSABLE] = true;
+  states[State::FOCUSED]   = (Self() == focusControl);
+
+  return states;
+}
+
+std::size_t EditableTextControlAccessible::GetCursorOffset() const
+{
+  return GetTextController()->GetCursorPosition();
+}
+
+bool EditableTextControlAccessible::SetCursorOffset(std::size_t offset)
+{
+  if(offset > GetCharacterCount())
+  {
+    return false;
+  }
+
+  GetTextController()->ResetCursorPosition(offset);
+  RequestTextRelayout();
+
+  return true;
+}
+
+bool EditableTextControlAccessible::CopyText(std::size_t startPosition, std::size_t endPosition)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, endPosition))
+  {
+    return false;
+  }
+
+  GetTextController()->CopyStringToClipboard(text.substr(startPosition, endPosition - startPosition));
+
+  return true;
+}
+
+bool EditableTextControlAccessible::CutText(std::size_t startPosition, std::size_t endPosition)
+{
+  if(!CopyText(startPosition, endPosition))
+  {
+    return false;
+  }
+
+  return DeleteText(startPosition, endPosition);
+}
+
+bool EditableTextControlAccessible::DeleteText(std::size_t startPosition, std::size_t endPosition)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, endPosition))
+  {
+    return false;
+  }
+
+  return SetTextContents(text.erase(startPosition, endPosition - startPosition));
+}
+
+bool EditableTextControlAccessible::InsertText(std::size_t startPosition, std::string newText)
+{
+  auto text = GetWholeText();
+
+  if(!ValidateRange(text, startPosition, startPosition + 1))
+  {
+    return false;
+  }
+
+  return SetTextContents(text.insert(startPosition, std::move(newText)));
+}
+
+bool EditableTextControlAccessible::SetTextContents(std::string newContents)
+{
+  GetTextController()->SetText(std::move(newContents));
+
+  return true;
+}
+
 } // namespace Dali::Toolkit::Internal
index 212f162..f6a9a2f 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/atspi-interfaces/editable-text.h>
+#include <dali/devel-api/atspi-interfaces/hypertext.h>
+#include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-accessible.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
-#include <dali/public-api/actors/actor.h>
-
-#include <dali/public-api/common/vector-wrapper.h>
 
 namespace Dali::Toolkit::Internal
 {
@@ -70,6 +77,181 @@ public:
     std::vector<Toolkit::TextAnchor>& anchorActors);
 };
 
+class TextControlAccessible : public DevelControl::ControlAccessible,
+                              public virtual Dali::Accessibility::Text,
+                              public virtual Dali::Accessibility::Hypertext
+{
+public:
+  using DevelControl::ControlAccessible::ControlAccessible;
+
+  // Text
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCharacterCount()
+   */
+  std::size_t GetCharacterCount() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+   */
+  std::size_t GetCursorOffset() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetRangeExtents()
+   */
+  Rect<> GetRangeExtents(std::size_t startOffset, std::size_t endOffset, Accessibility::CoordinateType type) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
+   */
+  Accessibility::Range GetRangeOfSelection(std::size_t selectionIndex) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetText()
+   */
+  std::string GetText(std::size_t startOffset, std::size_t endOffset) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetTextAtOffset()
+   */
+  Accessibility::Range GetTextAtOffset(std::size_t offset, Accessibility::TextBoundary boundary) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::RemoveSelection()
+   */
+  bool RemoveSelection(std::size_t selectionIndex) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+   */
+  bool SetCursorOffset(std::size_t offset) override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetRangeOfSelection()
+   */
+  bool SetRangeOfSelection(std::size_t selectionIndex, std::size_t startOffset, std::size_t endOffset) override;
+
+  // Hypertext
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLink()
+   */
+  Accessibility::Hyperlink* GetLink(std::int32_t linkIndex) const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+   */
+  std::int32_t GetLinkCount() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+   */
+  std::int32_t GetLinkIndex(std::int32_t characterOffset) const override;
+
+protected:
+  /**
+   * @brief Gets whole text.
+   *
+   * @return The text
+   */
+  std::string GetWholeText() const;
+
+  /**
+   * @brief Gets text anchors.
+   *
+   * @return Text anchors
+   */
+  virtual const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const = 0;
+
+  /**
+   * @brief Gets text controller.
+   *
+   * @return The text controller
+   */
+  virtual Toolkit::Text::ControllerPtr GetTextController() const = 0;
+
+  /**
+   * @brief Get substitute character for hidden text.
+   *
+   * @return The substitute character (Unicode codepoint)
+   */
+  virtual std::uint32_t GetSubstituteCharacter() const;
+
+  /**
+   * @brief Checks whether text should be hidden (replaced with substitute characters).
+   *
+   * @return True if text should be hidden, false otherwise
+   */
+  virtual bool IsHiddenInput() const;
+
+  /**
+   * @brief Checks whether [startPosition, endPosition) is a valid, non-empty range within a given string.
+   *
+   * @param string Source string
+   * @param begin Start index (inclusive)
+   * @param end End index (exclusive)
+   * @return true if the range is valid, false otherwise
+   */
+  static bool ValidateRange(const std::string& string, std::size_t begin, std::size_t end);
+};
+
+class EditableTextControlAccessible : public TextControlAccessible,
+                                      public virtual Dali::Accessibility::EditableText
+{
+public:
+  using TextControlAccessible::TextControlAccessible;
+
+  /**
+   * @copydoc Dali::Toolkit::DevelControl::ControlAccessible::CalculateStates()
+   */
+  Accessibility::States CalculateStates() override;
+
+  // Text
+
+  /**
+   * @copydoc Dali::Accessibility::Text::GetCursorOffset()
+   */
+  std::size_t GetCursorOffset() const override;
+
+  /**
+   * @copydoc Dali::Accessibility::Text::SetCursorOffset()
+   */
+  bool SetCursorOffset(std::size_t offset) override;
+
+  // EditableText
+
+  /**
+   * @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::EditableText::DeleteText()
+   */
+  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;
+
+protected:
+  /**
+   * @brief Requests text relayout.
+   */
+  virtual void RequestTextRelayout() = 0;
+};
+
 } // namespace Dali::Toolkit::Internal
 
 #endif //DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H
index 37831ea..8abb0ae 100644 (file)
@@ -145,13 +145,14 @@ void TextAnchor::OnInitialize()
 {
   Actor self = Self();
 
-  // Enable highlightability
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::LINK);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+}
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::LINK));
-  });
+DevelControl::ControlAccessible* TextAnchor::CreateAccessibleObject()
+{
+  return new TextAnchorAccessible(Self());
 }
 
 TextAnchor::TextAnchor()
@@ -166,35 +167,35 @@ TextAnchor::~TextAnchor()
 {
 }
 
-int32_t TextAnchor::AccessibleImpl::GetEndIndex() const
+int32_t TextAnchor::TextAnchorAccessible::GetEndIndex() const
 {
   auto self = Toolkit::TextAnchor::DownCast(Self());
   return self.GetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX).Get<int>();
 }
 
-int32_t TextAnchor::AccessibleImpl::GetStartIndex() const
+int32_t TextAnchor::TextAnchorAccessible::GetStartIndex() const
 {
   auto self = Toolkit::TextAnchor::DownCast(Self());
   return self.GetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX).Get<int>();
 }
 
-int32_t TextAnchor::AccessibleImpl::GetAnchorCount() const
+int32_t TextAnchor::TextAnchorAccessible::GetAnchorCount() const
 {
   return 1;
 }
 
-Dali::Accessibility::Accessible* TextAnchor::AccessibleImpl::GetAnchorAccessible(int32_t anchorIndex) const
+Dali::Accessibility::Accessible* TextAnchor::TextAnchorAccessible::GetAnchorAccessible(int32_t anchorIndex) const
 {
-  return Control::Impl::GetAccessibilityObject(Self());
+  return const_cast<TextAnchorAccessible*>(this);
 }
 
-std::string TextAnchor::AccessibleImpl::GetAnchorUri(int32_t anchorIndex) const
+std::string TextAnchor::TextAnchorAccessible::GetAnchorUri(int32_t anchorIndex) const
 {
   auto self = Toolkit::TextAnchor::DownCast(Self());
   return self.GetProperty(Toolkit::TextAnchor::Property::URI).Get<std::string>();
 }
 
-bool TextAnchor::AccessibleImpl::IsValid() const
+bool TextAnchor::TextAnchorAccessible::IsValid() const
 {
   return !GetAnchorUri(0).empty();
 }
index e26006d..8b32bdd 100644 (file)
@@ -71,6 +71,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Control::OnPropertySet()
    */
   // void OnPropertySet(Property::Index index, const Property::Value& propertyValue) override;
@@ -105,10 +110,12 @@ protected:
   /**
    * @brief This structure is to connect TextAnchor with Accessible functions.
    */
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::Hyperlink
+  class TextAnchorAccessible : public DevelControl::ControlAccessible,
+                               public virtual Dali::Accessibility::Hyperlink
   {
+  public:
     using DevelControl::ControlAccessible::ControlAccessible;
+
     /**
      * @copydoc Dali::Accessibility::Hyperlink::GetEndIndex()
      */
index 6202c8f..d3c0154 100644 (file)
@@ -33,7 +33,6 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
@@ -583,9 +582,6 @@ void TextEditor::OnInitialize()
   self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT);
   self.OnSceneSignal().Connect(this, &TextEditor::OnSceneConnect);
 
-  //Enable highightability
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
   DevelControl::SetInputMethodContext(*this, mInputMethodContext);
 
   // Creates an extra control to be used as stencil buffer.
@@ -603,15 +599,19 @@ void TextEditor::OnInitialize()
 
   self.Add(mStencil);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
-  });
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::ENTRY);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
 
   Accessibility::Bridge::EnabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged);
   Accessibility::Bridge::DisabledSignal().Connect(this, &TextEditor::OnAccessibilityStatusChanged);
 }
 
+DevelControl::ControlAccessible* TextEditor::CreateAccessibleObject()
+{
+  return new TextEditorAccessible(Self());
+}
+
 void TextEditor::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
 {
   DALI_LOG_INFO(gTextEditorLogFilter, Debug::Verbose, "TextEditor::OnStyleChange\n");
@@ -909,26 +909,17 @@ void TextEditor::RequestTextRelayout()
 
 void TextEditor::TextInserted(unsigned int position, unsigned int length, const std::string& content)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextInserted(position, length, content);
-  }
+  GetAccessibleObject()->EmitTextInserted(position, length, content);
 }
 
 void TextEditor::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextDeleted(position, length, content);
-  }
+  GetAccessibleObject()->EmitTextDeleted(position, length, content);
 }
 
 void TextEditor::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition);
-  }
+  GetAccessibleObject()->EmitTextCursorMoved(newPosition);
 
   if((oldPosition != newPosition) && !mCursorPositionChanged)
   {
@@ -1349,315 +1340,31 @@ TextEditor::~TextEditor()
   }
 }
 
-std::string TextEditor::AccessibleImpl::GetName() const
-{
-  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) const
-{
-  if(endOffset <= startOffset)
-  {
-    return {};
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
-
-  return text.substr(startOffset, endOffset - startOffset);
-}
-
-size_t TextEditor::AccessibleImpl::GetCharacterCount() const
-{
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  return text.size();
-}
-
-size_t TextEditor::AccessibleImpl::GetCursorOffset() const
-{
-  auto slf = Toolkit::TextEditor::DownCast(Self());
-  return Dali::Toolkit::GetImpl(slf).GetTextController()->GetCursorPosition();
-}
-
-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.GetTextController()->ResetCursorPosition(offset);
-  slfImpl.RequestTextRelayout();
-
-  return true;
-}
-
-Dali::Accessibility::Range TextEditor::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) const
-{
-  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{};
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      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     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return range;
-}
-
-Dali::Accessibility::Range TextEditor::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex) const
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  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>(indices.first), static_cast<size_t>(indices.second), value};
-}
-
-bool TextEditor::AccessibleImpl::RemoveSelection(size_t selectionIndex)
+std::string TextEditor::TextEditorAccessible::GetName() const
 {
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
+  return GetWholeText();
 }
 
-bool TextEditor::AccessibleImpl::SetRangeOfSelection(size_t selectionIndex, size_t startOffset, size_t endOffset)
+const std::vector<Toolkit::TextAnchor>& TextEditor::TextEditorAccessible::GetTextAnchors() const
 {
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextEditor::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
   auto self = Toolkit::TextEditor::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
 
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-bool TextEditor::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
+Toolkit::Text::ControllerPtr TextEditor::TextEditorAccessible::GetTextController() const
 {
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
   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;
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
-bool TextEditor::AccessibleImpl::CutText(size_t startPosition, size_t endPosition)
+void TextEditor::TextEditorAccessible::RequestTextRelayout()
 {
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
+  auto  self     = Toolkit::TextEditor::DownCast(Self());
+  auto& selfImpl = Toolkit::GetImpl(self);
 
-  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));
-
-  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)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
-  return true;
-}
-
-Dali::Accessibility::States TextEditor::AccessibleImpl::CalculateStates()
-{
-  using namespace Dali::Accessibility;
-
-  auto states              = DevelControl::ControlAccessible::CalculateStates();
-  states[State::EDITABLE]  = true;
-  states[State::FOCUSABLE] = true;
-
-  Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(Self() == focusControl)
-  {
-    states[State::FOCUSED] = true;
-  }
-
-  return states;
-}
-
-bool TextEditor::AccessibleImpl::InsertText(size_t startPosition, std::string text)
-{
-  auto self         = Toolkit::TextEditor::DownCast(Self());
-  auto insertedText = self.GetProperty(Toolkit::TextEditor::Property::TEXT).Get<std::string>();
-
-  insertedText.insert(startPosition, text);
-
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(insertedText));
-
-  return true;
-}
-
-bool TextEditor::AccessibleImpl::SetTextContents(std::string newContents)
-{
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  self.SetProperty(Toolkit::TextEditor::Property::TEXT, std::move(newContents));
-  return true;
-}
-
-int32_t TextEditor::AccessibleImpl::GetLinkCount() const
-{
-  auto self = Toolkit::TextEditor::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
-}
-
-Accessibility::Hyperlink* TextEditor::AccessibleImpl::GetLink(int32_t linkIndex) const
-{
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextEditor::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
-
-int32_t TextEditor::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextEditor::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  selfImpl.RequestTextRelayout();
 }
 
 } // namespace Internal
index 8a96a13..5739ac2 100644 (file)
@@ -32,6 +32,7 @@
 #include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
@@ -160,6 +161,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Control::OnStyleChange()
    */
   void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
@@ -577,106 +583,31 @@ private: // Data
   /**
    * @brief This structure is to connect TextEditor with Accessible functions.
    */
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::EditableText,
-                          public virtual Dali::Accessibility::Hypertext
+  class TextEditorAccessible : public EditableTextControlAccessible
   {
-    using DevelControl::ControlAccessible::ControlAccessible;
+  public:
+    using EditableTextControlAccessible::EditableTextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Accessible::GetName()
      */
     std::string GetName() const override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Text::GetText()
-     */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
-     */
-    size_t GetCharacterCount() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
-     */
-    size_t GetCursorOffset() const 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) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const 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::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) 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;
-
-    /**
-     * @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;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+     * @copydoc Dali::Toolkit::Internal::EditableTextControlAccessible::RequestTextRelayout()
      */
-    int32_t GetLinkCount() const override;
+    void RequestTextRelayout() override;
   };
 };
 
index 35d06ea..b1ea8e7 100644 (file)
@@ -33,7 +33,6 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
-#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-property-handler.h>
@@ -206,28 +205,6 @@ Toolkit::TextField::InputStyle::Mask ConvertInputStyle(Text::InputStyle::Mask in
   return fieldInputStyleMask;
 }
 
-bool IsHiddenInput(Toolkit::TextField textField)
-{
-  Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
-  auto          mode                = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
-  if(mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE))
-  {
-    return true;
-  }
-  return false;
-}
-
-char GetSubstituteCharacter(Toolkit::TextField textField)
-{
-  Property::Map hiddenInputSettings = textField.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
-  auto          substChar           = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
-  if(substChar)
-  {
-    return static_cast<char>(substChar->Get<int>());
-  }
-  return STAR;
-}
-
 } // namespace
 
 Toolkit::TextField TextField::New()
@@ -550,9 +527,6 @@ void TextField::OnInitialize()
   self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT);
   self.OnSceneSignal().Connect(this, &TextField::OnSceneConnect);
 
-  //Enable highightability
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
   DevelControl::SetInputMethodContext(*this, mInputMethodContext);
 
   if(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy)
@@ -560,15 +534,19 @@ void TextField::OnInitialize()
     EnableClipping();
   }
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::ENTRY));
-  });
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::ENTRY);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
 
   Accessibility::Bridge::EnabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
   Accessibility::Bridge::DisabledSignal().Connect(this, &TextField::OnAccessibilityStatusChanged);
 }
 
+DevelControl::ControlAccessible* TextField::CreateAccessibleObject()
+{
+  return new TextFieldAccessible(Self());
+}
+
 void TextField::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
 {
   DALI_LOG_INFO(gTextFieldLogFilter, Debug::Verbose, "TextField::OnStyleChange\n");
@@ -884,26 +862,17 @@ void TextField::SetEditable(bool editable)
 
 void TextField::TextInserted(unsigned int position, unsigned int length, const std::string& content)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextInserted(position, length, content);
-  }
+  GetAccessibleObject()->EmitTextInserted(position, length, content);
 }
 
 void TextField::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextDeleted(position, length, content);
-  }
+  GetAccessibleObject()->EmitTextDeleted(position, length, content);
 }
 
 void TextField::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
 {
-  if(Accessibility::IsUp())
-  {
-    Control::Impl::GetAccessibilityObject(Self())->EmitTextCursorMoved(newPosition);
-  }
+  GetAccessibleObject()->EmitTextCursorMoved(newPosition);
 
   if((oldPosition != newPosition) && !mCursorPositionChanged)
   {
@@ -1192,340 +1161,59 @@ Vector<Vector2> TextField::GetTextPosition(const uint32_t startIndex, const uint
   return mController->GetTextPosition(startIndex, endIndex);
 }
 
-std::string TextField::AccessibleImpl::GetName() const
+std::string TextField::TextFieldAccessible::GetName() const
 {
-  auto self = Toolkit::TextField::DownCast(Self());
-  if(IsHiddenInput(self))
+  if(IsHiddenInput())
   {
     return {};
   }
 
-  return self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-}
-
-std::string TextField::AccessibleImpl::GetText(size_t startOffset, size_t endOffset) const
-{
-  if(endOffset <= startOffset)
-  {
-    return {};
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
-  if(IsHiddenInput(self))
-  {
-    return std::string(endOffset - startOffset, GetSubstituteCharacter(self));
-  }
-  return text.substr(startOffset, endOffset - startOffset);
+  return GetWholeText();
 }
 
-size_t TextField::AccessibleImpl::GetCharacterCount() const
+const std::vector<Toolkit::TextAnchor>& TextField::TextFieldAccessible::GetTextAnchors() const
 {
   auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
 
-  return text.size();
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-size_t TextField::AccessibleImpl::GetCursorOffset() const
+Toolkit::Text::ControllerPtr TextField::TextFieldAccessible::GetTextController() const
 {
   auto self = Toolkit::TextField::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).GetTextController()->GetCursorPosition();
-}
-
-bool TextField::AccessibleImpl::SetCursorOffset(size_t offset)
-{
-  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();
-
-  return true;
-}
-
-Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
-  size_t offset, Dali::Accessibility::TextBoundary boundary) const
-{
-  auto self  = Toolkit::TextField::DownCast(Self());
-  auto range = Dali::Accessibility::Range{};
-
-  if(IsHiddenInput(self))
-  {
-    // Returning empty object, as there is no possibility to parse the textfield
-    // when its content is hidden.
-    return range;
-  }
-
-  auto text     = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-  auto textSize = text.size();
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      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     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
 
-  return range;
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
-Dali::Accessibility::Range TextField::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex) const
+std::uint32_t TextField::TextFieldAccessible::GetSubstituteCharacter() const
 {
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  auto self       = Toolkit::TextField::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  auto indices    = controller->GetSelectionIndexes();
-
-  auto startOffset = static_cast<size_t>(indices.first);
-  auto endOffset   = static_cast<size_t>(indices.second);
+  auto self                = Toolkit::TextField::DownCast(Self());
+  auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+  auto substChar           = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::SUBSTITUTE_CHARACTER);
 
-  if(IsHiddenInput(self))
-  {
-    return {startOffset, endOffset, std::string(endOffset - startOffset, GetSubstituteCharacter(self))};
-  }
-
-  std::string value{};
-  controller->RetrieveSelection(value);
-  return {startOffset, endOffset, value};
-}
-
-bool TextField::AccessibleImpl::RemoveSelection(size_t selectionIndex)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
-}
-
-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(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextField::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
-
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
-}
-
-bool TextField::AccessibleImpl::CopyText(size_t startPosition, size_t endPosition)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  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)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  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));
-
-  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)
-{
-  if(endPosition <= startPosition)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextField::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  self.SetProperty(Toolkit::TextField::Property::TEXT, text.substr(0, startPosition) + text.substr(endPosition));
-
-  return true;
-}
-
-Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
-{
-  using namespace Dali::Accessibility;
-
-  auto states = DevelControl::ControlAccessible::CalculateStates();
-
-  states[State::EDITABLE]  = true;
-  states[State::FOCUSABLE] = true;
-
-  Toolkit::Control focusControl = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
-  if(Self() == focusControl)
+  if(substChar)
   {
-    states[State::FOCUSED] = true;
+    return static_cast<std::uint32_t>(substChar->Get<int>());
   }
 
-  return states;
+  return TextControlAccessible::GetSubstituteCharacter();
 }
 
-bool TextField::AccessibleImpl::InsertText(size_t startPosition, std::string text)
+bool TextField::TextFieldAccessible::IsHiddenInput() const
 {
-  auto self         = Toolkit::TextField::DownCast(Self());
-  auto insertedText = self.GetProperty(Toolkit::TextField::Property::TEXT).Get<std::string>();
-
-  insertedText.insert(startPosition, text);
-
-  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(insertedText));
+  auto self                = Toolkit::TextField::DownCast(Self());
+  auto hiddenInputSettings = self.GetProperty<Property::Map>(Toolkit::TextField::Property::HIDDEN_INPUT_SETTINGS);
+  auto mode                = hiddenInputSettings.Find(Toolkit::HiddenInput::Property::MODE);
 
-  return true;
+  return (mode && (mode->Get<int>() != Toolkit::HiddenInput::Mode::HIDE_NONE));
 }
 
-bool TextField::AccessibleImpl::SetTextContents(std::string newContents)
+void TextField::TextFieldAccessible::RequestTextRelayout()
 {
-  auto self = Toolkit::TextField::DownCast(Self());
-  self.SetProperty(Toolkit::TextField::Property::TEXT, std::move(newContents));
-  return true;
-}
+  auto  self     = Toolkit::TextField::DownCast(Self());
+  auto& selfImpl = Toolkit::GetImpl(self);
 
-int32_t TextField::AccessibleImpl::GetLinkCount() const
-{
-  auto self = Toolkit::TextField::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
-}
-
-Accessibility::Hyperlink* TextField::AccessibleImpl::GetLink(int32_t linkIndex) const
-{
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextField::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
-
-int32_t TextField::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextField::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  selfImpl.RequestTextRelayout();
 }
 
 } // namespace Internal
index c10dd51..d2d7fdf 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
@@ -151,6 +152,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Control::OnStyleChange()
    */
   void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
@@ -526,106 +532,41 @@ protected:
   /**
    * @brief This structure is to connect TextField with Accessible functions.
    */
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::EditableText,
-                          public virtual Dali::Accessibility::Hypertext
+  class TextFieldAccessible : public EditableTextControlAccessible
   {
-    using DevelControl::ControlAccessible::ControlAccessible;
+  public:
+    using EditableTextControlAccessible::EditableTextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Accessible::GetName()
      */
     std::string GetName() const override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Text::GetText()
-     */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
-     */
-    size_t GetCharacterCount() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
-     */
-    size_t GetCursorOffset() const 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) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const 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::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) 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;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::InsertText()
-     */
-    bool InsertText(size_t startPosition, std::string text) override;
-
-    /**
-     * @copydoc Dali::Accessibility::EditableText::SetTextContents()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    bool SetTextContents(std::string newContents) override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::EditableText::DeleteText()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    bool DeleteText(size_t startPosition, size_t endPosition) override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetSubstituteCharacter()
      */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
+    std::uint32_t GetSubstituteCharacter() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::IsHiddenInput()
      */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
+    bool IsHiddenInput() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+     * @copydoc Dali::Toolkit::Internal::EditableTextControlAccessible::RequestTextRelayout()
      */
-    int32_t GetLinkCount() const override;
+    void RequestTextRelayout() override;
   };
 };
 
index fa9c6c0..76d0ee2 100644 (file)
@@ -883,9 +883,6 @@ void TextLabel::OnInitialize()
   self.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
   self.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
 
-  // Enable highlightability
-  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
-
   // Enable the text ellipsis.
   mController->SetTextElideEnabled(true); // If false then text larger than control will overflow
 
@@ -899,15 +896,19 @@ void TextLabel::OnInitialize()
   Layout::Engine& engine = mController->GetLayoutEngine();
   engine.SetCursorWidth(0u); // Do not layout space for the cursor.
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new AccessibleImpl(actor, Dali::Accessibility::Role::LABEL));
-  });
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::LABEL);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
 
   Accessibility::Bridge::EnabledSignal().Connect(this, &TextLabel::OnAccessibilityStatusChanged);
   Accessibility::Bridge::DisabledSignal().Connect(this, &TextLabel::OnAccessibilityStatusChanged);
 }
 
+DevelControl::ControlAccessible* TextLabel::CreateAccessibleObject()
+{
+  return new TextLabelAccessible(Self());
+}
+
 void TextLabel::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextLabel::OnStyleChange\n");
@@ -1198,227 +1199,28 @@ Vector<Vector2> TextLabel::GetTextPosition(const uint32_t startIndex, const uint
   return mController->GetTextPosition(startIndex, endIndex);
 }
 
-std::string TextLabel::AccessibleImpl::GetNameRaw() const
+std::string TextLabel::TextLabelAccessible::GetNameRaw() const
 {
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  return self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
+  return GetWholeText();
 }
 
-Property::Index TextLabel::AccessibleImpl::GetNamePropertyIndex()
+Property::Index TextLabel::TextLabelAccessible::GetNamePropertyIndex()
 {
   return Toolkit::TextLabel::Property::TEXT;
 }
 
-std::string TextLabel::AccessibleImpl::GetText(size_t startOffset, size_t endOffset) const
+const std::vector<Toolkit::TextAnchor>& TextLabel::TextLabelAccessible::GetTextAnchors() const
 {
-  if(endOffset <= startOffset)
-  {
-    return {};
-  }
-
   auto self = Toolkit::TextLabel::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
-
-  if(startOffset > text.size() || endOffset > text.size())
-  {
-    return {};
-  }
 
-  return text.substr(startOffset, endOffset - startOffset);
+  return Toolkit::GetImpl(self).mAnchorActors;
 }
 
-size_t TextLabel::AccessibleImpl::GetCharacterCount() const
+Toolkit::Text::ControllerPtr TextLabel::TextLabelAccessible::GetTextController() const
 {
   auto self = Toolkit::TextLabel::DownCast(Self());
-  auto text = self.GetProperty(Toolkit::TextLabel::Property::TEXT).Get<std::string>();
-
-  return text.size();
-}
-
-size_t TextLabel::AccessibleImpl::GetCursorOffset() const
-{
-  return {};
-}
-
-bool TextLabel::AccessibleImpl::SetCursorOffset(size_t offset)
-{
-  return {};
-}
-
-Dali::Accessibility::Range TextLabel::AccessibleImpl::GetTextAtOffset(size_t offset, Dali::Accessibility::TextBoundary boundary) const
-{
-  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{};
-
-  switch(boundary)
-  {
-    case Dali::Accessibility::TextBoundary::CHARACTER:
-    {
-      if(offset < textSize)
-      {
-        range.content     = text[offset];
-        range.startOffset = offset;
-        range.endOffset   = offset + 1;
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::WORD:
-    case Dali::Accessibility::TextBoundary::LINE:
-    {
-      auto textString = text.c_str();
-      auto breaks     = std::vector<char>(textSize, 0);
-
-      if(boundary == Dali::Accessibility::TextBoundary::WORD)
-      {
-        Accessibility::Accessible::FindWordSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-      else
-      {
-        Accessibility::Accessible::FindLineSeparationsUtf8(reinterpret_cast<const utf8_t*>(textString), textSize, "", breaks.data());
-      }
-
-      auto index   = 0u;
-      auto counter = 0u;
-      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     = text.substr(start, index - start + 1);
-          range.startOffset = start;
-          range.endOffset   = index + 1;
-        }
-
-        if(boundary == Dali::Accessibility::TextBoundary::LINE)
-        {
-          index++;
-        }
-      }
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::SENTENCE:
-    {
-      /* not supported by default */
-      break;
-    }
-    case Dali::Accessibility::TextBoundary::PARAGRAPH:
-    {
-      /* Paragraph is not supported by libunibreak library */
-      break;
-    }
-    default:
-      break;
-  }
-
-  return range;
-}
-
-Dali::Accessibility::Range TextLabel::AccessibleImpl::GetRangeOfSelection(size_t selectionIndex) const
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return {};
-  }
-
-  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>(indices.first), static_cast<size_t>(indices.second), value};
-}
-
-bool TextLabel::AccessibleImpl::RemoveSelection(size_t selectionIndex)
-{
-  // Since DALi supports only one selection indexes higher than 0 are ignored
-  if(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(0, 0);
-  return true;
-}
-
-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(selectionIndex > 0)
-  {
-    return false;
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  Dali::Toolkit::GetImpl(self).GetTextController()->SetSelection(startOffset, endOffset);
-  return true;
-}
-
-Rect<> TextLabel::AccessibleImpl::GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type)
-{
-  if (endOffset <= startOffset || endOffset <= 0)
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  auto rect = Dali::Toolkit::GetImpl(self).GetTextController()->GetTextBoundingRectangle(startOffset, endOffset - 1);
-
-  auto componentExtents = this->GetExtents(type);
-
-  rect.x += componentExtents.x;
-  rect.y += componentExtents.y;
-
-  return rect;
-}
-
-int32_t TextLabel::AccessibleImpl::GetLinkCount() const
-{
-  auto self = Toolkit::TextLabel::DownCast(Self());
-  return Dali::Toolkit::GetImpl(self).mAnchorActors.size();
-}
-
-Accessibility::Hyperlink* TextLabel::AccessibleImpl::GetLink(int32_t linkIndex) const
-{
-  if(linkIndex < 0 || linkIndex >= GetLinkCount())
-  {
-    return nullptr;
-  }
-  auto self        = Toolkit::TextLabel::DownCast(Self());
-  auto anchorActor = Dali::Toolkit::GetImpl(self).mAnchorActors[linkIndex];
-  return dynamic_cast<Accessibility::Hyperlink*>(Dali::Accessibility::Accessible::Get(anchorActor));
-}
-
-int32_t TextLabel::AccessibleImpl::GetLinkIndex(int32_t characterOffset) const
-{
-  auto self       = Toolkit::TextLabel::DownCast(Self());
-  auto controller = Dali::Toolkit::GetImpl(self).GetTextController();
-  return controller->GetAnchorIndex(static_cast<size_t>(characterOffset));
+  return Toolkit::GetImpl(self).GetTextController();
 }
 
 } // namespace Internal
index 9cba1c4..49f9197 100644 (file)
@@ -25,6 +25,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/controls/text-controls/common-text-utils.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
@@ -130,6 +131,11 @@ private: // From Control
   void OnInitialize() override;
 
   /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
+  /**
    * @copydoc Control::OnStyleChange()
    */
   void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
@@ -246,56 +252,10 @@ protected:
   /**
    * @brief This structure is to connect TextLabel with Accessible functions.
    */
-  struct AccessibleImpl : public DevelControl::ControlAccessible,
-                          public virtual Dali::Accessibility::Text,
-                          public virtual Dali::Accessibility::Hypertext
+  class TextLabelAccessible : public TextControlAccessible
   {
-    using DevelControl::ControlAccessible::ControlAccessible;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetText()
-     */
-    std::string GetText(size_t startOffset, size_t endOffset) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCharacterCount()
-     */
-    size_t GetCharacterCount() const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetCursorOffset()
-     */
-    size_t GetCursorOffset() const 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) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Text::GetRangeOfSelection()
-     */
-    Accessibility::Range GetRangeOfSelection(size_t selectionIndex) const 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::GetRangeExtents()
-     */
-    Rect<> GetRangeExtents(size_t startOffset, size_t endOffset, Accessibility::CoordinateType type) override;
+  public:
+    using TextControlAccessible::TextControlAccessible;
 
     /**
      * @copydoc Dali::Accessibility::Text::GetNameRaw()
@@ -307,20 +267,16 @@ protected:
      */
     Property::Index GetNamePropertyIndex() override;
 
+  protected:
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLink()
-     */
-    Accessibility::Hyperlink* GetLink(int32_t linkIndex) const override;
-
-    /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkIndex()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextAnchors()
      */
-    int32_t GetLinkIndex(int32_t characterOffset) const override;
+    const std::vector<Toolkit::TextAnchor>& GetTextAnchors() const override;
 
     /**
-     * @copydoc Dali::Accessibility::Hypertext::GetLinkCount()
+     * @copydoc Dali::Toolkit::Internal::TextControlAccessible::GetTextController()
      */
-    int32_t GetLinkCount() const override;
+    Toolkit::Text::ControllerPtr GetTextController() const override;
   };
 };
 
index 2ff1bd4..5d41058 100644 (file)
@@ -397,13 +397,23 @@ void TextSelectionPopup::OnInitialize()
   self.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
   self.SetProperty(Actor::Property::COLOR_ALPHA, 0.0f);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::DIALOG, true));
-  });
-
-  //Enable highightability
+  // Accessibility
   self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+  self.SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::DIALOG);
+}
+
+DevelControl::ControlAccessible* TextSelectionPopup::CreateAccessibleObject()
+{
+  return new TextSelectionPopupAccessible(Self());
+}
+
+Dali::Accessibility::States TextSelectionPopup::TextSelectionPopupAccessible::CalculateStates()
+{
+  auto states = ControlAccessible::CalculateStates();
+
+  states[Dali::Accessibility::State::MODAL] = true;
+
+  return states;
 }
 
 void TextSelectionPopup::HideAnimationFinished(Animation& animation)
index 64130e1..41686ee 100644 (file)
@@ -24,6 +24,7 @@
 #include <string>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
 #include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
@@ -139,6 +140,11 @@ private: // From Control
    */
   void OnInitialize() override;
 
+  /**
+   * @copydoc Toolkit::Internal::Control::CreateAccessibleObject()
+   */
+  DevelControl::ControlAccessible* CreateAccessibleObject() override;
+
 private: // Implementation
   void HideAnimationFinished(Animation& animation);
 
@@ -266,6 +272,18 @@ private: // Implementation
    */
   virtual ~TextSelectionPopup();
 
+protected:
+  class TextSelectionPopupAccessible : public DevelControl::ControlAccessible
+  {
+  public:
+    using DevelControl::ControlAccessible::ControlAccessible;
+
+    /**
+     * @copydoc DevelControl::ControlAccessible::CalculateStates()
+     */
+    Dali::Accessibility::States CalculateStates() override;
+  };
+
 private:
   // Undefined copy constructor and assignment operators
   TextSelectionPopup(const TextSelectionPopup&);
index 3220328..f28f92b 100644 (file)
@@ -164,10 +164,7 @@ void TextSelectionToolbar::OnInitialize()
 {
   SetUp();
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::TOOL_BAR));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TOOL_BAR);
 }
 
 void TextSelectionToolbar::OnRelayout(const Vector2& size, RelayoutContainer& container)
index 0e894df..19cb548 100644 (file)
@@ -311,10 +311,7 @@ void ToolBar::OnInitialize()
   mLayout.SetRelativeWidth(0, mLeftRelativeSpace);
   mLayout.SetRelativeWidth(1, mRightRelativeSpace);
 
-  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::TOOL_BAR));
-  });
+  Self().SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TOOL_BAR);
 }
 
 void ToolBar::OnChildAdd(Actor& child)
index c08625f..154caac 100644 (file)
@@ -118,13 +118,9 @@ void VideoView::OnInitialize()
   Actor self = Self();
   mVideoPlayer.FinishedSignal().Connect(this, &VideoView::EmitSignalFinish);
 
-  DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
-    return std::unique_ptr<Dali::Accessibility::Accessible>(
-      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::VIDEO));
-  });
-
-  //Enable highightability
-  Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
+  // Accessibility
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::VIDEO);
+  self.SetProperty(DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true);
 
   //update self property
   self.RegisterProperty(IS_VIDEO_VIEW_PROPERTY_NAME, true, Property::READ_WRITE);
index ac86419..977e2e0 100644 (file)
@@ -423,7 +423,7 @@ Toolkit::Control KeyboardFocusManager::GetParentLayoutControl(Actor actor) const
   return Toolkit::Control::DownCast(parent);
 }
 
-bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction)
+bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction, const std::string& deviceName)
 {
   Actor currentFocusActor = GetCurrentFocusActor();
 
@@ -519,7 +519,7 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
       if(mCustomAlgorithmInterface)
       {
         mIsWaitingKeyboardFocusChangeCommit = true;
-        nextFocusableActor                  = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction);
+        nextFocusableActor                  = mCustomAlgorithmInterface->GetNextFocusableActor(currentFocusActor, Actor(), direction, deviceName);
         mIsWaitingKeyboardFocusChangeCommit = false;
       }
       else if(!mPreFocusChangeSignal.Empty())
@@ -529,13 +529,27 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction
         nextFocusableActor                  = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction);
         mIsWaitingKeyboardFocusChangeCommit = false;
       }
-      else if(mEnableDefaultAlgorithm && currentFocusActor)
+      else if (mEnableDefaultAlgorithm)
       {
-        // We should find it among the actors nearby.
-        Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
-        if(window)
+        Layer rootLayer;
+        if (currentFocusActor)
         {
-          nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(window.GetRootLayer(), currentFocusActor, direction);
+          // Find the window of the focused actor.
+          Integration::SceneHolder window = Integration::SceneHolder::Get(currentFocusActor);
+          if (window)
+          {
+            rootLayer = window.GetRootLayer();
+          }
+        }
+        else
+        {
+          // Searches from the currently focused window.
+          rootLayer = mCurrentFocusedWindow.GetHandle();
+        }
+        if (rootLayer)
+        {
+          // We should find it among the actors nearby.
+          nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(rootLayer, currentFocusActor, direction);
         }
       }
     }
@@ -784,7 +798,8 @@ Actor KeyboardFocusManager::GetFocusIndicatorActor()
 
 void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 {
-  std::string keyName = event.GetKeyName();
+  const std::string& keyName = event.GetKeyName();
+  const std::string& deviceName = event.GetDeviceName();
 
   if(mIsFocusIndicatorShown == UNKNOWN)
   {
@@ -805,7 +820,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards left
-        MoveFocus(Toolkit::Control::KeyboardFocus::LEFT);
+        MoveFocus(Toolkit::Control::KeyboardFocus::LEFT, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -820,7 +835,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards right
-        MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
+        MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -835,7 +850,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards up
-        MoveFocus(Toolkit::Control::KeyboardFocus::UP);
+        MoveFocus(Toolkit::Control::KeyboardFocus::UP, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -850,7 +865,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards down
-        MoveFocus(Toolkit::Control::KeyboardFocus::DOWN);
+        MoveFocus(Toolkit::Control::KeyboardFocus::DOWN, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -865,7 +880,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards the previous page
-        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP);
+        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_UP, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -880,7 +895,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
       else
       {
         // Move the focus towards the next page
-        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN);
+        MoveFocus(Toolkit::Control::KeyboardFocus::PAGE_DOWN, deviceName);
       }
 
       isFocusStartableKey = true;
@@ -899,7 +914,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
         if(!DoMoveFocusToNextFocusGroup(!event.IsShiftModifier()))
         {
           // If the focus group is not changed, Move the focus towards forward, "Shift-Tap" key moves the focus towards backward.
-          MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::BACKWARD : Toolkit::Control::KeyboardFocus::FORWARD);
+          MoveFocus(event.IsShiftModifier() ? Toolkit::Control::KeyboardFocus::BACKWARD : Toolkit::Control::KeyboardFocus::FORWARD, deviceName);
         }
       }
 
@@ -972,7 +987,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       // No actor is focused but keyboard focus is activated by the key press
       // Let's try to move the initial focus
-      MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT);
+      MoveFocus(Toolkit::Control::KeyboardFocus::RIGHT, deviceName);
     }
   }
 }
index 3b4d59b..3b09623 100644 (file)
@@ -90,7 +90,7 @@ public:
   /**
    * @copydoc Toolkit::KeyboardFocusManager::MoveFocus
    */
-  bool MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction);
+  bool MoveFocus(Toolkit::Control::KeyboardFocus::Direction direction, const std::string& deviceName = "");
 
   /**
    * @copydoc Toolkit::KeyboardFocusManager::ClearFocus
index 4220b00..ce19a6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -178,7 +178,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
         else
         {
           Property::Array* array = imageURLValue->GetArray();
-          if(array)
+          if(array && array->Count() > 0)
           {
             visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap);
           }
@@ -217,7 +217,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
       std::string      imageUrl;
       if(imageURLValue && imageURLValue->Get(imageUrl))
       {
-        visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        if(!imageUrl.empty())
+        {
+          visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        }
       }
       break;
     }
@@ -228,7 +231,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
       std::string      imageUrl;
       if(imageURLValue && imageURLValue->Get(imageUrl))
       {
-        visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        if(!imageUrl.empty())
+        {
+          visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        }
       }
       break;
     }
@@ -241,12 +247,15 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
       {
         if(imageURLValue->Get(imageUrl))
         {
-          visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+          if(!imageUrl.empty())
+          {
+            visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+          }
         }
         else
         {
           Property::Array* array = imageURLValue->GetArray();
-          if(array)
+          if(array && array->Count() > 0)
           {
             visualPtr = AnimatedImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), *array, propertyMap);
           }
@@ -267,7 +276,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyM
       std::string      imageUrl;
       if(imageURLValue && imageURLValue->Get(imageUrl))
       {
-        visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        if(!imageUrl.empty())
+        {
+          visualPtr = AnimatedVectorImageVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), imageUrl, propertyMap);
+        }
       }
       break;
     }
@@ -370,14 +382,14 @@ Internal::TextureManager& VisualFactory::GetTextureManager()
 
 void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
 {
-  const std::string imageDirPath   = AssetManager::GetDaliImagePath();
-  std::string       brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
+  const std::string        imageDirPath   = AssetManager::GetDaliImagePath();
+  std::string              brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
   std::vector<std::string> customBrokenImageUrlList;
 
   if(styleManager)
   {
     customBrokenImageUrlList = Toolkit::DevelStyleManager::GetBrokenImageUrlList(styleManager);
-    Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+    Property::Map config     = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
     config["brokenImageUrl"].Get(brokenImageUrl);
   }
 
@@ -389,7 +401,7 @@ Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
 {
   if(!mFactoryCache)
   {
-    mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
+    mFactoryCache                      = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
     if(styleManager)
     {
index afb2bf9..271b826 100644 (file)
@@ -167,6 +167,11 @@ void Control::ClearBackground()
   RelayoutRequest();
 }
 
+Toolkit::DevelControl::ControlAccessible* Control::GetAccessibleObject()
+{
+  return mImpl->GetAccessibleObject();
+}
+
 void Control::EnableGestureDetection(GestureType::Value type)
 {
   if((type & GestureType::PINCH) && !mImpl->mPinchGestureDetector)
@@ -340,6 +345,11 @@ bool Control::OnAccessibilityZoom()
   return false; // Accessibility zoom action is not handled by default
 }
 
+DevelControl::ControlAccessible* Control::CreateAccessibleObject()
+{
+  return new DevelControl::ControlAccessible(Self());
+}
+
 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
 {
   return Actor();
@@ -484,7 +494,7 @@ void Control::EmitKeyInputFocusSignal(bool focusGained)
 
   if(Accessibility::IsUp())
   {
-    auto self = mImpl->GetAccessibilityObject(Self());
+    auto self = GetAccessibleObject();
     self->EmitFocused(focusGained);
     auto parent = self->GetParent();
     if(parent && !self->GetStates()[Dali::Accessibility::State::MANAGES_DESCENDANTS])
@@ -571,10 +581,7 @@ void Control::OnPropertySet(Property::Index index, const Property::Value& proper
     }
     case Actor::Property::VISIBLE:
     {
-      if(Dali::Accessibility::IsUp() && !Self().GetProperty<bool>(Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN))
-      {
-        Dali::Accessibility::Accessible::Get(Self())->EmitVisible(Self().GetProperty(Actor::Property::VISIBLE).Get<bool>());
-      }
+      GetAccessibleObject()->EmitVisible(Self().GetProperty<bool>(Actor::Property::VISIBLE));
       break;
     }
   }
index e2d1ca4..9ccb533 100644 (file)
@@ -43,6 +43,12 @@ namespace Toolkit
 
 class StyleManager;
 
+namespace DevelControl
+{
+class ControlAccessible;
+
+} // namespace DevelControl
+
 namespace Internal
 {
 
@@ -109,6 +115,19 @@ public:
    */
   void ClearBackground();
 
+  // Accessibility
+
+  /**
+   * @brief Gets the Accessible object that represents this control.
+   *
+   * This method calls CreateAccessibleObject() if necessary, so a non-null return is expected.
+   *
+   * @return The Accessible object
+   *
+   * @see CreateAccessibleObject()
+   */
+  Toolkit::DevelControl::ControlAccessible* GetAccessibleObject();
+
   // Gesture Detection
 
   /**
@@ -488,6 +507,24 @@ public: // API for derived classes to override
    */
   virtual bool OnAccessibilityZoom();
 
+  /**
+   * @brief This method should be overriden by deriving classes when they wish to be
+   * represented by a custom Accessible object implementation.
+   *
+   * The AT-SPI infrastructure is responsible for destroying the returned object.
+   *
+   * Currently, this method is called at most once in a given Control's lifetime, when
+   * GetAccessibleObject() is called for the first time. A future version of the
+   * AT-SPI infrastructure, however, may delete the Accessible object and request a new
+   * one to be created (by calling this method) multiple times, for example during
+   * scene connection and disconnection.
+   *
+   * @return The newly created Accessible object
+   *
+   * @see GetAccessibleObject()
+   */
+  virtual DevelControl::ControlAccessible* CreateAccessibleObject();
+
   // Keyboard focus
 
   /**
index 05b48a7..cb55cd0 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 13;
+const unsigned int TOOLKIT_MICRO_VERSION = 14;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
diff --git a/format b/format
deleted file mode 100755 (executable)
index c5630b4..0000000
--- a/format
+++ /dev/null
@@ -1 +0,0 @@
-git diff -U0 --no-color HEAD^ | clang-format-diff -i -p1
\ No newline at end of file
index ecfc401..74dfe63 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.1.13
+Version:    2.1.14
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT