[elm_dialoguegroup] modified for editfield design
[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, *new_item; 
257         
258         if (!wd || !subobj) return NULL;
259         
260         if (!wd->items) 
261                 new_item = _create_item(obj, subobj, style, "default"); 
262
263         else {
264                 if (wd->num == 1) {     
265                         item = eina_list_data_get(wd->items);
266                         _change_item_bg(item, "top");           
267                 }               
268                 else {
269                         item = eina_list_data_get( eina_list_last(wd->items) );
270                         _change_item_bg(item, "middle");                
271                 }
272                 new_item = _create_item(obj, subobj, style, "bottom");
273                 _set_line_show(item, new_item);
274         }
275         elm_box_pack_end(wd->box, new_item->bg_layout);
276         wd->items = eina_list_append(wd->items, new_item);                      
277         wd->num++;
278         _sizing_eval(obj);
279         return new_item;
280 }
281
282
283 /**
284  * Prepend an item to the dialogue group.
285  *
286  * @param obj dialoguegroup object 
287  * @param subobj item
288  * @return Dialogue_Item pointer, just made by this function
289  *
290  * @ingroup DialogueGroup
291  */
292 EAPI Dialogue_Item *
293 elm_dialoguegroup_prepend(Evas_Object *obj, Evas_Object *subobj, Elm_Dialoguegroup_Item_Style style)
294 {
295         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
296         Widget_Data *wd = elm_widget_data_get(obj);
297         Dialogue_Item *item, *new_item;
298         
299         if (!wd || !subobj) return NULL;
300         
301         if (!wd->items) 
302                 new_item = _create_item(obj, subobj, style, "default"); 
303
304         else {
305                 if (wd->num == 1) {     
306                         item = eina_list_data_get(wd->items);
307                         _change_item_bg(item, "bottom");
308                 }               
309                 else {
310                         item = eina_list_data_get(wd->items);
311                         _change_item_bg(item, "middle");                
312                 }
313                 new_item = _create_item(obj, subobj, style, "top");
314                 _set_line_show(new_item, item);
315         }
316         if(wd->title_layout)
317                 elm_box_pack_after(wd->box, item->bg_layout, wd->title_layout); 
318         else                    
319                 elm_box_pack_start(wd->box, item->bg_layout);           
320         wd->items = eina_list_prepend(wd->items, item);         
321         wd->num++;
322         _sizing_eval(obj);
323         return item;
324 }
325
326 /**
327  * Insert an item to the dialogue group just after the specified item.
328  *
329  * @param obj dialoguegroup object 
330  * @param subobj item
331  * @param after specified item existing in the dialogue group
332  * @return Dialogue_Item pointer, just made by this function
333  *
334  * @ingroup DialogueGroup
335  */
336 EAPI Dialogue_Item * 
337 elm_dialoguegroup_insert_after(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *after, Elm_Dialoguegroup_Item_Style style)
338 {
339         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
340         Widget_Data *wd = elm_widget_data_get(obj);
341         Dialogue_Item *after_item, *item = NULL;
342         Eina_List *l;
343
344         if (!wd || !subobj || !after || !wd->items) return NULL;
345
346         EINA_LIST_FOREACH(wd->items, l, after_item) {
347                 if(after == after_item) {
348                         if( !strcmp(item->location, "default") ) {
349                                 _change_item_bg(after_item, "top");
350                                 item = _create_item(obj, subobj, style, "bottom");
351                         }                       
352                         else if( !strcmp(item->location, "top") || !strcmp(item->location, "middle") )  
353                                 item = _create_item(obj, subobj, style, "middle");              
354                         else if( !strcmp(item->location, "bottom") ) {
355                                 _change_item_bg(after_item, "middle");
356                                 item = _create_item(obj, subobj, style, "bottom");              
357                         }
358
359                         elm_box_pack_after(wd->box, item->bg_layout, after_item->bg_layout);
360                         wd->items = eina_list_append_relative(wd->items, item, after_item);
361                         _set_line_show(item, after);
362                 }               
363         }
364                 
365         wd->num++;
366         _sizing_eval(obj);
367         return item;
368 }
369
370 /**
371  * Insert an item to the dialogue group just before the specified item.
372  *
373  * @param obj dialoguegroup object 
374  * @param subobj item
375  * @param before specified item existing in the dialogue group
376  * @return Dialogue_Item pointer, just made by this function
377  *
378  * @ingroup DialogueGroup
379  */
380 EAPI Dialogue_Item *
381 elm_dialoguegroup_insert_before(Evas_Object *obj, Evas_Object *subobj, Dialogue_Item *before, Elm_Dialoguegroup_Item_Style style)
382 {
383         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
384         Widget_Data *wd = elm_widget_data_get(obj);
385         Dialogue_Item *before_item, *item = NULL;
386         Eina_List *l;
387         
388         if (!wd || !subobj || !before || !wd->items) return NULL;
389
390         EINA_LIST_FOREACH(wd->items, l, before_item) {
391                 if(before == before_item) {
392                         if( !strcmp(item->location, "default") ) {
393                                 _change_item_bg(before_item, "bottom");
394                                 item = _create_item(obj, subobj, style, "top");
395                         }
396                                 
397                         else if( !strcmp(item->location, "top") ) {
398                                 _change_item_bg(before_item, "middle");
399                                 item = _create_item(obj, subobj, style, "top");                 
400                         }
401
402                         else if( !strcmp(item->location, "middle") || !strcmp(item->location, "bottom") )
403                                 item = _create_item(obj, subobj, style, "middle");
404
405                         elm_box_pack_before(wd->box, item->bg_layout, before_item->bg_layout);
406                         wd->items = eina_list_prepend_relative(wd->items, item, before_item);
407                         _set_line_show(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 }