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