1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define ELM_WIDGET_ITEM_PROTECTED
7 //#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define EFL_ACCESS_WIDGET_ACTION_PROTECTED
9 #define EFL_UI_L10N_PROTECTED
10 #define EFL_PART_PROTECTED
11 
12 #include <Elementary.h>
13 #include "elm_priv.h"
14 #include "elm_widget_multibuttonentry.h"
15 #include "elm_multibuttonentry_part.eo.h"
16 #include "elm_entry_eo.h"
17 #include "elm_part_helper.h"
18 
19 #define MY_CLASS ELM_MULTIBUTTONENTRY_CLASS
20 
21 #define MY_CLASS_NAME "Elm_Multibuttonentry"
22 #define MY_CLASS_NAME_LEGACY "elm_multibuttonentry"
23 
24 #define MAX_STR     256
25 #define MIN_W_ENTRY 10
26 
27 //widget signals
28 static const char SIG_ITEM_SELECTED[] = "item,selected";
29 static const char SIG_ITEM_ADDED[] = "item,added";
30 static const char SIG_ITEM_DELETED[] = "item,deleted";
31 static const char SIG_ITEM_CLICKED[] = "item,clicked";
32 static const char SIG_ITEM_LONGPRESSED[] = "item,longpressed";
33 static const char SIG_CLICKED[] = "clicked";
34 static const char SIG_FOCUSED[] = "focused";
35 static const char SIG_UNFOCUSED[] = "unfocused";
36 static const char SIG_EXPANDED[] = "expanded";
37 static const char SIG_CONTRACTED[] = "contracted";
38 static const char SIG_EXPAND_STATE_CHANGED[] = "expand,state,changed";
39 
40 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
41    {SIG_ITEM_SELECTED, ""},
42    {SIG_ITEM_ADDED, ""},
43    {SIG_ITEM_DELETED, ""},
44    {SIG_ITEM_CLICKED, ""},
45    {SIG_ITEM_LONGPRESSED, ""},
46    {SIG_CLICKED, ""},
47    {SIG_FOCUSED, ""},
48    {SIG_UNFOCUSED, ""},
49    {SIG_EXPANDED, ""},
50    {SIG_CONTRACTED, ""},
51    {SIG_EXPAND_STATE_CHANGED, ""},
52    {NULL, NULL}
53 };
54 
55 static const char PART_NAME_BUTTON[] = "btn";
56 static const char PART_NAME_GUIDE_TEXT[] = "guidetext";
57 static const char PART_NAME_LABEL[] = "label";
58 static const char PART_NAME_CLOSED_BUTTON[] = "closedbutton";
59 
60 static Eina_Bool _elm_multibuttonentry_smart_focus_next_enable = EINA_FALSE;
61 static Eina_Bool _elm_multibuttonentry_smart_focus_direction_enable = EINA_TRUE;
62 
63 static void _entry_changed_cb(void *data, const Efl_Event *event);
64 static void _entry_focus_changed_cb(void *data, const Efl_Event *event);
65 static void _entry_clicked_cb(void *data, const Efl_Event *event);
66 
67 EFL_CALLBACKS_ARRAY_DEFINE(_multi_buttonentry_cb,
68    { ELM_ENTRY_EVENT_CHANGED, _entry_changed_cb },
69    { EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED , _entry_focus_changed_cb },
70    { EFL_INPUT_EVENT_CLICKED, _entry_clicked_cb }
71 );
72 
73 EOLIAN static void
_elm_multibuttonentry_efl_ui_l10n_translation_update(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)74 _elm_multibuttonentry_efl_ui_l10n_translation_update(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
75 {
76    Elm_Object_Item *it;
77    Eina_List *l;
78 
79    EINA_LIST_FOREACH(sd->items, l, it)
80      elm_wdg_item_translate(it);
81 
82    efl_ui_l10n_translation_update(efl_super(obj, MY_CLASS));
83 }
84 
85 static char *
_format_count(int count,void * data EINA_UNUSED)86 _format_count(int count, void *data EINA_UNUSED)
87 {
88    char buf[32];
89 
90    if (!snprintf(buf, sizeof(buf), "+%d", count)) return NULL;
91    return strdup(buf);
92 }
93 
94 EOLIAN static Eina_Error
_elm_multibuttonentry_efl_ui_widget_theme_apply(Eo * obj,Elm_Multibuttonentry_Data * sd)95 _elm_multibuttonentry_efl_ui_widget_theme_apply(Eo *obj, Elm_Multibuttonentry_Data *sd)
96 {
97    const char *str;
98    int hpad = 0, vpad = 0;
99    Eina_List *l;
100    Elm_Object_Item *eo_item;
101    double pad_scale;
102 
103    Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
104    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
105    if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
106 
107    str = elm_layout_data_get(obj, "horizontal_pad");
108    if (str) hpad = atoi(str);
109    str = elm_layout_data_get(obj, "vertical_pad");
110    if (str) vpad = atoi(str);
111    pad_scale = efl_gfx_entity_scale_get(obj) * elm_config_scale_get()
112       / edje_object_base_scale_get(elm_layout_edje_get(obj));
113    elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale));
114 
115    EINA_LIST_FOREACH(sd->items, l, eo_item)
116      {
117         ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
118         if (VIEW(item))
119           if (!elm_layout_theme_set(VIEW(item), "multibuttonentry",
120                                     PART_NAME_BUTTON, elm_widget_style_get(obj)))
121             CRI("Failed to set layout!");
122      }
123 
124    elm_widget_theme_object_set
125       (obj, sd->label, "multibuttonentry", PART_NAME_LABEL,
126        elm_widget_style_get(obj));
127    elm_widget_theme_object_set
128       (obj, sd->end, "multibuttonentry", PART_NAME_CLOSED_BUTTON,
129        elm_widget_style_get(obj));
130    elm_widget_theme_object_set
131       (obj,sd->guide_text, "multibuttonentry", PART_NAME_GUIDE_TEXT,
132        elm_widget_style_get(obj));
133 
134    elm_layout_sizing_eval(obj);
135 
136    return int_ret;
137 }
138 
139 static void
_visual_guide_text_set(Evas_Object * obj)140 _visual_guide_text_set(Evas_Object *obj)
141 {
142    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
143 
144    elm_box_unpack(sd->box, sd->guide_text);
145    elm_box_unpack(sd->box, sd->entry);
146    if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) return;
147 
148    if (!elm_object_focus_get(obj))
149      elm_object_focus_set(sd->entry, EINA_FALSE);
150 
151    if ((!eina_list_count(sd->items)) && sd->guide_text
152        && (!elm_object_focus_get(obj)) && (!sd->n_str))
153      {
154         evas_object_hide(sd->entry);
155         elm_box_pack_end(sd->box, sd->guide_text);
156         evas_object_show(sd->guide_text);
157         sd->view_state = MULTIBUTTONENTRY_VIEW_GUIDETEXT;
158      }
159    else
160      {
161         evas_object_hide(sd->guide_text);
162 
163         if (sd->editable)
164           {
165              elm_box_pack_end(sd->box, sd->entry);
166              evas_object_show(sd->entry);
167              if (elm_object_focus_get(obj))
168                {
169                   if (!sd->selected_it)
170                     elm_object_focus_set(sd->entry, EINA_TRUE);
171                }
172           }
173         sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
174      }
175 }
176 
177 static void
_shrink_mode_set(Evas_Object * obj,Eina_Bool shrink)178 _shrink_mode_set(Evas_Object *obj,
179                  Eina_Bool shrink)
180 {
181    int count;
182    Eina_List *l;
183    Elm_Object_Item *eo_item;
184 
185    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
186 
187    if (!sd->items) return;
188    if (sd->view_state == MULTIBUTTONENTRY_VIEW_ENTRY)
189      evas_object_hide(sd->entry);
190    else if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
191      evas_object_hide(sd->guide_text);
192    else if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
193      evas_object_hide(sd->end);
194 
195    if (shrink == EINA_TRUE)
196      {
197         Evas_Coord w = 0;
198         Evas_Coord box_inner_item_width_padding = 0;
199 
200         elm_box_padding_get(sd->box, &box_inner_item_width_padding, NULL);
201         // unpack all items and entry
202         elm_box_unpack_all(sd->box);
203         EINA_LIST_FOREACH(sd->items, l, eo_item)
204           {
205              ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
206              evas_object_hide(VIEW(item));
207              item->visible = EINA_FALSE;
208           }
209         // pack buttons only 1line
210         w = sd->w_box;
211 
212         if (sd->label && sd->label_packed)
213           {
214              elm_box_pack_end(sd->box, sd->label);
215              w -= efl_gfx_hint_size_combined_min_get(sd->label).w;
216              w -= box_inner_item_width_padding;
217           }
218 
219         eo_item = NULL;
220         count = eina_list_count(sd->items);
221 
222         EINA_LIST_FOREACH(sd->items, l, eo_item)
223           {
224              Evas_Coord w_label_count = 0, h = 0;
225              char *buf;
226 
227              ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
228              elm_box_pack_end(sd->box, VIEW(item));
229              evas_object_show(VIEW(item));
230              item->visible = EINA_TRUE;
231 
232              w -= efl_gfx_hint_size_combined_min_get(VIEW(item)).w;
233              w -= box_inner_item_width_padding;
234              count--;
235 
236              if (count > 0)
237                {
238                   buf = sd->format_func(count, (void *)sd->format_func_data);
239                   if (buf)
240                     {
241                        edje_object_part_text_escaped_set
242                            (sd->end, "elm.text", buf);
243                        free(buf);
244                     }
245 
246                   edje_object_size_min_calc(sd->end, &w_label_count, NULL);
247                   elm_coords_finger_size_adjust(1, &w_label_count, 1, NULL);
248                }
249 
250              if ((w < 0) || (w < w_label_count))
251                {
252                   elm_box_unpack(sd->box, VIEW(item));
253                   evas_object_hide(VIEW(item));
254                   item->visible = EINA_FALSE;
255                   count++;
256 
257                   buf = sd->format_func(count, (void *)sd->format_func_data);
258                   if (buf)
259                     {
260                        edje_object_part_text_escaped_set
261                            (sd->end, "elm.text", buf);
262                        free(buf);
263                     }
264 
265                   edje_object_size_min_calc(sd->end, &w_label_count, &h);
266                   elm_coords_finger_size_adjust(1, &w_label_count, 1, &h);
267                   evas_object_size_hint_min_set
268                     (sd->end, w_label_count, h);
269                   elm_box_pack_end(sd->box, sd->end);
270                   evas_object_show(sd->end);
271 
272                   break;
273                }
274           }
275 
276         if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK)
277           {
278              sd->view_state = MULTIBUTTONENTRY_VIEW_SHRINK;
279              efl_event_callback_legacy_call
280                (obj, ELM_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)1);
281           }
282      }
283    else
284      {
285         // unpack all items and entry
286         elm_box_unpack_all(sd->box);
287         EINA_LIST_FOREACH(sd->items, l, eo_item)
288           {
289              ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
290              evas_object_hide(VIEW(item));
291              item->visible = EINA_FALSE;
292           }
293         evas_object_hide(sd->end);
294 
295         // pack buttons only 1line
296 
297         if (sd->label && sd->label_packed) elm_box_pack_end(sd->box, sd->label);
298 
299         // pack remain btns
300         eo_item = NULL;
301         EINA_LIST_FOREACH(sd->items, l, eo_item)
302           {
303              ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
304              elm_box_pack_end(sd->box, VIEW(item));
305              evas_object_show(VIEW(item));
306              item->visible = EINA_TRUE;
307           }
308 
309         if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
310           {
311              sd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
312              efl_event_callback_legacy_call
313                (obj, ELM_MULTIBUTTONENTRY_EVENT_EXPAND_STATE_CHANGED, (void *)(uintptr_t)sd->shrink);
314           }
315      }
316 
317    if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
318      _elm_multibuttonentry_smart_focus_direction_enable = EINA_FALSE;
319    else
320      _elm_multibuttonentry_smart_focus_direction_enable = EINA_TRUE;
321 
322    if (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK)
323      _visual_guide_text_set(obj);
324 }
325 
326 static void
_view_update(Elm_Multibuttonentry_Data * sd)327 _view_update(Elm_Multibuttonentry_Data *sd)
328 {
329    Evas_Coord width = 1, height = 1;
330    Evas_Object *obj = sd->parent;
331 
332    if (sd->w_box <= 0) return;
333 
334    // update label
335    if (sd->label)
336      evas_object_size_hint_combined_min_get(sd->label, &width, &height);
337 
338    if (sd->guide_text)
339      {
340         Evas_Coord guide_text_width = sd->w_box - width;
341 
342         evas_object_size_hint_min_set(sd->guide_text, guide_text_width, height);
343      }
344 
345    // update buttons in shrink mode
346    if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
347      _shrink_mode_set(obj, EINA_TRUE);
348 
349    // update guidetext
350    _visual_guide_text_set(obj);
351 }
352 
353 static void
_item_del(Elm_Multibuttonentry_Item_Data * item)354 _item_del(Elm_Multibuttonentry_Item_Data *item)
355 {
356    Evas_Object *obj = WIDGET(item);
357 
358    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
359 
360    sd->items = eina_list_remove(sd->items, EO_OBJ(item));
361    elm_box_unpack(sd->box, VIEW(item));
362 
363    efl_event_callback_legacy_call
364      (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_DELETED, EO_OBJ(item));
365 
366    if (sd->selected_it == item)
367      sd->selected_it = NULL;
368 
369    if (sd->focused_it == item)
370      sd->focused_it = NULL;
371 
372    if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
373      _shrink_mode_set(obj, EINA_TRUE);
374 
375    if (!eina_list_count(sd->items))
376      _visual_guide_text_set(obj);
377 }
378 
379 static void
_current_item_state_change(Evas_Object * obj,Multibuttonentry_Button_State state)380 _current_item_state_change(Evas_Object *obj,
381                              Multibuttonentry_Button_State state)
382 {
383    Elm_Multibuttonentry_Item_Data *item;
384 
385    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
386 
387    item = sd->selected_it;
388 
389    if (!item) return;
390 
391    switch (state)
392      {
393       case MULTIBUTTONENTRY_BUTTON_STATE_SELECTED:
394         elm_layout_signal_emit(VIEW(item), "elm,state,focused", "elm");
395         efl_event_callback_legacy_call
396           (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_SELECTED, EO_OBJ(item));
397         break;
398       case MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT:
399       default:
400         elm_layout_signal_emit(VIEW(item), "elm,state,default", "elm");
401         sd->selected_it = NULL;
402         break;
403      }
404 }
405 
406 static void
_current_item_change(Evas_Object * obj,Elm_Object_Item * eo_it)407 _current_item_change(Evas_Object *obj,
408                        Elm_Object_Item *eo_it)
409 {
410    Eina_List *l;
411    Elm_Object_Item *eo_temp_it;
412 
413    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
414    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it);
415 
416    // change the state of previous item to "default"
417    _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
418 
419    // change the current
420    EINA_LIST_FOREACH(sd->items, l, eo_temp_it)
421      {
422         if (eo_temp_it == eo_it)
423           {
424              sd->selected_it = it;
425              break;
426           }
427      }
428    // change the state of current item to "focused"
429    _current_item_state_change(obj, MULTIBUTTONENTRY_BUTTON_STATE_SELECTED);
430 }
431 
432 static void
_item_select(Evas_Object * obj,Elm_Multibuttonentry_Item_Data * it)433 _item_select(Evas_Object *obj,
434                Elm_Multibuttonentry_Item_Data *it)
435 {
436    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
437 
438    if (it)
439      {
440         _current_item_change(obj, EO_OBJ(it));
441 
442         if (it->func) it->func((void *)(WIDGET_ITEM_DATA_GET(EO_OBJ(it))), WIDGET(it), EO_OBJ(it));
443 
444         if (elm_object_focus_get(obj))
445           {
446              elm_object_focus_set(sd->entry, EINA_FALSE);
447              elm_object_focus_set(VIEW(it), EINA_TRUE);
448 
449              // ACCESS
450              if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
451                {
452                   Evas_Object *ao, *po, *o;
453                   Eina_Strbuf *buf;
454                   const char *part;
455 
456                   part = "elm.btn.text";
457                   o = elm_layout_edje_get(VIEW(it));
458                   edje_object_freeze(o);
459                   po = (Evas_Object *)edje_object_part_object_get(o, part);
460                   edje_object_thaw(o);
461                   ao = evas_object_data_get(po, "_part_access_obj");
462                   _elm_access_highlight_set(ao);
463 
464                   buf = eina_strbuf_new();
465                   eina_strbuf_append_printf(buf,
466                     "multi button entry item %s is selected",
467                     edje_object_part_text_get(o, part));
468 
469                   _elm_access_say(eina_strbuf_string_get(buf));
470                   eina_strbuf_free(buf);
471                }
472           }
473      }
474    else
475      {
476         _current_item_state_change
477           (obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
478         if (elm_object_focus_get(obj) && sd->editable)
479           elm_object_focus_set(sd->entry, EINA_TRUE);
480      }
481 }
482 
483 static void
_on_item_clicked(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)484 _on_item_clicked(void *data,
485                    Evas_Object *obj EINA_UNUSED,
486                    const char *emission EINA_UNUSED,
487                    const char *source EINA_UNUSED)
488 {
489    Elm_Object_Item *eo_it = data;
490 
491    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it);
492    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
493 
494    _item_select(WIDGET(it), it);
495 
496    if (_elm_config->atspi_mode)
497      efl_access_state_changed_signal_emit(eo_it,
498                                           EFL_ACCESS_STATE_TYPE_CHECKED,
499                                           EINA_TRUE);
500 
501    if (sd->selected_it)
502      efl_event_callback_legacy_call
503        (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_CLICKED, eo_it);
504 }
505 
506 static void
_on_item_deleted(void * data,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)507 _on_item_deleted(void *data,
508                    Evas_Object *obj,
509                    const char *emission EINA_UNUSED,
510                    const char *source EINA_UNUSED)
511 {
512    Eina_List *l;
513    Elm_Object_Item *eo_it = data;
514    Elm_Object_Item *eo_temp_it;
515 
516    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it);
517    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
518    // change the current
519    EINA_LIST_FOREACH(sd->items, l, eo_temp_it)
520      {
521         ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_temp_it, temp_it);
522         if (VIEW(temp_it) == obj)
523           {
524              elm_object_item_del(eo_temp_it);
525              break;
526           }
527      }
528 }
529 
530 static void
_on_item_focused(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)531 _on_item_focused(void *data,
532                  Evas_Object *obj EINA_UNUSED,
533                  void *event_info EINA_UNUSED)
534 {
535    Elm_Multibuttonentry_Item_Data *it = data;
536    if (!it) return;
537 
538    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
539 
540    sd->focused_it = it;
541 }
542 
543 static void
_on_item_unfocused(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)544 _on_item_unfocused(void *data,
545                    Evas_Object *obj EINA_UNUSED,
546                    void *event_info EINA_UNUSED)
547 {
548    Elm_Multibuttonentry_Item_Data *it = data;
549    if (!it) return;
550 
551    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
552 
553    sd->focused_it = NULL;
554 }
555 
556 static Eina_Bool
_long_press_cb(void * data)557 _long_press_cb(void *data)
558 {
559    Elm_Multibuttonentry_Item_Data *it = data;
560 
561    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
562 
563    sd->longpress_timer = NULL;
564 
565    efl_event_callback_legacy_call
566      (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, EO_OBJ(it));
567 
568    return ECORE_CALLBACK_CANCEL;
569 }
570 
571 static void
_mouse_down_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)572 _mouse_down_cb(void  *data,
573                Evas *evas EINA_UNUSED,
574                Evas_Object *obj EINA_UNUSED,
575                void *event_info)
576 {
577    Elm_Multibuttonentry_Item_Data *it = data;
578    Evas_Event_Mouse_Down *ev = event_info;
579 
580    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
581 
582    if (ev->button != 1) return;
583 
584    ecore_timer_del(sd->longpress_timer);
585    sd->longpress_timer = ecore_timer_add
586       (_elm_config->longpress_timeout, _long_press_cb, it);
587 }
588 
589 static void
_mouse_up_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)590 _mouse_up_cb(void *data,
591              Evas *evas EINA_UNUSED,
592              Evas_Object *obj EINA_UNUSED,
593              void *event_info EINA_UNUSED)
594 {
595    Elm_Multibuttonentry_Item_Data *it = data;
596 
597    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(it), sd);
598 
599    ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
600 }
601 
602 EOLIAN static void
_elm_multibuttonentry_item_elm_widget_item_signal_emit(Eo * eo_item EINA_UNUSED,Elm_Multibuttonentry_Item_Data * item,const char * emission,const char * source)603 _elm_multibuttonentry_item_elm_widget_item_signal_emit(Eo *eo_item EINA_UNUSED,
604                                                        Elm_Multibuttonentry_Item_Data *item,
605                                                        const char *emission,
606                                                        const char *source)
607 {
608    elm_layout_signal_emit(VIEW(item), emission, source);
609 }
610 
611 EOLIAN static void
_elm_multibuttonentry_item_elm_widget_item_part_text_set(Eo * eo_item EINA_UNUSED,Elm_Multibuttonentry_Item_Data * item,const char * part,const char * label)612 _elm_multibuttonentry_item_elm_widget_item_part_text_set(Eo *eo_item EINA_UNUSED,
613                                                     Elm_Multibuttonentry_Item_Data *item,
614                                                     const char *part,
615                                                     const char *label)
616 {
617    const char *dest_part = NULL;
618    Evas_Coord minw = -1, minh = -1, boxw;
619    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(WIDGET(item), sd);
620 
621    if (!part || !strcmp(part, "elm.text"))
622      dest_part = "elm.btn.text";
623    else
624      dest_part = part;
625 
626    edje_object_part_text_escaped_set(elm_layout_edje_get(VIEW(item)), dest_part, label);
627 
628    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
629    edje_object_size_min_restricted_calc
630      (elm_layout_edje_get(VIEW(item)), &minw, &minh, minw, minh);
631    evas_object_size_hint_min_set(VIEW(item), minw, minh);
632    evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL);
633 
634    if (minw > boxw)
635      {
636          evas_object_size_hint_min_set(VIEW(item), boxw, minh);
637          evas_object_resize(VIEW(item), boxw, minh);
638      }
639 }
640 
641 EOLIAN static const char *
_elm_multibuttonentry_item_elm_widget_item_part_text_get(const Eo * eo_item EINA_UNUSED,Elm_Multibuttonentry_Item_Data * item,const char * part)642 _elm_multibuttonentry_item_elm_widget_item_part_text_get(const Eo *eo_item EINA_UNUSED,
643                                                     Elm_Multibuttonentry_Item_Data *item,
644                                                     const char *part)
645 {
646    const char *src_part = NULL;
647 
648    if (!part || !strcmp(part, "elm.text"))
649      src_part = "elm.btn.text";
650    else
651      src_part = part;
652 
653    return edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), src_part);
654 }
655 
656 EOLIAN static void
_elm_multibuttonentry_item_efl_object_destructor(Eo * eo_it,Elm_Multibuttonentry_Item_Data * it)657 _elm_multibuttonentry_item_efl_object_destructor(Eo *eo_it,
658                                               Elm_Multibuttonentry_Item_Data *it)
659 {
660    if (_elm_config->atspi_mode)
661      efl_access_children_changed_del_signal_emit(WIDGET(it), eo_it);
662    _item_del(it);
663 
664    efl_destructor(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS));
665 }
666 
667 static void
_access_multibuttonentry_label_register(Evas_Object * obj,Eina_Bool is_access)668 _access_multibuttonentry_label_register(Evas_Object *obj, Eina_Bool is_access)
669 {
670    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
671    Evas_Object *po;
672 
673    edje_object_freeze(sd->label);
674    po = (Evas_Object *)edje_object_part_object_get(sd->label, "elm.text");
675    edje_object_thaw(sd->label);
676    if (is_access)
677      {
678         Evas_Object *ao;
679         ao = _elm_access_edje_object_part_object_register
680                             (obj, sd->label, "elm.text");
681         _elm_access_text_set(_elm_access_info_get(ao),
682                              ELM_ACCESS_TYPE, E_("multi button entry label"));
683      }
684    else
685      _elm_access_edje_object_part_object_unregister
686                       (obj, sd->label, "elm.text");
687 
688    evas_object_pass_events_set(po, !is_access);
689    evas_object_propagate_events_set(sd->label, !is_access);
690 }
691 
692 static void
_access_multibuttonentry_item_register(Evas_Object * obj,Elm_Object_Item * eo_item,Eina_Bool is_access)693 _access_multibuttonentry_item_register(Evas_Object *obj,
694                                        Elm_Object_Item *eo_item,
695                                        Eina_Bool is_access)
696 {
697    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
698    if (is_access)
699      {
700         Evas_Object *ao;
701         ao = _elm_access_edje_object_part_object_register
702                       (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text");
703         _elm_access_text_set(_elm_access_info_get(ao),
704                              ELM_ACCESS_TYPE, E_("multi button entry item"));
705      }
706    else
707      _elm_access_edje_object_part_object_unregister
708                 (obj, elm_layout_edje_get(VIEW(item)), "elm.btn.text");
709 
710    /* cannot read item because mouse-in event is delivered to
711       the multibuttonentry resize_obj which is registered as an access
712       object, so the mouse-in event should be blocked here */
713    evas_object_propagate_events_set(VIEW(item), !is_access);
714 }
715 
716 EOLIAN static Eo *
_elm_multibuttonentry_item_efl_object_constructor(Eo * eo_item,Elm_Multibuttonentry_Item_Data * item)717 _elm_multibuttonentry_item_efl_object_constructor(Eo *eo_item, Elm_Multibuttonentry_Item_Data *item)
718 {
719    eo_item = efl_constructor(efl_super(eo_item, ELM_MULTIBUTTONENTRY_ITEM_CLASS));
720    item->base = efl_data_scope_get(eo_item, ELM_WIDGET_ITEM_CLASS);
721 
722    return eo_item;
723 }
724 
725 static Elm_Object_Item *
_item_new(Elm_Multibuttonentry_Data * sd,const char * str,Multibuttonentry_Pos pos,Elm_Object_Item * efl_reference,Evas_Smart_Cb func,void * data)726 _item_new(Elm_Multibuttonentry_Data *sd,
727                  const char *str,
728                  Multibuttonentry_Pos pos,
729                  Elm_Object_Item *efl_reference,
730                  Evas_Smart_Cb func,
731                  void *data)
732 {
733    Eina_List *l;
734    Eo *eo_item;
735    Elm_Multibuttonentry_Item_Filter *item_filter;
736    Elm_Multibuttonentry_Item_Data *reference = efl_reference?
737       efl_data_scope_get(efl_reference, ELM_MULTIBUTTONENTRY_ITEM_CLASS):
738       NULL;
739    Evas_Object *obj;
740    int minw, minh, boxw;
741 
742    obj = sd->parent;
743 
744    if (!str) return NULL;
745 
746    EINA_LIST_FOREACH(sd->filter_list, l, item_filter)
747      {
748         if (!(item_filter->callback_func(obj, str, data, item_filter->data)))
749           return NULL;
750      }
751 
752    eo_item = efl_add(ELM_MULTIBUTTONENTRY_ITEM_CLASS, obj);
753    if (!eo_item)
754      return NULL;
755    WIDGET_ITEM_DATA_SET(eo_item, data);
756 
757    efl_access_object_role_set(eo_item, EFL_ACCESS_ROLE_RADIO_BUTTON);
758 
759    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
760    VIEW_SET(item, elm_layout_add(obj));
761 
762    efl_access_object_access_type_set(VIEW(item), EFL_ACCESS_TYPE_DISABLED);
763 
764    if (!elm_layout_theme_set(VIEW(item), "multibuttonentry", PART_NAME_BUTTON,
765                              elm_widget_style_get(obj)))
766      CRI("Failed to set layout!");
767 
768    elm_object_part_text_set(VIEW(item), "elm.btn.text", str);
769 
770    //entry is cleared when text is made to button
771    elm_object_text_set(sd->entry, "");
772 
773    elm_layout_signal_callback_add
774      (VIEW(item), "mouse,clicked,1", "*", _on_item_clicked, EO_OBJ(item));
775    elm_layout_signal_callback_add
776      (VIEW(item), "elm,deleted", "elm", _on_item_deleted, EO_OBJ(item));
777    evas_object_smart_callback_add
778      (VIEW(item), "focused", _on_item_focused, item);
779    evas_object_smart_callback_add
780      (VIEW(item), "unfocused", _on_item_unfocused, item);
781    evas_object_event_callback_add
782       (VIEW(item),
783        EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, item);
784    evas_object_event_callback_add
785       (VIEW(item),
786        EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, item);
787 
788    evas_object_show(VIEW(item));
789 
790    evas_object_smart_calculate(VIEW(item));
791    evas_object_size_hint_combined_min_get(VIEW(item), &minw, &minh);
792    evas_object_geometry_get(sd->box, NULL, NULL, &boxw, NULL);
793 
794    if (sd->w_box && minw > boxw)
795      {
796         elm_coords_finger_size_adjust(1, &boxw, 1, &minh);
797         evas_object_size_hint_min_set(VIEW(item), boxw, minh);
798         evas_object_resize(VIEW(item), boxw, minh);
799      }
800 
801    elm_object_focus_allow_set(VIEW(item), EINA_TRUE);
802 
803    item->visible = EINA_TRUE;
804 
805    // ACCESS
806    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
807      {
808         Eina_Strbuf *buf;
809         buf = eina_strbuf_new();
810 
811         eina_strbuf_append_printf(buf,
812           "multi button entry item %s is added",
813           edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text"));
814 
815         _elm_access_say(eina_strbuf_string_get(buf));
816         eina_strbuf_free(buf);
817 
818         _access_multibuttonentry_item_register(obj, eo_item, EINA_TRUE);
819      }
820 
821    if (func)
822      {
823         item->func = func;
824      }
825 
826    switch (pos)
827      {
828       case MULTIBUTTONENTRY_POS_START:
829         sd->items = eina_list_prepend(sd->items, eo_item);
830         if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
831           {
832              elm_widget_sub_object_add(obj, VIEW(item));
833              _shrink_mode_set(obj, EINA_TRUE);
834           }
835         else
836           {
837              if (sd->label && sd->label_packed)
838                elm_box_pack_after(sd->box, VIEW(item), sd->label);
839              else
840                elm_box_pack_start(sd->box, VIEW(item));
841              if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
842                _visual_guide_text_set(obj);
843           }
844         break;
845 
846       case MULTIBUTTONENTRY_POS_END:
847         sd->items = eina_list_append(sd->items, eo_item);
848         if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
849           {
850              elm_widget_sub_object_add(obj, VIEW(item));
851              evas_object_hide(VIEW(item));
852           }
853         else
854           {
855              if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
856                _visual_guide_text_set(obj);
857 
858              if (sd->editable)
859                elm_box_pack_before(sd->box, VIEW(item), sd->entry);
860              else
861                elm_box_pack_end(sd->box, VIEW(item));
862           }
863         break;
864 
865       case MULTIBUTTONENTRY_POS_BEFORE:
866         if (efl_reference)
867           sd->items = eina_list_prepend_relative(sd->items, eo_item, efl_reference);
868         else
869           sd->items = eina_list_append(sd->items, eo_item);
870         if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
871           {
872              elm_widget_sub_object_add(obj, VIEW(item));
873              evas_object_hide(VIEW(item));
874              _shrink_mode_set(obj, EINA_TRUE);
875           }
876         else
877           {
878              if (efl_reference)
879                elm_box_pack_before(sd->box, VIEW(item), VIEW(reference));
880              else
881                {
882                   if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
883                     _visual_guide_text_set(obj);
884                   if (sd->editable)
885                     elm_box_pack_before(sd->box, VIEW(item), sd->entry);
886                   else
887                     elm_box_pack_end(sd->box, VIEW(item));
888                }
889           }
890         break;
891 
892       case MULTIBUTTONENTRY_POS_AFTER:
893         if (efl_reference)
894           sd->items = eina_list_append_relative(sd->items, eo_item, efl_reference);
895         else
896           sd->items = eina_list_append(sd->items, eo_item);
897         if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
898           {
899              elm_widget_sub_object_add(obj, VIEW(item));
900              _shrink_mode_set(obj, EINA_TRUE);
901           }
902         else
903           {
904              if (efl_reference)
905                elm_box_pack_after(sd->box, VIEW(item), VIEW(reference));
906              else
907                {
908                   if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
909                     _visual_guide_text_set(obj);
910                   if (sd->editable)
911                     elm_box_pack_before(sd->box, VIEW(item), sd->entry);
912                   else
913                     elm_box_pack_end(sd->box, VIEW(item));
914                }
915           }
916         break;
917 
918       default:
919         break;
920      }
921 
922    if (!elm_object_focus_get(obj) && sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK && sd->w_box)
923      _shrink_mode_set(obj, EINA_TRUE);
924 
925 
926    efl_event_callback_legacy_call
927      (obj, ELM_MULTIBUTTONENTRY_EVENT_ITEM_ADDED, eo_item);
928 
929    if (_elm_config->atspi_mode)
930      {
931         efl_access_children_changed_added_signal_emit(obj, eo_item);
932         efl_access_added(eo_item);
933      }
934 
935    return eo_item;
936 }
937 
938 //FIXME: having an empty event handling function and reacting on Evas
939 //events on specific objects is crazy, someone should fix that.
940 EOLIAN static Eina_Bool
_elm_multibuttonentry_efl_ui_widget_widget_input_event_handler(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd EINA_UNUSED,const Efl_Event * eo_event EINA_UNUSED,Evas_Object * src EINA_UNUSED)941 _elm_multibuttonentry_efl_ui_widget_widget_input_event_handler(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *src EINA_UNUSED)
942 {
943    // ACCESS
944    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON) return EINA_FALSE;
945 
946    //lets stop eating all events
947    return EINA_FALSE;
948 }
949 
950 static void
_mouse_clicked_signal_cb(void * data EINA_UNUSED,Evas_Object * obj,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)951 _mouse_clicked_signal_cb(void *data EINA_UNUSED,
952                          Evas_Object *obj,
953                          const char *emission EINA_UNUSED,
954                          const char *source EINA_UNUSED)
955 {
956    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
957 
958    if (sd->editable) elm_entry_input_panel_show(sd->entry);
959 
960    evas_object_smart_callback_call(obj, "clicked", NULL);
961 }
962 
963 static void
_box_resize_cb(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event EINA_UNUSED)964 _box_resize_cb(void *data,
965                Evas *evas EINA_UNUSED,
966                Evas_Object *obj EINA_UNUSED,
967                void *event EINA_UNUSED)
968 {
969    Evas_Coord w, h, mnw, mnh;
970    Eina_List *l;
971    Elm_Object_Item *eo_it;
972    int hpad;
973 
974    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
975 
976    evas_object_geometry_get(sd->box, NULL, NULL, &w, &h);
977    if ((w <= elm_config_finger_size_get()) || (h <= elm_config_finger_size_get())) return;
978 
979    elm_box_padding_get(obj, &hpad, NULL);
980 
981    if (sd->h_box < h)
982      efl_event_callback_legacy_call
983        (sd->parent, ELM_MULTIBUTTONENTRY_EVENT_EXPANDED, NULL);
984    else if (sd->h_box > h)
985      efl_event_callback_legacy_call
986        (sd->parent, ELM_MULTIBUTTONENTRY_EVENT_CONTRACTED, NULL);
987 
988    if (sd->items && sd->w_box != w)
989      {
990         EINA_LIST_FOREACH (sd->items, l, eo_it)
991           {
992              ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_it, it);
993 
994              elm_layout_sizing_eval(VIEW(it));
995              evas_object_smart_calculate(VIEW(it));
996 
997              evas_object_size_hint_combined_min_get(VIEW(it), &mnw, &mnh);
998 
999              if (mnw > w - hpad)
1000                {
1001                   mnw = w - hpad;
1002                   evas_object_size_hint_min_set(VIEW(it), mnw, mnh);
1003                   evas_object_resize(VIEW(it), mnw, mnh);
1004                }
1005           }
1006      }
1007 
1008    sd->w_box = w;
1009    sd->h_box = h;
1010 
1011    if (sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
1012      _shrink_mode_set(data, EINA_TRUE);
1013 }
1014 
1015 static void
_entry_resize_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1016 _entry_resize_cb(void *data,
1017                  Evas *e EINA_UNUSED,
1018                  Evas_Object *obj EINA_UNUSED,
1019                  void *event_info EINA_UNUSED)
1020 {
1021    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1022 
1023    if (elm_object_focus_get(sd->parent))
1024      elm_widget_show_region_set(sd->entry, efl_gfx_entity_geometry_get(sd->entry), EINA_TRUE);
1025 }
1026 
1027 static void
_entry_changed_cb(void * data,const Efl_Event * event EINA_UNUSED)1028 _entry_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
1029 {
1030    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1031    const char *str;
1032 
1033    str = elm_object_text_get(sd->entry);
1034    sd->n_str = str ? strlen(str) : 0;
1035 }
1036 
1037 static void
_entry_focus_changed_cb(void * data,const Efl_Event * event)1038 _entry_focus_changed_cb(void *data, const Efl_Event *event)
1039 {
1040    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1041 
1042    if (elm_object_focus_get(event->object))
1043      {
1044         Elm_Multibuttonentry_Item_Data *item = NULL;
1045 
1046         if (sd->selected_it)
1047           {
1048              item = sd->selected_it;
1049              elm_object_focus_set(sd->entry, EINA_FALSE);
1050              elm_object_focus_set(VIEW(item), EINA_TRUE);
1051           }
1052      }
1053    else
1054      {
1055         const char *str;
1056 
1057         str = elm_object_text_get(sd->entry);
1058         if (str && str[0])
1059           _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL);
1060      }
1061 }
1062 
1063 static void
_entry_clicked_cb(void * data,const Efl_Event * event EINA_UNUSED)1064 _entry_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
1065 {
1066    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1067 
1068    _current_item_state_change(sd->parent, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
1069    elm_object_focus_set(sd->entry, EINA_TRUE);
1070 }
1071 
1072 static void
_layout_key_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1073 _layout_key_down_cb(void *data,
1074                   Evas *e EINA_UNUSED,
1075                   Evas_Object *obj EINA_UNUSED,
1076                   void *event_info)
1077 {
1078    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1079    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
1080 
1081    if (!sd->box) return;
1082 
1083    if (sd->last_it_select)
1084      {
1085         if (sd->selected_it &&
1086             ((!strcmp(ev->key, "BackSpace")) ||
1087              (!strcmp(ev->key, "Delete"))))
1088           {
1089              Elm_Multibuttonentry_Item_Data *item = sd->selected_it;
1090              if (item && sd->editable)
1091                {
1092                   elm_object_item_del(EO_OBJ(item));
1093                   elm_object_focus_set(sd->entry, EINA_TRUE);
1094                }
1095           }
1096         else if (sd->focused_it &&
1097             ((!strcmp(ev->key, "KP_Enter")) ||
1098              (!strcmp(ev->key, "Return"))))
1099           {
1100              Elm_Multibuttonentry_Item_Data *item = sd->focused_it;
1101              if (item)
1102                _on_item_clicked(EO_OBJ(item), NULL, NULL, NULL);
1103           }
1104         else if (((!sd->selected_it && (sd->n_str == 0) &&
1105                    (!strcmp(ev->key, "BackSpace"))) ||
1106                   (!strcmp(ev->key, "Delete"))))
1107           {
1108              Elm_Object_Item *eo_item = eina_list_data_get(eina_list_last(sd->items));
1109              if (eo_item)
1110                {
1111                   ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
1112                   _item_select(sd->parent, item);
1113                }
1114           }
1115      }
1116    else
1117      sd->last_it_select = EINA_TRUE;
1118 }
1119 
1120 static void
_entry_key_down_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1121 _entry_key_down_cb(void *data,
1122                    Evas *e EINA_UNUSED,
1123                    Evas_Object *obj EINA_UNUSED,
1124                    void *event_info)
1125 {
1126    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1127    Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
1128 
1129    if (sd->n_str == 1 &&
1130        (!strcmp(ev->key, "BackSpace") || !strcmp(ev->key, "Delete")))
1131      sd->last_it_select = EINA_FALSE;
1132 }
1133 
1134 static void
_entry_key_up_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1135 _entry_key_up_cb(void *data,
1136                  Evas *e EINA_UNUSED,
1137                  Evas_Object *obj EINA_UNUSED,
1138                  void *event_info)
1139 {
1140    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(data, sd);
1141    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
1142    const char *str;
1143 
1144    if (!sd->box) return;
1145 
1146    str = elm_object_text_get(sd->entry);
1147    if (!str) return;
1148 
1149    if (strlen(str) &&
1150        (!strcmp(ev->key, "KP_Enter") || !strcmp(ev->key, "Return")))
1151      {
1152         _item_new(sd, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL);
1153         sd->n_str = 0;
1154      }
1155 }
1156 
1157 static void
_callbacks_register(Evas_Object * obj)1158 _callbacks_register(Evas_Object *obj)
1159 {
1160    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
1161    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1162 
1163    elm_layout_signal_callback_add
1164      (obj, "mouse,clicked,1", "*", _mouse_clicked_signal_cb, NULL);
1165 
1166    evas_object_event_callback_add
1167      (wd->resize_obj, EVAS_CALLBACK_KEY_DOWN,
1168      _layout_key_down_cb, obj);
1169 
1170    evas_object_event_callback_add
1171      (sd->box, EVAS_CALLBACK_RESIZE, _box_resize_cb, obj);
1172 
1173    evas_object_event_callback_add
1174      (sd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
1175    evas_object_event_callback_add
1176      (sd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj);
1177    evas_object_event_callback_add
1178      (sd->entry, EVAS_CALLBACK_RESIZE, _entry_resize_cb, obj);
1179    efl_event_callback_array_add(sd->entry, _multi_buttonentry_cb(), obj);
1180 }
1181 
1182 static void
_label_set(Evas_Object * obj,const char * str)1183 _label_set(Evas_Object *obj,
1184            const char *str)
1185 {
1186    Evas_Coord width, height;
1187 
1188    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
1189 
1190    if (!str) return;
1191 
1192    eina_stringshare_replace(&sd->label_str, str);
1193 
1194    edje_object_part_text_escaped_set(sd->label, "elm.text", str);
1195 
1196    if (!strlen(str))
1197      {
1198         sd->label_packed = EINA_FALSE;
1199         elm_box_unpack(sd->box, sd->label);
1200         evas_object_hide(sd->label);
1201      }
1202    else
1203      {
1204         if (sd->label_packed)
1205           elm_box_unpack(sd->box, sd->label);
1206         sd->label_packed = EINA_TRUE;
1207         edje_object_size_min_calc(sd->label, &width, &height);
1208         evas_object_size_hint_min_set(sd->label, width, height);
1209         elm_box_pack_start(sd->box, sd->label);
1210         evas_object_show(sd->label);
1211      }
1212 
1213    _view_update(sd);
1214 }
1215 
1216 static void
_guide_text_set(Evas_Object * obj,const char * str)1217 _guide_text_set(Evas_Object *obj,
1218                 const char *str)
1219 {
1220    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
1221 
1222    if (!str) return;
1223 
1224    eina_stringshare_replace(&sd->guide_text_str, str);
1225    if (sd->guide_text == NULL)
1226      sd->guide_text = edje_object_add(evas_object_evas_get(obj));
1227 
1228    if (sd->guide_text)
1229      {
1230         elm_widget_theme_object_set(obj, sd->guide_text, "multibuttonentry",
1231                                     PART_NAME_GUIDE_TEXT,
1232                                     elm_widget_style_get(obj));
1233         evas_object_size_hint_weight_set
1234           (sd->guide_text, 0.0, EVAS_HINT_EXPAND);
1235         evas_object_size_hint_align_set
1236           (sd->guide_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
1237         edje_object_part_text_escaped_set(sd->guide_text, "elm.text", str);
1238         _view_update(sd);
1239      }
1240 }
1241 
1242 static Elm_Multibuttonentry_Item_Filter *
_filter_new(Elm_Multibuttonentry_Item_Filter_Cb func,void * data)1243 _filter_new(Elm_Multibuttonentry_Item_Filter_Cb func,
1244             void *data)
1245 {
1246    Elm_Multibuttonentry_Item_Filter *item_filter =
1247      ELM_NEW(Elm_Multibuttonentry_Item_Filter);
1248    if (!item_filter) return NULL;
1249 
1250    item_filter->callback_func = func;
1251    item_filter->data = data;
1252 
1253    return item_filter;
1254 }
1255 
1256 static void
_filter_free(Elm_Multibuttonentry_Item_Filter * item_filter)1257 _filter_free(Elm_Multibuttonentry_Item_Filter *item_filter)
1258 {
1259    free(item_filter);
1260 }
1261 
1262 static Eina_Bool
_box_min_size_calculate(Evas_Object * box,Evas_Object_Box_Data * priv,int * line_height,void * data EINA_UNUSED)1263 _box_min_size_calculate(Evas_Object *box,
1264                         Evas_Object_Box_Data *priv,
1265                         int *line_height,
1266                         void *data EINA_UNUSED)
1267 {
1268    Evas_Coord mnw, mnh, w, minw, minh = 0, linew = 0, lineh = 0;
1269    int line_num;
1270    Eina_List *l;
1271    Evas_Object_Box_Option *opt;
1272 
1273    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1274    evas_object_size_hint_combined_min_get(box, &minw, NULL);
1275 
1276    if (!w) return EINA_FALSE;
1277 
1278    line_num = 1;
1279    EINA_LIST_FOREACH(priv->children, l, opt)
1280      {
1281         evas_object_size_hint_combined_min_get(opt->obj, &mnw, &mnh);
1282 
1283         linew += mnw;
1284         if (lineh < mnh) lineh = mnh;
1285 
1286         if (linew > w)
1287           {
1288              linew = mnw;
1289              line_num++;
1290           }
1291 
1292         if ((linew != 0) && (l != eina_list_last(priv->children)))
1293           linew += priv->pad.h;
1294      }
1295    minh = lineh * line_num + (line_num - 1) * priv->pad.v;
1296 
1297    evas_object_size_hint_min_set(box, minw, minh);
1298    *line_height = lineh;
1299 
1300    return EINA_TRUE;
1301 }
1302 
1303 static void
_box_layout_cb(Evas_Object * o,Evas_Object_Box_Data * priv,void * data)1304 _box_layout_cb(Evas_Object *o,
1305                Evas_Object_Box_Data *priv,
1306                void *data)
1307 {
1308    Evas_Coord x, y, w, h, xx, yy;
1309    Evas_Coord minw, minh, linew = 0, lineh = 0;
1310    Evas_Object_Box_Option *opt;
1311    const Eina_List *l, *l_next;
1312    Evas_Object *obj;
1313    double ax, ay;
1314    Eina_Bool rtl;
1315 
1316    if (!_box_min_size_calculate(o, priv, &lineh, data)) return;
1317 
1318    evas_object_geometry_get(o, &x, &y, &w, &h);
1319 
1320    evas_object_size_hint_combined_min_get(o, &minw, &minh);
1321    evas_object_size_hint_align_get(o, &ax, &ay);
1322 
1323    rtl = efl_ui_mirrored_get(data);
1324    if (rtl) ax = 1.0 - ax;
1325 
1326    if (w < minw)
1327      {
1328         x = x + ((w - minw) * (1.0 - ax));
1329         w = minw;
1330      }
1331    if (h < minh)
1332      {
1333         y = y + ((h - minh) * (1.0 - ay));
1334         h = minh;
1335      }
1336 
1337    xx = x;
1338    yy = y;
1339 
1340    EINA_LIST_FOREACH_SAFE(priv->children, l, l_next, opt)
1341      {
1342         Evas_Coord mnw, mnh;
1343         Evas_Coord ww, hh, ow, oh;
1344         double wx, wy;
1345         int fw, fh;
1346 
1347         obj = opt->obj;
1348         evas_object_size_hint_align_get(obj, &ax, &ay);
1349         evas_object_size_hint_weight_get(obj, &wx, &wy);
1350         evas_object_size_hint_combined_min_get(obj, &mnw, &mnh);
1351 
1352         fw = fh = EINA_FALSE;
1353         if (EINA_DBL_EQ(ax, -1)) {fw = 1; ax = 0.5; }
1354         if (EINA_DBL_EQ(ay, -1)) {fh = 1; ay = 0.5; }
1355         if (rtl) ax = 1.0 - ax;
1356 
1357         ww = mnw;
1358         if (!EINA_DBL_EQ(wx, 0))
1359           {
1360              if (ww <= w - linew) ww = w - linew;
1361              else ww = w;
1362           }
1363         hh = lineh;
1364 
1365         ow = mnw;
1366         if (fw) ow = ww;
1367         oh = mnh;
1368         if (fh) oh = hh;
1369 
1370         linew += ww;
1371         if (linew > w && l != priv->children)
1372           {
1373              xx = x;
1374              yy += hh;
1375              yy += priv->pad.v;
1376              linew = ww;
1377           }
1378 
1379         evas_object_geometry_set(obj,
1380                                  ((!rtl) ? (xx) : (x + (w - (xx - x) - ww)))
1381                                  + (Evas_Coord)(((double)(ww - ow)) * ax),
1382                                  yy + (Evas_Coord)(((double)(hh - oh)) * ay),
1383                                  ow, oh);
1384 
1385         xx += ww;
1386         xx += priv->pad.h;
1387 
1388         if (linew > w)
1389           {
1390              opt = eina_list_data_get(l_next);
1391              if (opt && opt->obj && efl_isa(opt->obj, ELM_ENTRY_CLASS))
1392                {
1393                   xx = x;
1394                   yy += hh;
1395                   yy += priv->pad.v;
1396                   linew = 0;
1397                }
1398           }
1399         if ((linew != 0) && (l != eina_list_last(priv->children)))
1400           linew += priv->pad.h;
1401      }
1402 }
1403 
1404 static void
_view_init(Evas_Object * obj,Elm_Multibuttonentry_Data * sd)1405 _view_init(Evas_Object *obj, Elm_Multibuttonentry_Data *sd)
1406 {
1407    const char *str;
1408    double pad_scale;
1409    int hpad = 0, vpad = 0;
1410 
1411    sd->box = elm_box_add(obj);
1412 
1413    if (!sd->box) return;
1414 
1415    str = elm_layout_data_get(obj, "horizontal_pad");
1416    if (str) hpad = atoi(str);
1417    str = elm_layout_data_get(obj, "vertical_pad");
1418    if (str) vpad = atoi(str);
1419    pad_scale = efl_gfx_entity_scale_get(obj) * elm_config_scale_get()
1420       / edje_object_base_scale_get(elm_layout_edje_get(obj));
1421    elm_box_padding_set(sd->box, (hpad * pad_scale), (vpad * pad_scale));
1422 
1423    elm_box_layout_set(sd->box, _box_layout_cb, obj, NULL);
1424    elm_box_homogeneous_set(sd->box, EINA_FALSE);
1425    if (!elm_layout_content_set(obj, "elm.swallow.box", sd->box))
1426      elm_layout_content_set(obj, "box.swallow", sd->box);
1427 
1428    sd->label = edje_object_add(evas_object_evas_get(obj));
1429    if (!sd->label) return;
1430    elm_widget_theme_object_set
1431       (obj, sd->label, "multibuttonentry", PART_NAME_LABEL,
1432        elm_widget_style_get(obj));
1433 
1434    // ACCESS
1435    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1436      _access_multibuttonentry_label_register(obj, EINA_TRUE);
1437 
1438    sd->entry = elm_entry_add(obj);
1439    if (!sd->entry) return;
1440    elm_entry_single_line_set(sd->entry, EINA_TRUE);
1441    elm_entry_cnp_mode_set(sd->entry, ELM_CNP_MODE_PLAINTEXT);
1442    elm_object_text_set(sd->entry, "");
1443    elm_entry_input_panel_enabled_set(sd->entry, EINA_FALSE);
1444    evas_object_size_hint_min_set(sd->entry, MIN_W_ENTRY, 0);
1445    evas_object_size_hint_weight_set
1446      (sd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1447    evas_object_size_hint_align_set(sd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1448    elm_box_pack_end(sd->box, sd->entry);
1449    evas_object_show(sd->entry);
1450 
1451    sd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
1452 
1453      {
1454         Evas_Coord button_min_width = 0, button_min_height = 0;
1455 
1456         sd->end = edje_object_add(evas_object_evas_get(obj));
1457         if (!sd->end) return;
1458         elm_widget_theme_object_set
1459            (obj, sd->end, "multibuttonentry", PART_NAME_CLOSED_BUTTON,
1460             elm_widget_style_get(obj));
1461 
1462         edje_object_size_min_calc(sd->end, &button_min_width, &button_min_height);
1463         elm_coords_finger_size_adjust(1, &button_min_width, 1, &button_min_height);
1464         evas_object_size_hint_min_set(sd->end, button_min_width, button_min_height);
1465         elm_widget_sub_object_add(obj, sd->end);
1466      }
1467 }
1468 
1469 static void
_elm_multibuttonentry_text_set(Eo * obj,Elm_Multibuttonentry_Data * sd EINA_UNUSED,const char * part,const char * label)1470 _elm_multibuttonentry_text_set(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED, const char *part, const char *label)
1471 {
1472    if (!part || !strcmp(part, "elm.text"))
1473      {
1474         if (label) _label_set(obj, label);
1475      }
1476    else if (!strcmp(part, "guide"))
1477      {
1478         if (label) _guide_text_set(obj, label);
1479      }
1480    else
1481      elm_object_part_text_set(obj, part, label);
1482 }
1483 
1484 EOLIAN static const char*
_elm_multibuttonentry_text_get(Eo * obj,Elm_Multibuttonentry_Data * sd,const char * part)1485 _elm_multibuttonentry_text_get(Eo *obj, Elm_Multibuttonentry_Data *sd, const char *part)
1486 {
1487    const char *text = NULL;
1488 
1489    if (!part || !strcmp(part, "elm.text"))
1490      {
1491         text = sd->label_str;
1492      }
1493    else if (!strcmp(part, "guide"))
1494      {
1495         text = sd->guide_text_str;
1496      }
1497    else
1498      text = elm_object_part_text_get(obj, part);
1499 
1500    return text;
1501 }
1502 
1503 static char *
_access_info_cb(void * data EINA_UNUSED,Evas_Object * obj)1504 _access_info_cb(void *data EINA_UNUSED, Evas_Object *obj)
1505 {
1506    char *ret;
1507    Eina_Strbuf *buf;
1508    Eina_List *l = NULL;
1509    Elm_Object_Item *eo_item;
1510 
1511    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(obj, sd, NULL);
1512 
1513    if (sd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
1514      {
1515         if (sd->guide_text_str) return strdup(sd->guide_text_str);
1516         return NULL;
1517      }
1518 
1519    buf = eina_strbuf_new();
1520 
1521    if (sd->label_str) eina_strbuf_append(buf, sd->label_str);
1522 
1523    int invisible_its = 0;
1524    EINA_LIST_FOREACH (sd->items, l, eo_item)
1525      {
1526         ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(eo_item, item);
1527         if (item->visible)
1528           eina_strbuf_append_printf(buf, ", %s",
1529             edje_object_part_text_get(elm_layout_edje_get(VIEW(item)), "elm.btn.text"));
1530         else
1531            invisible_its++;
1532      }
1533 
1534    if (invisible_its)
1535      eina_strbuf_append_printf(buf, ", and %d more", invisible_its);
1536 
1537    ret = eina_strbuf_string_steal(buf);
1538    eina_strbuf_free(buf);
1539    return ret;
1540 }
1541 
1542 EOLIAN static void
_elm_multibuttonentry_efl_canvas_group_group_add(Eo * obj,Elm_Multibuttonentry_Data * priv)1543 _elm_multibuttonentry_efl_canvas_group_group_add(Eo *obj, Elm_Multibuttonentry_Data *priv)
1544 {
1545    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1546 
1547    if (!elm_widget_theme_klass_get(obj))
1548      elm_widget_theme_klass_set(obj, "multibuttonentry");
1549    efl_canvas_group_add(efl_super(obj, MY_CLASS));
1550 
1551    if (elm_widget_theme_object_set(obj, wd->resize_obj,
1552                                        elm_widget_theme_klass_get(obj),
1553                                        elm_widget_theme_element_get(obj),
1554                                        elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
1555      CRI("Failed to set layout!");
1556 
1557    elm_widget_can_focus_set(obj, EINA_FALSE);
1558 
1559    priv->last_it_select = EINA_TRUE;
1560    priv->editable = EINA_TRUE;
1561    priv->parent = obj;
1562 	   priv->format_func = _format_count;
1563 
1564    _view_init(obj, priv);
1565    _callbacks_register(obj);
1566 
1567    // ACCESS
1568    _elm_access_object_register(obj, wd->resize_obj);
1569    _elm_access_text_set
1570      (_elm_access_info_get(obj), ELM_ACCESS_TYPE, E_("multi button entry"));
1571    _elm_access_callback_set
1572      (_elm_access_info_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
1573 }
1574 
1575 EOLIAN static void
_elm_multibuttonentry_efl_canvas_group_group_del(Eo * obj,Elm_Multibuttonentry_Data * sd)1576 _elm_multibuttonentry_efl_canvas_group_group_del(Eo *obj, Elm_Multibuttonentry_Data *sd)
1577 {
1578    Eina_List *l;
1579    Elm_Object_Item *eo_item;
1580    Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1581 
1582    EINA_LIST_FOREACH(sd->items, l, eo_item)
1583      efl_del(eo_item);
1584 
1585    sd->items = eina_list_free(sd->items);
1586 
1587    sd->selected_it = NULL;
1588    sd->focused_it = NULL;
1589 
1590    eina_stringshare_del(sd->label_str);
1591    eina_stringshare_del(sd->guide_text_str);
1592    evas_object_del(sd->entry);
1593    evas_object_del(sd->label);
1594    evas_object_del(sd->guide_text);
1595    evas_object_del(sd->end);
1596    ecore_timer_del(sd->longpress_timer);
1597 
1598    EINA_LIST_FREE(sd->filter_list, _item_filter)
1599      _filter_free(_item_filter);
1600 
1601    efl_canvas_group_del(efl_super(obj, MY_CLASS));
1602 }
1603 
1604 static void
_access_obj_process(Evas_Object * obj,Eina_Bool is_access)1605 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1606 {
1607    Eina_List *l;
1608    Elm_Object_Item *it;
1609 
1610    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN(obj, sd);
1611 
1612    /* label */
1613    _access_multibuttonentry_label_register(obj, is_access);
1614 
1615    /* buttons */
1616    EINA_LIST_FOREACH(sd->items, l, it)
1617      _access_multibuttonentry_item_register(obj, it, is_access);
1618 }
1619 
1620 EOLIAN static void
_elm_multibuttonentry_efl_ui_widget_on_access_update(Eo * obj,Elm_Multibuttonentry_Data * sd EINA_UNUSED,Eina_Bool acs)1621 _elm_multibuttonentry_efl_ui_widget_on_access_update(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED, Eina_Bool acs)
1622 {
1623    _elm_multibuttonentry_smart_focus_next_enable = acs;
1624    _access_obj_process(obj, _elm_multibuttonentry_smart_focus_next_enable);
1625 }
1626 
1627 EAPI Evas_Object *
elm_multibuttonentry_add(Evas_Object * parent)1628 elm_multibuttonentry_add(Evas_Object *parent)
1629 {
1630    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1631    return elm_legacy_add(MY_CLASS, parent);
1632 }
1633 
1634 EOLIAN static Eo *
_elm_multibuttonentry_efl_object_constructor(Eo * obj,Elm_Multibuttonentry_Data * sd EINA_UNUSED)1635 _elm_multibuttonentry_efl_object_constructor(Eo *obj, Elm_Multibuttonentry_Data *sd EINA_UNUSED)
1636 {
1637 
1638    legacy_child_focus_handle(obj);
1639    obj = efl_constructor(efl_super(obj, MY_CLASS));
1640    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
1641    evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
1642    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PANEL);
1643 
1644    return obj;
1645 }
1646 
1647 EOLIAN static Evas_Object*
_elm_multibuttonentry_entry_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1648 _elm_multibuttonentry_entry_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1649 {
1650    return sd->entry;
1651 }
1652 
1653 EOLIAN static Eina_Bool
_elm_multibuttonentry_expanded_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1654 _elm_multibuttonentry_expanded_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1655 {
1656    return sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK ?
1657           EINA_FALSE : EINA_TRUE;
1658 }
1659 
1660 EOLIAN static void
_elm_multibuttonentry_format_function_set(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Multibuttonentry_Format_Cb f_func,const void * data)1661 _elm_multibuttonentry_format_function_set(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Format_Cb f_func, const void *data)
1662 {
1663    sd->format_func = f_func;
1664    if (!sd->format_func) sd->format_func = _format_count;
1665 
1666    sd->format_func_data = data;
1667 
1668    _view_update(sd);
1669 }
1670 
1671 EOLIAN static void
_elm_multibuttonentry_expanded_set(Eo * obj,Elm_Multibuttonentry_Data * sd,Eina_Bool expanded)1672 _elm_multibuttonentry_expanded_set(Eo *obj, Elm_Multibuttonentry_Data *sd, Eina_Bool expanded)
1673 {
1674    if (((sd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) ?
1675         EINA_FALSE : EINA_TRUE) == expanded) return;
1676 
1677    if (expanded)
1678      _shrink_mode_set(obj, EINA_FALSE);
1679    else
1680      _shrink_mode_set(obj, EINA_TRUE);
1681 }
1682 
1683 EOLIAN static void
_elm_multibuttonentry_editable_set(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Eina_Bool editable)1684 _elm_multibuttonentry_editable_set(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Eina_Bool editable)
1685 {
1686    editable = !!editable;
1687    if (sd->editable == editable) return;
1688    sd->editable = editable;
1689 
1690    if (sd->editable && (sd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK))
1691      {
1692         elm_box_pack_end(sd->box, sd->entry);
1693         evas_object_show(sd->entry);
1694      }
1695    else
1696      {
1697         elm_box_unpack(sd->box, sd->entry);
1698         evas_object_hide(sd->entry);
1699      }
1700 }
1701 
1702 EOLIAN static Eina_Bool
_elm_multibuttonentry_editable_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1703 _elm_multibuttonentry_editable_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1704 {
1705    return sd->editable;
1706 }
1707 
1708 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_item_prepend(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,const char * label,Evas_Smart_Cb func,void * data)1709 _elm_multibuttonentry_item_prepend(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data)
1710 {
1711    return _item_new(sd, label, MULTIBUTTONENTRY_POS_START, NULL, func, data);
1712 }
1713 
1714 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_item_append(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,const char * label,Evas_Smart_Cb func,void * data)1715 _elm_multibuttonentry_item_append(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, const char *label, Evas_Smart_Cb func, void *data)
1716 {
1717    return _item_new(sd, label, MULTIBUTTONENTRY_POS_END, NULL, func, data);
1718 }
1719 
1720 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_item_insert_before(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Object_Item * before,const char * label,Evas_Smart_Cb func,void * data)1721 _elm_multibuttonentry_item_insert_before(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Object_Item *before, const char *label, Evas_Smart_Cb func, void *data)
1722 {
1723    return _item_new(sd, label, MULTIBUTTONENTRY_POS_BEFORE, before, func, data);
1724 }
1725 
1726 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_item_insert_after(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Object_Item * after,const char * label,Evas_Smart_Cb func,void * data)1727 _elm_multibuttonentry_item_insert_after(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Object_Item *after, const char *label, Evas_Smart_Cb func, void *data)
1728 {
1729    return _item_new(sd, label, MULTIBUTTONENTRY_POS_AFTER, after, func, data);
1730 }
1731 
1732 EOLIAN static const Eina_List*
_elm_multibuttonentry_items_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1733 _elm_multibuttonentry_items_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1734 {
1735    return sd->items;
1736 }
1737 
1738 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_first_item_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1739 _elm_multibuttonentry_first_item_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1740 {
1741    return eina_list_data_get(sd->items);
1742 }
1743 
1744 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_last_item_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1745 _elm_multibuttonentry_last_item_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1746 {
1747    return eina_list_data_get(eina_list_last(sd->items));
1748 }
1749 
1750 EOLIAN static Elm_Object_Item*
_elm_multibuttonentry_selected_item_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1751 _elm_multibuttonentry_selected_item_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1752 {
1753    return EO_OBJ(sd->selected_it);
1754 }
1755 
1756 EOLIAN static void
_elm_multibuttonentry_item_selected_set(Eo * eo_item EINA_UNUSED,Elm_Multibuttonentry_Item_Data * item,Eina_Bool selected)1757 _elm_multibuttonentry_item_selected_set(Eo *eo_item EINA_UNUSED,
1758                                         Elm_Multibuttonentry_Item_Data *item,
1759                                         Eina_Bool selected)
1760 {
1761    if (selected) _item_select(WIDGET(item), item);
1762    else _item_select(WIDGET(item), NULL);
1763 }
1764 
1765 EOLIAN static Eina_Bool
_elm_multibuttonentry_item_selected_get(const Eo * eo_item,Elm_Multibuttonentry_Item_Data * item)1766 _elm_multibuttonentry_item_selected_get(const Eo *eo_item,
1767                                         Elm_Multibuttonentry_Item_Data *item)
1768 {
1769    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(item), sd, EINA_FALSE);
1770    if (!eo_item) return EINA_FALSE;
1771    if (EO_OBJ(sd->selected_it) == eo_item)
1772       return EINA_TRUE;
1773 
1774    return EINA_FALSE;
1775 }
1776 
1777 EOLIAN static void
_elm_multibuttonentry_clear(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd)1778 _elm_multibuttonentry_clear(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd)
1779 {
1780    while (sd->items)
1781      elm_object_item_del(eina_list_data_get(sd->items));
1782 
1783    sd->selected_it = NULL;
1784    _view_update(sd);
1785 }
1786 
1787 EOLIAN static Elm_Object_Item *
_elm_multibuttonentry_item_prev_get(const Eo * eo_it,Elm_Multibuttonentry_Item_Data * it)1788 _elm_multibuttonentry_item_prev_get(const Eo *eo_it,
1789                                    Elm_Multibuttonentry_Item_Data *it)
1790 {
1791    Eina_List *l;
1792    Elm_Object_Item *eo_temp_it;
1793 
1794    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL);
1795 
1796    EINA_LIST_FOREACH(sd->items, l, eo_temp_it)
1797      {
1798         if (eo_temp_it == eo_it)
1799           {
1800              l = eina_list_prev(l);
1801              if (!l) return NULL;
1802              return eina_list_data_get(l);
1803           }
1804      }
1805    return NULL;
1806 }
1807 
1808 EOLIAN static Elm_Object_Item *
_elm_multibuttonentry_item_next_get(const Eo * eo_it,Elm_Multibuttonentry_Item_Data * it)1809 _elm_multibuttonentry_item_next_get(const Eo *eo_it,
1810                                    Elm_Multibuttonentry_Item_Data *it)
1811 {
1812    Eina_List *l;
1813    Elm_Object_Item *eo_temp_it;
1814 
1815    ELM_MULTIBUTTONENTRY_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, NULL);
1816 
1817    EINA_LIST_FOREACH(sd->items, l, eo_temp_it)
1818      {
1819         if (eo_temp_it == eo_it)
1820           {
1821              l = eina_list_next(l);
1822              if (!l) return NULL;
1823              return eina_list_data_get(l);
1824           }
1825      }
1826    return NULL;
1827 }
1828 
1829 EOLIAN static void
_elm_multibuttonentry_item_elm_widget_item_disable(Eo * eo_it,Elm_Multibuttonentry_Item_Data * it)1830 _elm_multibuttonentry_item_elm_widget_item_disable(Eo *eo_it, Elm_Multibuttonentry_Item_Data *it)
1831 {
1832    const char* emission;
1833    if (elm_wdg_item_disabled_get(eo_it))
1834      emission = "elm,state,disabled";
1835    else
1836      emission = "elm,state,enabled";
1837 
1838    elm_layout_signal_emit(VIEW(it), emission, "elm");
1839 }
1840 
1841 EINA_DEPRECATED EAPI void *
elm_multibuttonentry_item_data_get(const Elm_Object_Item * it)1842 elm_multibuttonentry_item_data_get(const Elm_Object_Item *it)
1843 {
1844    return (void *)WIDGET_ITEM_DATA_GET(it);
1845 }
1846 
1847 EINA_DEPRECATED EAPI void
elm_multibuttonentry_item_data_set(Elm_Object_Item * it,void * data)1848 elm_multibuttonentry_item_data_set(Elm_Object_Item *it,
1849                                    void *data)
1850 {
1851    WIDGET_ITEM_DATA_SET(it, data);
1852 }
1853 
1854 EOLIAN static void
_elm_multibuttonentry_item_filter_append(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Multibuttonentry_Item_Filter_Cb func,void * data)1855 _elm_multibuttonentry_item_filter_append(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1856 {
1857    Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1858    Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1859    Eina_List *l;
1860 
1861    EINA_SAFETY_ON_NULL_RETURN(func);
1862 
1863    EINA_LIST_FOREACH(sd->filter_list, l, _item_filter)
1864      {
1865         if (_item_filter && ((_item_filter->callback_func == func)
1866                              && (_item_filter->data == data)))
1867           {
1868              INF("Already Registered this item filter!!!!\n");
1869              return;
1870           }
1871      }
1872    new_item_filter = _filter_new(func, data);
1873    if (!new_item_filter) return;
1874 
1875    sd->filter_list = eina_list_append(sd->filter_list, new_item_filter);
1876 }
1877 
1878 EOLIAN static void
_elm_multibuttonentry_item_filter_prepend(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Multibuttonentry_Item_Filter_Cb func,void * data)1879 _elm_multibuttonentry_item_filter_prepend(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1880 {
1881    Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1882    Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1883    Eina_List *l;
1884 
1885    EINA_SAFETY_ON_NULL_RETURN(func);
1886 
1887    new_item_filter = _filter_new(func, data);
1888    if (!new_item_filter) return;
1889 
1890    EINA_LIST_FOREACH(sd->filter_list, l, _item_filter)
1891      {
1892         if (_item_filter && ((_item_filter->callback_func == func)
1893                              && (_item_filter->data == data)))
1894           {
1895              INF("Already Registered this item filter!!!!\n");
1896              _filter_free(new_item_filter);
1897              return;
1898           }
1899      }
1900    sd->filter_list = eina_list_prepend(sd->filter_list, new_item_filter);
1901 }
1902 
1903 EOLIAN static void
_elm_multibuttonentry_item_filter_remove(Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Data * sd,Elm_Multibuttonentry_Item_Filter_Cb func,void * data)1904 _elm_multibuttonentry_item_filter_remove(Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Data *sd, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1905 {
1906    Eina_List *l;
1907    Elm_Multibuttonentry_Item_Filter *item_filter;
1908 
1909    EINA_SAFETY_ON_NULL_RETURN(func);
1910 
1911    EINA_LIST_FOREACH(sd->filter_list, l, item_filter)
1912      {
1913         if ((item_filter->callback_func == func)
1914             && ((!data) || (item_filter->data == data)))
1915           {
1916              sd->filter_list = eina_list_remove_list(sd->filter_list, l);
1917              _filter_free(item_filter);
1918              return;
1919           }
1920      }
1921 }
1922 
1923 static void
_elm_multibuttonentry_class_constructor(Efl_Class * klass)1924 _elm_multibuttonentry_class_constructor(Efl_Class *klass)
1925 {
1926    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1927 
1928    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
1929       _elm_multibuttonentry_smart_focus_next_enable = EINA_TRUE;
1930 }
1931 
1932 EOLIAN static Eina_List*
_elm_multibuttonentry_efl_access_object_access_children_get(const Eo * obj,Elm_Multibuttonentry_Data * sd)1933 _elm_multibuttonentry_efl_access_object_access_children_get(const Eo *obj, Elm_Multibuttonentry_Data *sd)
1934 {
1935    Eina_List *ret;
1936    ret = efl_access_object_access_children_get(efl_super(obj, ELM_MULTIBUTTONENTRY_CLASS));
1937    return eina_list_merge(eina_list_clone(sd->items), ret);
1938 }
1939 
1940 EOLIAN static const char*
_elm_multibuttonentry_item_efl_access_object_i18n_name_get(const Eo * eo_it,Elm_Multibuttonentry_Item_Data * item)1941 _elm_multibuttonentry_item_efl_access_object_i18n_name_get(const Eo *eo_it, Elm_Multibuttonentry_Item_Data *item)
1942 {
1943    const char *ret;
1944    ret = efl_access_object_i18n_name_get(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS));
1945    if (ret) return ret;
1946 
1947    ret = elm_object_part_text_get(VIEW(item), "elm.btn.text");
1948    return _elm_widget_item_accessible_plain_name_get(eo_it, ret);
1949 }
1950 
1951 EOLIAN static Efl_Access_State_Set
_elm_multibuttonentry_item_efl_access_object_state_set_get(const Eo * eo_it,Elm_Multibuttonentry_Item_Data * sd EINA_UNUSED)1952 _elm_multibuttonentry_item_efl_access_object_state_set_get(const Eo *eo_it, Elm_Multibuttonentry_Item_Data *sd EINA_UNUSED)
1953 {
1954    Efl_Access_State_Set ret;
1955    Eina_Bool sel;
1956 
1957    ret = efl_access_object_state_set_get(efl_super(eo_it, ELM_MULTIBUTTONENTRY_ITEM_CLASS));
1958 
1959    sel = elm_obj_multibuttonentry_item_selected_get(eo_it);
1960 
1961    STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_EDITABLE);
1962 
1963    if (sel)
1964      STATE_TYPE_SET(ret, EFL_ACCESS_STATE_TYPE_CHECKED);
1965 
1966    return ret;
1967 }
1968 
1969 static Eina_Bool
_key_action_activate(Eo * obj,const char * params EINA_UNUSED)1970 _key_action_activate(Eo *obj, const char *params EINA_UNUSED)
1971 {
1972    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it);
1973    elm_layout_signal_emit(VIEW(it), "mouse,clicked,1", "elm");
1974    return EINA_TRUE;
1975 }
1976 
1977 static Eina_Bool
_key_action_delete(Eo * obj,const char * params EINA_UNUSED)1978 _key_action_delete(Eo *obj, const char *params EINA_UNUSED)
1979 {
1980    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it);
1981    elm_layout_signal_emit(VIEW(it), "elm,deleted", "elm");
1982    return EINA_TRUE;
1983 }
1984 
1985 static Eina_Bool
_key_action_longpress(Eo * obj,const char * params EINA_UNUSED)1986 _key_action_longpress(Eo *obj, const char *params EINA_UNUSED)
1987 {
1988    ELM_MULTIBUTTONENTRY_ITEM_DATA_GET(obj, it);
1989    efl_event_callback_legacy_call
1990      (WIDGET(it), ELM_MULTIBUTTONENTRY_EVENT_ITEM_LONGPRESSED, obj);
1991    return EINA_TRUE;
1992 }
1993 
1994 EOLIAN const Efl_Access_Action_Data *
_elm_multibuttonentry_item_efl_access_widget_action_elm_actions_get(const Eo * obj EINA_UNUSED,Elm_Multibuttonentry_Item_Data * pd EINA_UNUSED)1995 _elm_multibuttonentry_item_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Elm_Multibuttonentry_Item_Data *pd EINA_UNUSED)
1996 {
1997    static Efl_Access_Action_Data atspi_actions[] = {
1998           { "activate", NULL, NULL, _key_action_activate },
1999           { "delete", NULL, NULL, _key_action_delete},
2000           { "longpress", NULL, NULL, _key_action_longpress},
2001           { NULL, NULL, NULL, NULL}
2002    };
2003    return &atspi_actions[0];
2004 }
2005 
2006 /* Efl.Part begin */
2007 
2008 ELM_PART_OVERRIDE(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, Elm_Multibuttonentry_Data)
2009 ELM_PART_OVERRIDE_TEXT_SET(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, Elm_Multibuttonentry_Data)
2010 ELM_PART_OVERRIDE_TEXT_GET(elm_multibuttonentry, ELM_MULTIBUTTONENTRY, Elm_Multibuttonentry_Data)
2011 #include "elm_multibuttonentry_part.eo.c"
2012 
2013 /* Efl.Part end */
2014 /* Internal EO APIs and hidden overrides */
2015 
2016 #define ELM_MULTIBUTTONENTRY_EXTRA_OPS \
2017    EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_multibuttonentry)
2018 
2019 #include "elm_multibuttonentry_item_eo.c"
2020 #include "elm_multibuttonentry_eo.c"
2021