Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[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", "base", "title");
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
134         if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT)
135                 elm_layout_theme_set(item->bg_layout, "dialoguegroup", "bg", location);
136         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD)
137                 elm_layout_theme_set(item->bg_layout, "dialoguegroup", "editfield", location);
138 }
139
140 static void _set_line_show(Dialogue_Item *item, Dialogue_Item *after)
141 {
142         if(!item || !after) return;
143
144         if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT) {
145                 if (after->style == ELM_DIALOGUEGROUP_ITEM_STYLE_DEFAULT) {
146                         item->line_show = EINA_TRUE;
147                         edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,show", "elm");    
148                 }
149                 else if (after->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD) {
150                         item->line_show = EINA_FALSE;
151                         edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,hide", "elm");    
152                 }       
153         }
154         else if (item->style == ELM_DIALOGUEGROUP_ITEM_STYLE_EDITFIELD) 
155                 item->line_show = EINA_TRUE;    
156 }
157
158 static void _change_item_bg(Dialogue_Item *item, const char *location)
159 {
160         if (!item) return;
161         
162         eina_stringshare_replace(&item->location, location);
163         _set_item_theme(item, location);
164         elm_layout_content_set(item->bg_layout, "swallow", item->content);
165         if(item->press == EINA_TRUE)
166                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,on", "elm");
167         else
168                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,off", "elm");    
169
170         if(item->line_show == EINA_FALSE)
171                 edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,line,hide", "elm");
172                         
173 }
174
175 static Dialogue_Item* _create_item(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style, const char *location)
176 {
177         Widget_Data *wd = elm_widget_data_get(obj);
178         Dialogue_Item *item;
179
180         if (!wd) return NULL;
181         
182         item = ELM_NEW(Dialogue_Item);
183         item->parent = obj;
184         item->content = subobj;
185         item->press = EINA_TRUE;
186         item->style = style;
187         item->line_show = EINA_TRUE;
188         eina_stringshare_replace(&item->location, location);
189         
190         item->bg_layout = elm_layout_add(wd->parent);
191         _set_item_theme(item, location);
192         evas_object_size_hint_weight_set(item->bg_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
193         evas_object_size_hint_align_set(item->bg_layout, EVAS_HINT_FILL, 0.0);
194         evas_object_show(item->bg_layout);      
195
196         elm_layout_content_set(item->bg_layout, "swallow", item->content);
197
198         return item;
199 }
200
201 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
202 {
203         _sizing_eval(data);
204 }
205
206 /**
207  * Add a new dialoguegroup to the parent.
208  *
209  * @param parent The parent object
210  * @return The new object or NULL if it cannot be created
211  *
212  * @ingroup DialogueGroup
213  */
214 EAPI Evas_Object *elm_dialoguegroup_add(Evas_Object *parent)
215 {
216         Evas_Object *obj = NULL;
217         Widget_Data *wd = NULL;
218
219         wd = ELM_NEW(Widget_Data);
220         wd->e = evas_object_evas_get(parent);
221         if (wd->e == NULL) return NULL;
222         obj = elm_widget_add(wd->e);
223         ELM_SET_WIDTYPE(widtype, "dialoguegroup");
224         elm_widget_type_set(obj, "dialoguegroup");
225         elm_widget_sub_object_add(parent, obj);
226         elm_widget_data_set(obj, wd);
227         elm_widget_del_hook_set(obj, _del_hook);
228         elm_widget_theme_hook_set(obj, _theme_hook);
229
230         wd->parent = parent;
231         wd->num = 0;
232         
233         wd->box = elm_box_add(parent);
234         evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
235         evas_object_show(wd->box);
236         elm_widget_resize_object_set(obj, wd->box);
237         
238         _sizing_eval(obj);
239         return obj;
240 }
241
242 /**
243  * Append an item to the dialogue group.
244  *
245  * @param obj dialoguegroup object 
246  * @param subobj item
247  * @return Dialogue_Item pointer, just made by this function
248  * 
249  * @ingroup DialogueGroup
250  */
251 EAPI Dialogue_Item *
252 elm_dialoguegroup_append(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style)
253 {
254         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
255         Widget_Data *wd = elm_widget_data_get(obj);
256         Dialogue_Item *item = NULL, *new_item = NULL;   
257         
258         if (!wd || !subobj) return NULL;
259         
260         if (!wd->items) 
261                 new_item = _create_item(obj, subobj, style, "default");
262         else {
263                 if (wd->num == 1) {     
264                         item = eina_list_data_get(wd->items);
265                         _change_item_bg(item, "top");           
266                 }               
267                 else {
268                         item = eina_list_data_get( eina_list_last(wd->items) );
269                         _change_item_bg(item, "middle");                
270                 }
271                 new_item = _create_item(obj, subobj, style, "bottom");
272                 _set_line_show(item, new_item);
273         }
274         elm_box_pack_end(wd->box, new_item->bg_layout);
275         wd->items = eina_list_append(wd->items, new_item);                      
276         wd->num++;
277         _sizing_eval(obj);
278         return new_item;
279 }
280
281
282 /**
283  * Prepend an item to the dialogue group.
284  *
285  * @param obj dialoguegroup object 
286  * @param subobj item
287  * @return Dialogue_Item pointer, just made by this function
288  *
289  * @ingroup DialogueGroup
290  */
291 EAPI Dialogue_Item *
292 elm_dialoguegroup_prepend(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style)
293 {
294         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
295         Widget_Data *wd = elm_widget_data_get(obj);
296         Dialogue_Item *item = NULL, *new_item = NULL;
297         
298         if (!wd || !subobj) return NULL;
299         
300         if (!wd->items)
301                 new_item = _create_item(obj, subobj, style, "default"); 
302         else {
303                 if (wd->num == 1) {     
304                         item = eina_list_data_get(wd->items);
305                         _change_item_bg(item, "bottom");
306                 }               
307                 else {
308                         item = eina_list_data_get(wd->items);
309                         _change_item_bg(item, "middle");                
310                 }
311                 new_item = _create_item(obj, subobj, style, "top");
312                 _set_line_show(new_item, item);
313         }
314         if(wd->title_layout)
315                 elm_box_pack_after(wd->box, new_item->bg_layout, wd->title_layout);     
316         else                    
317                 elm_box_pack_start(wd->box, new_item->bg_layout);               
318         wd->items = eina_list_prepend(wd->items, new_item);             
319         wd->num++;
320         _sizing_eval(obj);
321         return new_item;
322 }
323
324 /**
325  * Insert an item to the dialogue group just after the specified item.
326  *
327  * @param obj dialoguegroup object 
328  * @param subobj item
329  * @param after specified item existing in the dialogue group
330  * @return Dialogue_Item pointer, just made by this function
331  *
332  * @ingroup DialogueGroup
333  */
334 EAPI Dialogue_Item * 
335 elm_dialoguegroup_insert_after(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *after, Elm_Dialoguegroup_Item_Style style)
336 {
337         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
338         Widget_Data *wd = elm_widget_data_get(obj);
339         Dialogue_Item *after_item = NULL, *item = NULL;
340         Eina_List *l;
341
342         if (!wd || !subobj || !after || !wd->items) return NULL;
343
344         EINA_LIST_FOREACH(wd->items, l, after_item) {
345                 if(after == after_item) {
346                         if( !strcmp(after_item->location, "default") ) {
347                                 _change_item_bg(after_item, "top");
348                                 item = _create_item(obj, subobj, style, "bottom");
349                         }                       
350                         else if( !strcmp(after_item->location, "top") || !strcmp(after_item->location, "middle") )      
351                                 item = _create_item(obj, subobj, style, "middle");              
352                         else if( !strcmp(after_item->location, "bottom") ) {
353                                 _change_item_bg(after_item, "middle");
354                                 item = _create_item(obj, subobj, style, "bottom");              
355                         }
356
357                         elm_box_pack_after(wd->box, item->bg_layout, after_item->bg_layout);
358                         wd->items = eina_list_append_relative(wd->items, item, after_item);
359                         _set_line_show(after, item);
360                 }               
361         }
362                 
363         wd->num++;
364         _sizing_eval(obj);
365         return item;
366 }
367
368 /**
369  * Insert an item to the dialogue group just before the specified item.
370  *
371  * @param obj dialoguegroup object 
372  * @param subobj item
373  * @param before specified item existing in the dialogue group
374  * @return Dialogue_Item pointer, just made by this function
375  *
376  * @ingroup DialogueGroup
377  */
378 EAPI Dialogue_Item *
379 elm_dialoguegroup_insert_before(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *before, Elm_Dialoguegroup_Item_Style style)
380 {
381         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
382         Widget_Data *wd = elm_widget_data_get(obj);
383         Dialogue_Item *before_item = NULL, *item = NULL;
384         Eina_List *l;
385         Eina_List *prev;
386         
387         if (!wd || !subobj || !before || !wd->items) return NULL;
388
389         EINA_LIST_FOREACH(wd->items, l, before_item) {
390                 if(before == before_item) {
391                         if( !strcmp(before_item->location, "default") ) {
392                                 _change_item_bg(before_item, "bottom");
393                                 item = _create_item(obj, subobj, style, "top");
394                         }
395                                 
396                         else if( !strcmp(before_item->location, "top") ) {
397                                 _change_item_bg(before_item, "middle");
398                                 item = _create_item(obj, subobj, style, "top");                 
399                         }
400
401                         else if( !strcmp(before_item->location, "middle") || !strcmp(before_item->location, "bottom") ) {
402                                 item = _create_item(obj, subobj, style, "middle");
403                                 prev = eina_list_prev(l);
404                                 _set_line_show(prev->data, item);
405                         }
406                         elm_box_pack_before(wd->box, item->bg_layout, before_item->bg_layout);
407                         wd->items = eina_list_prepend_relative(wd->items, item, before_item);
408                 }               
409         }
410                 
411         wd->num++;
412         _sizing_eval(obj);      
413         return item;
414 }
415
416 /**
417  * Remove an item from the dialogue group.
418  *
419  * @param obj dialoguegroup object 
420  * @param subobj item
421  *
422  * @ingroup DialogueGroup
423  */
424 EAPI void
425 elm_dialoguegroup_remove(Dialogue_Item *item)
426 {
427         ELM_CHECK_WIDTYPE(item->parent, widtype) ;
428         Dialogue_Item *current_item;
429         Widget_Data *wd = elm_widget_data_get(item->parent);
430         Eina_List *l;
431         
432         if (!wd || !wd->items || !item) return ;
433         
434         EINA_LIST_FOREACH(wd->items, l, current_item) {
435                 if (current_item == item) {
436                         if (current_item->content){
437                                 evas_object_del(current_item->content);
438                                 current_item->content = NULL;
439                         }
440                         if (current_item->bg_layout){
441                                 evas_object_del(current_item->bg_layout);
442                                 current_item->bg_layout = NULL;
443                         }
444                         elm_box_unpack(wd->box, current_item->bg_layout);                       
445                         wd->items = eina_list_remove(wd->items, current_item);
446                 }
447         }
448                 
449         wd->num--;
450         
451         if (wd->num == 0) return;
452         
453         if (wd->num == 1) {
454                 current_item = eina_list_data_get(wd->items);
455                 _change_item_bg(current_item, "default");
456         }
457
458         else {          
459                 current_item = eina_list_data_get(wd->items);
460                 _change_item_bg(current_item, "top");
461                 current_item = eina_list_data_get( eina_list_last(wd->items) );
462                 _change_item_bg(current_item, "bottom");                
463         }
464
465         _sizing_eval(item->parent);     
466 }
467
468 /**
469  * Remove all items from the dialogue group.
470  *
471  * @param obj dialoguegroup object 
472  *
473  * @ingroup DialogueGroup
474  */
475 EAPI void
476 elm_dialoguegroup_remove_all(Evas_Object *obj)
477 {
478         ELM_CHECK_WIDTYPE(obj, widtype);
479         _remove_all(obj);       
480         _sizing_eval(obj);      
481 }
482
483
484 /**
485  * Set the title text of the  dialogue group.
486  *
487  * @param obj dialoguegroup object 
488  * @param title title text, if NULL title space will be disappeared 
489  * 
490  * @ingroup DialogueGroup
491  */
492 EAPI void 
493 elm_dialoguegroup_title_set(Evas_Object *obj, const char *title)
494 {
495         ELM_CHECK_WIDTYPE(obj, widtype);
496         Widget_Data *wd = elm_widget_data_get(obj);
497         
498         if (!wd) return ;
499         eina_stringshare_replace(&wd->title, title);
500         if (!title) {
501                 wd->title = NULL;       
502                 elm_box_unpack(wd->box, wd->title_layout);              
503         }
504         if (!wd->title_layout) {
505                 wd->title_layout = elm_layout_add(wd->parent);
506                 elm_widget_sub_object_add(obj, wd->title_layout);
507                 elm_layout_theme_set(wd->title_layout, "dialoguegroup", "base", "title");
508                 evas_object_size_hint_weight_set(wd->title_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
509                 evas_object_size_hint_align_set(wd->title_layout, EVAS_HINT_FILL, 0.0);
510                 evas_object_show(wd->title_layout);     
511         }
512         edje_object_part_text_set(elm_layout_edje_get(wd->title_layout), "text", title);
513         elm_box_pack_start(wd->box, wd->title_layout);
514 }
515
516 /**
517  * Get the title text of the dialogue group
518  *
519  * @param obj The dialoguegroup object
520  * @return The text title string in UTF-8
521  *
522  * @ingroup DialogueGroup
523  */
524 EAPI const char *
525 elm_dialoguegroup_title_get(Evas_Object *obj)
526 {
527    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
528    Widget_Data *wd = elm_widget_data_get(obj);
529    if (!wd) return NULL;
530    return wd->title;
531 }
532
533 /**
534  * Set whether the press effect will be shown or not
535  *
536  * @param obj The dialoguegroup object
537  * @param item Dialogue_Item pointer
538  * @param press If set as 1, press effect will be shown 
539  *
540  * @ingroup DialogueGroup 
541  */
542 EAPI void 
543 elm_dialoguegroup_press_effect_set(Dialogue_Item *item, Eina_Bool press)
544 {
545    ELM_CHECK_WIDTYPE(item->parent, widtype) ;
546    if(!item) return;
547    
548    item->press = press;
549    if(press == EINA_TRUE)
550            edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,on", "elm");
551    else
552            edje_object_signal_emit(elm_layout_edje_get(item->bg_layout), "elm,state,press,off", "elm"); 
553 }
554
555 /**
556  * Get the press effect state
557  *
558  * @param obj The dialoguegroup object
559  * @param item Dialogue_Item pointer
560  * @return 1 if press effect on, 0 if press effect off 
561  *
562  * @ingroup DialogueGroup 
563  */
564 EAPI Eina_Bool
565 elm_dialoguegroup_press_effect_get(Dialogue_Item *item)
566 {
567    ELM_CHECK_WIDTYPE(item->parent, widtype) EINA_FALSE;
568    if(!item) return EINA_FALSE;
569    
570    return item->press;
571 }
572
573 /**
574  * Get the conetent object from the specified dialogue item
575  *
576  * @param obj The dialoguegroup object
577  * @param item Dialogue_Item pointer
578  * @return content object 
579  *
580  * @ingroup DialogueGroup 
581  */
582 EAPI Evas_Object *
583 elm_dialoguegroup_item_content_get(Dialogue_Item *item)
584 {
585    ELM_CHECK_WIDTYPE(item->parent, widtype) EINA_FALSE;
586    if(!item) return EINA_FALSE;
587    
588    return item->content;
589 }