1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #include <Elementary.h>
6 
7 #include "elm_priv.h"
8 #include "efl_ui_item_private.h"
9 
10 #define MY_CLASS      EFL_UI_ITEM_CLASS
11 #define MY_CLASS_PFX  efl_ui_item
12 
13 #define MY_CLASS_NAME "Efl.Ui.Item"
14 
15 static Eina_Bool _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED);
16 
17 static const Elm_Action key_actions[] = {
18    {"select", _key_action_select},
19    {NULL, NULL}
20 };
21 
22 static Eina_Bool
_key_action_select(Evas_Object * obj,const char * params EINA_UNUSED)23 _key_action_select(Evas_Object *obj, const char *params EINA_UNUSED)
24 {
25    efl_ui_selectable_selected_set(obj, EINA_TRUE);
26    return EINA_FALSE;
27 }
28 
29 static Efl_Ui_Select_Mode
_fetch_state(Eo * obj)30 _fetch_state(Eo *obj)
31 {
32    if (efl_isa(obj, EFL_UI_MULTI_SELECTABLE_INTERFACE))
33      return efl_ui_multi_selectable_select_mode_get(obj);
34    if (efl_isa(obj, EFL_UI_SINGLE_SELECTABLE_INTERFACE))
35      return EFL_UI_SELECT_MODE_SINGLE;
36    ERR("Uncaught state %s", efl_debug_name_get(obj));
37    return EFL_UI_SELECT_MODE_NONE;
38 }
39 
40 static void
_item_select(Eo * obj,Efl_Ui_Item_Data * pd)41 _item_select(Eo *obj, Efl_Ui_Item_Data *pd)
42 {
43    Efl_Ui_Select_Mode m;
44 
45    if (pd->container)
46      {
47         m = _fetch_state(pd->container);
48         if (m == EFL_UI_SELECT_MODE_NONE)
49           return;
50      }
51    else
52      {
53         if (pd->selected)
54           return;
55      }
56 
57    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
58 
59    Eina_Bool tmp = pd->selected = EINA_TRUE;
60    edje_object_signal_emit(wd->resize_obj, "efl,state,selected", "efl");
61    efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED_CHANGED, &tmp);
62 }
63 
64 static void
_item_unselect(Eo * obj,Efl_Ui_Item_Data * pd)65 _item_unselect(Eo *obj, Efl_Ui_Item_Data *pd)
66 {
67    if (!pd->selected) return;
68    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
69 
70    Eina_Bool tmp = pd->selected =EINA_FALSE;
71    edje_object_signal_emit(wd->resize_obj, "efl,state,unselected", "efl");
72    efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED_CHANGED, &tmp);
73 }
74 
75 /* Mouse Controls */
76 static void
_item_pressed(void * data,const Efl_Event * ev EINA_UNUSED)77 _item_pressed(void *data, const Efl_Event *ev EINA_UNUSED)
78 {
79    Efl_Ui_Item *obj = data;
80    if (efl_ui_widget_disabled_get(obj)) return;
81 
82    efl_layout_signal_emit(obj, "efl,state,pressed", "efl");
83 }
84 
85 static void
_item_unpressed(void * data,const Efl_Event * ev EINA_UNUSED)86 _item_unpressed(void *data, const Efl_Event *ev EINA_UNUSED)
87 {
88    Efl_Ui_Item *obj = data;
89    Efl_Ui_Select_Mode m;
90    EFL_UI_ITEM_DATA_GET_OR_RETURN(obj, pd);
91 
92    if (efl_ui_widget_disabled_get(obj)) return;
93    if (!efl_ui_item_container_get(obj)) return;
94 
95    efl_layout_signal_emit(obj, "efl,state,unpressed", "efl");
96    m = _fetch_state(pd->container);
97 
98    if (pd->selected)
99      {
100         if (efl_ui_selectable_allow_manual_deselection_get(pd->container))
101           efl_ui_selectable_selected_set(obj, EINA_FALSE);
102      }
103    else if (m != EFL_UI_SELECT_MODE_NONE)
104      efl_ui_selectable_selected_set(obj, EINA_TRUE);
105 }
106 
107 EFL_CALLBACKS_ARRAY_DEFINE(self_listening,
108   {EFL_INPUT_EVENT_PRESSED, _item_pressed},
109   {EFL_INPUT_EVENT_UNPRESSED, _item_unpressed},
110 )
111 
112 /* Mouse Controls ends */
113 
114 EOLIAN static Eo *
_efl_ui_item_efl_object_constructor(Eo * obj,Efl_Ui_Item_Data * pd EINA_UNUSED)115 _efl_ui_item_efl_object_constructor(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED)
116 {
117    obj = efl_constructor(efl_super(obj, MY_CLASS));
118    efl_ui_layout_finger_size_multiplier_set(obj, 0, 0);
119 
120    efl_event_callback_array_add(obj, self_listening(), obj);
121 
122    return obj;
123 }
124 
125 EOLIAN static Efl_Object *
_efl_ui_item_efl_object_finalize(Eo * obj,Efl_Ui_Item_Data * pd EINA_UNUSED)126 _efl_ui_item_efl_object_finalize(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED)
127 {
128    Eo *eo;
129    eo = efl_finalize(efl_super(obj, MY_CLASS));
130    ELM_WIDGET_DATA_GET_OR_RETURN(eo, wd, eo);
131 
132    /* Support Item Focus Feature */
133    elm_widget_can_focus_set(obj, EINA_TRUE);
134 
135    if (efl_ui_layout_theme_version_get(obj) == 123)
136      efl_ui_action_connector_bind_clickable_to_object(wd->resize_obj, obj);
137    else
138      efl_ui_action_connector_bind_clickable_to_theme(wd->resize_obj, obj);
139    return eo;
140 }
141 
142 EOLIAN static void
_efl_ui_item_efl_object_destructor(Eo * obj,Efl_Ui_Item_Data * pd EINA_UNUSED)143 _efl_ui_item_efl_object_destructor(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED)
144 {
145    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
146 
147    efl_destructor(efl_super(obj, MY_CLASS));
148 }
149 
150 EOLIAN static int
_efl_ui_item_index_get(const Eo * obj,Efl_Ui_Item_Data * pd)151 _efl_ui_item_index_get(const Eo *obj, Efl_Ui_Item_Data *pd)
152 {
153    EINA_SAFETY_ON_NULL_RETURN_VAL(pd->container, -1);
154    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(pd->container, EFL_PACK_LINEAR_INTERFACE), -1);
155    return efl_pack_index_get(pd->container, obj);
156 }
157 
158 EOLIAN static void
_efl_ui_item_efl_ui_selectable_selected_set(Eo * obj,Efl_Ui_Item_Data * pd,Eina_Bool select)159 _efl_ui_item_efl_ui_selectable_selected_set(Eo *obj, Efl_Ui_Item_Data *pd, Eina_Bool select)
160 {
161    Eina_Bool selected = !!select;
162    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
163    if (wd->disabled) return;
164 
165    if (selected) _item_select(obj, pd);
166    else _item_unselect(obj, pd);
167 }
168 
169 EOLIAN static Eina_Bool
_efl_ui_item_efl_ui_selectable_selected_get(const Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd)170 _efl_ui_item_efl_ui_selectable_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
171 {
172    return pd->selected;
173 }
174 
175 EOLIAN static void
_efl_ui_item_container_set(Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd,Efl_Ui_Widget * container)176 _efl_ui_item_container_set(Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd, Efl_Ui_Widget *container)
177 {
178    pd->container = container;
179    if (!pd->container)
180      {
181         pd->parent = NULL;
182      }
183 }
184 
185 EOLIAN static Efl_Ui_Widget*
_efl_ui_item_container_get(const Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd)186 _efl_ui_item_container_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
187 {
188    return pd->container;
189 }
190 
191 EOLIAN static void
_efl_ui_item_item_parent_set(Eo * obj,Efl_Ui_Item_Data * pd,Efl_Ui_Item * parent)192 _efl_ui_item_item_parent_set(Eo *obj, Efl_Ui_Item_Data *pd, Efl_Ui_Item *parent)
193 {
194    if (pd->parent)
195      {
196         ERR("Parent is already set on object %p", obj);
197         return;
198      }
199    if (efl_invalidated_get(obj) || efl_invalidating_get(obj))
200      {
201         ERR("Parent cannot be set during invalidate");
202         return;
203      }
204    if (pd->container)
205      {
206         ERR("Parent must be set before adding the object to the container");
207         return;
208      }
209    pd->parent = parent;
210 }
211 
212 
213 EOLIAN static Efl_Ui_Item*
_efl_ui_item_item_parent_get(const Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd)214 _efl_ui_item_item_parent_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
215 {
216    return pd->parent;
217 }
218 
219 EOLIAN static void
_efl_ui_item_calc_locked_set(Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd,Eina_Bool locked)220 _efl_ui_item_calc_locked_set(Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd, Eina_Bool locked)
221 {
222    pd->locked = !!locked;
223 }
224 
225 EOLIAN static Eina_Bool
_efl_ui_item_calc_locked_get(const Eo * obj EINA_UNUSED,Efl_Ui_Item_Data * pd)226 _efl_ui_item_calc_locked_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd)
227 {
228    return pd->locked;
229 }
230 
231 EOLIAN static void
_efl_ui_item_efl_canvas_group_group_need_recalculate_set(Eo * obj,Efl_Ui_Item_Data * pd EINA_UNUSED,Eina_Bool value)232 _efl_ui_item_efl_canvas_group_group_need_recalculate_set(Eo *obj, Efl_Ui_Item_Data *pd EINA_UNUSED, Eina_Bool value)
233 {
234    // Prevent recalc when the item are stored in the cache
235    // As due to async behavior, we can still have text updated from future that just finished after
236    // we have left the releasing stage of factories. This is the simplest way to prevent those later
237    // update.
238    if (pd->locked) return;
239    efl_canvas_group_need_recalculate_set(efl_super(obj, EFL_UI_ITEM_CLASS), value);
240 }
241 
242 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_item, Efl_Ui_Item_Data)
243 
244 #include "efl_ui_item.eo.c"
245 #include "efl_ui_selectable.eo.c"
246 #include "efl_ui_multi_selectable.eo.c"
247 #include "efl_ui_multi_selectable_object_range.eo.c"
248 #include "efl_ui_single_selectable.eo.c"
249 #include "efl_ui_item_clickable.eo.c"
250 
251