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