ee0e67a880673b92c39174c6b61f2743f2a11de3
[framework/uifw/elementary.git] / src / lib / elm_panel.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_panel.h"
4
5 EAPI const char ELM_PANEL_SMART_NAME[] = "elm_panel";
6
7 static const char ACCESS_OUTLINE_PART[] = "access.outline";
8
9 static const char SIG_SCROLL[] = "scroll";
10
11 static const Evas_Smart_Cb_Description _smart_callbacks[] =
12 {
13    {SIG_SCROLL, ""}
14 };
15
16 static const Evas_Smart_Interface *_smart_interfaces[] =
17 {
18    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
19 };
20
21 EVAS_SMART_SUBCLASS_IFACE_NEW
22   (ELM_PANEL_SMART_NAME, _elm_panel, Elm_Panel_Smart_Class,
23    Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks,
24    _smart_interfaces);
25
26 static void
27 _mirrored_set(Evas_Object *obj,
28               Eina_Bool rtl)
29 {
30    ELM_PANEL_DATA_GET(obj, sd);
31
32    elm_widget_mirrored_set(sd->bx, rtl);
33    elm_panel_orient_set(obj, elm_panel_orient_get(obj));
34 }
35
36 static void
37 _elm_panel_smart_sizing_eval(Evas_Object *obj)
38 {
39    Evas_Coord mw = -1, mh = -1;
40
41    ELM_PANEL_DATA_GET(obj, sd);
42
43    if (sd->on_deletion) return;
44
45    evas_object_smart_calculate(sd->bx);
46    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh);
47    evas_object_size_hint_min_set(obj, mw, mh);
48    evas_object_size_hint_max_set(obj, -1, -1);
49 }
50
51 static char *
52 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
53 {
54    ELM_PANEL_DATA_GET(data, sd);
55
56    if (!sd->hidden) return strdup(E_("state: opened"));
57    else return strdup(E_("state: closed"));
58
59    return NULL;
60 }
61
62 static Evas_Object *
63 _access_object_get(const Evas_Object *obj, const char *part)
64 {
65    Evas_Object *po, *ao;
66    ELM_PANEL_DATA_GET(obj, sd);
67
68    po = (Evas_Object *)edje_object_part_object_get
69       (elm_layout_edje_get(sd->scr_ly), part);
70    ao = evas_object_data_get(po, "_part_access_obj");
71
72    return ao;
73 }
74
75 static void
76 _access_activate_cb(void *data,
77                     Evas_Object *part_obj __UNUSED__,
78                     Elm_Object_Item *item __UNUSED__)
79 {
80    elm_panel_hidden_set(data, EINA_TRUE);
81 }
82
83 static void
84 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
85 {
86    Evas_Object *ao;
87    ELM_PANEL_DATA_GET(obj, sd);
88
89    if (is_access)
90      {
91         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
92         if (!ao)
93           {
94              ao = _elm_access_edje_object_part_object_register
95                 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
96              _elm_access_text_set(_elm_access_object_get(ao),
97                                   ELM_ACCESS_TYPE, E_("A drawer is open"));
98              _elm_access_text_set(_elm_access_object_get(ao),
99                                   ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close drawer menu"));
100              _elm_access_activate_callback_set
101                 (_elm_access_object_get(ao), _access_activate_cb, obj);
102           }
103      }
104    else
105      {
106         _elm_access_edje_object_part_object_unregister
107            (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
108      }
109 }
110
111 static void
112 _orient_set_do(Evas_Object *obj)
113 {
114    ELM_PANEL_DATA_GET(obj, sd);
115
116    switch (sd->orient)
117      {
118       case ELM_PANEL_ORIENT_TOP:
119         elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
120         break;
121
122       case ELM_PANEL_ORIENT_BOTTOM:
123         elm_layout_theme_set
124           (obj, "panel", "bottom", elm_widget_style_get(obj));
125         break;
126
127       case ELM_PANEL_ORIENT_LEFT:
128         if (!elm_widget_mirrored_get(obj))
129           elm_layout_theme_set
130             (obj, "panel", "left", elm_widget_style_get(obj));
131         else
132           elm_layout_theme_set
133             (obj, "panel", "right", elm_widget_style_get(obj));
134         break;
135
136       case ELM_PANEL_ORIENT_RIGHT:
137         if (!elm_widget_mirrored_get(obj))
138           elm_layout_theme_set
139             (obj, "panel", "right", elm_widget_style_get(obj));
140         else
141           elm_layout_theme_set
142             (obj, "panel", "left", elm_widget_style_get(obj));
143         break;
144      }
145
146    /* access */
147    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
148      {
149         Evas_Object *ao;
150         ao = _elm_access_edje_object_part_object_register
151                (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
152         _elm_access_text_set(_elm_access_object_get(ao),
153                              ELM_ACCESS_TYPE, E_("panel button"));
154         _elm_access_callback_set
155           (_elm_access_object_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
156      }
157 }
158
159 static void
160 _scrollable_layout_theme_set(Evas_Object *obj, Elm_Panel_Smart_Data *sd)
161 {
162    switch (sd->orient)
163      {
164       case ELM_PANEL_ORIENT_TOP:
165          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/top",
166                                    elm_widget_style_get(obj)))
167            CRITICAL("Failed to set layout!");
168          break;
169       case ELM_PANEL_ORIENT_BOTTOM:
170          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/bottom",
171                                    elm_widget_style_get(obj)))
172            CRITICAL("Failed to set layout!");
173          break;
174       case ELM_PANEL_ORIENT_LEFT:
175          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/left",
176                                    elm_widget_style_get(obj)))
177            CRITICAL("Failed to set layout!");
178          break;
179       case ELM_PANEL_ORIENT_RIGHT:
180          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/right",
181                                    elm_widget_style_get(obj)))
182            CRITICAL("Failed to set layout!");
183          break;
184      }
185
186    /* access */
187    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
188      _access_obj_process(obj, EINA_TRUE);
189 }
190
191 static Eina_Bool
192 _elm_panel_smart_theme(Evas_Object *obj)
193 {
194    const char *str;
195
196    ELM_PANEL_DATA_GET(obj, sd);
197
198    if (!ELM_WIDGET_CLASS(_elm_panel_parent_sc)->theme(obj))
199      return EINA_FALSE;
200
201    _mirrored_set(obj, elm_widget_mirrored_get(obj));
202
203    if (sd->scrollable)
204      {
205         const char *handler_size;
206         elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
207                                     elm_widget_style_get(obj));
208         _scrollable_layout_theme_set(obj, sd);
209
210         handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
211         if (handler_size)
212           sd->handler_size = (Evas_Coord) (elm_object_scale_get(obj)) * (atoi(handler_size));
213      }
214    else
215      {
216         str = edje_object_data_get
217            (ELM_WIDGET_DATA(sd)->resize_obj, "focus_highlight");
218         if ((str) && (!strcmp(str, "on")))
219           elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
220         else
221           elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
222
223         _orient_set_do(obj);
224      }
225
226    elm_layout_sizing_eval(obj);
227
228    return EINA_TRUE;
229 }
230
231 static Eina_Bool
232 _elm_panel_smart_focus_next(const Evas_Object *obj,
233                             Elm_Focus_Direction dir,
234                             Evas_Object **next)
235 {
236    Evas_Object *cur;
237    Eina_List *items = NULL;
238    Eina_Bool ret = EINA_FALSE;
239
240    ELM_PANEL_DATA_GET(obj, sd);
241
242    if (!sd->content)
243      return EINA_FALSE;
244
245    if (sd->scrollable)
246      {
247         if (sd->hidden) return EINA_FALSE;
248
249         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
250           {
251              Evas_Object *ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
252              if (ao) items = eina_list_append(items, ao);
253              items = eina_list_append(items, sd->content);
254
255              ret = elm_widget_focus_list_next_get
256                 (obj, items, eina_list_data_get, dir, next);
257              eina_list_free(items);
258
259              return ret;
260           }
261
262         return elm_widget_focus_next_get(sd->content, dir, next);
263      }
264
265    cur = sd->content;
266
267    /* Try to Focus cycle in subitem */
268    if (!sd->hidden)
269      return elm_widget_focus_next_get(cur, dir, next);
270
271    /* access */
272    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
273      {
274         Evas_Object *ao, *po;
275         po = (Evas_Object *)edje_object_part_object_get
276                (ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
277         ao = evas_object_data_get(po, "_part_access_obj");
278         _elm_access_highlight_set(ao, EINA_FALSE);
279      }
280
281    /* Return */
282    *next = (Evas_Object *)obj;
283    return !elm_widget_focus_get(obj);
284 }
285
286 static void
287 _box_layout_cb(Evas_Object *o,
288                Evas_Object_Box_Data *priv,
289                void *data __UNUSED__)
290 {
291    _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE);
292 }
293
294 static void
295 _handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
296 {
297    ELM_PANEL_DATA_GET(obj, sd);
298
299    if (sd->handler_size == 0) return;
300
301    switch (sd->orient)
302      {
303       case ELM_PANEL_ORIENT_TOP:
304          sd->s_iface->region_bring_in
305             (obj, 0, (h * sd->content_size_ratio) - sd->handler_size, w, h);
306          break;
307       case ELM_PANEL_ORIENT_BOTTOM:
308          sd->s_iface->region_bring_in
309             (obj, 0, sd->handler_size, w, h);
310          break;
311       case ELM_PANEL_ORIENT_LEFT:
312          sd->s_iface->region_bring_in
313             (obj, (w * sd->content_size_ratio) - sd->handler_size, 0, w, h);
314          break;
315       case ELM_PANEL_ORIENT_RIGHT:
316          sd->s_iface->region_bring_in
317             (obj, sd->handler_size, 0, w, h);
318          break;
319      }
320 }
321
322 static void
323 _drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
324 {
325    ELM_PANEL_DATA_GET(obj, sd);
326    Evas_Coord x = 0, y = 0;
327
328    if (sd->freeze)
329      {
330         sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
331         sd->freeze = EINA_FALSE;
332         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
333         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
334      }
335
336    switch (sd->orient)
337      {
338       case ELM_PANEL_ORIENT_TOP:
339       case ELM_PANEL_ORIENT_LEFT:
340          break;
341
342       case ELM_PANEL_ORIENT_BOTTOM:
343          y = h * sd->content_size_ratio;
344          break;
345
346       case ELM_PANEL_ORIENT_RIGHT:
347          x = w * sd->content_size_ratio;
348          break;
349      }
350
351    if (anim) sd->s_iface->region_bring_in(obj, x, y, w, h);
352    else sd->s_iface->content_region_show(obj, x, y, w, h);
353 }
354
355 static void
356 _drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
357 {
358    ELM_PANEL_DATA_GET(obj, sd);
359    Evas_Coord x = 0, y = 0;
360    Eina_Bool horizontal = EINA_FALSE;
361
362    switch (sd->orient)
363      {
364       case ELM_PANEL_ORIENT_TOP:
365          y = h * sd->content_size_ratio;
366          break;
367
368       case ELM_PANEL_ORIENT_LEFT:
369          x = w * sd->content_size_ratio;
370          horizontal = EINA_TRUE;
371          break;
372
373       case ELM_PANEL_ORIENT_BOTTOM:
374          break;
375       case ELM_PANEL_ORIENT_RIGHT:
376          horizontal = EINA_TRUE;
377          break;
378      }
379
380    if (anim)
381      {
382         if (sd->freeze)
383           {
384              sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
385              sd->freeze = EINA_FALSE;
386              elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
387              elm_object_signal_emit(obj, "elm,state,unhold", "elm");
388           }
389         sd->s_iface->region_bring_in(obj, x, y, w, h);
390      }
391    else
392      {
393         sd->s_iface->content_region_show(obj, x, y, w, h);
394         if (!sd->freeze)
395           {
396              if (horizontal)
397                sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
398              else
399                sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
400              sd->freeze = EINA_TRUE;
401              elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
402              elm_object_signal_emit(obj, "elm,state,hold", "elm");
403           }
404      }
405 }
406
407 static void
408 _panel_toggle(void *data __UNUSED__,
409               Evas_Object *obj,
410               const char *emission __UNUSED__,
411               const char *source __UNUSED__)
412 {
413    ELM_PANEL_DATA_GET(obj, sd);
414
415    Evas_Coord w, h;
416
417    if (sd->scrollable)
418      {
419         if (elm_widget_disabled_get(obj)) return;
420
421         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
422         if (sd->hidden)
423           {
424              sd->hidden = EINA_FALSE;
425              _drawer_open(obj, w, h, EINA_TRUE);
426              elm_object_signal_emit(obj, "elm,state,active", "elm");
427           }
428         else
429           {
430              sd->hidden = EINA_TRUE;
431              _drawer_close(obj, w, h, EINA_TRUE);
432              elm_object_signal_emit(obj, "elm,state,inactive", "elm");
433           }
434      }
435    else
436      {
437         if (sd->hidden)
438           {
439              elm_layout_signal_emit(obj, "elm,action,show", "elm");
440              sd->hidden = EINA_FALSE;
441              evas_object_repeat_events_set(obj, EINA_FALSE);
442           }
443         else
444           {
445              elm_layout_signal_emit(obj, "elm,action,hide", "elm");
446              sd->hidden = EINA_TRUE;
447              evas_object_repeat_events_set(obj, EINA_TRUE);
448              if (elm_widget_focus_get(sd->content))
449                {
450                   elm_widget_focused_object_clear(obj);
451                   elm_widget_focus_steal(obj);
452                }
453           }
454
455         edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj);
456      }
457 }
458
459 static Eina_Bool
460 _state_sync(Evas_Object *obj)
461 {
462    ELM_PANEL_DATA_GET(obj, sd);
463    Evas_Object *ao;
464    Evas_Coord pos, panel_size, w, h;
465    Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE;
466    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
467
468    switch (sd->orient)
469      {
470       case ELM_PANEL_ORIENT_TOP:
471          panel_size = h * sd->content_size_ratio;
472          sd->s_iface->content_pos_get(obj, NULL, &pos);
473
474          if (pos == 0) open = EINA_TRUE;
475          else if (pos == panel_size) open = EINA_FALSE;
476          else return EINA_FALSE;
477          break;
478
479       case ELM_PANEL_ORIENT_BOTTOM:
480          panel_size = h * sd->content_size_ratio;
481          sd->s_iface->content_pos_get(obj, NULL, &pos);
482
483          if (pos == panel_size) open = EINA_TRUE;
484          else if (pos == 0) open = EINA_FALSE;
485          else return EINA_FALSE;
486          break;
487
488       case ELM_PANEL_ORIENT_LEFT:
489          panel_size = w * sd->content_size_ratio;
490          sd->s_iface->content_pos_get(obj, &pos, NULL);
491          horizontal = EINA_TRUE;
492
493          if (pos == 0) open = EINA_TRUE;
494          else if (pos == panel_size) open = EINA_FALSE;
495          else return EINA_FALSE;
496          break;
497
498       case ELM_PANEL_ORIENT_RIGHT:
499          panel_size = w * sd->content_size_ratio;
500          sd->s_iface->content_pos_get(obj, &pos, NULL);
501          horizontal = EINA_TRUE;
502
503          if (pos == panel_size) open = EINA_TRUE;
504          else if (pos == 0) open = EINA_FALSE;
505          else return EINA_FALSE;
506          break;
507      }
508
509    if (open)
510      {
511         if (sd->hidden)
512           {
513              sd->hidden = EINA_FALSE;
514              elm_object_signal_emit(obj, "elm,state,active", "elm");
515           }
516         sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_HARD);
517
518         //focus & access
519         elm_object_tree_focus_allow_set(obj, EINA_TRUE);
520         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
521           {
522              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
523              evas_object_show(ao);
524              _elm_access_highlight_set(ao, EINA_FALSE);
525           }
526         else
527           elm_object_focus_set(obj, EINA_TRUE);
528      }
529    else
530      {
531         if (!sd->hidden)
532           {
533              sd->hidden = EINA_TRUE;
534              elm_object_signal_emit(obj, "elm,state,inactive", "elm");
535           }
536         if (horizontal)
537           sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
538         else
539           sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
540         sd->freeze = EINA_TRUE;
541         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
542         elm_object_signal_emit(obj, "elm,state,hold", "elm");
543
544         sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
545
546         //focus & access
547         elm_object_tree_focus_allow_set(obj, EINA_FALSE);
548         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
549           {
550              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
551              evas_object_hide(ao);
552           }
553      }
554
555    return EINA_TRUE;
556 }
557
558 static Eina_Bool
559 _timer_cb(void *data)
560 {
561    ELM_PANEL_DATA_GET(data, sd);
562    Evas_Object *obj = data;
563    Evas_Coord w, h;
564
565    sd->timer = NULL;
566
567    if (sd->freeze)
568      {
569         sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
570         sd->freeze = EINA_FALSE;
571         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
572         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
573         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
574         _handler_open(obj, w, h);
575      }
576
577    return ECORE_CALLBACK_CANCEL;
578 }
579
580 static void
581 _event_mouse_up(void *data,
582                 Evas *e EINA_UNUSED,
583                 Evas_Object *obj EINA_UNUSED,
584                 void *event_info)
585 {
586    ELM_PANEL_DATA_GET(data, sd);
587    Evas_Event_Mouse_Up *ev = event_info;
588    Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
589    evas_object_geometry_get(data, &x, &y, NULL, NULL);
590
591    up_x = ev->output.x - x;
592    up_y = ev->output.y - y;
593
594    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
595
596    if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
597      elm_panel_hidden_set(data, EINA_TRUE);
598 }
599
600 static void
601 _on_mouse_down(void *data,
602                Evas *e EINA_UNUSED,
603                Evas_Object *obj,
604                void *event_info)
605 {
606    Elm_Panel_Smart_Data *sd = data;
607    Evas_Event_Mouse_Down *ev = event_info;
608    Evas_Coord finger_size = elm_config_finger_size_get();
609    Evas_Coord x, y, w, h;
610    evas_object_geometry_get(obj, &x, &y, &w, &h);
611    const char *timer_duration;
612    double timer_duration_num;
613
614    sd->down_x = ev->output.x - x;
615    sd->down_y = ev->output.y - y;
616
617    // if freeze state & mouse down on the edge
618    // then set timer for un-freeze
619    timer_duration = edje_object_data_get(sd->scr_edje, "timer_duration");
620    if (timer_duration) timer_duration_num = atof(timer_duration);
621    else timer_duration_num = 0.2;
622
623    switch (sd->orient)
624      {
625       case ELM_PANEL_ORIENT_TOP:
626          if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
627            {
628               if (sd->timer) ecore_timer_del(sd->timer);
629               sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
630            }
631          break;
632       case ELM_PANEL_ORIENT_BOTTOM:
633          if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - finger_size)))
634            {
635               if (sd->timer) ecore_timer_del(sd->timer);
636               sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
637            }
638          break;
639       case ELM_PANEL_ORIENT_LEFT:
640          if ((sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size))
641            {
642               if (sd->timer) ecore_timer_del(sd->timer);
643               sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
644            }
645          break;
646       case ELM_PANEL_ORIENT_RIGHT:
647          if ((sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size)))
648            {
649               if (sd->timer) ecore_timer_del(sd->timer);
650               sd->timer = ecore_timer_add(timer_duration_num, _timer_cb, obj);
651            }
652          break;
653      }
654 }
655
656 static void
657 _on_mouse_move(void *data,
658                Evas *e EINA_UNUSED,
659                Evas_Object *obj,
660                void *event_info)
661 {
662    Elm_Panel_Smart_Data *sd = data;
663    Evas_Event_Mouse_Move *ev = event_info;
664    Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
665    evas_object_geometry_get(obj, &x, &y, &w, &h);
666    finger_size = elm_config_finger_size_get();
667
668    cur_x = ev->cur.canvas.x - x;
669    cur_y = ev->cur.canvas.y - y;
670
671    // if mouse down on the edge (it means sd->timer is not null)
672    //    and move more than finger size
673    // then un-freeze
674    switch (sd->orient)
675      {
676       case ELM_PANEL_ORIENT_TOP:
677          if (sd->timer && ((cur_y - sd->down_y) > finger_size))
678            {
679               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
680               sd->freeze = EINA_FALSE;
681               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
682               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
683            }
684          break;
685       case ELM_PANEL_ORIENT_BOTTOM:
686          if (sd->timer && ((sd->down_y - cur_y) > finger_size))
687            {
688               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
689               sd->freeze = EINA_FALSE;
690               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
691               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
692            }
693          break;
694       case ELM_PANEL_ORIENT_LEFT:
695          if (sd->timer && ((cur_x - sd->down_x) > finger_size))
696            {
697               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
698               sd->freeze = EINA_FALSE;
699               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
700               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
701            }
702          break;
703       case ELM_PANEL_ORIENT_RIGHT:
704          if (sd->timer && ((sd->down_x - cur_x) > finger_size))
705            {
706               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
707               sd->freeze = EINA_FALSE;
708               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
709               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
710            }
711          break;
712      }
713
714    if (!sd->freeze && sd->hidden)
715      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
716 }
717
718 static void
719 _on_mouse_up(void *data,
720              Evas *e EINA_UNUSED,
721              Evas_Object *obj,
722              void *event_info)
723 {
724    Elm_Panel_Smart_Data *sd = data;
725    Evas_Event_Mouse_Up *ev = event_info;
726    Evas_Coord panel_size, threshold, pos, w, h;
727
728    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
729
730    ELM_SAFE_FREE(sd->timer, ecore_timer_del);
731
732    if (_state_sync(obj)) return;
733
734    switch (sd->orient)
735      {
736       case ELM_PANEL_ORIENT_TOP:
737          panel_size = h * sd->content_size_ratio;
738          threshold = panel_size / 4;
739          sd->s_iface->content_pos_get(obj, NULL, &pos);
740
741          if (sd->hidden)
742            {
743               if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
744               else _drawer_close(obj, w, h, EINA_TRUE);
745            }
746          else
747            {
748               if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
749               else _drawer_close(obj, w, h, EINA_TRUE);
750            }
751          break;
752
753       case ELM_PANEL_ORIENT_BOTTOM:
754          panel_size = h * sd->content_size_ratio;
755          threshold = panel_size / 4;
756          sd->s_iface->content_pos_get(obj, NULL, &pos);
757
758          if (sd->hidden)
759            {
760               if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
761               else _drawer_close(obj, w, h, EINA_TRUE);
762            }
763          else
764            {
765               if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
766               else _drawer_close(obj, w, h, EINA_TRUE);
767            }
768          break;
769
770       case ELM_PANEL_ORIENT_LEFT:
771          panel_size = w * sd->content_size_ratio;
772          threshold = panel_size / 4;
773          sd->s_iface->content_pos_get(obj, &pos, NULL);
774
775          if (sd->hidden)
776            {
777               if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
778               else _drawer_close(obj, w, h, EINA_TRUE);
779            }
780          else
781            {
782               if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
783               else _drawer_close(obj, w, h, EINA_TRUE);
784            }
785          break;
786
787       case ELM_PANEL_ORIENT_RIGHT:
788          panel_size = w * sd->content_size_ratio;
789          threshold = panel_size / 4;
790          sd->s_iface->content_pos_get(obj, &pos, NULL);
791
792          if (sd->hidden)
793            {
794               if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
795               else _drawer_close(obj, w, h, EINA_TRUE);
796            }
797          else
798            {
799               if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
800               else _drawer_close(obj, w, h, EINA_TRUE);
801            }
802          break;
803      }
804
805    if (!sd->freeze && sd->hidden)
806      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
807 }
808
809 static Eina_Bool
810 _elm_panel_smart_event(Evas_Object *obj,
811                        Evas_Object *src,
812                        Evas_Callback_Type type,
813                        void *event_info)
814 {
815    // TIZEN ONLY (2013.11.27): when panel is scrollable, ignore smart event
816    ELM_PANEL_DATA_GET(obj, sd);
817    if (sd->scrollable) return EINA_FALSE;
818    // TIZEN ONLY
819
820    Evas_Event_Key_Down *ev = event_info;
821
822    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
823    if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE;
824    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
825
826    if ((strcmp(ev->keyname, "Return")) &&
827        (strcmp(ev->keyname, "KP_Enter")) &&
828        (strcmp(ev->keyname, "space")))
829      return EINA_FALSE;
830
831    _panel_toggle(NULL, obj, NULL, NULL);
832
833    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
834    return EINA_TRUE;
835 }
836
837 static Eina_Bool
838 _elm_panel_smart_content_set(Evas_Object *obj,
839                              const char *part,
840                              Evas_Object *content)
841 {
842    ELM_PANEL_DATA_GET(obj, sd);
843
844    if (part && strcmp(part, "default"))
845      return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_set
846               (obj, part, content);
847
848    if (sd->content == content) return EINA_TRUE;
849    if (sd->content)
850      evas_object_box_remove_all(sd->bx, EINA_TRUE);
851    sd->content = content;
852    if (content)
853      {
854         evas_object_box_append(sd->bx, sd->content);
855         evas_object_show(sd->content);
856      }
857
858    elm_layout_sizing_eval(obj);
859
860    return EINA_TRUE;
861 }
862
863 static Evas_Object *
864 _elm_panel_smart_content_get(const Evas_Object *obj,
865                              const char *part)
866 {
867    ELM_PANEL_DATA_GET(obj, sd);
868
869    if (part && strcmp(part, "default"))
870      return ELM_CONTAINER_CLASS(_elm_panel_parent_sc)->content_get(obj, part);
871
872    return sd->content;
873 }
874
875 static Evas_Object *
876 _elm_panel_smart_content_unset(Evas_Object *obj,
877                                const char *part)
878 {
879    Evas_Object *content;
880
881    ELM_PANEL_DATA_GET(obj, sd);
882
883    if (part && strcmp(part, "default"))
884      return ELM_CONTAINER_CLASS
885               (_elm_panel_parent_sc)->content_unset(obj, part);
886
887    if (!sd->content) return NULL;
888    content = sd->content;
889
890    evas_object_box_remove_all(sd->bx, EINA_FALSE);
891    sd->content = NULL;
892
893    return content;
894 }
895
896 static void
897 _elm_panel_smart_add(Evas_Object *obj)
898 {
899    EVAS_SMART_DATA_ALLOC(obj, Elm_Panel_Smart_Data);
900
901    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.add(obj);
902 }
903
904 static void
905 _elm_panel_smart_del(Evas_Object *obj)
906 {
907    Evas_Object *child;
908    Eina_List *l;
909
910    ELM_PANEL_DATA_GET(obj, sd);
911
912    sd->on_deletion = EINA_TRUE;
913
914    ELM_SAFE_FREE(sd->timer, ecore_timer_del);
915    ELM_SAFE_FREE(sd->animator, ecore_animator_del);
916
917    /* let's make our box object the *last* to be processed, since it
918     * may (smart) parent other sub objects here */
919    EINA_LIST_FOREACH(ELM_WIDGET_DATA(sd)->subobjs, l, child)
920      {
921         if (child == sd->bx)
922           {
923              ELM_WIDGET_DATA(sd)->subobjs =
924                eina_list_demote_list(ELM_WIDGET_DATA(sd)->subobjs, l);
925              break;
926           }
927      }
928
929    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.del(obj);
930 }
931
932 static void
933 _elm_panel_smart_orientation_set(Evas_Object *obj, int rotation)
934 {
935     ELM_PANEL_DATA_GET(obj, sd);
936
937     if(rotation == 90 || rotation == 270)
938       sd->content_size_ratio = 0.45;
939     else
940       sd->content_size_ratio = 0.80;
941 }
942
943 static void
944 _elm_panel_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
945 {
946    ELM_PANEL_DATA_GET(obj, sd);
947
948    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.move(obj, x, y);
949
950    evas_object_move(sd->hit_rect, x, y);
951 }
952
953 static Eina_Bool
954 _elm_panel_anim_cb(void *data)
955 {
956    Evas_Object *obj = data;
957    ELM_PANEL_DATA_GET(obj, sd);
958    int w, h;
959
960    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
961
962    if (sd->hidden) _drawer_close(obj, w, h, EINA_FALSE);
963    else _drawer_open(obj, w, h, EINA_FALSE);
964
965    sd->animator = NULL;
966
967    return ECORE_CALLBACK_CANCEL;
968 }
969
970 static void
971 _elm_panel_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
972 {
973    ELM_PANEL_DATA_GET(obj, sd);
974    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.resize(obj, w, h);
975
976    if (!sd->scrollable) return;
977
978    evas_object_resize(sd->hit_rect, w, h);
979    switch (sd->orient)
980      {
981       case ELM_PANEL_ORIENT_TOP:
982       case ELM_PANEL_ORIENT_BOTTOM:
983          // vertical
984          evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
985          evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
986          evas_object_size_hint_min_set(sd->scr_event, w, h);
987          break;
988       case ELM_PANEL_ORIENT_LEFT:
989       case ELM_PANEL_ORIENT_RIGHT:
990          // horizontal
991          evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
992          evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
993          evas_object_size_hint_min_set(sd->scr_event, w, h);
994          break;
995      }
996
997    //Close/Open the drawer after sizing calculation is finished.
998    if (sd->animator) ecore_animator_del(sd->animator);
999    sd->animator = ecore_animator_add(_elm_panel_anim_cb, obj);
1000 }
1001
1002 static void
1003 _elm_panel_smart_member_add(Evas_Object *obj, Evas_Object *member)
1004 {
1005    ELM_PANEL_DATA_GET(obj, sd);
1006    ELM_WIDGET_CLASS(_elm_panel_parent_sc)->base.member_add(obj, member);
1007
1008    if (sd->hit_rect) evas_object_raise(sd->hit_rect);
1009 }
1010
1011 static void
1012 _elm_panel_smart_access(Evas_Object *obj, Eina_Bool is_access)
1013 {
1014    ELM_PANEL_CHECK(obj);
1015    ELM_PANEL_DATA_GET(obj, sd);
1016
1017    /* drawer access */
1018    if (sd->scrollable)
1019      {
1020         _access_obj_process(obj, is_access);
1021         return;
1022      }
1023
1024    if (is_access)
1025      _elm_access_edje_object_part_object_register
1026        (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
1027    else
1028      _elm_access_edje_object_part_object_unregister
1029        (obj, ELM_WIDGET_DATA(sd)->resize_obj, "btn_icon");
1030 }
1031
1032 static Evas_Object *
1033 _elm_panel_smart_access_object_get(Evas_Object *obj, char *part)
1034 {
1035    ELM_PANEL_CHECK(obj) NULL;
1036    ELM_PANEL_DATA_GET(obj, sd);
1037
1038    if (sd->scrollable && sd->scr_ly)
1039      return _access_object_get(obj, part);
1040
1041    return NULL;
1042 }
1043
1044 static Eina_Bool
1045 _elm_panel_smart_disable(Evas_Object *obj)
1046 {
1047    ELM_PANEL_DATA_GET(obj, sd);
1048
1049    if (sd->scrollable)
1050      {
1051         if (elm_widget_disabled_get(obj))
1052           {
1053              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
1054                                             _on_mouse_down);
1055              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
1056                                             _on_mouse_move);
1057              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
1058                                             _on_mouse_up);
1059              evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1060                                             _event_mouse_up);
1061           }
1062         else
1063           {
1064              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1065                                             _on_mouse_down, sd);
1066              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1067                                             _on_mouse_move, sd);
1068              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1069                                             _on_mouse_up, sd);
1070              evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1071                                             _event_mouse_up, obj);
1072           }
1073      }
1074
1075    return EINA_TRUE;
1076 }
1077
1078 static void
1079 _elm_panel_smart_set_user(Elm_Panel_Smart_Class *sc)
1080 {
1081    ELM_WIDGET_CLASS(sc)->base.add = _elm_panel_smart_add;
1082    ELM_WIDGET_CLASS(sc)->base.del = _elm_panel_smart_del;
1083    ELM_WIDGET_CLASS(sc)->base.move = _elm_panel_smart_move;
1084    ELM_WIDGET_CLASS(sc)->base.resize = _elm_panel_smart_resize;
1085    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_panel_smart_member_add;
1086
1087    ELM_WIDGET_CLASS(sc)->focus_next = _elm_panel_smart_focus_next;
1088    ELM_WIDGET_CLASS(sc)->theme = _elm_panel_smart_theme;
1089    ELM_WIDGET_CLASS(sc)->event = _elm_panel_smart_event;
1090    ELM_WIDGET_CLASS(sc)->access = _elm_panel_smart_access;
1091    ELM_WIDGET_CLASS(sc)->access_object_get = _elm_panel_smart_access_object_get;
1092    ELM_WIDGET_CLASS(sc)->disable = _elm_panel_smart_disable;
1093    ELM_WIDGET_CLASS(sc)->orientation_set = _elm_panel_smart_orientation_set;
1094
1095    ELM_CONTAINER_CLASS(sc)->content_set = _elm_panel_smart_content_set;
1096    ELM_CONTAINER_CLASS(sc)->content_get = _elm_panel_smart_content_get;
1097    ELM_CONTAINER_CLASS(sc)->content_unset = _elm_panel_smart_content_unset;
1098
1099    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_panel_smart_sizing_eval;
1100 }
1101
1102 static void
1103 _anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED)
1104 {
1105    if (elm_widget_disabled_get(obj)) return;
1106    _state_sync(obj);
1107 }
1108
1109 static void
1110 _scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
1111 {
1112    ELM_PANEL_DATA_GET(obj, sd);
1113    Elm_Panel_Scroll_Info event;
1114    Evas_Coord x, y, w, h;
1115
1116    if (elm_widget_disabled_get(obj)) return;
1117    // in the case of
1118    // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
1119    if (sd->freeze)
1120      {
1121         sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_NO_BLOCK);
1122         sd->freeze = EINA_FALSE;
1123         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
1124         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
1125      }
1126
1127    sd->s_iface->content_pos_get(obj, &x, &y);
1128    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1129
1130    switch (sd->orient)
1131      {
1132       case ELM_PANEL_ORIENT_TOP:
1133          event.rel_x = 1;
1134          event.rel_y = 1 - ((double) y / (double) ((sd->content_size_ratio) * h));
1135         break;
1136       case ELM_PANEL_ORIENT_BOTTOM:
1137          event.rel_x = 1;
1138          event.rel_y = (double) y / (double) ((sd->content_size_ratio) * h);
1139         break;
1140       case ELM_PANEL_ORIENT_LEFT:
1141          event.rel_x = 1 - ((double) x / (double) ((sd->content_size_ratio) * w));
1142          event.rel_y = 1;
1143         break;
1144       case ELM_PANEL_ORIENT_RIGHT:
1145          event.rel_x = (double) x / (double) ((sd->content_size_ratio) * w);
1146          event.rel_y = 1;
1147         break;
1148      }
1149    evas_object_smart_callback_call(obj, SIG_SCROLL, (void *) &event);
1150 }
1151
1152 EAPI const Elm_Panel_Smart_Class *
1153 elm_panel_smart_class_get(void)
1154 {
1155    static Elm_Panel_Smart_Class _sc =
1156      ELM_PANEL_SMART_CLASS_INIT_NAME_VERSION(ELM_PANEL_SMART_NAME);
1157    static const Elm_Panel_Smart_Class *class = NULL;
1158
1159    if (class) return class;
1160
1161    _elm_panel_smart_set(&_sc);
1162    class = &_sc;
1163
1164    return class;
1165 }
1166
1167 EAPI Evas_Object *
1168 elm_panel_add(Evas_Object *parent)
1169 {
1170    Evas_Object *obj;
1171
1172    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1173
1174    obj = elm_widget_add(_elm_panel_smart_class_new(), parent);
1175    if (!obj) return NULL;
1176
1177    if (!elm_widget_sub_object_add(parent, obj))
1178      ERR("could not add %p as sub object of %p", obj, parent);
1179
1180    ELM_PANEL_DATA_GET(obj, sd);
1181
1182    elm_widget_can_focus_set(obj, EINA_TRUE);
1183
1184    /* just to bootstrap and have theme hook to work */
1185    elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj));
1186
1187    _elm_panel_smart_theme(obj);
1188
1189    elm_widget_can_focus_set(obj, EINA_TRUE);
1190
1191    sd->hidden = EINA_FALSE;
1192
1193    sd->bx = evas_object_box_add(evas_object_evas_get(obj));
1194    evas_object_size_hint_align_set(sd->bx, 0.5, 0.5);
1195    evas_object_box_layout_set(sd->bx, _box_layout_cb, sd, NULL);
1196    elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1197    evas_object_show(sd->bx);
1198
1199    elm_layout_signal_callback_add
1200      (obj, "elm,action,panel,toggle", "*", _panel_toggle, obj);
1201
1202    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1203
1204    elm_layout_sizing_eval(obj);
1205
1206    //Tizen Only: This should be removed when eo is applied.
1207    ELM_WIDGET_DATA_GET(obj, wsd);
1208    wsd->on_create = EINA_FALSE;
1209    wsd->highlight_root = EINA_TRUE;
1210
1211    sd->panel_edje = wsd->resize_obj;
1212
1213    return obj;
1214 }
1215
1216 EAPI void
1217 elm_panel_orient_set(Evas_Object *obj,
1218                      Elm_Panel_Orient orient)
1219 {
1220    ELM_PANEL_CHECK(obj);
1221    ELM_PANEL_DATA_GET(obj, sd);
1222
1223    if (sd->orient == orient) return;
1224    sd->orient = orient;
1225
1226    if (sd->scrollable) _scrollable_layout_theme_set(obj, sd);
1227    else _orient_set_do(obj);
1228
1229    elm_layout_sizing_eval(obj);
1230 }
1231
1232 EAPI Elm_Panel_Orient
1233 elm_panel_orient_get(const Evas_Object *obj)
1234 {
1235    ELM_PANEL_CHECK(obj) ELM_PANEL_ORIENT_LEFT;
1236    ELM_PANEL_DATA_GET(obj, sd);
1237
1238    return sd->orient;
1239 }
1240
1241 EAPI void
1242 elm_panel_hidden_set(Evas_Object *obj,
1243                      Eina_Bool hidden)
1244 {
1245    ELM_PANEL_CHECK(obj);
1246    ELM_PANEL_DATA_GET(obj, sd);
1247
1248    if (sd->hidden == hidden)
1249      {
1250         if (sd->hidden && !sd->freeze)
1251           {
1252              Evas_Coord w, h;
1253              evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1254              _drawer_close(obj, w, h, EINA_TRUE);
1255           }
1256         return;
1257      }
1258
1259    _panel_toggle(NULL, obj, NULL, NULL);
1260 }
1261
1262 EAPI Eina_Bool
1263 elm_panel_hidden_get(const Evas_Object *obj)
1264 {
1265    ELM_PANEL_CHECK(obj) EINA_FALSE;
1266    ELM_PANEL_DATA_GET(obj, sd);
1267
1268    return sd->hidden;
1269 }
1270
1271 EAPI void
1272 elm_panel_toggle(Evas_Object *obj)
1273 {
1274    ELM_PANEL_CHECK(obj);
1275
1276    _panel_toggle(NULL, obj, NULL, NULL);
1277 }
1278
1279 EAPI void
1280 elm_panel_scrollable_set(Evas_Object *obj, Eina_Bool scrollable)
1281 {
1282    ELM_PANEL_DATA_GET(obj, sd);
1283
1284    scrollable = !!scrollable;
1285    if (sd->scrollable == scrollable) return;
1286    sd->scrollable = scrollable;
1287
1288    if (scrollable)
1289      {
1290         elm_layout_content_unset(obj, "elm.swallow.content");
1291
1292         elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1293         elm_widget_sub_object_add(obj, sd->panel_edje);
1294
1295         if (!sd->scr_edje)
1296           {
1297              const char *handler_size;
1298
1299              sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
1300              elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
1301                                          elm_widget_style_get(obj));
1302              evas_object_size_hint_weight_set
1303                 (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1304              evas_object_size_hint_align_set
1305                 (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1306
1307              handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
1308              if (handler_size)
1309                sd->handler_size = (Evas_Coord) (elm_object_scale_get(obj)) * (atoi(handler_size));
1310           }
1311
1312         elm_widget_resize_object_set(obj, sd->scr_edje, EINA_TRUE);
1313
1314         //Temporary code: will be removed after elm_panel_scrollable_content_size_set is applied
1315         if (elm_win_rotation_get(elm_widget_top_get(obj)) == 90 || elm_win_rotation_get(elm_widget_top_get(obj)) == 270)
1316           sd->content_size_ratio = 0.45;
1317         else
1318           sd->content_size_ratio = 0.80;
1319
1320         if (!sd->hit_rect)
1321           {
1322              sd->s_iface = evas_object_smart_interface_get
1323                 (obj, ELM_SCROLLABLE_IFACE_NAME);
1324
1325              sd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
1326              evas_object_smart_member_add(sd->hit_rect, obj);
1327              elm_widget_sub_object_add(obj, sd->hit_rect);
1328              evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
1329              evas_object_show(sd->hit_rect);
1330              evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
1331
1332              sd->s_iface->objects_set(obj, sd->scr_edje, sd->hit_rect);
1333              sd->s_iface->animate_stop_cb_set(obj, _anim_stop_cb);
1334              sd->s_iface->scroll_cb_set(obj, _scroll_cb);
1335           }
1336
1337         if (!sd->scr_ly)
1338           {
1339              sd->scr_ly = elm_layout_add(obj);
1340              evas_object_smart_member_add(sd->scr_ly, obj);
1341              elm_widget_sub_object_add(obj, sd->scr_ly);
1342              _scrollable_layout_theme_set(obj, sd);
1343
1344              sd->scr_panel = evas_object_rectangle_add(evas_object_evas_get(obj));
1345              evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
1346              elm_widget_sub_object_add(obj, sd->scr_panel);
1347              elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
1348
1349              sd->scr_event = evas_object_rectangle_add(evas_object_evas_get(obj));
1350              evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
1351              elm_widget_sub_object_add(obj, sd->scr_event);
1352              elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
1353           }
1354
1355         sd->s_iface->content_set(obj, sd->scr_ly);
1356         sd->freeze = EINA_TRUE;
1357         elm_layout_content_set(sd->scr_ly, "elm.swallow.content", sd->bx);
1358
1359         switch (sd->orient)
1360           {
1361            case ELM_PANEL_ORIENT_TOP:
1362            case ELM_PANEL_ORIENT_BOTTOM:
1363               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
1364               break;
1365            case ELM_PANEL_ORIENT_LEFT:
1366            case ELM_PANEL_ORIENT_RIGHT:
1367               sd->s_iface->movement_block_set(obj, ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL);
1368               break;
1369           }
1370
1371         sd->s_iface->single_direction_set(obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
1372
1373         if (!elm_widget_disabled_get(obj))
1374           {
1375              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1376                                             _on_mouse_down, sd);
1377              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1378                                             _on_mouse_move, sd);
1379              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1380                                             _on_mouse_up, sd);
1381              evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1382                                             _event_mouse_up, obj);
1383           }
1384      }
1385    else
1386      {
1387         sd->s_iface->content_set(obj, NULL);
1388
1389         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down);
1390         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move);
1391         evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up);
1392         evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1393                                        _event_mouse_up);
1394
1395         elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1396         elm_widget_sub_object_add(obj, sd->scr_edje);
1397
1398         elm_widget_resize_object_set(obj, sd->panel_edje, EINA_TRUE);
1399
1400         elm_layout_content_unset(sd->scr_ly, "elm.swallow.content");
1401         elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1402      }
1403 }
1404
1405 EAPI Eina_Bool
1406 elm_panel_scrollable_get(const Evas_Object *obj)
1407 {
1408    ELM_PANEL_DATA_GET(obj, sd);
1409
1410    return sd->scrollable;
1411 }
1412
1413 EAPI void
1414 elm_panel_scrollable_content_size_set(Evas_Object *obj, double ratio)
1415 {
1416    Evas_Coord w, h;
1417    ELM_PANEL_DATA_GET(obj, sd);
1418
1419    sd->content_size_ratio = ratio;
1420    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1421
1422    switch (sd->orient)
1423      {
1424       case ELM_PANEL_ORIENT_TOP:
1425       case ELM_PANEL_ORIENT_BOTTOM:
1426          // vertical
1427          evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
1428          evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
1429          evas_object_size_hint_min_set(sd->scr_event, w, h);
1430          break;
1431       case ELM_PANEL_ORIENT_LEFT:
1432       case ELM_PANEL_ORIENT_RIGHT:
1433          // horizontal
1434          evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
1435          evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
1436          evas_object_size_hint_min_set(sd->scr_event, w, h);
1437          break;
1438      }
1439
1440    if (sd->animator) ecore_animator_del(sd->animator);
1441    sd->animator = ecore_animator_add(_elm_panel_anim_cb, obj);
1442 }