[TIZEN] Check if child is visible in scrollable parent.
[platform/core/uifw/dali-adaptor.git] / dali / devel-api / adaptor-framework / accessibility.cpp
index ddc4f20..5c5d1ce 100644 (file)
@@ -22,8 +22,9 @@
 #include <dali/public-api/object/object-registry.h>
 #include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/type-registry-helper.h>
+#include <map>
+#include <sstream>
 #include <string_view>
-#include <unordered_map>
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
@@ -40,6 +41,8 @@
 #include <dali/devel-api/atspi-interfaces/hypertext.h>
 #include <dali/devel-api/atspi-interfaces/selection.h>
 #include <dali/devel-api/atspi-interfaces/socket.h>
+#include <dali/devel-api/atspi-interfaces/table.h>
+#include <dali/devel-api/atspi-interfaces/table-cell.h>
 #include <dali/devel-api/atspi-interfaces/text.h>
 #include <dali/devel-api/atspi-interfaces/value.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
@@ -61,7 +64,7 @@ std::string Accessible::GetLocalizedRoleName() const
 
 std::string Accessible::GetRoleName() const
 {
-  static const std::unordered_map<Role, std::string_view> roleMap{
+  static const std::map<Role, std::string_view> roleMap{
     {Role::INVALID, "invalid"},
     {Role::ACCELERATOR_LABEL, "accelerator label"},
     {Role::ALERT, "alert"},
@@ -195,6 +198,79 @@ std::string Accessible::GetRoleName() const
   return std::string{it->second};
 }
 
+void Accessible::UpdateAttributes(Attributes& attributes) const
+{
+  using MapType = std::map<ReadingInfoType, std::string_view>;
+
+  static const std::string readingInfoTypeKey = "reading_info_type";
+  static const char        separator          = '|';
+  static const MapType     readingInfoTypeMap{
+    {ReadingInfoType::NAME, "name"},
+    {ReadingInfoType::ROLE, "role"},
+    {ReadingInfoType::DESCRIPTION, "description"},
+    {ReadingInfoType::STATE, "state"},
+  };
+
+  bool allEnabled = mReadingInfoTypes[ReadingInfoType::NAME]
+    && mReadingInfoTypes[ReadingInfoType::ROLE]
+    && mReadingInfoTypes[ReadingInfoType::DESCRIPTION]
+    && mReadingInfoTypes[ReadingInfoType::STATE];
+
+  if(DALI_LIKELY(allEnabled))
+  {
+    attributes.erase(readingInfoTypeKey);
+    return;
+  }
+
+  std::stringstream buf;
+  for(auto& item : readingInfoTypeMap)
+  {
+    if(mReadingInfoTypes[item.first])
+    {
+      if(buf.tellp()) // non-empty
+      {
+        buf << separator;
+      }
+
+      buf << item.second;
+    }
+  }
+
+  attributes.insert_or_assign(readingInfoTypeKey, buf.str());
+}
+
+const Attributes& Accessible::GetAttributes() const
+{
+  UpdateAttributes(mAttributes);
+
+  return mAttributes;
+}
+
+bool Accessible::SetAttribute(const std::string& key, const std::string& value)
+{
+  return mAttributes.insert_or_assign(key, value).second;
+}
+
+bool Accessible::UnsetAttribute(const std::string& key)
+{
+  return (mAttributes.erase(key) > 0);
+}
+
+void Accessible::ClearAttributes()
+{
+  mAttributes.clear();
+}
+
+ReadingInfoTypes Accessible::GetReadingInfoTypes() const
+{
+  return mReadingInfoTypes;
+}
+
+void Accessible::SetReadingInfoTypes(ReadingInfoTypes types)
+{
+  mReadingInfoTypes = types;
+}
+
 AtspiInterfaces Accessible::GetInterfaces() const
 {
   if(!mInterfaces)
@@ -241,6 +317,8 @@ AtspiInterfaces Accessible::DoGetInterfaces() const
   interfaces[AtspiInterface::HYPERTEXT]     = dynamic_cast<const Hypertext*>(this);
   interfaces[AtspiInterface::SELECTION]     = dynamic_cast<const Selection*>(this);
   interfaces[AtspiInterface::SOCKET]        = dynamic_cast<const Socket*>(this);
+  interfaces[AtspiInterface::TABLE]         = dynamic_cast<const Table*>(this);
+  interfaces[AtspiInterface::TABLE_CELL]    = dynamic_cast<const TableCell*>(this);
   interfaces[AtspiInterface::TEXT]          = dynamic_cast<const Text*>(this);
   interfaces[AtspiInterface::VALUE]         = dynamic_cast<const Value*>(this);
 
@@ -249,7 +327,7 @@ AtspiInterfaces Accessible::DoGetInterfaces() const
 
 std::string Accessible::GetInterfaceName(AtspiInterface interface)
 {
-  static const std::unordered_map<AtspiInterface, std::string_view> interfaceMap{
+  static const std::map<AtspiInterface, std::string_view> interfaceMap{
     {AtspiInterface::ACCESSIBLE, "org.a11y.atspi.Accessible"},
     {AtspiInterface::ACTION, "org.a11y.atspi.Action"},
     {AtspiInterface::APPLICATION, "org.a11y.atspi.Application"},
@@ -338,6 +416,9 @@ namespace
 {
 class AdaptorAccessible : public ActorAccessible
 {
+private:
+  std::unique_ptr<TriggerEventInterface> mRenderNotification = nullptr;
+
 protected:
   bool mRoot = false;
 
@@ -438,31 +519,33 @@ public:
       state[State::VISIBLE]   = true;
       state[State::ACTIVE]    = visible;
     }
-    else
+    else if (GetParent())
     {
       auto parentState      = GetParent()->GetStates();
       state[State::SHOWING] = parentState[State::SHOWING];
       state[State::VISIBLE] = parentState[State::VISIBLE];
     }
+    else
+    {
+      state[State::SHOWING] = false;
+      state[State::VISIBLE] = false;
+    }
     return state;
   }
 
-  Attributes GetAttributes() const override
+  void UpdateAttributes(Attributes& attributes) const override
   {
-    Attributes attributes;
+    static const std::string resIDKey = "resID";
 
-    if(mRoot)
+    ActorAccessible::UpdateAttributes(attributes);
+
+    if(mRoot && attributes.find(resIDKey) == attributes.end())
     {
       Dali::Window window                         = Dali::DevelWindow::Get(Self());
       Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
-      attributes["resID"]                         = windowImpl.GetNativeResourceId();
-    }
-
-    Dali::TypeInfo type;
-    Self().GetTypeInfo(type);
-    attributes["class"] = type.GetName();
 
-    return attributes;
+      attributes.emplace(resIDKey, windowImpl.GetNativeResourceId());
+    }
   }
 
   bool DoGesture(const GestureInfo& gestureInfo) override
@@ -474,9 +557,42 @@ public:
   {
     return {};
   }
+
+  void SetListenPostRender(bool enabled) override
+  {
+    if (!mRoot)
+    {
+      return;
+    }
+
+    auto window                                 = Dali::DevelWindow::Get(Self());
+    Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+
+    if(!mRenderNotification)
+    {
+      mRenderNotification = std::unique_ptr<TriggerEventInterface>(
+                                           TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &AdaptorAccessible::OnPostRender),
+                                           TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+    }
+
+    if (enabled)
+    {
+      windowImpl.SetRenderNotification(mRenderNotification.get());
+    }
+    else
+    {
+      windowImpl.SetRenderNotification(nullptr);
+    }
+  }
+
+  void OnPostRender()
+  {
+    Accessibility::Bridge::GetCurrentBridge()->Emit(Accessibility::Accessible::Get(Self()), Accessibility::WindowEvent::POST_RENDER);
+  }
+
 }; // AdaptorAccessible
 
-using AdaptorAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible> >;
+using AdaptorAccessiblesType = std::map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible>>;
 
 // Save RefObject from an Actor in Accessible::Get()
 AdaptorAccessiblesType gAdaptorAccessibles;
@@ -501,7 +617,7 @@ void Accessible::RegisterExternalAccessibleGetter(std::function<Accessible*(Dali
   convertingFunctor = functor;
 }
 
-Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
+Accessible* Accessible::Get(Dali::Actor actor)
 {
   if(!actor)
   {
@@ -514,6 +630,12 @@ Accessible* Accessible::Get(Dali::Actor actor, bool isRoot)
     auto pair = gAdaptorAccessibles.emplace(&actor.GetBaseObject(), nullptr);
     if(pair.second)
     {
+      bool isRoot                    = false;
+      Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
+      if(scene)
+      {
+        isRoot = (actor == scene.GetRootLayer());
+      }
       pair.first->second.reset(new AdaptorAccessible(actor, isRoot));
     }
     accessible = pair.first->second.get();