add searchbar and toolbar2
[framework/uifw/elementary.git] / src / lib / elm_toolbar2.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 #include <Elementary.h>
5 #include "elm_priv.h"
6
7 /**
8  * @addtogroup Toolbar Toolbar
9  *
10  * @addtogroup Toolbar Toolbar
11  * For listing a selection of items in a list within a "bar", each item having an icon and label.
12  * This is more or less intended for use when selecting different modes - much like a tab widget,
13  * but this is just the bar piece.
14  */
15
16 typedef struct _Widget_Data Widget_Data;
17
18 struct _Widget_Data
19 {
20    Evas_Object *scr, *bx;
21    Eina_List *items;
22    int icon_size;
23    Eina_Bool scrollable : 1;
24    Eina_Bool homogeneous : 1;
25    double align;
26 };
27
28 struct _Elm_Toolbar2_Item
29 {
30    Evas_Object *obj;
31    Evas_Object *base;
32    Evas_Object *icon;
33    void (*func) (void *data, Evas_Object *obj, void *event_info);
34    void (*del_cb) (void *data, Evas_Object *obj, void *event_info);
35    const void *data;
36 };
37
38 static void _item_show(Elm_Toolbar2_Item *it);
39 static void _del_pre_hook(Evas_Object *obj);
40 static void _del_hook(Evas_Object *obj);
41 static void _theme_hook(Evas_Object *obj);
42 static void _sizing_eval(Evas_Object *obj);
43 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
44 static void press_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
45 static void press_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info);
46
47 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
48
49 static void _item_show(Elm_Toolbar2_Item *it)
50 {
51    Widget_Data *wd = elm_widget_data_get(it->obj);
52    Evas_Coord x, y, w, h, bx, by, bw, bh;
53
54    if (!wd) return;
55    evas_object_geometry_get(wd->bx, &bx, &by, &bw, &bh);
56    evas_object_geometry_get(it->base, &x, &y, &w, &h);
57    elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
58
59
60 }
61
62 static void _del_pre_hook(Evas_Object *obj)
63 {
64    Widget_Data *wd = elm_widget_data_get(obj);
65    Elm_Toolbar2_Item *it;
66
67    if (!wd) return;
68    EINA_LIST_FREE(wd->items, it)
69      {
70         if (it->del_cb) it->del_cb((void *)it->data, it->obj, it);
71         if (it->icon) evas_object_del(it->icon);
72         evas_object_del(it->base);
73         free(it);
74      }
75 }
76
77 static void _del_hook(Evas_Object *obj)
78 {
79    Widget_Data *wd = elm_widget_data_get(obj);
80
81    if (!wd) return;
82    free(wd);
83 }
84
85 static void _theme_hook(Evas_Object *obj)
86 {
87    Widget_Data *wd = elm_widget_data_get(obj);
88    const Eina_List *l;
89    Elm_Toolbar2_Item *it;
90    const char *style = elm_widget_style_get(obj);
91    int ms = 0;
92    int scale = 0;
93
94    if (!wd) return;
95    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
96    edje_object_scale_set(wd->scr, scale);
97    EINA_LIST_FOREACH(wd->items, l, it)
98    {
99            Evas_Coord mw, mh;
100            Evas_Coord ic_w, ic_h;
101
102            edje_object_scale_set(it->base, scale);
103
104            _elm_theme_set(it->base, "toolbar2", "item", style);
105            if (it->icon)
106            {
107
108                    evas_object_size_hint_min_get(it->icon, &ic_w, &ic_h);
109
110                    ms = ((double)wd->icon_size * _elm_config->scale);
111                    if (ic_w > 0 && ic_h > 0)
112                    {
113                            if (ic_h > wd->icon_size) ic_h = wd->icon_size;
114                            evas_object_size_hint_min_set(it->icon, ic_w, ic_h);
115                            evas_object_size_hint_max_set(it->icon, ic_w, ic_h);
116                    }
117                    else {
118                            evas_object_size_hint_min_set(it->icon, ms, ms);
119                            evas_object_size_hint_max_set(it->icon, ms, ms);
120                    }
121
122                    evas_object_size_hint_align_set(it->icon, 0.5, 0.5);
123                    edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);
124                    evas_object_show(it->icon);
125                    elm_widget_sub_object_add(obj, it->icon);
126            }
127 /*
128            mw = mh = -1;
129            elm_coords_finger_size_adjust(1, &mw, 1, &mh);
130            edje_object_size_min_restricted_calc(it->base, &mw, &mh, mw, mh);
131            elm_coords_finger_size_adjust(1, &mw, 1, &mh);
132 */
133            evas_object_size_hint_weight_set(it->base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
134            evas_object_size_hint_align_set(it->base, 0.5, 0.5);
135
136            if (ic_w > 0 && ic_h > 0) {
137                    evas_object_size_hint_min_set(it->base, ic_w, ic_h);
138            }
139            else {
140                    //              evas_object_size_hint_min_set(it->base, mw, mh);
141                    ms = ((double)wd->icon_size * _elm_config->scale);
142
143                    evas_object_size_hint_min_set(it->base, ms, ms);
144            }
145    }
146    _sizing_eval(obj);
147 }
148
149 static void _sizing_eval(Evas_Object *obj)
150 {
151         Widget_Data *wd = elm_widget_data_get(obj);
152         Evas_Coord minw = -1, minh = -1;
153         Evas_Coord vw = 0, vh = 0;
154         Evas_Coord w, h;
155
156         if (!wd) return;
157
158         evas_object_smart_calculate(wd->bx);
159         edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
160         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
161
162         if (w < minw) w = minw;
163         if (h < minh) h = minh;
164
165         evas_object_resize(wd->scr, w, h);
166
167         evas_object_size_hint_min_get(wd->bx, &minw, &minh);
168         if (w > minw) minw = w;
169
170         evas_object_resize(wd->bx, minw, 66);
171         if (w > minw) minw = w;
172         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
173
174         if (wd->scrollable)
175                 minw = w - vw;
176         else
177                 minw = minw + (w - vw);
178
179         minh = minh + (h - vh);
180
181         evas_object_size_hint_min_set(obj, vw, vh);
182         evas_object_size_hint_max_set(obj, -1, -1);
183 }
184
185 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
186 {
187         Widget_Data *wd = elm_widget_data_get(data);
188         Evas_Coord mw, mh, vw, vh, x, y, w, h;
189         const Eina_List *l;
190         Elm_Toolbar2_Item *it;
191
192         if (!wd) return;
193
194         elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
195         evas_object_size_hint_min_get(wd->bx, &mw, &mh);
196         evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
197
198         if (vw >= mw)
199         {
200                 if (w != vw) evas_object_resize(wd->bx, vw, h);
201         }
202 }
203
204 static void press_down_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
205 {
206         Evas_Event_Mouse_Down *ev = event_info;
207 //      printf("\nDown %d\n", ev->flags);
208         //Evas_Event_Mouse_Down *ev = event_info;
209         Elm_Toolbar2_Item *it = (Elm_Toolbar2_Item *)data;
210         edje_object_signal_emit(it->base, "elm,state,selected", "elm");
211         _item_show(it);
212 }
213
214 static void press_up_cb(void *data, Evas *evas, Evas_Object *obj, void *event_info)
215 {
216
217         Elm_Toolbar2_Item *it = (Elm_Toolbar2_Item *)data;
218
219         edje_object_signal_emit(it->base, "elm,state,unselected", "elm");
220
221         Evas_Event_Mouse_Up *ev = event_info;
222 //      printf("\nUp %d\n", ev->flags);
223         if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) {
224 //              printf("\nReturn\n");
225                 return;
226         }
227
228 //      printf("\nSend\n");
229         if (it->func) it->func((void *)(it->data), it->obj, it);
230         evas_object_smart_callback_call(it->obj, "clicked", it);
231 }
232
233
234
235 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
236 {
237    Widget_Data *wd = data;
238
239    _els_box_layout(o, priv, 1, wd->homogeneous);
240 }
241
242 /**
243  * Add a new Toolbar object
244  *
245  * @param parent The parent object
246  * @return The new object or NULL if it cannot be created
247  *
248  * @ingroup Toolbar
249  */
250 EAPI Evas_Object *elm_toolbar2_add(Evas_Object *parent)
251 {
252    Evas_Object *obj;
253    Evas *e;
254    Widget_Data *wd;
255
256    wd = ELM_NEW(Widget_Data);
257    e = evas_object_evas_get(parent);
258    obj = elm_widget_add(e);
259    elm_widget_type_set(obj, "toolbar");
260    elm_widget_sub_object_add(parent, obj);
261    elm_widget_data_set(obj, wd);
262    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
263    elm_widget_del_hook_set(obj, _del_hook);
264    elm_widget_theme_hook_set(obj, _theme_hook);
265    elm_widget_can_focus_set(obj, 0);
266
267    wd->scr = elm_smart_scroller_add(e);
268    elm_smart_scroller_bounce_allow_set(wd->scr, 0, 0);
269    elm_smart_scroller_theme_set(wd->scr, "toolbar2", "base", "default");
270    elm_widget_resize_object_set(obj, wd->scr);
271    elm_smart_scroller_policy_set(wd->scr,
272                                  ELM_SMART_SCROLLER_POLICY_AUTO,
273                                  ELM_SMART_SCROLLER_POLICY_OFF);
274
275    wd->icon_size = 50;
276    wd->scrollable = EINA_TRUE;
277    wd->homogeneous = EINA_TRUE;
278    wd->align = 0.5;
279
280    wd->bx = evas_object_box_add(e);
281    evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
282    evas_object_box_layout_set(wd->bx, _layout, wd, NULL);
283    elm_widget_sub_object_add(obj, wd->bx);
284    elm_smart_scroller_child_set(wd->scr, wd->bx);
285    evas_object_show(wd->bx);
286
287    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
288
289    _sizing_eval(obj);
290    return obj;
291 }
292
293 /**
294  * Set the size of icon of Toolbar object
295  *
296  * @param obj The Toolbar object
297  * @param icon_size The size of icon to be set
298  *
299  * @ingroup Toolbar
300  */
301 EAPI void elm_toolbar2_icon_size_set(Evas_Object *obj, int icon_size)
302 {
303    Widget_Data *wd = elm_widget_data_get(obj);
304
305    if (!wd) return;
306    if (icon_size > 50) return;
307    if (wd->icon_size == icon_size) return;
308    wd->icon_size = icon_size;
309    _theme_hook(obj);
310 }
311
312 /**
313  * Get the size of icon of Toolbar object
314  *
315  * @param obj The Toolbar object
316  * @return The size of icon to be set
317  *
318  * @ingroup Toolbar
319  */
320 EAPI int elm_toolbar2_icon_size_get(Evas_Object *obj)
321 {
322    Widget_Data *wd = elm_widget_data_get(obj);
323
324    if (!wd) return 0;
325    return wd->icon_size;
326 }
327
328 /**
329  * Add items to Toolbar object
330  *
331  * @param obj The Toolbar object
332  * @param icon The icon
333  * @param label The Label
334  * @param func The function
335  * @param data The data
336  * @return TheToolbar item
337  *
338  * @ingroup Toolbar
339  */
340 EAPI Elm_Toolbar2_Item *elm_toolbar2_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data)
341 {
342         Widget_Data *wd = elm_widget_data_get(obj);
343         int ms = 0;
344         Evas_Coord mw, mh;
345         Evas_Coord ic_w, ic_h;
346         Elm_Toolbar2_Item *it;
347
348         if (!wd) return NULL;
349         it = ELM_NEW(Elm_Toolbar2_Item);
350         if (!it) return NULL;
351         wd->items = eina_list_append(wd->items, it);
352
353         it->obj = obj;
354         it->icon = icon;
355         it->func = func;
356         it->data = data;
357         it->base = edje_object_add(evas_object_evas_get(obj));
358
359         _elm_theme_set(it->base, "toolbar2", "item", elm_widget_style_get(obj));
360
361         evas_object_event_callback_add(it->icon, EVAS_CALLBACK_MOUSE_DOWN,  press_down_cb, it);
362         evas_object_event_callback_add(it->icon, EVAS_CALLBACK_MOUSE_UP,  press_up_cb, it);
363
364         elm_widget_sub_object_add(obj, it->base);
365
366         ic_w = 0;
367         ic_h = 0;
368         if (it->icon)
369         {
370         
371                 evas_object_size_hint_min_get(it->icon, &ic_w, &ic_h);
372
373                 if (ic_w > 0 && ic_h > 0)
374                 {
375                         if (ic_h > wd->icon_size) ic_h = wd->icon_size;
376                         evas_object_size_hint_min_set(it->icon, ic_w, ic_h);
377                         evas_object_size_hint_max_set(it->icon, ic_w, ic_h);
378                 }
379                 else {
380                         ms = ((double)wd->icon_size * _elm_config->scale);
381
382                         evas_object_size_hint_min_set(it->icon, ms, ms);
383                         evas_object_size_hint_max_set(it->icon, ms, ms);
384                 }
385
386 //              evas_object_size_hint_weight_set(it->icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
387 //              evas_object_size_hint_align_set(it->icon, 0.5, 0.5);
388
389                 edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon);
390                 evas_object_show(it->icon);
391                 elm_widget_sub_object_add(obj, it->icon);
392         }
393 /*
394         mw = mh = -1;
395
396         elm_coords_finger_size_adjust(1, &mw, 1, &mh);
397         edje_object_size_min_restricted_calc(it->base, &mw, &mh, mw, mh);
398         elm_coords_finger_size_adjust(1, &mw, 1, &mh);
399 */
400         evas_object_size_hint_weight_set(it->base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
401         evas_object_size_hint_align_set(it->base, 0.5, 0.5);
402
403         if (ic_w > 0 && ic_h > 0) {
404                 evas_object_size_hint_min_set(it->base, ic_w, ic_h);
405         }
406         else {
407 //              evas_object_size_hint_min_set(it->base, mw, mh);
408                 ms = ((double)wd->icon_size * _elm_config->scale);
409
410                 evas_object_size_hint_min_set(it->base, ms, ms);
411         }
412         evas_object_box_append(wd->bx, it->base);
413         evas_object_show(it->base);
414         _sizing_eval(obj);
415         return it;
416 }
417
418 /**
419  * Get icon of item of Toolbar object
420  *
421  * @param item TheToolbar item
422  * @return The icon object
423  *
424  * @ingroup Toolbar
425  */
426 EAPI Evas_Object *elm_toolbar2_item_icon_get(Elm_Toolbar2_Item *item)
427 {
428    if (!item) return NULL;
429    return item->icon;
430 }
431
432
433 /**
434  * Delete the Toolbar item
435  *
436  * @param it TheToolbar item
437  *
438  * @ingroup Toolbar
439  */
440 EAPI void elm_toolbar2_item_del(Elm_Toolbar2_Item *it)
441 {
442    Widget_Data *wd = elm_widget_data_get(it->obj);
443    Evas_Object *obj2 = it->obj;
444
445    if ((!wd) || (!it)) return;
446    if (it->del_cb) it->del_cb((void *)it->data, it->obj, it);
447    wd->items = eina_list_remove(wd->items, it);
448    if (it->icon) evas_object_del(it->icon);
449    evas_object_del(it->base);
450    free(it);
451    _theme_hook(obj2);
452 }
453
454 /**
455  * Set the function called when a toolbar item is freed.
456  *
457  * @param it The item to set the callback on
458  * @param func The function called
459  *
460  * @ingroup Toolbar
461  */
462 EAPI void elm_toolbar2_item_del_cb_set(Elm_Toolbar2_Item *it, void (*func)(void *data, Evas_Object *obj, void *event_info))
463 {
464    if(!it) return;
465
466    it->del_cb = func;
467 }
468
469 /**
470  * Whether toolbar is scrollable
471  *
472  * @param obj The Toolbar
473  * @param scrollable The scrollable flag (1 if toolbar is scrollable, 0 otherwise)
474  *
475  * @ingroup Toolbar
476  */
477 EAPI void elm_toolbar2_scrollable_set(Evas_Object *obj, Eina_Bool scrollable)
478 {
479    Widget_Data *wd = elm_widget_data_get(obj);
480
481    if (!wd) return;
482    wd->scrollable = scrollable;
483    _sizing_eval(obj);
484 }
485
486
487 /**
488  * Whether toolbar is homogenous
489  *
490  * @param obj The Toolbar
491  * @param homogenous The homogenous flag (1 if toolbar is homogenous, 0 otherwise)
492  *
493  * @ingroup Toolbar
494  *
495  */
496 EAPI void
497 elm_toolbar2_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
498 {
499    Widget_Data *wd = elm_widget_data_get(obj);
500
501    if (!wd) return;
502    wd->homogeneous = !!homogenous;
503    evas_object_smart_calculate(wd->bx);
504 }
505
506
507 /**
508  * Set if the alignment of the items.
509  *
510  * @param obj The toolbar object
511  * @param align The new alignment. (left) 0.0 ... 1.0 (right)
512  *
513  * @ingroup Toolbar
514  */
515 EAPI void elm_toolbar2_align_set(Evas_Object *obj, double align)
516 {
517    Eina_List *l;
518    Elm_Toolbar2_Item *it;
519    Widget_Data *wd = elm_widget_data_get(obj);
520
521    if (!wd) return;
522    if(wd->align != align)
523      evas_object_size_hint_align_set(wd->bx, align, 0.5);
524     wd->align = align;
525 }