[AT-SPI] Implement proper accessibility for Slider
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / slider / slider-impl.cpp
index 791adea..3c48abc 100644 (file)
@@ -159,10 +159,6 @@ Slider::Slider()
   mShowValue( false ),
   mSnapToMarks( false )
 {
-  DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
-    return std::unique_ptr< Dali::Accessibility::Accessible >(
-        new AccessibleImpl( actor, Dali::Accessibility::Role::SLIDER ) );
-  } );
 }
 
 Slider::~Slider()
@@ -207,8 +203,16 @@ 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 ) );
+  } );
 }
 
 void Slider::OnRelayout( const Vector2& size, RelayoutContainer& container )
@@ -610,6 +614,7 @@ Toolkit::TextLabel Slider::CreatePopupText()
   textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
   textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
   textLabel.SetProperty( Actor::Property::PADDING, Padding( POPUP_TEXT_PADDING, POPUP_TEXT_PADDING, 0.0f, 0.0f ) );
+  textLabel.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
   return textLabel;
 }
 
@@ -693,6 +698,7 @@ void Slider::CreateHandleValueDisplay()
     mHandleValueTextLabel.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
     mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
     mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
+    mHandleValueTextLabel.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
     mHandle.Add( mHandleValueTextLabel );
   }
 }
@@ -1433,17 +1439,61 @@ double Slider::AccessibleImpl::GetMaximum()
 
 bool Slider::AccessibleImpl::SetCurrent( double current )
 {
-  if( current < GetMinimum() || current > GetMaximum() )
+  if (current < GetMinimum() || current > GetMaximum())
     return false;
+
   auto p = Toolkit::Slider::DownCast( self );
-  p.SetProperty( Toolkit::Slider::Property::VALUE, static_cast< float >( current ) );
+  auto &impl = Toolkit::GetImpl(p);
+
+  const float prev = p.GetProperty<float>(Toolkit::Slider::Property::VALUE);
+  float next = static_cast<float>(current);
+
+  if (fabsf(next - prev) < Math::MACHINE_EPSILON_0)
+  {
+    // do nothing
+  }
+  else if (p.GetProperty<bool>(Toolkit::Slider::Property::SNAP_TO_MARKS))
+  {
+    auto marks = p.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS);
+
+    int prevIdx;
+    if (impl.MarkReached(impl.MapValuePercentage(prev), prevIdx))
+    {
+      int nextIdx = prevIdx;
+      nextIdx += (next > prev) ? 1 : -1;
+
+      if (nextIdx < 0 || nextIdx >= static_cast<int>(marks.Count()))
+        return false;
+
+      next = marks[nextIdx].Get<float>();
+    }
+    else
+    {
+      next = impl.MapBounds(impl.SnapToMark(impl.MapValuePercentage(next)), impl.GetLowerBound(), impl.GetUpperBound());
+    }
+  }
+  else
+  {
+    next = impl.MapBounds(impl.MarkFilter(impl.MapValuePercentage(next)), impl.GetLowerBound(), impl.GetUpperBound());
+  }
+
+  impl.SetValue(next);
+  impl.DisplayPopup(next);
+
   return true;
 }
 
 double Slider::AccessibleImpl::GetMinimumIncrement()
 {
   auto p = Toolkit::Slider::DownCast( self );
-  return p.GetProperty( Toolkit::Slider::Property::MARK_TOLERANCE ).Get< float >();
+
+  bool hasMarks = !p.GetProperty<Property::Array>(Toolkit::Slider::Property::MARKS).Empty();
+  float tolerance = p.GetProperty<float>(Toolkit::Slider::Property::MARK_TOLERANCE);
+
+  if (!hasMarks || fabsf(tolerance) < 0.01)
+    return 0.0; // let screen-reader choose the increment
+
+  return Math::MACHINE_EPSILON_10000 + tolerance * (GetMaximum() - GetMinimum());
 }
 
 } // namespace Internal