jpeg pushed a commit to branch feature/eo_theme.

http://git.enlightenment.org/core/efl.git/commit/?id=589c7924e937a611625082626839205277c90a5d

commit 589c7924e937a611625082626839205277c90a5d
Author: Sungtaek Hong <sth253.h...@samsung.com>
Date:   Tue Nov 14 18:42:48 2017 +0900

    efl_ui_widget: add new internal EAPI for new group name
    
    theme_klass: set/get klass name used for resize_obj
    theme_element: set/get group name used for resize_obj
    theme_style: set/get style name used for resize_obj
    element_update: automatically sets and apply theme for
                 sub object of widget.
---
 src/lib/elementary/efl_ui_layout.c      |  29 +++----
 src/lib/elementary/efl_ui_panes.c       |   5 +-
 src/lib/elementary/efl_ui_progressbar.c |   5 +-
 src/lib/elementary/efl_ui_slider.c      |   9 +--
 src/lib/elementary/elc_hoversel.c       |   4 +-
 src/lib/elementary/elm_bubble.c         |   5 +-
 src/lib/elementary/elm_index.c          |   5 +-
 src/lib/elementary/elm_scroller.c       |   8 +-
 src/lib/elementary/elm_separator.c      |   5 +-
 src/lib/elementary/elm_widget.c         | 133 ++++++++++++++++++++++++++++++++
 src/lib/elementary/elm_widget.h         |  10 +++
 src/lib/elementary/elm_widget_layout.h  |   2 -
 12 files changed, 177 insertions(+), 43 deletions(-)

diff --git a/src/lib/elementary/efl_ui_layout.c 
b/src/lib/elementary/efl_ui_layout.c
index 15534c7b7d..353caa945f 100644
--- a/src/lib/elementary/efl_ui_layout.c
+++ b/src/lib/elementary/efl_ui_layout.c
@@ -362,8 +362,10 @@ _efl_ui_layout_theme_internal(Eo *obj, Efl_Ui_Layout_Data 
*sd)
    if (!sd->file_set)
      {
         ret = elm_widget_theme_object_set
-                (obj, wd->resize_obj, sd->klass, sd->group,
-                 elm_widget_style_get(obj));
+                (obj, wd->resize_obj,
+                elm_widget_theme_klass_get(obj), 
+                elm_widget_theme_element_get(obj),
+                elm_widget_theme_style_get(obj));
      }
 
    if (ret)
@@ -682,9 +684,6 @@ _efl_ui_layout_efl_canvas_group_group_del(Eo *obj, 
Efl_Ui_Layout_Data *sd)
    eina_hash_free(sd->factories);
    sd->factories = NULL;
 
-   eina_stringshare_del(sd->klass);
-   eina_stringshare_del(sd->group);
-
    /* let's make our Edje object the *last* to be processed, since it
     * may (smart) parent other sub objects here */
    EINA_LIST_FOREACH(wd->subobjs, l, child)
@@ -799,6 +798,7 @@ _efl_ui_layout_efl_file_mmap_get(Eo *obj, 
Efl_Ui_Layout_Data *sd EINA_UNUSED, co
 EOLIAN static Efl_Ui_Theme_Apply
 _efl_ui_layout_theme_set(Eo *obj, Efl_Ui_Layout_Data *sd, const char *klass, 
const char *group, const char *style)
 {
+   Eina_Bool changed = EINA_FALSE;
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
 
    if (!wd->legacy && efl_finalized_get(obj))
@@ -808,11 +808,14 @@ _efl_ui_layout_theme_set(Eo *obj, Efl_Ui_Layout_Data *sd, 
const char *klass, con
      }
 
    if (sd->file_set) sd->file_set = EINA_FALSE;
-   eina_stringshare_replace(&(sd->klass), klass);
-   eina_stringshare_replace(&(sd->group), group);
-   eina_stringshare_replace(&(wd->style), style);
 
-   return _efl_ui_layout_theme_internal(obj, sd);
+   changed |= elm_widget_theme_klass_set(obj, klass);
+   changed |= elm_widget_theme_element_set(obj, group);
+   changed |= elm_widget_theme_style_set(obj, style);
+
+   if (changed)
+     return efl_ui_widget_theme_apply(obj);
+   return EFL_UI_THEME_APPLY_SUCCESS;
 }
 
 EOLIAN static void
@@ -2376,7 +2379,7 @@ elm_layout_theme_set(Evas_Object *obj, const char *klass, 
const char *group, con
 /* Efl.Part implementation */
 
 EOLIAN static Eo *
-_efl_ui_layout_efl_part_part(const Eo *obj, Efl_Ui_Layout_Data *sd, const char 
*part)
+_efl_ui_layout_efl_part_part(const Eo *obj, Efl_Ui_Layout_Data *sd 
EINA_UNUSED, const char *part)
 {
    Efl_Canvas_Layout_Part_Type type;
 
@@ -2397,7 +2400,7 @@ _efl_ui_layout_efl_part_part(const Eo *obj, 
Efl_Ui_Layout_Data *sd, const char *
                   const char *file = NULL, *key = NULL;
                   efl_file_get(wd->resize_obj, &file, &key);
                   WRN("Layout has a background but it's not a swallow: '%s'",
-                      sd->group);
+                      elm_widget_theme_element_get(obj));
                }
              return efl_part(efl_super(obj, MY_CLASS), part);
           }
@@ -2407,7 +2410,7 @@ _efl_ui_layout_efl_part_part(const Eo *obj, 
Efl_Ui_Layout_Data *sd, const char *
 
    if (type >= EFL_CANVAS_LAYOUT_PART_TYPE_LAST)
      {
-        ERR("Invalid type found for part '%s' in group '%s'", part, sd->group);
+        ERR("Invalid type found for part '%s' in group '%s'", part, 
elm_widget_theme_element_get(obj));
         return NULL;
      }
 
@@ -2422,7 +2425,7 @@ _efl_ui_layout_efl_part_part(const Eo *obj, 
Efl_Ui_Layout_Data *sd, const char *
       case EFL_CANVAS_LAYOUT_PART_TYPE_SWALLOW:
         return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_CONTENT_CLASS, obj, part);
       case EFL_CANVAS_LAYOUT_PART_TYPE_NONE:
-        WRN("No such part '%s' in group '%s'", part, sd->group);
+        WRN("No such part '%s' in group '%s'", part, 
elm_widget_theme_element_get(obj));
         return NULL;
       default:
         return ELM_PART_IMPLEMENT(EFL_UI_LAYOUT_PART_CLASS, obj, part);
diff --git a/src/lib/elementary/efl_ui_panes.c 
b/src/lib/elementary/efl_ui_panes.c
index 9c46cab040..1d70fd23d5 100644
--- a/src/lib/elementary/efl_ui_panes.c
+++ b/src/lib/elementary/efl_ui_panes.c
@@ -60,12 +60,11 @@ _efl_ui_panes_elm_widget_theme_apply(Eo *obj, 
Efl_Ui_Panes_Data *sd)
    Evas_Coord minw = 0, minh = 0;
 
    Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED;
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
 
    if (sd->dir == EFL_UI_DIR_HORIZONTAL)
-     eina_stringshare_replace(&ld->group, "horizontal");
+     elm_widget_theme_element_set(obj, "horizontal");
    else
-     eina_stringshare_replace(&ld->group, "vertical");
+     elm_widget_theme_element_set(obj, "vertical");
 
    evas_object_hide(sd->event);
    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
diff --git a/src/lib/elementary/efl_ui_progressbar.c 
b/src/lib/elementary/efl_ui_progressbar.c
index 10d67b4289..0ca030e7bf 100644
--- a/src/lib/elementary/efl_ui_progressbar.c
+++ b/src/lib/elementary/efl_ui_progressbar.c
@@ -202,12 +202,11 @@ EOLIAN static Efl_Ui_Theme_Apply
 _efl_ui_progressbar_elm_widget_theme_apply(Eo *obj, Efl_Ui_Progressbar_Data 
*sd)
 {
    Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED;
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_FAILED);
 
    if (_is_horizontal(sd->dir))
-     eina_stringshare_replace(&ld->group, "horizontal");
-   else eina_stringshare_replace(&ld->group, "vertical");
+     elm_widget_theme_element_set(obj, "horizontal");
+   else elm_widget_theme_element_set(obj, "vertical");
 
    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
    if (!int_ret) return EFL_UI_THEME_APPLY_FAILED;
diff --git a/src/lib/elementary/efl_ui_slider.c 
b/src/lib/elementary/efl_ui_slider.c
index b5da71ef2a..274b03c6a0 100644
--- a/src/lib/elementary/efl_ui_slider.c
+++ b/src/lib/elementary/efl_ui_slider.c
@@ -699,15 +699,14 @@ EOLIAN static Efl_Ui_Theme_Apply
 _efl_ui_slider_elm_widget_theme_apply(Eo *obj, Efl_Ui_Slider_Data *sd)
 {
    Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED;
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_FAILED);
 
    if (_is_horizontal(sd->dir))
      {
         if (!sd->intvl_enable)
-          eina_stringshare_replace(&ld->group, "horizontal");
+          elm_widget_theme_element_set(obj, "horizontal");
         else
-          eina_stringshare_replace(&ld->group, "range/horizontal");
+          elm_widget_theme_element_set(obj, "range/horizontal");
         if (sd->popup)
           _elm_theme_set(elm_widget_theme_get(obj), sd->popup,
                          "slider", "horizontal/popup",
@@ -720,9 +719,9 @@ _efl_ui_slider_elm_widget_theme_apply(Eo *obj, 
Efl_Ui_Slider_Data *sd)
    else
      {
         if (!sd->intvl_enable)
-          eina_stringshare_replace(&ld->group, "vertical");
+          elm_widget_theme_element_set(obj, "vertical");
         else
-          eina_stringshare_replace(&ld->group, "range/vertical");
+          elm_widget_theme_element_set(obj, "range/vertical");
 
         if (sd->popup)
           _elm_theme_set(elm_widget_theme_get(obj), sd->popup,
diff --git a/src/lib/elementary/elc_hoversel.c 
b/src/lib/elementary/elc_hoversel.c
index 01181a53e8..26d9355b63 100644
--- a/src/lib/elementary/elc_hoversel.c
+++ b/src/lib/elementary/elc_hoversel.c
@@ -81,12 +81,12 @@ _elm_hoversel_elm_widget_theme_apply(Eo *obj, 
Elm_Hoversel_Data *sd)
      snprintf(buf, sizeof(buf), "hoversel_vertical/%s", style);
 
    /* hoversel's style has an extra bit: orientation */
-   eina_stringshare_replace(&(wd->style), buf);
+   elm_widget_theme_style_set(obj, buf);
 
    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
    if (!int_ret) return EFL_UI_THEME_APPLY_FAILED;
 
-   eina_stringshare_replace(&(wd->style), style);
+   elm_widget_theme_style_set(obj, style);
 
    if (sd->hover)
      efl_ui_mirrored_set(sd->hover, efl_ui_mirrored_get(obj));
diff --git a/src/lib/elementary/elm_bubble.c b/src/lib/elementary/elm_bubble.c
index b46018a47b..7747809f70 100644
--- a/src/lib/elementary/elm_bubble.c
+++ b/src/lib/elementary/elm_bubble.c
@@ -205,15 +205,12 @@ EOLIAN static void
 _elm_bubble_pos_set(Eo *obj, Elm_Bubble_Data *sd, Elm_Bubble_Pos pos)
 {
    /* FIXME: Why is this dealing with layout data directly? */
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
-
    if (pos < ELM_BUBBLE_POS_TOP_LEFT || pos > ELM_BUBBLE_POS_BOTTOM_RIGHT)
      return;
 
    sd->pos = pos;
 
-   eina_stringshare_replace
-     (&ld->group, corner_string[sd->pos]);
+   elm_widget_theme_element_set(obj, corner_string[sd->pos]);
 
    efl_ui_widget_theme_apply(obj);
 }
diff --git a/src/lib/elementary/elm_index.c b/src/lib/elementary/elm_index.c
index ccc08a1a18..bb33e027ab 100644
--- a/src/lib/elementary/elm_index.c
+++ b/src/lib/elementary/elm_index.c
@@ -441,15 +441,14 @@ _elm_index_elm_widget_theme_apply(Eo *obj, Elm_Index_Data 
*sd)
    Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED;
 
    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
 
    _index_box_clear(obj, 0);
    _index_box_clear(obj, 1);
 
    if (efl_ui_dir_is_horizontal(sd->dir, EINA_FALSE))
-     eina_stringshare_replace(&ld->group, "base/horizontal");
+     elm_widget_theme_element_set(obj, "base/horizontal");
    else
-     eina_stringshare_replace(&ld->group, "base/vertical");
+     elm_widget_theme_element_set(obj, "base/vertical");
 
    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
    if (!int_ret) return EFL_UI_THEME_APPLY_FAILED;
diff --git a/src/lib/elementary/elm_scroller.c 
b/src/lib/elementary/elm_scroller.c
index e953961bbe..40eb846e77 100644
--- a/src/lib/elementary/elm_scroller.c
+++ b/src/lib/elementary/elm_scroller.c
@@ -895,14 +895,12 @@ _elm_scroller_efl_object_constructor(Eo *obj, 
Elm_Scroller_Data *_pd EINA_UNUSED
 EOLIAN static void
 _elm_scroller_custom_widget_base_theme_set(Eo *obj, Elm_Scroller_Data *_pd 
EINA_UNUSED, const char *klass, const char *group)
 {
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
-
    EINA_SAFETY_ON_NULL_RETURN(klass);
    EINA_SAFETY_ON_NULL_RETURN(group);
 
-   if (eina_stringshare_replace(&(ld->klass), klass) ||
-       eina_stringshare_replace(&(ld->group), group))
-      efl_ui_widget_theme_apply(obj);
+   if (elm_widget_theme_klass_set(obj, klass) ||
+       elm_widget_theme_element_set(obj, group))
+       efl_ui_widget_theme_apply(obj);
 }
 
 EAPI void
diff --git a/src/lib/elementary/elm_separator.c 
b/src/lib/elementary/elm_separator.c
index e720f4e410..2f25d53ea6 100644
--- a/src/lib/elementary/elm_separator.c
+++ b/src/lib/elementary/elm_separator.c
@@ -20,12 +20,11 @@ EOLIAN static Efl_Ui_Theme_Apply
 _elm_separator_elm_widget_theme_apply(Eo *obj, Elm_Separator_Data *sd 
EINA_UNUSED)
 {
    Efl_Ui_Theme_Apply int_ret = EFL_UI_THEME_APPLY_FAILED;
-   EFL_UI_LAYOUT_DATA_GET(obj, ld);
 
    if (sd->horizontal)
-     eina_stringshare_replace(&ld->group, "horizontal");
+     elm_widget_theme_element_set(obj, "horizontal");
    else
-     eina_stringshare_replace(&ld->group, "vertical");
+     elm_widget_theme_element_set(obj, "vertical");
 
    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
    if (!int_ret) return EFL_UI_THEME_APPLY_FAILED;
diff --git a/src/lib/elementary/elm_widget.c b/src/lib/elementary/elm_widget.c
index e629d7c700..bd10b63a49 100644
--- a/src/lib/elementary/elm_widget.c
+++ b/src/lib/elementary/elm_widget.c
@@ -794,6 +794,8 @@ _elm_widget_efl_canvas_group_group_del(Eo *obj, 
Elm_Widget_Smart_Data *sd)
    EINA_LIST_FREE(sd->event_cb, ecb)
       free(ecb);
 
+   eina_stringshare_del(sd->klass);
+   eina_stringshare_del(sd->group);
    eina_stringshare_del(sd->style);
    if (sd->theme) elm_theme_free(sd->theme);
    eina_stringshare_del(sd->access_info);
@@ -3602,6 +3604,137 @@ _elm_widget_focus_move_policy_automatic_set(Eo *obj, 
Elm_Widget_Smart_Data *sd,
      }
 }
 
+/**
+ * @internal
+ *
+ * Sets the klass name of a widget.
+ * @param obj The widget.
+ * @param name Name of the klass to use.
+ * @return Whether the name was different and thus replaced.
+ */
+EAPI Eina_Bool
+elm_widget_theme_klass_set(Evas_Object *obj, const char *name)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, EINA_FALSE);
+   return eina_stringshare_replace(&(pd->klass), name);
+}
+
+/**
+ * @internal
+ *
+ * Gets the klass name of a widget.
+ * @param obj The widget.
+ * @return The current klass name of internal canvas object.
+ */
+EAPI const char *
+elm_widget_theme_klass_get(const Evas_Object *obj)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+   return (const char *)pd->klass;
+}
+
+/**
+ * @internal
+ *
+ * Sets the element name of a widget.
+ *
+ * @param obj The widget.
+ * @param name Name of the element to use.
+ * @return Whether the name was different and thus replaced.
+ */
+EAPI Eina_Bool
+elm_widget_theme_element_set(Evas_Object *obj, const char *name)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, EINA_FALSE);
+   return eina_stringshare_replace(&(pd->group), name);
+}
+
+/**
+ * @internal
+ *
+ * Gets the element name of a widget.
+ * @param obj The widget.
+ * @return The current element name of internal canvas object.
+ */
+EAPI const char *
+elm_widget_theme_element_get(const Evas_Object *obj)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+   return (const char *)pd->group;
+}
+
+/**
+ * @internal
+ *
+ * Sets the style name of a widget.
+ *
+ * @param obj The widget.
+ * @param name Name of the style to use.
+ * @return Whether the name was different and thus replaced.
+ */
+EAPI Eina_Bool
+elm_widget_theme_style_set(Evas_Object *obj, const char *name)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, EINA_FALSE);
+   return eina_stringshare_replace(&(pd->style), name);
+}
+
+/**
+ * @internal
+ *
+ * Gets the style name of a widget.
+ * @param obj The widget.
+ * @return The current style name of internal canvas object.
+ */
+EAPI const char *
+elm_widget_theme_style_get(const Evas_Object *obj)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, pd, NULL);
+   return (const char *)pd->style;
+}
+
+/**
+ * @internal
+ *
+ * Register sub object as a group of a widget and re-apply its theme.
+ * @param obj The widget.
+ * @param component A sub object to be added as an element of the widget.
+ * @param name An element name of sub object.
+ * @return Whether the style was successfully applied or not.
+ */
+EAPI Efl_Ui_Theme_Apply
+elm_widget_element_update(Evas_Object *obj, Evas_Object *component, const char 
*name)
+{
+   Efl_Ui_Theme_Apply ret = EFL_UI_THEME_APPLY_SUCCESS;
+   Eina_Bool changed = EINA_FALSE;
+   const char *obj_group;
+   Eina_Stringshare *group;
+
+   obj_group = elm_widget_theme_element_get(obj);
+   if (!obj_group)
+     group = eina_stringshare_add(name);
+   else
+     group = eina_stringshare_printf("%s/%s", 
elm_widget_theme_element_get(obj), name);
+   if (efl_isa(component, ELM_WIDGET_CLASS))
+     {
+        changed |= elm_widget_theme_klass_set(component, 
elm_widget_theme_klass_get(obj));
+        changed |= elm_widget_theme_element_set(component, (const char 
*)group);
+        changed |= elm_widget_theme_style_set(component, 
elm_widget_theme_style_get(obj));
+        if (changed)
+          ret = efl_ui_widget_theme_apply(component);
+     }
+   else
+     {
+        ret = efl_ui_widget_theme_object_set(obj, component,
+                                   elm_widget_theme_klass_get(obj),
+                                   (const char *)group,
+                                   elm_widget_theme_style_get(obj));
+     }
+   eina_stringshare_del(group);
+
+   return ret;
+}
+
 static void
 _track_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
 
diff --git a/src/lib/elementary/elm_widget.h b/src/lib/elementary/elm_widget.h
index abc92795a8..5112048b20 100644
--- a/src/lib/elementary/elm_widget.h
+++ b/src/lib/elementary/elm_widget.h
@@ -407,6 +407,8 @@ typedef struct _Elm_Widget_Smart_Data
 
    double                        scale;
    Elm_Theme                    *theme;
+   const char                   *klass; /**< 1st identifier of an edje object 
group which is used in theme_set. klass and group are used together. */
+   const char                   *group; /**< 2nd identifier of an edje object 
group which is used in theme_set. klass and group are used together. */
    const char                   *style;
    const char                   *access_info;
    const char                   *accessible_name;
@@ -743,6 +745,14 @@ EAPI Elm_Focus_Region_Show_Mode 
elm_widget_focus_region_show_mode_get(const Evas
 const char           *elm_widget_part_translatable_text_get(const Eo *obj, 
const char *part, const char **domain);
 void                  elm_widget_part_translatable_text_set(Eo *obj, const 
char *part, const char *label, const char *domain);
 
+EAPI Eina_Bool        elm_widget_theme_klass_set(Evas_Object *obj, const char 
*name);
+EAPI const char      *elm_widget_theme_klass_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_theme_element_set(Evas_Object *obj, const 
char *name);
+EAPI const char      *elm_widget_theme_element_get(const Evas_Object *obj);
+EAPI Eina_Bool        elm_widget_theme_style_set(Evas_Object *obj, const char 
*name);
+EAPI const char      *elm_widget_theme_style_get(const Evas_Object *obj);
+EAPI Efl_Ui_Theme_Apply elm_widget_element_update(Evas_Object *obj, 
Evas_Object *component, const char *name);
+
 /* debug function. don't use it unless you are tracking parenting issues */
 EAPI void             elm_widget_tree_dump(const Evas_Object *top);
 EAPI void             elm_widget_tree_dot_dump(const Evas_Object *top, FILE 
*output);
diff --git a/src/lib/elementary/elm_widget_layout.h 
b/src/lib/elementary/elm_widget_layout.h
index ab4058fec7..1a3cf2a394 100644
--- a/src/lib/elementary/elm_widget_layout.h
+++ b/src/lib/elementary/elm_widget_layout.h
@@ -56,8 +56,6 @@ typedef struct _Elm_Layout_Smart_Data
    Eina_List            *prop_connect; /**< The hash of properties connected 
to layout parts. */
    Eina_Hash            *factories; /**< The hash with parts connected to 
factories. */
    Efl_Model            *model; /**< The model */
-   const char           *klass; /**< 1st identifier of an edje object group 
which is used in theme_set. klass and group are used together. */
-   const char           *group; /**< 2nd identifier of an edje object group 
which is used in theme_set. klass and group are used together. */
    int                   frozen; /**< Layout freeze counter */
 
    Eina_Bool             needs_size_calc : 1; /**< This flas is set true when 
the layout sizing eval is already requested. This defers sizing evaluation 
until smart calculation to avoid unnecessary calculation. */

-- 


Reply via email to