[efl-upgrade]
[framework/uifw/elementary.git] / src / lib / elm_dialoguegroup.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include <Ecore.h>
4
5 /**
6  * @defgroup DialogueGroup DialogueGroup 
7  * @ingroup Elementary
8  *
9  * Using dialoguegroup, you can make a dialogue group.
10  */
11
12 struct _Dialogue_Item
13 {
14         Evas_Object *parent;
15         Evas_Object *bg_layout;
16         Evas_Object *content;
17         Elm_Dialoguegroup_Item_Style style;
18         const char *location;
19         Eina_Bool press;
20 //      Eina_Bool line_show;
21 };
22
23
24 typedef struct _Widget_Data Widget_Data;
25 struct _Widget_Data
26 {
27         Evas_Object *parent;
28         Evas *e;
29         Evas_Object *box;
30         Evas_Object *title_layout;
31         const char *title;
32         unsigned int num;
33         Eina_List *items;
34 };
35
36 static const char*widtype = NULL;
37
38 static void _del_hook(Evas_Object *obj);
39 static void _theme_hook(Evas_Object *obj);
40 static void _sizing_eval(Evas_Object *obj);
41 static void _disable_hook(Evas_Object *obj);
42
43 static void _remove_all(Evas_Object *obj);
44 static void _set_item_theme(Dialogue_Item *item, const char *location);
45 static void _change_item_bg(Dialogue_Item *item, const char *location);
46 static Dialogue_Item* _create_item(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style, const char *location);
47
48         
49 static void
50 _del_hook(Evas_Object *obj)
51 {
52         Widget_Data *wd = elm_widget_data_get(obj);
53
54         if (!wd) return;
55         if (wd->title) eina_stringshare_del(wd->title);
56         
57         _remove_all(obj);
58         
59         if (wd->box){
60                 evas_object_del(wd->box);
61                 wd->box = NULL;
62         }
63         
64         free(wd);
65 }
66
67
68 static void
69 _theme_hook(Evas_Object *obj)
70 {
71         Widget_Data *wd = elm_widget_data_get(obj);
72         Eina_List *l;
73         Dialogue_Item *item;    
74         
75         if (!wd) return;        
76         if (wd->title) {
77                 elm_layout_theme_set(wd->title_layout, "dialoguegroup", "title", elm_widget_style_get(obj));
78                 edje_object_part_text_set(elm_layout_edje_get(wd->title_layout), "text", wd->title);
79         }
80         EINA_LIST_FOREACH(wd->items, l, item) 
81                 _change_item_bg( item, item->location );        
82         _sizing_eval(obj);
83 }
84
85 static void
86 _disable_hook(Evas_Object *obj)
87 {
88
89 }
90
91 static void
92 _sizing_eval(Evas_Object *obj)
93 {
94         Widget_Data *wd = elm_widget_data_get(obj);
95         Evas_Coord minw, minh, maxw, maxh;
96         
97         if (!wd) return;
98         evas_object_size_hint_min_get(wd->box, &minw, &minh);
99         evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
100         evas_object_size_hint_min_set(obj, minw, minh);
101         evas_object_size_hint_max_set(obj, maxw, maxh);
102 }
103
104 static void _remove_all(Evas_Object *obj)
105 {
106         Widget_Data *wd = elm_widget_data_get(obj);
107         Dialogue_Item *item;    
108
109         if (!wd) return;
110
111         wd->num = 0;
112         
113         if (wd->items) {
114                 EINA_LIST_FREE(wd->items, item) {
115                         if (item->content){
116                                 evas_object_del(item->content);
117                                 item->content = NULL;
118                         }
119                         if (item->bg_layout){
120                                 evas_object_del(item->bg_layout);
121                                 item->bg_layout = NULL;
122                         }
123                         if (item->location)
124                                 eina_stringshare_del(item->location);
125                         free(item);
126                 }
127         }
128 }
129
130 static void _set_item_theme(Dialogue_Item *item, const char *location)
131 {
132         if (!item) return;
133         char buf[30];
134
135         if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT) 
136                 snprintf(buf, sizeof(buf), "bg_%s", location);
137         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD) 
138                 snprintf(buf, sizeof(buf), "editfield_%s", location);
139         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD_WITH_TITLE) 
140                 snprintf(buf, sizeof(buf), "editfield_with_title_%s", location);
141         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDIT_TITLE) 
142                 snprintf(buf, sizeof(buf), "edit_title_%s", location);
143         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_HIDDEN) 
144                 snprintf(buf, sizeof(buf), "hidden_%s", location);
145         elm_layout_theme_set(item->bg_layout, "dialoguegroup", buf, elm_widget_style_get(item->parent));
146 }
147
148 /*
149 static void _set_line_show(Dialogue_Item *item, Dialogue_Item *after)
150 {
151         if(!item || !after) return;
152
153         if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT) {
154                 if (after->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT) {
155                         item->line_show = EINA_TRUE;
156                         edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,show", "elm");    
157                 }
158                 else if (after->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD) {
159                         item->line_show = EINA_FALSE;
160                         edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,hide", "elm");    
161                 }       
162         }
163         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD) 
164                 item->line_show = EINA_TRUE;    
165 }
166 */
167
168 static void _change_item_bg(Dialogue_Item *item, const char *location)
169 {
170         if (!item) return;
171         
172         eina_stringshare_replace(&item->location, location);
173         _set_item_theme(item, location);
174         elm_layout_content_set(item->bg_layout, "swallow", item->content);
175         if(item->press == EINA_TRUE)
176                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,on", "elm");
177         else
178                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,off", "elm");
179
180 /*      if(item->line_show == EINA_FALSE)
181                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,hide", "elm");*/
182                         
183 }
184
185 static Dialogue_Item* _create_item(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style, const char *location)
186 {
187         Widget_Data *wd = elm_widget_data_get(obj);
188         Dialogue_Item *item;
189
190         if (!wd) return NULL;
191         
192         item = ELM_NEW(Dialogue_Item);
193         item->parent = obj;
194         item->content = subobj;
195         item->press = EINA_TRUE;
196         item->style = style;
197 //      item->line_show = EINA_TRUE;
198         eina_stringshare_replace(&item->location, location);
199         
200         item->bg_layout = elm_layout_add(wd->box);
201         _set_item_theme(item, location);
202         evas_object_size_hint_weight_set(item->bg_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
203         evas_object_size_hint_align_set(item->bg_layout, EVAS_HINT_FILL, 0.0);
204         evas_object_show(item->bg_layout);      
205
206         elm_layout_content_set(item->bg_layout, "swallow", item->content);
207
208         return item;
209 }
210
211 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
212 {
213         _sizing_eval(data);
214 }
215
216 /**
217  * Add a new dialoguegroup to the parent.
218  *
219  * @param parent The parent object
220  * @return The new object or NULL if it cannot be created
221  *
222  * @ingroup DialogueGroup
223  */
224 EAPI Evas_Object *elm_dialoguegroup_add(Evas_Object *parent)
225 {
226         Evas_Object *obj = NULL;
227         Widget_Data *wd = NULL;
228
229         wd = ELM_NEW(Widget_Data);
230         wd->e = evas_object_evas_get(parent);
231         if (wd->e == NULL) return NULL;
232         obj = elm_widget_add(wd->e);
233         ELM_SET_WIDTYPE(widtype, "dialoguegroup");
234         elm_widget_type_set(obj, "dialoguegroup");
235         elm_widget_sub_object_add(parent, obj);
236         elm_widget_data_set(obj, wd);
237         elm_widget_del_hook_set(obj, _del_hook);
238         elm_widget_theme_hook_set(obj, _theme_hook);
239
240         wd->parent = parent;
241         wd->num = 0;
242         
243         wd->box = elm_box_add(obj);
244         evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
245         evas_object_show(wd->box);
246         elm_widget_resize_object_set(obj, wd->box);
247         
248         _sizing_eval(obj);
249         return obj;
250 }
251
252 /**
253  * Append an item to the dialogue group.
254  *
255  * @param obj dialoguegroup object 
256  * @param subobj item
257  * @return Dialogue_Item pointer, just made by this function
258  * 
259  * @ingroup DialogueGroup
260  */
261 EAPI Dialogue_Item *
262 elm_dialoguegroup_append(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style)
263 {
264         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
265         Widget_Data *wd = elm_widget_data_get(obj);
266         Dialogue_Item *item = NULL, *new_item = NULL;   
267         
268         if (!wd || !subobj) return NULL;
269         
270         if (!wd->items) 
271                 new_item = _create_item(obj, subobj, style, "default");
272         else {
273                 if (wd->num == 1) {     
274                         item = eina_list_data_get(wd->items);
275                         _change_item_bg(item, "top");           
276                 }               
277                 else {
278                         item = eina_list_data_get( eina_list_last(wd->items) );
279                         _change_item_bg(item, "middle");                
280                 }
281                 new_item = _create_item(obj, subobj, style, "bottom");
282 //              _set_line_show(item, new_item);
283         }
284         elm_box_pack_end(wd->box, new_item->bg_layout);
285         wd->items = eina_list_append(wd->items, new_item);                      
286         wd->num++;
287         _sizing_eval(obj);
288         return new_item;
289 }
290
291
292 /**
293  * Prepend an item to the dialogue group.
294  *
295  * @param obj dialoguegroup object 
296  * @param subobj item
297  * @return Dialogue_Item pointer, just made by this function
298  *
299  * @ingroup DialogueGroup
300  */
301 EAPI Dialogue_Item *
302 elm_dialoguegroup_prepend(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style)
303 {
304         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
305         Widget_Data *wd = elm_widget_data_get(obj);
306         Dialogue_Item *item = NULL, *new_item = NULL;
307         
308         if (!wd || !subobj) return NULL;
309         
310         if (!wd->items)
311                 new_item = _create_item(obj, subobj, style, "default"); 
312         else {
313                 if (wd->num == 1) {     
314                         item = eina_list_data_get(wd->items);
315                         _change_item_bg(item, "bottom");
316                 }               
317                 else {
318                         item = eina_list_data_get(wd->items);
319                         _change_item_bg(item, "middle");                
320                 }
321                 new_item = _create_item(obj, subobj, style, "top");
322 //              _set_line_show(new_item, item);
323         }
324         if(wd->title_layout)
325                 elm_box_pack_after(wd->box, new_item->bg_layout, wd->title_layout);     
326         else                    
327                 elm_box_pack_start(wd->box, new_item->bg_layout);               
328         wd->items = eina_list_prepend(wd->items, new_item);             
329         wd->num++;
330         _sizing_eval(obj);
331         return new_item;
332 }
333
334 /**
335  * Insert an item to the dialogue group just after the specified item.
336  *
337  * @param obj dialoguegroup object 
338  * @param subobj item
339  * @param after specified item existing in the dialogue group
340  * @return Dialogue_Item pointer, just made by this function
341  *
342  * @ingroup DialogueGroup
343  */
344 EAPI Dialogue_Item * 
345 elm_dialoguegroup_insert_after(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *after, Elm_Dialoguegroup_Item_Style style)
346 {
347         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
348         Widget_Data *wd = elm_widget_data_get(obj);
349         Dialogue_Item *after_item = NULL, *item = NULL;
350         Eina_List *l;
351
352         if (!wd || !subobj || !after || !wd->items) return NULL;
353
354         EINA_LIST_FOREACH(wd->items, l, after_item) {
355                 if(after == after_item) {
356                         if( !strcmp(after_item->location, "default") ) {
357                                 _change_item_bg(after_item, "top");
358                                 item = _create_item(obj, subobj, style, "bottom");
359                         }                       
360                         else if( !strcmp(after_item->location, "top") || !strcmp(after_item->location, "middle") )      
361                                 item = _create_item(obj, subobj, style, "middle");              
362                         else if( !strcmp(after_item->location, "bottom") ) {
363                                 _change_item_bg(after_item, "middle");
364                                 item = _create_item(obj, subobj, style, "bottom");              
365                         }
366
367                         elm_box_pack_after(wd->box, item->bg_layout, after_item->bg_layout);
368                         wd->items = eina_list_append_relative(wd->items, item, after_item);
369                 //      _set_line_show(after, item);
370                 }               
371         }
372                 
373         wd->num++;
374         _sizing_eval(obj);
375         return item;
376 }
377
378 /**
379  * Insert an item to the dialogue group just before the specified item.
380  *
381  * @param obj dialoguegroup object 
382  * @param subobj item
383  * @param before specified item existing in the dialogue group
384  * @return Dialogue_Item pointer, just made by this function
385  *
386  * @ingroup DialogueGroup
387  */
388 EAPI Dialogue_Item *
389 elm_dialoguegroup_insert_before(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *before, Elm_Dialoguegroup_Item_Style style)
390 {
391         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
392         Widget_Data *wd = elm_widget_data_get(obj);
393         Dialogue_Item *before_item = NULL, *item = NULL;
394         Eina_List *l;
395         Eina_List *prev;
396         
397         if (!wd || !subobj || !before || !wd->items) return NULL;
398
399         EINA_LIST_FOREACH(wd->items, l, before_item) {
400                 if(before == before_item) {
401                         if( !strcmp(before_item->location, "default") ) {
402                                 _change_item_bg(before_item, "bottom");
403                                 item = _create_item(obj, subobj, style, "top");
404                         }
405                                 
406                         else if( !strcmp(before_item->location, "top") ) {
407                                 _change_item_bg(before_item, "middle");
408                                 item = _create_item(obj, subobj, style, "top");                 
409                         }
410
411                         else if( !strcmp(before_item->location, "middle") || !strcmp(before_item->location, "bottom") ) {
412                                 item = _create_item(obj, subobj, style, "middle");
413                                 prev = eina_list_prev(l);
414                         //      _set_line_show(prev->data, item);
415                         }
416                         elm_box_pack_before(wd->box, item->bg_layout, before_item->bg_layout);
417                         wd->items = eina_list_prepend_relative(wd->items, item, before_item);
418                 }               
419         }
420                 
421         wd->num++;
422         _sizing_eval(obj);      
423         return item;
424 }
425
426 /**
427  * Remove an item from the dialogue group.
428  *
429  * @param obj dialoguegroup object 
430  * @param subobj item
431  *
432  * @ingroup DialogueGroup
433  */
434 EAPI void
435 elm_dialoguegroup_remove(Dialogue_Item *item)
436 {
437         ELM_CHECK_WIDTYPE(item->parent, widtype) ;
438         Dialogue_Item *current_item;
439         Widget_Data *wd = elm_widget_data_get(item->parent);
440         Eina_List *l;
441         
442         if (!wd || !wd->items || !item) return ;
443         
444         EINA_LIST_FOREACH(wd->items, l, current_item) {
445                 if (current_item == item) {
446                         if (current_item->content){
447                                 evas_object_del(current_item->content);
448                                 current_item->content = NULL;
449                         }
450                         if (current_item->bg_layout){
451                                 evas_object_del(current_item->bg_layout);
452                                 current_item->bg_layout = NULL;
453                         }
454                         elm_box_unpack(wd->box, current_item->bg_layout);                       
455                         wd->items = eina_list_remove(wd->items, current_item);
456                 }
457         }
458                 
459         wd->num--;
460         
461         if (wd->num == 0) return;
462         
463         if (wd->num == 1) {
464                 current_item = eina_list_data_get(wd->items);
465                 _change_item_bg(current_item, "default");
466         }
467
468         else {          
469                 current_item = eina_list_data_get(wd->items);
470                 _change_item_bg(current_item, "top");
471                 current_item = eina_list_data_get( eina_list_last(wd->items) );
472                 _change_item_bg(current_item, "bottom");                
473         }
474
475         _sizing_eval(item->parent);     
476 }
477
478 /**
479  * Remove all items from the dialogue group.
480  *
481  * @param obj dialoguegroup object 
482  *
483  * @ingroup DialogueGroup
484  */
485 EAPI void
486 elm_dialoguegroup_remove_all(Evas_Object *obj)
487 {
488         ELM_CHECK_WIDTYPE(obj, widtype);
489         _remove_all(obj);       
490         _sizing_eval(obj);      
491 }
492
493
494 /**
495  * Set the title text of the  dialogue group.
496  *
497  * @param obj dialoguegroup object 
498  * @param title title text, if NULL title space will be disappeared 
499  * 
500  * @ingroup DialogueGroup
501  */
502 EAPI void 
503 elm_dialoguegroup_title_set(Evas_Object *obj, const char *title)
504 {
505         ELM_CHECK_WIDTYPE(obj, widtype);
506         Widget_Data *wd = elm_widget_data_get(obj);
507         
508         if (!wd) return ;
509         eina_stringshare_replace(&wd->title, title);
510         if (!title) {
511                 wd->title = NULL;       
512                 elm_box_unpack(wd->box, wd->title_layout);              
513         }
514         if (!wd->title_layout) {
515                 wd->title_layout = elm_layout_add(wd->box);
516                 elm_layout_theme_set(wd->title_layout, "dialoguegroup", "title", elm_widget_style_get(obj));
517                 evas_object_size_hint_weight_set(wd->title_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
518                 evas_object_size_hint_align_set(wd->title_layout, EVAS_HINT_FILL, 0.0);
519                 evas_object_show(wd->title_layout);     
520         }
521         edje_object_part_text_set(elm_layout_edje_get(wd->title_layout), "text", title);
522         elm_box_pack_start(wd->box, wd->title_layout);
523 }
524
525 /**
526  * Get the title text of the dialogue group
527  *
528  * @param obj The dialoguegroup object
529  * @return The text title string in UTF-8
530  *
531  * @ingroup DialogueGroup
532  */
533 EAPI const char *
534 elm_dialoguegroup_title_get(Evas_Object *obj)
535 {
536    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
537    Widget_Data *wd = elm_widget_data_get(obj);
538    if (!wd) return NULL;
539    return wd->title;
540 }
541
542 /**
543  * Set whether the press effect will be shown or not
544  *
545  * @param obj The dialoguegroup object
546  * @param item Dialogue_Item pointer
547  * @param press If set as 1, press effect will be shown 
548  *
549  * @ingroup DialogueGroup 
550  */
551 EAPI void 
552 elm_dialoguegroup_press_effect_set(Dialogue_Item *item, Eina_Bool press)
553 {
554    ELM_CHECK_WIDTYPE(item->parent, widtype) ;
555    if(!item) return;
556    
557    item->press = press;
558    if(press == EINA_TRUE)
559            edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,on", "elm");
560    else
561            edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,off", "elm"); 
562 }
563
564 /**
565  * Get the press effect state
566  *
567  * @param obj The dialoguegroup object
568  * @param item Dialogue_Item pointer
569  * @return 1 if press effect on, 0 if press effect off 
570  *
571  * @ingroup DialogueGroup 
572  */
573 EAPI Eina_Bool
574 elm_dialoguegroup_press_effect_get(Dialogue_Item *item)
575 {
576    ELM_CHECK_WIDTYPE(item->parent, widtype) EINA_FALSE;
577    if(!item) return EINA_FALSE;
578    
579    return item->press;
580 }
581
582 /**
583  * Get the conetent object from the specified dialogue item
584  *
585  * @param obj The dialoguegroup object
586  * @param item Dialogue_Item pointer
587  * @return content object 
588  *
589  * @ingroup DialogueGroup 
590  */
591 EAPI Evas_Object *
592 elm_dialoguegroup_item_content_get(Dialogue_Item *item)
593 {
594    ELM_CHECK_WIDTYPE(item->parent, widtype) EINA_FALSE;
595    if(!item) return EINA_FALSE;
596    
597    return item->content;
598 }