TizenRefApp-8117 Implement Screen Reader functionality in the Widget 14/142814/1
authorEugene Kurzberg <i.kurtsberg@samsung.com>
Mon, 7 Aug 2017 08:43:56 +0000 (11:43 +0300)
committerEugene Kurzberg <i.kurtsberg@samsung.com>
Mon, 7 Aug 2017 08:44:08 +0000 (11:44 +0300)
Change-Id: Ic3573e6cfdc00c20ad53f98c0f89b345d2bf3efd

alarm-app/src/List/AlarmItem.cpp
alarm-widget/inc/AlarmWidget.h
alarm-widget/res/widget/edje/WidgetLayout.h
alarm-widget/res/widget/edje/widget-layout.edc
alarm-widget/src/AlarmWidget.cpp
lib-apps-common/inc/Ui/Accessibility.h
lib-common/inc/Common/Format.h
lib-common/src/Common/Format.cpp

index 6573d367b9781467174af3fffc7a35e85d8ccd7c..5028c4b4fbf836b79299b2e3665c63127b2a43cd 100644 (file)
@@ -94,17 +94,7 @@ Evas_Object *AlarmItem::getContent(Evas_Object *parent, const char *part)
 char *AlarmItem::getAccessibleName(Evas_Object *obj)
 {
        auto &alarm = getDataItem<Alarm>();
-
-       std::string name;
-       name.append(Common::formatTime(alarm.getDate()));
-       name.append(", ");
-
-       if (alarm.getRepeat()) {
-               name.append(Common::formatVerbalRepeat(alarm.getRepeat()));
-       } else {
-               name.append(Common::formatVerbalDate(alarm.getDate()));
-       }
-       return strdup(name.c_str());
+       return strdup(Common::formatVerbalDescription(alarm.getDate(), alarm.getRepeat()).c_str());
 }
 
 void AlarmItem::onInserted()
index 56feea8eb84224b0ed6debe6ec93ec13f168ee21..c33dc48f8ca90d1c262b5808b454d390afd1e0ca 100644 (file)
@@ -49,8 +49,8 @@ private:
        void updateContentLayout(int changes);
        void updateEmptyState();
        void onCheckedPressed(Evas_Object *obj, void *eventInfo);
-       void onCreatePressed(Evas_Object *obj, void *eventInfo);
-       void onContentPressed(Evas_Object *obj, void *eventInfo);
+       void onCreatePressed();
+       void onContentPressed();
 
        void onPickReply(app_control_h request, app_control_h reply, app_control_result_e result);
        void onCreateReply(app_control_h request, app_control_h reply, app_control_result_e result);
index 76ca983fad37ece1479e7adb2a98503d25256e06..2acdc71b2b65c32713b39533a9132d989350f9fd 100644 (file)
@@ -26,6 +26,9 @@
 #define PART_TIME                   "text.time"
 #define PART_REPEAT                 "text.repeat"
 #define PART_ON_OFF                 "swallow.on_off"
+#define PART_EVENT                  "rect.event"
+#define PART_ACCESS                 "rect.access"
+
 #define SIGNAL_ALARM_ENABLE         "state,alarm,enabled"
 #define SIGNAL_ALARM_DISABLE        "state,alarm,disabled"
 
index 6341cd57232c83df8e07907ccc8757153dfcc86d..9a4ce636bbe9017da7af3c76dbe5549abdbea08c 100644 (file)
@@ -217,6 +217,18 @@ collections {
                                        text.style: "time_disabled_style";
                                }
                        }
+                       rect { PART_ACCESS;
+                               desc { "default";
+                                       rel1.to: PART_REPEAT;
+                                       rel2.to: "spacer.on_off.top";
+                                       color: 0 0 0 0;
+                               }
+                       }
+                       rect { PART_EVENT;
+                               desc { "default";
+                                       color: 0 0 0 0;
+                               }
+                       }
                        spacer { "spacer.on_off.top"; scale;
                                desc { "default";
                                        fixed: 0 1;
@@ -225,11 +237,6 @@ collections {
                                        rel2.relative: 1.0 0.0;
                                }
                        }
-                       rect { "rect.event";
-                               desc { "default";
-                                       color: 0 0 0 0;
-                               }
-                       }
                        swallow { PART_ON_OFF; scale;
                                desc { "default";
                                        fixed: 1 1;
index 2473960dd67d4242d22028614bd4ecfbee908ea8..662ebc0412496cf8be2e980b90073bd2c5e88ba5 100644 (file)
  */
 
 #include "AlarmWidget.h"
-#include "App/AppControl.h"
-#include "App/AppControlUtils.h"
-#include "App/Path.h"
 #include "Common/Format.h"
 #include "Common/Model/Alarm.h"
 #include "Common/Model/AlarmConsumer.h"
+
+#include "App/AppControl.h"
+#include "App/AppControlUtils.h"
+#include "App/Path.h"
+#include "Ui/Accessibility.h"
 #include "Ui/Window.h"
 #include "Utils/Bundle.h"
 #include "Utils/Callback.h"
@@ -68,15 +70,32 @@ Evas_Object *AlarmWidget::createContentLayout(Evas_Object *parent)
 {
        Evas_Object *layout = elm_layout_add(parent);
        elm_layout_file_set(layout, App::getResourcePath(PATH_WIDGET_LAYOUT).c_str(), LAYOUT_ALARM);
-       elm_layout_signal_callback_add(layout, "mouse,clicked,*", "rect.event",
+       elm_layout_signal_callback_add(layout, "mouse,clicked,*", PART_EVENT,
                        (Edje_Signal_Cb) makeCallback(&AlarmWidget::onContentPressed), this);
 
+       Evas_Object *accessObject = Ui::createPartAccessObject(layout, PART_ACCESS);
+       elm_atspi_accessible_reading_info_type_set(accessObject, ELM_ACCESSIBLE_READING_INFO_TYPE_NAME);
+       elm_atspi_accessible_name_cb_set(accessObject,
+               [](void *data, Evas_Object *) {
+                       auto alarm = (Alarm *) data;
+                       return strdup(formatVerbalDescription(alarm->getDate(), alarm->getRepeat()).c_str());
+               }, m_Alarm);
+       elm_atspi_accessible_gesture_cb_set(accessObject,
+               ACCESS_CALLBACK(ELM_ATSPI_GESTURE_ONE_FINGER_DOUBLE_TAP,
+                       auto widget = (AlarmWidget *) data;
+                       widget->onContentPressed();
+               ), this);
+
        Evas_Object *check = elm_check_add(layout);
        evas_object_propagate_events_set(check, EINA_FALSE);
        elm_object_style_set(check, STYLE_CHECK_ALARM_ON_OFF);
        elm_object_part_content_set(layout, PART_ON_OFF, check);
        evas_object_smart_callback_add(check, "changed", makeCallback(&AlarmWidget::onCheckedPressed), this);
 
+       elm_atspi_accessible_role_set(check, ELM_ATSPI_ROLE_TOGGLE_BUTTON);
+       elm_atspi_accessible_translation_domain_set(check, TEXT_DOMAIN);
+       elm_atspi_accessible_name_set(check, "WDS_ALM_TBOPT_SWITCH");
+
        return layout;
 }
 
@@ -88,6 +107,14 @@ Evas_Object *AlarmWidget::createEmptyLayout(Evas_Object *parent)
                        (Edje_Signal_Cb) makeCallback(&AlarmWidget::onCreatePressed), this);
 
        elm_object_translatable_part_text_set(layout, PART_NO_ALARM_TEXT, "WDS_ALM_OPT_ADD_ALARM_ABB");
+       elm_atspi_accessible_role_set(layout, ELM_ATSPI_ROLE_PUSH_BUTTON);
+       elm_atspi_accessible_translation_domain_set(layout, TEXT_DOMAIN);
+       elm_atspi_accessible_name_set(layout, "WDS_ALM_OPT_ADD_ALARM_ABB");
+       elm_atspi_accessible_gesture_cb_set(layout,
+               ACCESS_CALLBACK(ELM_ATSPI_GESTURE_ONE_FINGER_DOUBLE_TAP,
+                       auto widget = (AlarmWidget *) data;
+                       widget->onCreatePressed();
+               ), this);
 
        return layout;
 }
@@ -133,7 +160,7 @@ void AlarmWidget::onCheckedPressed(Evas_Object *obj, void *eventInfo)
        elm_layout_signal_emit(m_Layout, m_Alarm->isEnabled() ? SIGNAL_ALARM_ENABLE : SIGNAL_ALARM_DISABLE, "");
 }
 
-void AlarmWidget::onCreatePressed(Evas_Object *obj, void *eventInfo)
+void AlarmWidget::onCreatePressed()
 {
        AlarmConsumer::getInstance().getDataItems([this](AlarmConsumer::DataList dataList) {
                if (dataList.empty()) {
@@ -152,7 +179,7 @@ void AlarmWidget::onCreatePressed(Evas_Object *obj, void *eventInfo)
        });
 }
 
-void AlarmWidget::onContentPressed(Evas_Object *obj, void *eventInfo)
+void AlarmWidget::onContentPressed()
 {
        App::AppControl request(APP_CONTROL_OPERATION_EDIT, APP_CONTROL_MIME_ALARM);
        request.addExtra(APP_CONTROL_DATA_ID, std::to_string(m_Alarm->getId()).c_str());
index 01b85bbc54a7dd2ec7270c4ddb506191aa139c26..6e23399761fd9a7fbb62fbc6c025152ccf39c283 100644 (file)
 #include <Elementary.h>
 #include <tizen.h>
 
+/**
+ * @brief Define accessibility callback for a certain gesture type.
+ * @param[in]   gestureType Gesture to define callback for
+ * @param[in]   body        Callback body
+ */
+#define ACCESS_CALLBACK(gestureType, body) \
+       [](void *data, Elm_Atspi_Gesture_Info gesture, Evas_Object *obj) { \
+               if (gesture.type == gestureType) { \
+                       body \
+                       return EINA_TRUE; \
+               } \
+               return EINA_FALSE; \
+       }
+
 namespace Ui
 {
        /**
index dc8055756bf301c8a98bb82978f2410267a18eec..0f1fa7acca69d6824c71ad8d04c286cd2f34788f 100644 (file)
@@ -83,6 +83,14 @@ namespace Common
         */
        EXPORT_API const char *formatVerbalRepeat(int repeat);
 
+       /**
+        * @brief Create verbal description of the alarm for Screen Reader.
+        * @param[in]   date    Alarm's date
+        * @param[in]   repeat  Alarm's repeat mask
+        * @return Formatted time and repeat/date verbal description.
+        */
+       EXPORT_API std::string formatVerbalDescription(const tm &date, int repeat);
+
        /**
         * @brief Create "Alarm set for ... from now" message.
         * @param[in]   date    Alarm date
index b56ca2b1a0cee2799216866598791649b52eea58..cb09d0f231db3f288af0bb63cfc709cd7eb6a518 100644 (file)
@@ -167,6 +167,20 @@ const char *Common::formatVerbalRepeat(int repeat)
        return buffer.c_str();
 }
 
+std::string Common::formatVerbalDescription(const tm &date, int repeat)
+{
+       std::string desc;
+       desc.append(Common::formatTime(date));
+       desc.append(", ");
+
+       if (repeat) {
+               desc.append(Common::formatVerbalRepeat(repeat));
+       } else {
+               desc.append(Common::formatVerbalDate(date));
+       }
+       return desc;
+}
+
 /*
  * The function selects a translatable string such as:
  *      WDS_ALM_TPOP_ALARM_SET_FOR_1_HR_PD_MINS_FROM_NOW_ABB