Merge "[entry] fixed bug in getting geometry of wd->scroller"
[framework/uifw/elementary.git] / src / lib / elm_slidingdrawer.c
1 /*
2  * @defgroup SlidingDrawer SlidingDrawer
3  * @ingroup Elementary
4  *
5  * This is a slidingdrawer.
6  */
7
8 #include <Elementary.h>
9 #include "elm_priv.h"
10
11 typedef struct _Widget_Data Widget_Data;
12
13 struct _Widget_Data
14 {
15    Evas_Object *parent;
16    Evas_Object *base;
17    Evas_Object *handler;
18    Evas_Object *dragable_rect;
19    Elm_SlidingDrawer_Pos pos;
20    double max_drag_w;
21    double max_drag_h;
22    Elm_SlidingDrawer_Drag_Value value;
23 };
24
25 static const char *widtype = NULL;
26
27 static void _del_hook(Evas_Object *obj);
28
29 static void _theme_hook(Evas_Object *obj);
30
31 static void _sizing_eval(Evas_Object *obj);
32
33 static void _parent_resize(void *data, Evas * e, Evas_Object *obj, void *event_info);
34 static void _drag_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
35 static void _up_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
36 static void _down_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
37
38 static void
39 _del_hook(Evas_Object *obj)
40 {
41    Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj);
42
43    evas_object_event_callback_del(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize);
44    free(wd);
45 }
46
47 static void \r
48 _theme_hook(Evas_Object *obj)
49 {
50    Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj);
51
52    elm_slidingdrawer_pos_set(obj, wd->pos);
53 }
54
55 static void
56 _parent_resize(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
57 {
58    _sizing_eval(data);
59 }
60
61 static void
62 _drag_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
63 {
64    Widget_Data *wd = elm_widget_data_get(data);
65
66    edje_object_part_drag_value_get(wd->base, "elm.dragable.handler", &wd->value.x, &wd->value.y);
67    evas_object_smart_callback_call(data, "mouse,move", (void *)&wd->value);
68 }
69
70 static void
71 _up_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
72 {
73    Widget_Data *wd = elm_widget_data_get(data);
74
75    edje_object_part_drag_value_get(wd->base, "elm.dragable.handler", &wd->value.x, &wd->value.y);
76    evas_object_smart_callback_call(data, "mouse,up", (void *)&wd->value);
77 }
78
79 static void
80 _down_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
81 {
82    Widget_Data *wd = elm_widget_data_get(data);
83
84    edje_object_part_drag_value_get(wd->base, "elm.dragable.handler", &wd->value.x, &wd->value.y);
85    evas_object_smart_callback_call(data, "mouse,down", (void *)&wd->value);
86 }
87
88 static void
89 _sizing_eval(Evas_Object *obj)
90 {
91    Widget_Data *wd;
92
93    Evas_Coord x, y, w, h;
94
95    const Evas_Object *part;
96
97    wd = elm_widget_data_get(obj);
98
99    evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
100    evas_object_move(obj, x, y);
101    evas_object_resize(obj, w, h);
102
103    evas_object_size_hint_max_set(wd->dragable_rect, ((double)w) * wd->max_drag_w, ((double)h) * wd->max_drag_h);
104
105    part = edje_object_part_object_get(wd->base, "elm.dragable.handler");
106
107    if ((wd->pos == ELM_SLIDINGDRAWER_TOP)
108        || (wd->pos == ELM_SLIDINGDRAWER_BOTTOM))
109      edje_object_size_min_get(part, NULL, &h);
110    else
111      edje_object_size_min_get(part, &w, NULL);
112
113    evas_object_size_hint_min_set(wd->handler, w, h);
114 }
115
116 /**
117  * Unswallow the user content
118  *
119  * @param[in] obj               SlidingDrawer object
120  * @return              The unswallowed contents
121  *
122  * @ingroup SlidingDrawer
123  */
124 EAPI Evas_Object *
125 elm_slidingdrawer_content_unset(Evas_Object *obj)
126 {
127    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
128    Widget_Data *wd;
129    Evas_Object *content;
130    wd = elm_widget_data_get(obj);
131    content = edje_object_part_swallow_get(wd->base, "elm.swallow.content");
132    if (!content)
133       return NULL;
134    edje_object_part_unswallow(wd->base, content);
135    elm_widget_sub_object_del(obj, content);
136    return content;
137 }
138
139 /**
140  * Swallow the user contents
141  *
142  * @param[in] obj               SlidingDrawer object
143  * @param[in] content           Content to be swallowed.
144  *
145  * @ingroup SlidingDrawer
146  */
147 EAPI void
148 elm_slidingdrawer_content_set(Evas_Object *obj, Evas_Object *content){
149    ELM_CHECK_WIDTYPE(obj, widtype);
150    Widget_Data *wd;
151    Evas_Object *prev_content;
152    if (!content) return;
153    wd = elm_widget_data_get(obj);
154    elm_widget_sub_object_add(obj, content);
155    prev_content = edje_object_part_swallow_get(wd->base, "elm.swallow.content");
156    if (prev_content)
157      {
158         edje_object_part_unswallow(wd->base, prev_content);
159         elm_widget_sub_object_del(obj, prev_content);
160         evas_object_del(prev_content);
161      }
162    edje_object_part_swallow(wd->base, "elm.swallow.content", content);
163 }
164
165 /**
166  * Set the position of SlidingDrawer
167  *
168  * @param[in] obj               SlidingDrawer object
169  * @param[in] pos               Position of drawer's handle
170  *
171  * @ingroup SlidingDrawer
172  */
173 EAPI void
174 elm_slidingdrawer_pos_set(Evas_Object *obj, Elm_SlidingDrawer_Pos pos)
175 {
176    ELM_CHECK_WIDTYPE(obj, widtype);
177
178    Widget_Data *wd = elm_widget_data_get(obj);
179
180    switch (pos)
181      {
182       case ELM_SLIDINGDRAWER_BOTTOM:
183          _elm_theme_object_set(obj, wd->base, "slidingdrawer", "bottom", elm_widget_style_get(obj));
184          break;
185       case ELM_SLIDINGDRAWER_LEFT:
186          _elm_theme_object_set(obj, wd->base, "slidingdrawer", "left", elm_widget_style_get(obj));
187          break;
188       case ELM_SLIDINGDRAWER_RIGHT:
189          _elm_theme_object_set(obj, wd->base, "slidingdrawer", "right", elm_widget_style_get(obj));
190          break;
191       case ELM_SLIDINGDRAWER_TOP:
192          _elm_theme_object_set(obj, wd->base, "slidingdrawer", "top", elm_widget_style_get(obj));
193          break;
194      }
195
196    edje_object_part_drag_value_set(wd->base, "elm.dragable.handler", 0, 0);
197    wd->pos = pos;
198    _sizing_eval(obj);
199 }
200
201 /**
202  * Set the current dragable value.
203  *
204  * @param[in] obj               SlidingDrawer object
205  * @param[in] dx                The x value (range: 0 ~ 1)
206  * @param[in] dy            The y value (range: 0 ~ 1)
207  *
208  * @ingroup SlidingDrawer
209  */
210 EAPI void
211 elm_slidingdrawer_drag_value_set(Evas_Object *obj, double dx, double dy)
212 {
213    ELM_CHECK_WIDTYPE(obj, widtype);
214    Widget_Data *wd;
215
216    wd = elm_widget_data_get(obj);
217    edje_object_part_drag_value_set(wd->base, "elm.dragable.handler", dx, dy);
218 }
219
220 /**
221  * Set the dragable max value.
222  *
223  * @param[in] obj               SlidingDrawer object
224  * @param[in] dw                The maximum width value (range: 0 ~ 1)
225  * @param[in] dh                The maximum height value (range: 0 ~ 1)
226  *
227  * @ingroup SlidingDrawer
228  */
229 EAPI void
230 elm_slidingdrawer_max_drag_value_set(Evas_Object *obj, double dw, double dh)
231 {
232    ELM_CHECK_WIDTYPE(obj, widtype);
233    Widget_Data *wd;
234
235    wd = elm_widget_data_get(obj);
236    wd->max_drag_w = dw;
237    wd->max_drag_h = dh;
238    _sizing_eval(obj);
239
240 }
241
242 /**
243  * Add a new slidingdrawer object to the parent.
244  *
245  * @param[in] parent    Parent object
246  * @return              New object or NULL if it cannot be created
247  *
248  * @ingroup SlidingDrawer
249  */
250 EAPI Evas_Object *
251 elm_slidingdrawer_add(Evas_Object *parent)
252 {
253    Evas_Object *obj;
254    Evas *e;
255    Widget_Data *wd;
256
257    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
258
259    wd->parent = parent;
260    ELM_SET_WIDTYPE(widtype, "slidingdrawer");
261    elm_widget_type_set(obj, "slidingdrawer");
262    elm_widget_can_focus_set(obj, EINA_FALSE);
263    elm_widget_sub_object_add(parent, obj);
264    elm_widget_data_set(obj, wd);
265    elm_widget_del_hook_set(obj, _del_hook);
266    elm_widget_theme_hook_set(obj, _theme_hook);
267
268    //base
269    wd->base = edje_object_add(e);
270    _elm_theme_object_set(obj, wd->base, "slidingdrawer", "bottom", "default");
271    edje_object_signal_callback_add(wd->base, "drag", "*", _drag_cb, obj);
272    edje_object_signal_callback_add(wd->base, "mouse,up,*", "*", _up_cb, obj);
273    edje_object_signal_callback_add(wd->base, "mouse,down,*", "*", _down_cb, obj);
274    elm_widget_sub_object_add(obj, wd->base);
275    elm_widget_resize_object_set(obj, wd->base);
276
277    //dragable_rect
278    wd->dragable_rect = evas_object_rectangle_add(e);
279    elm_widget_sub_object_add(obj, wd->dragable_rect);
280    edje_object_part_swallow(wd->base, "elm.swallow.dragable_rect", wd->dragable_rect);
281    wd->max_drag_w = 1;
282    wd->max_drag_h = 1;
283
284    //handler
285    wd->handler = evas_object_rectangle_add(e);
286    elm_widget_sub_object_add(obj, wd->handler);
287    evas_object_color_set(wd->handler, 0, 0, 0, 0);
288    edje_object_part_swallow(wd->base, "elm.dragable.handler", wd->handler);
289
290    evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj);
291
292    _sizing_eval(obj);
293
294    return obj;
295 }