and now add custom access info for items too and clean up nicely.
[framework/uifw/elementary.git] / src / lib / elm_widget.c
index 4c3916e..d56b469 100644 (file)
@@ -19,6 +19,7 @@ static const char SMART_NAME[] = "elm_widget";
 typedef struct _Smart_Data        Smart_Data;
 typedef struct _Edje_Signal_Data  Edje_Signal_Data;
 typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
+typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
 
 struct _Smart_Data
 {
@@ -36,6 +37,7 @@ struct _Smart_Data
    void       (*activate_func)(Evas_Object *obj);
    void       (*disable_func)(Evas_Object *obj);
    void       (*theme_func)(Evas_Object *obj);
+   void       (*translate_func)(Evas_Object *obj);
    Eina_Bool  (*event_func)(Evas_Object       *obj,
                             Evas_Object       *source,
                             Evas_Callback_Type type,
@@ -88,6 +90,7 @@ struct _Smart_Data
    double       scale;
    Elm_Theme   *theme;
    const char  *style;
+   const char  *access_info;
    unsigned int focus_order;
    Eina_Bool    focus_order_on_calc;
 
@@ -95,6 +98,7 @@ struct _Smart_Data
    int          child_drag_y_locked;
 
    Eina_List   *edje_signals;
+   Eina_List   *translate_strings;
 
    Eina_Bool    drag_x_locked : 1;
    Eina_Bool    drag_y_locked : 1;
@@ -102,6 +106,7 @@ struct _Smart_Data
    Eina_Bool    can_focus : 1;
    Eina_Bool    child_can_focus : 1;
    Eina_Bool    focused : 1;
+   Eina_Bool    top_win_focused : 1;
    Eina_Bool    tree_unfocusable : 1;
    Eina_Bool    highlight_ignore : 1;
    Eina_Bool    highlight_in_theme : 1;
@@ -129,6 +134,13 @@ struct _Elm_Event_Cb_Data
    const void  *data;
 };
 
+struct _Elm_Translate_String_Data
+{
+   const char *id;
+   const char *domain;
+   const char *string;
+};
+
 /* local subsystem functions */
 static void _smart_reconfigure(Smart_Data *sd);
 static void _smart_add(Evas_Object *obj);
@@ -368,12 +380,13 @@ _parent_focus(Evas_Object *obj)
 
    focus_order++;
    sd->focus_order = focus_order;
-   sd->focused = EINA_TRUE;
-   if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
-   if (sd->focus_func) sd->focus_func(obj);
-
-   _elm_widget_focus_region_show(obj);
-
+   if (sd->top_win_focused)
+     {
+        sd->focused = EINA_TRUE;
+        if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
+        if (sd->focus_func) sd->focus_func(obj);
+        _elm_widget_focus_region_show(obj);
+     }
    sd->focus_order_on_calc = EINA_FALSE;
 }
 
@@ -530,6 +543,14 @@ elm_widget_theme_hook_set(Evas_Object *obj,
 }
 
 EAPI void
+elm_widget_translate_hook_set(Evas_Object *obj,
+                              void       (*func)(Evas_Object *obj))
+{
+   API_ENTRY return;
+   sd->translate_func = func;
+}
+
+EAPI void
 elm_widget_event_hook_set(Evas_Object *obj,
                           Eina_Bool  (*func)(Evas_Object       *obj,
                                              Evas_Object       *source,
@@ -908,6 +929,7 @@ elm_widget_sub_object_add(Evas_Object *obj,
              if (sd2->parent_obj)
                elm_widget_sub_object_del(sd2->parent_obj, sobj);
              sd2->parent_obj = obj;
+             sd2->top_win_focused = sd->top_win_focused;
              if (!sd->child_can_focus && (_is_focusable(sobj)))
                sd->child_can_focus = EINA_TRUE;
           }
@@ -1060,7 +1082,11 @@ elm_widget_resize_object_set(Evas_Object *obj,
         if (_elm_widget_is(sd->resize_obj))
           {
              Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
-             if (sd2) sd2->parent_obj = obj;
+             if (sd2)
+               {
+                  sd2->parent_obj = obj;
+                  sd2->top_win_focused = sd->top_win_focused;
+               }
              evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
                                             _sub_obj_hide, sd);
           }
@@ -1934,6 +1960,30 @@ elm_widget_focus_restore(Evas_Object *obj)
      }
 }
 
+void
+_elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
+{
+   const Eina_List *l;
+   Evas_Object *child;
+   API_ENTRY return;
+
+   if (sd->top_win_focused == top_win_focused) return;
+   if (sd->resize_obj)
+     _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
+   EINA_LIST_FOREACH(sd->subobjs, l, child)
+     {
+        _elm_widget_top_win_focused_set(child, top_win_focused);
+     }
+   sd->top_win_focused = top_win_focused;
+}
+
+Eina_Bool
+_elm_widget_top_win_focused_get(const Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->top_win_focused;
+}
+
 EAPI void
 elm_widget_activate(Evas_Object *obj)
 {
@@ -2195,6 +2245,100 @@ elm_widget_text_part_get(const Evas_Object *obj, const char *item)
 }
 
 EAPI void
+elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
+{
+   const char *str;
+   Eina_List *l;
+   Elm_Translate_String_Data *ts = NULL;
+   API_ENTRY return;
+
+   str = eina_stringshare_add(part);
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+      if (ts->id == str)
+        break;
+      else
+        ts = NULL;
+
+   if (!ts && !label)
+     eina_stringshare_del(str);
+   else if (!ts)
+     {
+        ts = malloc(sizeof(Elm_Translate_String_Data));
+        if (!ts) return;
+
+        ts->id = str;
+        ts->domain = eina_stringshare_add(domain);
+        ts->string = eina_stringshare_add(label);
+        sd->translate_strings = eina_list_append(sd->translate_strings, ts);
+     }
+   else
+     {
+        if (label)
+          {
+             eina_stringshare_replace(&ts->domain, domain);
+             eina_stringshare_replace(&ts->string, label);
+          }
+        else
+          {
+             sd->translate_strings = eina_list_remove_list(
+                                                sd->translate_strings, l);
+             eina_stringshare_del(ts->id);
+             eina_stringshare_del(ts->domain);
+             eina_stringshare_del(ts->string);
+             free(ts);
+          }
+        eina_stringshare_del(str);
+     }
+
+#ifdef HAVE_GETTEXT
+   if (label && label[0])
+     label = dgettext(domain, label);
+#endif
+   elm_widget_text_part_set(obj, part, label);
+}
+
+EAPI const char *
+elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
+{
+   const char *str, *ret = NULL;
+   Eina_List *l;
+   Elm_Translate_String_Data *ts;
+   API_ENTRY return NULL;
+
+   str = eina_stringshare_add(part);
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+      if (ts->id == str)
+        {
+           ret = ts->string;
+           break;
+        }
+   eina_stringshare_del(str);
+   return ret;
+}
+
+EAPI void
+elm_widget_translate(Evas_Object *obj)
+{
+   const Eina_List *l;
+   Evas_Object *child;
+   Elm_Translate_String_Data *ts;
+
+   API_ENTRY return;
+   EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
+   if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
+   if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
+   if (sd->translate_func) sd->translate_func(obj);
+
+#ifdef HAVE_GETTEXT
+   EINA_LIST_FOREACH(sd->translate_strings, l, ts)
+     {
+        const char *s = dgettext(ts->domain, ts->string);
+        elm_widget_text_part_set(obj, ts->id, s);
+     }
+#endif
+}
+
+EAPI void
 elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
 {
    API_ENTRY return;
@@ -2221,6 +2365,23 @@ elm_widget_content_part_unset(Evas_Object *obj, const char *part)
    return sd->on_content_unset_func(obj, part);
 }
 
+EAPI void
+elm_widget_access_info_set(Evas_Object *obj, const char *txt)
+{
+   API_ENTRY return;
+   if (sd->access_info) eina_stringshare_del(sd->access_info);
+   if (!txt) sd->access_info = NULL;
+   else sd->access_info = eina_stringshare_add(txt);
+}
+
+EAPI const char *
+elm_widget_access_info_get(Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+   return sd->access_info;
+}
+
+
 EAPI Elm_Theme *
 elm_widget_theme_get(const Evas_Object *obj)
 {
@@ -2537,6 +2698,30 @@ _elm_widget_item_del(Elm_Widget_Item *item)
 
    if (item->view)
      evas_object_del(item->view);
+   
+   if (item->access)
+     {
+        _elm_access_clear(item->access);
+        free(item->access);
+        item->access = NULL;
+     }
+   if (item->access_info)
+     {
+        eina_stringshare_del(item->access_info);
+        item->access_info = NULL;
+     }
+
+   if (item->access)
+     {
+        _elm_access_clear(item->access);
+        free(item->access);
+        item->access = NULL;
+     }
+   if (item->access_info)
+     {
+        eina_stringshare_del(item->access_info);
+        item->access_info = NULL;
+     }
 
    EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
    free(item);
@@ -2658,6 +2843,19 @@ _elm_widget_item_tooltip_label_create(void        *data,
    return label;
 }
 
+static Evas_Object *
+_elm_widget_item_tooltip_trans_label_create(void        *data,
+                                            Evas_Object *obj __UNUSED__,
+                                            void        *item __UNUSED__)
+{
+   Evas_Object *label = elm_label_add(obj);
+   if (!label)
+     return NULL;
+   elm_object_style_set(label, "tooltip");
+   elm_object_translatable_text_set(label, data);
+   return label;
+}
+
 static void
 _elm_widget_item_tooltip_label_del_cb(void        *data,
                                       Evas_Object *obj __UNUSED__,
@@ -2692,6 +2890,19 @@ _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
      _elm_widget_item_tooltip_label_del_cb);
 }
 
+EAPI void
+_elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
+                                               const char      *text)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   EINA_SAFETY_ON_NULL_RETURN(text);
+
+   text = eina_stringshare_add(text);
+   _elm_widget_item_tooltip_content_cb_set
+     (item, _elm_widget_item_tooltip_trans_label_create, text,
+     _elm_widget_item_tooltip_label_del_cb);
+}
+
 static Evas_Object *
 _elm_widget_item_tooltip_create(void        *data,
                                 Evas_Object *obj)
@@ -3055,6 +3266,16 @@ _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
    item->on_signal_emit_func = func;
 }
 
+EAPI void
+_elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
+{
+   ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
+   if (item->access_info) eina_stringshare_del(item->access_info);
+   if (!txt) item->access_info = NULL;
+   else item->access_info = eina_stringshare_add(txt);
+}
+
+
 static void
 _smart_add(Evas_Object *obj)
 {
@@ -3123,8 +3344,8 @@ _if_focused_revert(Evas_Object *obj,
         newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
         if (newest)
           {
-             elm_object_unfocus(newest);
-             elm_object_focus(newest);
+             elm_object_focus_set(newest, EINA_FALSE);
+             elm_object_focus_set(newest, EINA_TRUE);
           }
      }
 }
@@ -3134,6 +3355,7 @@ _smart_del(Evas_Object *obj)
 {
    Evas_Object *sobj;
    Edje_Signal_Data *esd;
+   Elm_Translate_String_Data *ts;
 
    INTERNAL_ENTRY
 
@@ -3168,12 +3390,20 @@ _smart_del(Evas_Object *obj)
         eina_stringshare_del(esd->source);
         free(esd);
      }
+   EINA_LIST_FREE(sd->translate_strings, ts)
+     {
+        eina_stringshare_del(ts->id);
+        eina_stringshare_del(ts->domain);
+        eina_stringshare_del(ts->string);
+        free(ts);
+     }
    eina_list_free(sd->event_cb); /* should be empty anyway */
    if (sd->del_func) sd->del_func(obj);
    if (sd->style) eina_stringshare_del(sd->style);
    if (sd->type) eina_stringshare_del(sd->type);
    if (sd->theme) elm_theme_free(sd->theme);
    _if_focused_revert(obj, EINA_TRUE);
+   if (sd->access_info) eina_stringshare_del(sd->access_info);
    free(sd);
 }