1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
7 #define ELM_LAYOUT_PROTECTED
8 #define EFL_PART_PROTECTED
9
10 #include <Elementary.h>
11 #include "elm_priv.h"
12 #include "efl_ui_check_private.h"
13 #include "elm_part_helper.h"
14
15 #define MY_CLASS EFL_UI_CHECK_CLASS
16 #define MY_CLASS_PFX efl_ui_check
17
18 #define MY_CLASS_NAME "Efl.Ui.Check"
19
20 static const Elm_Layout_Part_Alias_Description _text_aliases[] =
21 {
22 {"default", "elm.text"},
23 {"on", "elm.ontext"},
24 {"off", "elm.offtext"},
25 {NULL, NULL}
26 };
27
28 static const Elm_Layout_Part_Alias_Description _content_aliases[] =
29 {
30 {"icon", "elm.swallow.content"},
31 {NULL, NULL}
32 };
33
34 static const char SIG_CHANGED[] = "changed";
35
36 /* smart callbacks coming from elm check objects: */
37 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
38 {SIG_CHANGED, ""},
39 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
40 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
41 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
42 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
43 {NULL, NULL}
44 };
45
46 static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
47
48 static const Elm_Action key_actions[] = {
49 {"activate", _key_action_activate},
50 {NULL, NULL}
51 };
52
53 static void
_check_legacy_event(Eo * obj)54 _check_legacy_event(Eo *obj)
55 {
56 EFL_UI_CHECK_DATA_GET(obj, pd);
57 if (pd->selected)
58 {
59 if (pd->legacy_changed_emitted_select) return;
60 pd->legacy_changed_emitted_select = EINA_TRUE;
61 pd->legacy_changed_emitted_unselect = EINA_FALSE;
62 }
63 else
64 {
65 if (pd->legacy_changed_emitted_unselect) return;
66 pd->legacy_changed_emitted_unselect = EINA_TRUE;
67 pd->legacy_changed_emitted_select = EINA_FALSE;
68 }
69 evas_object_smart_callback_call(obj, "changed", NULL);
70 }
71
72 static void
_activate(Evas_Object * obj)73 _activate(Evas_Object *obj)
74 {
75 // state will be changed by the later call to the selected_set call
76 if (!efl_ui_selectable_selected_get(obj))
77 {
78 // FIXME: to do animation during state change , we need different signal
79 // so that we can distinguish between state change by user or state change
80 // by calling state_change() api. Keep both the signal for backward compatibility
81 // and remove "elm,state,check,on" signal emission when we can break ABI.
82 // efl_ui_selectable_selected_set below will emit "elm,state,check,*" or "efl,state,*selected"
83 if (elm_widget_is_legacy(obj))
84 {
85 elm_layout_signal_emit(obj, "elm,activate,check,on", "elm");
86 }
87 else
88 {
89 elm_layout_signal_emit(obj, "efl,state,selected", "efl");
90 }
91
92 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
93 _elm_access_say(E_("State: On"));
94 }
95 else
96 {
97 // FIXME: to do animation during state change , we need different signal
98 // so that we can distinguish between state change by user or state change
99 // by calling state_change() api. Keep both the signal for backward compatibility
100 // and remove "elm,state,check,off" signal emission when we can break ABI.
101 // efl_ui_selectable_selected_set below will emit "elm,state,check,*" or "efl,state,*selected"
102 if (elm_widget_is_legacy(obj))
103 {
104 elm_layout_signal_emit(obj, "elm,activate,check,off", "elm");
105 }
106 else
107 {
108 elm_layout_signal_emit(obj, "efl,state,unselected", "efl");
109 }
110
111 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
112 _elm_access_say(E_("State: Off"));
113 }
114 //This commit will update the theme with the correct signals
115 // "elm,state,check,on" or "elm,state,check,off" for legacy
116 // "efl,state,selected" or "efl,state,unselected" for eo-api
117 efl_ui_selectable_selected_set(obj, !efl_ui_selectable_selected_get(obj));
118 if (elm_widget_is_legacy(obj))
119 _check_legacy_event(obj);
120 if (_elm_config->atspi_mode)
121 efl_access_state_changed_signal_emit(obj,
122 EFL_ACCESS_STATE_TYPE_CHECKED,
123 efl_ui_selectable_selected_get(obj));
124 }
125
126 EOLIAN static Efl_Access_State_Set
_efl_ui_check_efl_access_object_state_set_get(const Eo * obj,Efl_Ui_Check_Data * _pd EINA_UNUSED)127 _efl_ui_check_efl_access_object_state_set_get(const Eo *obj, Efl_Ui_Check_Data *_pd EINA_UNUSED)
128 {
129 Efl_Access_State_Set states = 0;
130
131 states = efl_access_object_state_set_get(efl_super(obj, EFL_UI_CHECK_CLASS));
132
133 if (elm_check_state_get(obj))
134 STATE_TYPE_SET(states, EFL_ACCESS_STATE_TYPE_CHECKED);
135
136 return states;
137 }
138
139 EOLIAN static Eina_Bool
_efl_ui_check_efl_ui_widget_on_access_activate(Eo * obj EINA_UNUSED,Efl_Ui_Check_Data * _pd EINA_UNUSED,Efl_Ui_Activate act)140 _efl_ui_check_efl_ui_widget_on_access_activate(Eo *obj EINA_UNUSED, Efl_Ui_Check_Data *_pd EINA_UNUSED, Efl_Ui_Activate act)
141 {
142 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
143 if (act != EFL_UI_ACTIVATE_DEFAULT) return EINA_FALSE;
144
145 _activate(obj);
146
147 return EINA_TRUE;
148 }
149
150 static Eina_Bool
_key_action_activate(Evas_Object * obj,const char * params EINA_UNUSED)151 _key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
152 {
153 _activate(obj);
154 return EINA_TRUE;
155 }
156
157 EOLIAN static Eina_Error
_efl_ui_check_efl_ui_widget_theme_apply(Eo * obj,Efl_Ui_Check_Data * sd EINA_UNUSED)158 _efl_ui_check_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Check_Data *sd EINA_UNUSED)
159 {
160 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
161
162 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_ERROR_GENERIC);
163
164 int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
165 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
166
167 if (elm_widget_is_legacy(obj))
168 {
169 if (!efl_ui_selectable_selected_get(obj))
170 elm_layout_signal_emit(obj, "elm,state,check,off", "elm");
171 else
172 elm_layout_signal_emit(obj, "elm,state,check,on", "elm");
173 }
174 else
175 {
176 if (!efl_ui_selectable_selected_get(obj))
177 elm_layout_signal_emit(obj, "efl,state,unselected", "efl");
178 else
179 elm_layout_signal_emit(obj, "efl,state,selected", "efl");
180 }
181
182 edje_object_message_signal_process(wd->resize_obj);
183
184 return int_ret;
185 }
186
187 static char *
_access_info_cb(void * data EINA_UNUSED,Evas_Object * obj)188 _access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
189 {
190 const char *txt = elm_widget_access_info_get(obj);
191
192 if (!txt) txt = elm_layout_text_get(obj, NULL);
193 if (txt) return strdup(txt);
194
195 return NULL;
196 }
197
198 static char *
_access_state_cb(void * data,Evas_Object * obj)199 _access_state_cb(void *data, Evas_Object *obj)
200 {
201 const char *on_text, *off_text;
202
203 if (elm_widget_disabled_get(obj))
204 return strdup(E_("State: Disabled"));
205 if (efl_ui_selectable_selected_get(obj))
206 {
207 on_text = elm_layout_text_get(data, "on");
208
209 if (on_text)
210 {
211 char buf[1024];
212
213 snprintf(buf, sizeof(buf), "%s: %s", E_("State"), on_text);
214 return strdup(buf);
215 }
216 else
217 return strdup(E_("State: On"));
218 }
219
220 off_text = elm_layout_text_get(data, "off");
221
222 if (off_text)
223 {
224 char buf[1024];
225
226 snprintf(buf, sizeof(buf), "%s: %s", E_("State"), off_text);
227 return strdup(buf);
228 }
229 return strdup(E_("State: Off"));
230 }
231
232 static void
_flush_selected(Eo * obj,Eina_Bool sel)233 _flush_selected(Eo *obj, Eina_Bool sel)
234 {
235 efl_ui_selectable_selected_set(obj, sel);
236
237 if (_elm_config->atspi_mode)
238 efl_access_state_changed_signal_emit(obj,
239 EFL_ACCESS_STATE_TYPE_CHECKED,
240 efl_ui_selectable_selected_get(obj));
241 }
242
243 static void
_on_check_off(void * data,Evas_Object * o EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)244 _on_check_off(void *data,
245 Evas_Object *o EINA_UNUSED,
246 const char *emission EINA_UNUSED,
247 const char *source EINA_UNUSED)
248 {
249 Evas_Object *obj = data;
250
251 _flush_selected(obj, EINA_FALSE);
252 if (elm_widget_is_legacy(obj))
253 _check_legacy_event(obj);
254 }
255
256 static void
_on_check_on(void * data,Evas_Object * o EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)257 _on_check_on(void *data,
258 Evas_Object *o EINA_UNUSED,
259 const char *emission EINA_UNUSED,
260 const char *source EINA_UNUSED)
261 {
262 Evas_Object *obj = data;
263
264 _flush_selected(obj, EINA_TRUE);
265 if (elm_widget_is_legacy(obj))
266 _check_legacy_event(obj);
267 }
268
269 static void
_on_check_toggle(void * data,Evas_Object * o EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)270 _on_check_toggle(void *data,
271 Evas_Object *o EINA_UNUSED,
272 const char *emission EINA_UNUSED,
273 const char *source EINA_UNUSED)
274 {
275 _activate(data);
276 }
277
278 static void
_clicked_cb(void * data,const Efl_Event * ev EINA_UNUSED)279 _clicked_cb(void *data, const Efl_Event *ev EINA_UNUSED)
280 {
281 _activate(data);
282 }
283
284 EOLIAN static Eina_Bool
_efl_ui_check_efl_ui_selectable_selected_get(const Eo * obj EINA_UNUSED,Efl_Ui_Check_Data * pd EINA_UNUSED)285 _efl_ui_check_efl_ui_selectable_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Check_Data *pd EINA_UNUSED)
286 {
287 return pd->selected;
288 }
289
290 EOLIAN static void
_efl_ui_check_efl_ui_selectable_selected_set(Eo * obj,Efl_Ui_Check_Data * pd,Eina_Bool value)291 _efl_ui_check_efl_ui_selectable_selected_set(Eo *obj, Efl_Ui_Check_Data *pd, Eina_Bool value)
292 {
293 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
294
295 if (pd->selected == value) return;
296
297 if (elm_widget_is_legacy(obj))
298 {
299 if (pd->statep)
300 *pd->statep = value;
301 }
302
303 if (elm_widget_is_legacy(obj))
304 {
305 if (value == 1)
306 elm_layout_signal_emit(obj, "elm,state,check,on", "elm");
307 else
308 elm_layout_signal_emit(obj, "elm,state,check,off", "elm");
309 }
310 else
311 {
312 if (value == 1)
313 elm_layout_signal_emit(obj, "efl,state,selected", "efl");
314 else
315 elm_layout_signal_emit(obj, "efl,state,unselected", "efl");
316 }
317
318 edje_object_message_signal_process(wd->resize_obj);
319
320 pd->selected = value;
321
322 pd->legacy_changed_emitted_select = !pd->selected;
323 pd->legacy_changed_emitted_unselect = pd->selected;
324
325 if (!elm_widget_is_legacy(obj))
326 efl_event_callback_call(obj, EFL_UI_EVENT_SELECTED_CHANGED, &pd->selected);
327 }
328
329 EOLIAN static Eo *
_efl_ui_check_efl_object_constructor(Eo * obj,Efl_Ui_Check_Data * pd EINA_UNUSED)330 _efl_ui_check_efl_object_constructor(Eo *obj, Efl_Ui_Check_Data *pd EINA_UNUSED)
331 {
332 if (!elm_widget_theme_klass_get(obj))
333 elm_widget_theme_klass_set(obj, "check");
334 obj = efl_constructor(efl_super(obj, MY_CLASS));
335 evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
336
337 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
338 efl_ui_action_connector_bind_clickable_to_theme(wd->resize_obj, obj);
339 if (elm_widget_is_legacy(obj))
340 {
341 efl_layout_signal_callback_add
342 (wd->resize_obj, "elm,action,check,on", "*", obj, _on_check_on, NULL);
343 efl_layout_signal_callback_add
344 (wd->resize_obj, "elm,action,check,off", "*", obj, _on_check_off, NULL);
345 efl_layout_signal_callback_add
346 (wd->resize_obj, "elm,action,check,toggle", "*", obj, _on_check_toggle, NULL);
347 }
348 else
349 {
350 efl_layout_signal_callback_add
351 (wd->resize_obj, "efl,action,select", "*", obj, _on_check_on, NULL);
352 efl_layout_signal_callback_add
353 (wd->resize_obj, "efl,action,unselect", "*", obj, _on_check_off, NULL);
354 efl_event_callback_add(obj, EFL_INPUT_EVENT_CLICKED, _clicked_cb, obj);
355 }
356
357 efl_access_object_role_set(obj, EFL_ACCESS_ROLE_CHECK_BOX);
358 _elm_access_object_register(obj, wd->resize_obj);
359 _elm_access_text_set
360 (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("Check"));
361 _elm_access_callback_set
362 (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, obj);
363 _elm_access_callback_set
364 (_elm_access_info_get(obj), ELM_ACCESS_STATE, _access_state_cb, obj);
365
366 elm_widget_can_focus_set(obj, EINA_TRUE);
367
368 return obj;
369 }
370
371 EAPI void
elm_check_state_set(Evas_Object * obj,Eina_Bool state)372 elm_check_state_set(Evas_Object *obj, Eina_Bool state)
373 {
374 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
375 EFL_UI_CHECK_DATA_GET_OR_RETURN(obj, sd);
376
377 efl_ui_selectable_selected_set(obj, state);
378 }
379
380 EAPI Eina_Bool
elm_check_state_get(const Evas_Object * obj)381 elm_check_state_get(const Evas_Object *obj)
382 {
383 return !!efl_ui_selectable_selected_get(obj);
384 }
385
386 EAPI void
elm_check_state_pointer_set(Eo * obj,Eina_Bool * statep)387 elm_check_state_pointer_set(Eo *obj, Eina_Bool *statep)
388 {
389 EFL_UI_CHECK_DATA_GET_OR_RETURN(obj, sd);
390
391 if (!statep)
392 {
393 sd->statep = NULL;
394 return;
395 }
396
397 sd->statep = statep;
398 if (*sd->statep != sd->selected)
399 {
400 efl_ui_selectable_selected_set(obj, *sd->statep);
401 }
402 }
403
404 EOLIAN const Efl_Access_Action_Data *
_efl_ui_check_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Efl_Ui_Check_Data * pd EINA_UNUSED)405 _efl_ui_check_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Efl_Ui_Check_Data *pd EINA_UNUSED)
406 {
407 static Efl_Access_Action_Data atspi_action[] = {
408 { "activate", "activate", NULL, _key_action_activate },
409 { NULL, NULL, NULL, NULL }
410 };
411 return &atspi_action[0];
412 }
413
414 /* Standard widget overrides */
415
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_check,Efl_Ui_Check_Data)416 ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_check, Efl_Ui_Check_Data)
417 ELM_PART_TEXT_DEFAULT_IMPLEMENT(efl_ui_check, Efl_Ui_Check_Data)
418 ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_check, Efl_Ui_Check_Data)
419 EFL_UI_LAYOUT_CONTENT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
420
421 /* Internal EO APIs and hidden overrides */
422
423 EFL_UI_LAYOUT_TEXT_ALIASES_IMPLEMENT(MY_CLASS_PFX)
424
425 #define EFL_UI_CHECK_EXTRA_OPS \
426 EFL_UI_LAYOUT_CONTENT_ALIASES_OPS(MY_CLASS_PFX), \
427 EFL_UI_LAYOUT_TEXT_ALIASES_OPS(MY_CLASS_PFX)
428
429
430 #include "efl_ui_check.eo.c"
431 #include "efl_ui_check_eo.legacy.c"
432
433 #include "efl_ui_check_legacy_eo.h"
434 #include "efl_ui_check_legacy_part.eo.h"
435
436 #define MY_CLASS_NAME_LEGACY "elm_check"
437
438 static void
439 _efl_ui_check_legacy_class_constructor(Efl_Class *klass)
440 {
441 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
442 }
443
444 EOLIAN static Eo *
_efl_ui_check_legacy_efl_object_constructor(Eo * obj,void * pd EINA_UNUSED)445 _efl_ui_check_legacy_efl_object_constructor(Eo *obj, void *pd EINA_UNUSED)
446 {
447 obj = efl_constructor(efl_super(obj, EFL_UI_CHECK_LEGACY_CLASS));
448 efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
449 legacy_object_focus_handle(obj);
450 return obj;
451 }
452
453 /* FIXME: replicated from elm_layout just because check's icon spot
454 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
455 * can changed the theme API */
456 EOLIAN static Eina_Error
_efl_ui_check_legacy_efl_ui_widget_theme_apply(Eo * obj,void * _pd EINA_UNUSED)457 _efl_ui_check_legacy_efl_ui_widget_theme_apply(Eo *obj, void *_pd EINA_UNUSED)
458 {
459 Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
460
461 int_ret = efl_ui_widget_theme_apply(efl_super(obj, EFL_UI_CHECK_LEGACY_CLASS));
462 if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
463
464 if (efl_finalized_get(obj)) _elm_layout_legacy_icon_signal_emit(obj);
465
466 return int_ret;
467 }
468
469 /* FIXME: replicated from elm_layout just because check's icon spot
470 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
471 * can changed the theme API */
472 EOLIAN static Eina_Bool
_efl_ui_check_legacy_efl_ui_widget_widget_sub_object_del(Eo * obj,void * _pd EINA_UNUSED,Evas_Object * sobj)473 _efl_ui_check_legacy_efl_ui_widget_widget_sub_object_del(Eo *obj, void *_pd EINA_UNUSED, Evas_Object *sobj)
474 {
475 Eina_Bool int_ret = EINA_FALSE;
476
477 int_ret = elm_widget_sub_object_del(efl_super(obj, EFL_UI_CHECK_LEGACY_CLASS), sobj);
478 if (!int_ret) return EINA_FALSE;
479
480 _elm_layout_legacy_icon_signal_emit(obj);
481
482 return EINA_TRUE;
483 }
484
485 /* FIXME: replicated from elm_layout just because check's icon spot
486 * is elm.swallow.content, not elm.swallow.icon. Fix that whenever we
487 * can changed the theme API */
488 static Eina_Bool
_efl_ui_check_legacy_content_set(Eo * obj,void * _pd EINA_UNUSED,const char * part,Evas_Object * content)489 _efl_ui_check_legacy_content_set(Eo *obj, void *_pd EINA_UNUSED, const char *part, Evas_Object *content)
490 {
491 Eina_Bool int_ret = EINA_FALSE;
492
493 int_ret = efl_content_set(efl_part(efl_super(obj, EFL_UI_CHECK_LEGACY_CLASS), part), content);
494 if (!int_ret) return EINA_FALSE;
495
496 _elm_layout_legacy_icon_signal_emit(obj);
497
498 return EINA_TRUE;
499 }
500
501 /* Efl.Part begin */
502
503 static Eina_Bool
_part_is_efl_ui_check_legacy_part(const Eo * obj EINA_UNUSED,const char * part)504 _part_is_efl_ui_check_legacy_part(const Eo *obj EINA_UNUSED, const char *part)
505 {
506 return eina_streq(part, "elm.swallow.content");
507 }
508
ELM_PART_OVERRIDE_PARTIAL(efl_ui_check_legacy,EFL_UI_CHECK_LEGACY,void,_part_is_efl_ui_check_legacy_part)509 ELM_PART_OVERRIDE_PARTIAL(efl_ui_check_legacy, EFL_UI_CHECK_LEGACY, void, _part_is_efl_ui_check_legacy_part)
510 ELM_PART_OVERRIDE_CONTENT_SET_NO_SD(efl_ui_check_legacy)
511 #include "efl_ui_check_legacy_part.eo.c"
512
513 /* Efl.Part end */
514
515 EAPI Evas_Object *
516 elm_check_add(Evas_Object *parent)
517 {
518 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
519 return elm_legacy_add(EFL_UI_CHECK_LEGACY_CLASS, parent);
520 }
521
522 #include "efl_ui_check_legacy_eo.c"
523