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