Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[framework/uifw/elementary.git] / src / lib / elm_actionslider.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4 /*
5  * SLP
6  * Copyright (c) 2009 Samsung Electronics, Inc.
7  * All rights reserved.
8  *
9  * This software is a confidential and proprietary information
10  * of Samsung Electronics, Inc. ("Confidential Information").  You
11  * shall not disclose such Confidential Information and shall use
12  * it only in accordance with the terms of the license agreement
13  * you entered into with Samsung Electronics.
14  */
15
16 /**
17  *
18  * @defgroup Actionslider Actionslider
19  * @ingroup Elementary
20  *
21  * This is an actionslider.
22  */
23
24 #include <Elementary.h>
25 #include <math.h>
26 #include "elm_priv.h"
27
28 /**
29  * internal data structure of actionslider object
30  */
31 typedef struct _Widget_Data Widget_Data;
32
33 struct _Widget_Data
34 {
35    Evas_Object  *as;            // actionslider
36    Evas_Object  *icon;          // an icon for a button or a bar
37    Evas_Object  *icon_fake;             // an icon for a button or a bar
38
39    // setting
40    Elm_Actionslider_Magnet_Pos  magnet_position;
41    const char *text_left, *text_right, *text_center, *text_button;
42
43    // status
44    Eina_Bool    mouse_down;
45    Eina_Bool    mouse_hold;
46
47    // icon animation
48    Ecore_Animator       *icon_animator;
49    double               final_position;
50 };
51
52 static void _del_hook(Evas_Object *obj);
53 static void _theme_hook(Evas_Object *obj);
54 static void _disable_hook(Evas_Object *obj);
55 static void _sizing_eval(Evas_Object *obj);
56 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
57
58 /*
59  * callback functions
60  */
61 static void _icon_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
62 static void _icon_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
63 static void _icon_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
64
65 /*
66  * internal functions
67  */
68 static Eina_Bool _icon_animation(void *data);
69
70 static const char *widtype = NULL;
71
72
73 static void
74 _del_hook(Evas_Object *obj)
75 {
76    Widget_Data *wd = elm_widget_data_get(obj);
77
78    if(wd->icon) 
79      {
80         evas_object_del(wd->icon);
81         wd->icon = NULL;
82      }
83    if(wd->icon_fake) 
84      {
85         evas_object_del(wd->icon_fake);
86         wd->icon_fake = NULL;
87      }
88    if (wd->text_left) 
89      {
90         eina_stringshare_del(wd->text_left);
91      }
92    if (wd->text_right) 
93      {
94         eina_stringshare_del(wd->text_right);
95      }
96    if (wd->text_center) 
97      {
98         eina_stringshare_del(wd->text_center);
99      }
100    if (wd->text_button) 
101      {
102         eina_stringshare_del(wd->text_button);
103      }
104    if(wd->as) 
105      {
106         evas_object_smart_member_del(wd->as);
107         evas_object_del(wd->as);
108         wd->as = NULL;
109      }
110    free(wd);
111 }
112
113 static void
114 _theme_hook(Evas_Object *obj)
115 {
116    Widget_Data *wd = elm_widget_data_get(obj);
117
118    if (edje_object_part_swallow_get(wd->as, "elm.swallow.icon") == NULL) 
119      {
120         edje_object_part_unswallow(wd->as, wd->icon);
121      }
122    if (edje_object_part_swallow_get(wd->as, "elm.swallow.space") == NULL) 
123      {
124         edje_object_part_unswallow(wd->as, wd->icon_fake);
125      }
126
127    _elm_theme_object_set(obj, wd->as, "actionslider", "base", elm_widget_style_get(obj));
128    _elm_theme_object_set(obj, wd->icon, "actionslider", "icon", elm_widget_style_get(obj));
129    _elm_theme_object_set(obj, wd->icon_fake, "actionslider", "icon", elm_widget_style_get(obj));
130    edje_object_part_swallow(wd->as, "elm.swallow.icon", wd->icon);
131    edje_object_part_swallow(wd->as, "elm.swallow.space", wd->icon_fake);
132    edje_object_part_text_set(wd->as, "elm.text.left", wd->text_left);
133    edje_object_part_text_set(wd->as, "elm.text.right", wd->text_right);
134    edje_object_part_text_set(wd->as, "elm.text.center", wd->text_center);
135    edje_object_message_signal_process(wd->as);
136    //edje_object_scale_set(wd->as, elm_widget_scale_get(obj) * _elm_config->scale);
137    _sizing_eval(obj);
138 }
139
140 static void
141 _disable_hook(Evas_Object *obj)
142 {
143 //   Widget_Data *wd = elm_widget_data_get(obj);
144 /*
145            TODO
146    if (elm_widget_disabled_get(obj))
147      edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
148    else
149      edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm");
150 */
151 }
152
153 static void
154 _sizing_eval(Evas_Object *obj)
155 {
156 //   Widget_Data *wd = elm_widget_data_get(obj);
157 }
158
159 static void
160 _sub_del(void *data, Evas_Object *obj, void *event_info)
161 {
162 //   Widget_Data *wd = elm_widget_data_get(obj);
163 //   Evas_Object *sub = event_info;
164 }
165
166 static void
167 _icon_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
168 {
169    Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
170
171    wd->mouse_down = EINA_TRUE;
172 }
173
174 static void
175 _icon_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
176 {
177    Evas_Object *as = (Evas_Object *)data;
178    Widget_Data *wd = elm_widget_data_get(as);
179    double pos = 0.0;
180
181    elm_actionslider_hold(as, EINA_FALSE);
182    if (wd->mouse_down == EINA_FALSE) return;
183
184    edje_object_part_drag_value_get(wd->as, "elm.swallow.icon", &pos, NULL);
185
186    if (pos == 0.0) 
187      {
188         evas_object_smart_callback_call(as, "position", "left");
189      } 
190    else if (pos == 1.0) 
191      {
192         evas_object_smart_callback_call(as, "position", "right");
193
194      } 
195    else if (pos >= 0.495 && pos <= 0.505) 
196      {
197         evas_object_smart_callback_call(as, "position", "center");
198      }
199
200         /*
201          * TODO
202         if (    wd->type == ELM_ACTIONSLIDER_TYPE_BAR_GREEN ||
203                 wd->type == ELM_ACTIONSLIDER_TYPE_BAR_RED ) {
204                 if (pos == 1.0) {
205                         //edje_object_signal_emit(wd->as, "elm,show,bar,text,center", "elm");
206                         edje_object_signal_emit(wd->as, "elm,show,text,center", "elm");
207                 } else {
208                         //edje_object_signal_emit(wd->as, "elm,hide,bar,text,center", "elm");
209                         edje_object_signal_emit(wd->as, "elm,hide,text,center", "elm");
210                 }
211         }
212         */
213 }
214
215 static void
216 _icon_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
217 {
218    Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
219    double position = 0.0;
220
221    wd->mouse_down = EINA_FALSE;
222
223    if (wd->mouse_hold == EINA_FALSE) 
224      {
225         if (wd->magnet_position == ELM_ACTIONSLIDER_MAGNET_LEFT) 
226           {
227              wd->final_position = 0.0;
228           } 
229         else if (wd->magnet_position == ELM_ACTIONSLIDER_MAGNET_RIGHT) 
230           {
231              wd->final_position = 1.0;
232           } 
233         else if (wd->magnet_position == ELM_ACTIONSLIDER_MAGNET_CENTER) 
234           {
235              wd->final_position = 0.5;
236           } 
237         else if ( wd->magnet_position == ELM_ACTIONSLIDER_MAGNET_BOTH) 
238           {
239              edje_object_part_drag_value_get(wd->as, "elm.swallow.icon", &position, NULL);
240              if (position <= 0.5) 
241                {
242                   wd->final_position = 0.0;
243                } 
244              else 
245                {
246                   wd->final_position = 1.0;
247                }
248           }
249
250         wd->icon_animator = ecore_animator_add(_icon_animation, wd);
251      }
252 }
253
254 static Eina_Bool
255 _icon_animation(void *data)
256 {
257    Widget_Data *wd = (Widget_Data *)data;
258    double cur_position = 0.0, new_position = 0.0;
259    double move_amount = 0.05;
260    Eina_Bool flag_finish_animation = EINA_FALSE;
261
262    edje_object_part_drag_value_get(wd->as, "elm.swallow.icon", &cur_position, NULL);
263
264    if ( (wd->final_position == 0.0) ||
265          (wd->final_position == 0.5 && cur_position >= wd->final_position) ) 
266      {
267         new_position = cur_position - move_amount;
268         if (new_position <= wd->final_position) 
269           {
270              new_position = wd->final_position;
271              flag_finish_animation = EINA_TRUE;
272           }
273      } 
274    else if (    (wd->final_position == 1.0) ||
275          (wd->final_position == 0.5 && cur_position < wd->final_position) ) 
276      {
277         new_position = cur_position + move_amount;
278         if (new_position >= wd->final_position) 
279           {
280              new_position = wd->final_position;
281              flag_finish_animation = EINA_TRUE;
282              /*
283              // TODO
284              if (wd->type == ELM_ACTIONSLIDER_TYPE_BAR_GREEN ||
285                    wd->type == ELM_ACTIONSLIDER_TYPE_BAR_RED ) {
286                   edje_object_signal_emit(wd->as, "elm,show,bar,text,center", "elm");
287              }
288              */
289           }
290      }
291
292    edje_object_part_drag_value_set(wd->as, "elm.swallow.icon", new_position, 0.5);
293
294    if (flag_finish_animation == EINA_TRUE) 
295      {
296         return 0;
297      } 
298    else 
299      {
300         return 1;
301      }
302 }
303
304 /**
305  * Add a new actionslider to the parent.
306  *
307  * @param parent The parent object
308  * @return The new actionslider object or NULL if it cannot be created
309  *
310  * @ingroup Actionslider
311  */
312 EAPI Evas_Object *
313 elm_actionslider_add(Evas_Object *parent)
314 {
315    Evas_Object *obj;
316    Evas *e;
317    Widget_Data *wd = NULL;
318
319    wd = ELM_NEW(Widget_Data);
320    e = evas_object_evas_get(parent);
321    if (e == NULL) return NULL;
322    ELM_SET_WIDTYPE(widtype, "actionslider");
323    obj = elm_widget_add(e);
324    elm_widget_type_set(obj, "actionslider");
325    elm_widget_sub_object_add(parent, obj);
326    elm_widget_data_set(obj, wd);
327
328    elm_widget_del_hook_set(obj, _del_hook);
329    elm_widget_theme_hook_set(obj, _theme_hook);
330    elm_widget_disable_hook_set(obj, _disable_hook);
331
332    wd->mouse_down = EINA_FALSE;
333    wd->mouse_hold = EINA_FALSE;
334
335    // load background edj
336    wd->as = edje_object_add(e);
337    if(wd->as == NULL) 
338      {
339         printf("Cannot load actionslider edj!\n");
340         return NULL;
341      }
342    _elm_theme_object_set(obj, wd->as, "actionslider", "base", "default");
343    elm_widget_resize_object_set(obj, wd->as);
344
345    // load icon
346    wd->icon = edje_object_add(e);
347    if (wd->icon == NULL) 
348      {
349         printf("Cannot load acitionslider icon!\n");
350         return NULL;
351      }
352    evas_object_smart_member_add(wd->icon, obj);
353    _elm_theme_object_set(obj, wd->icon, "actionslider", "icon", "default");
354    edje_object_part_swallow(wd->as, "elm.swallow.icon", wd->icon);
355
356    wd->icon_fake = edje_object_add(e);
357    evas_object_smart_member_add(wd->icon_fake, obj);
358    _elm_theme_object_set(obj, wd->icon_fake, "actionslider", "icon", "default");
359    edje_object_part_swallow(wd->as, "elm.swallow.space", wd->icon_fake);
360
361    // event callbacks
362    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
363    evas_object_event_callback_add(wd->icon, EVAS_CALLBACK_MOUSE_DOWN, _icon_down_cb, obj);
364    evas_object_event_callback_add(wd->icon, EVAS_CALLBACK_MOUSE_MOVE, _icon_move_cb, obj);
365    evas_object_event_callback_add(wd->icon, EVAS_CALLBACK_MOUSE_UP, _icon_up_cb, obj);
366
367    return obj;
368 }
369
370 /*
371 EAPI Evas_Object *
372 elm_actionslider_add_with_set(Evas_Object *parent, Elm_Actionslider_Icon_Pos pos, Elm_Actionslider_Magnet_Pos magnet, const char* label_left, const char* label_center, const char* label_right)
373 {
374         Evas_Object *obj;
375
376         obj = elm_actionslider_add(parent);
377
378         elm_actionslider_icon_set(obj, pos);
379         elm_actionslider_magnet_set(obj, magnet);
380         if (label_left != NULL)
381                 elm_actionslider_label_set(obj, ELM_ACTIONSLIDER_LABEL_LEFT, label_left);
382         if (label_center != NULL)
383                 elm_actionslider_label_set(obj, ELM_ACTIONSLIDER_LABEL_CENTER, label_center);
384         if (label_right != NULL)
385                 elm_actionslider_label_set(obj, ELM_ACTIONSLIDER_LABEL_RIGHT, label_right);
386
387         return obj;
388 }
389 */
390
391 /**
392  * Set actionslider indicator position. 
393  *
394  * @param obj The actionslider object. 
395  * @param pos The position of the indicator.
396  * (ELM_ACTIONSLIDER_INDICATOR_LEFT, ELM_ACTIONSLIDER_INDICATOR_RIGHT,
397  *  ELM_ACTIONSLIDER_INDICATOR_CENTER)
398  *
399  * @ingroup Actionslider
400  */
401 EAPI void
402 elm_actionslider_indicator_pos_set(Evas_Object *obj, Elm_Actionslider_Indicator_Pos pos)
403 {
404    ELM_CHECK_WIDTYPE(obj, widtype);
405
406    Widget_Data *wd = elm_widget_data_get(obj);
407    double position = 0.0;
408
409    if (pos == ELM_ACTIONSLIDER_INDICATOR_LEFT) 
410      {
411         position = 0.0;
412      } 
413    else if (pos == ELM_ACTIONSLIDER_INDICATOR_RIGHT) 
414      {
415         position = 1.0;
416      } 
417    else if (pos == ELM_ACTIONSLIDER_INDICATOR_CENTER) 
418      {
419         position = 0.5;
420      } 
421    else 
422      {
423         position = 0.0;
424      }
425
426    edje_object_part_drag_value_set(wd->as, "elm.swallow.icon", position, 0.5);
427 }
428
429 /**
430  * Set actionslider magnet position. 
431  *
432  * @param obj The actionslider object. 
433  * @param pos The position of the magnet.
434  * (ELM_ACTIONSLIDER_MAGNET_LEFT, ELM_ACTIONSLIDER_MAGNET_RIGHT,
435  *  ELM_ACTIONSLIDER_MAGNET_BOTH, ELM_ACTIONSLIDER_MAGNET_CENTER)
436  *
437  * @ingroup Actionslider
438  */
439 EAPI void
440 elm_actionslider_magnet_pos_set(Evas_Object *obj, Elm_Actionslider_Magnet_Pos pos)
441 {
442    ELM_CHECK_WIDTYPE(obj, widtype);
443    Widget_Data *wd = elm_widget_data_get(obj);
444    wd->magnet_position = pos;
445 }
446
447 /**
448  * Set actionslider label.
449  *
450  * @param obj The actionslider object
451  * @param pos The position of the label.
452  * (ELM_ACTIONSLIDER_LABEL_LEFT, ELM_ACTIONSLIDER_LABEL_RIGHT)
453  * @param label The label which is going to be set.
454  *
455  * @ingroup Actionslider
456  */
457 EAPI void 
458 elm_actionslider_label_set(Evas_Object *obj, Elm_Actionslider_Label_Pos pos, const char *label)
459 {
460    ELM_CHECK_WIDTYPE(obj, widtype);
461    Widget_Data *wd = elm_widget_data_get(obj);
462
463    if(label == NULL) 
464      {
465         label = "";
466      }
467
468    if (pos == ELM_ACTIONSLIDER_LABEL_RIGHT) 
469      {
470         if (wd->text_right) 
471           {
472              eina_stringshare_del(wd->text_right);
473           }
474         wd->text_right = eina_stringshare_add(label);
475         edje_object_part_text_set(wd->as, "elm.text.right", label);
476      } 
477    else if (pos == ELM_ACTIONSLIDER_LABEL_LEFT) 
478      {
479         if (wd->text_left) 
480           {
481              eina_stringshare_del(wd->text_left);
482           }
483         wd->text_left = eina_stringshare_add(label);
484         edje_object_part_text_set(wd->as, "elm.text.left", label);
485      } 
486    else if (pos == ELM_ACTIONSLIDER_LABEL_CENTER) 
487      {
488         if (wd->text_center) 
489           {
490              eina_stringshare_del(wd->text_center);
491           }
492         wd->text_center = eina_stringshare_add(label);
493         edje_object_part_text_set(wd->as, "elm.text.center", label);
494      }
495    else if (pos == ELM_ACTIONSLIDER_LABEL_BUTTON)
496      {
497         if (wd->text_button)
498           {
499              eina_stringshare_del(wd->text_button);
500           }
501         wd->text_button = eina_stringshare_add(label);
502         edje_object_part_text_set(wd->icon, "elm.text.button", label);
503
504         /* Resize button width */
505         Evas_Object *txt;
506         txt = (Evas_Object *)edje_object_part_object_get (wd->icon, "elm.text.button");
507         if (txt != NULL) 
508           {
509              evas_object_text_text_set (txt, wd->text_button);
510
511              Evas_Coord x,y,w,h;
512              evas_object_geometry_get (txt, &x,&y,&w,&h);
513
514              char *data_left = NULL, *data_right = NULL;
515              int pad_left = 0, pad_right = 0;
516
517              data_left = (char *)edje_object_data_get (wd->icon, "left");
518              data_right = (char *)edje_object_data_get (wd->icon, "right");
519
520              if (data_left) pad_left = atoi(data_left);
521              if (data_right) pad_right = atoi(data_right);
522
523              evas_object_size_hint_min_set (wd->icon, w + pad_left + pad_right, 0);
524              evas_object_size_hint_min_set (wd->icon_fake, w + pad_left + pad_right, 0);
525           }
526      }
527
528 }
529
530 /**
531  * Hold actionslider object movement.
532  *
533  * @param obj The actionslider object
534  * @param flag Actionslider hold/release
535  * (EINA_TURE = hold/EIN_FALSE = release)
536  *
537  * @ingroup Actionslider
538  */
539 EAPI void
540 elm_actionslider_hold(Evas_Object *obj, Eina_Bool flag)
541 {
542    ELM_CHECK_WIDTYPE(obj, widtype);
543    Widget_Data *wd = elm_widget_data_get(obj);
544
545    wd->mouse_hold = flag;
546 }