elm_panel: prevent redundant callback function addition or deletion
[platform/upstream/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_TOGGLED[] = "toggled";
23 static const char SIG_SCROLL[] = "scroll";
24
25 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
26    {SIG_TOGGLED, ""},
27    {SIG_SCROLL, ""},
28    {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
29    {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
30    {NULL, NULL}
31 };
32 static void _panel_toggle(void *, Evas_Object *, const char *,const char *);
33 static Eina_Bool _key_action_toggle(Evas_Object *obj, const char *params);
34 static void _drawer_open(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool );
35 static void _drawer_close(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool);
36
37 static const Elm_Action key_actions[] = {
38    {"toggle", _key_action_toggle},
39    {NULL, NULL}
40 };
41
42 static void
43 _mirrored_set(Evas_Object *obj,
44               Eina_Bool rtl)
45 {
46    ELM_PANEL_DATA_GET(obj, sd);
47
48    if ((sd->content) && (eo_isa(sd->content, ELM_WIDGET_CLASS)))
49      elm_widget_mirrored_set(sd->content, rtl);
50    elm_panel_orient_set(obj, elm_panel_orient_get(obj));
51 }
52
53 EOLIAN static void
54 _elm_panel_elm_layout_sizing_eval(Eo *obj, Elm_Panel_Data *sd)
55 {
56    Evas_Coord mw = -1, mh = -1;
57
58    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
59
60    if (sd->delete_me) return;
61
62    if (sd->scrollable)
63      {
64         if (sd->hidden) _drawer_close(obj, wd->w, wd->h, EINA_FALSE);
65         else _drawer_open(obj, wd->w, wd->h, EINA_FALSE);
66      }
67
68    evas_object_smart_calculate(sd->bx);
69    edje_object_size_min_calc(wd->resize_obj, &mw, &mh);
70    evas_object_size_hint_min_set(obj, mw, mh);
71    evas_object_size_hint_max_set(obj, -1, -1);
72 }
73
74 static char *
75 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
76 {
77    ELM_PANEL_DATA_GET(data, sd);
78
79    if (!sd->hidden) return strdup(E_("state: opened"));
80    else return strdup(E_("state: closed"));
81
82    return NULL;
83 }
84
85 static Evas_Object *
86 _access_object_get(const Evas_Object *obj, const char *part)
87 {
88    Evas_Object *po, *ao;
89    ELM_PANEL_DATA_GET(obj, sd);
90
91    po = (Evas_Object *)edje_object_part_object_get
92       (elm_layout_edje_get(sd->scr_ly), part);
93    ao = evas_object_data_get(po, "_part_access_obj");
94
95    return ao;
96 }
97
98 static void
99 _access_activate_cb(void *data,
100                     Evas_Object *part_obj EINA_UNUSED,
101                     Elm_Object_Item *item EINA_UNUSED)
102 {
103    elm_panel_hidden_set(data, EINA_TRUE);
104 }
105
106 static void
107 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
108 {
109    Evas_Object *ao;
110    ELM_PANEL_DATA_GET(obj, sd);
111
112    if (is_access)
113      {
114         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
115         if (!ao)
116           {
117              ao = _elm_access_edje_object_part_object_register
118                 (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
119              _elm_access_text_set(_elm_access_info_get(ao),
120                                   ELM_ACCESS_TYPE, E_("A panel is open"));
121              _elm_access_text_set(_elm_access_info_get(ao),
122                                   ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close panel menu"));
123              _elm_access_activate_callback_set
124                 (_elm_access_info_get(ao), _access_activate_cb, obj);
125           }
126      }
127    else
128      {
129         _elm_access_edje_object_part_object_unregister
130            (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
131      }
132 }
133
134 // TIZEN_ONLY(20170829): [atspi][panel] Adds accessibility support for the panel widget.
135 static void
136 _accessible_panel_hidden_set(Evas_Object* obj, Eina_Bool is_hidden)
137 {
138    is_hidden = !!is_hidden;
139    elm_atspi_accessible_can_highlight_set(obj, !is_hidden);
140    elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_SHOWING, !is_hidden);
141
142    if (is_hidden)
143      _elm_win_default_label_obj_remove(obj);
144    else
145      _elm_win_default_label_obj_append(obj);
146 }
147 //
148
149 static void
150 _orient_set_do(Evas_Object *obj)
151 {
152    ELM_PANEL_DATA_GET(obj, sd);
153    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
154
155    switch (sd->orient)
156      {
157       case ELM_PANEL_ORIENT_TOP:
158         if (!elm_layout_theme_set
159               (obj, "panel", "top", elm_widget_style_get(obj)))
160           CRI("Failed to set layout!");
161         break;
162
163       case ELM_PANEL_ORIENT_BOTTOM:
164         if (!elm_layout_theme_set
165               (obj, "panel", "bottom", elm_widget_style_get(obj)))
166           CRI("Failed to set layout!");
167         break;
168
169       case ELM_PANEL_ORIENT_LEFT:
170         if (!elm_layout_theme_set(obj, "panel", "left",
171                 elm_widget_style_get(obj)))
172             CRI("Failed to set layout!");
173         break;
174
175       case ELM_PANEL_ORIENT_RIGHT:
176         if (!elm_layout_theme_set(obj, "panel", "right",
177                 elm_widget_style_get(obj)))
178             CRI("Failed to set layout!");
179         break;
180      }
181
182    /* access */
183    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
184      {
185         Evas_Object *ao;
186         ao = _elm_access_edje_object_part_object_register
187             (obj, wd->resize_obj, "btn_icon");
188         _elm_access_text_set(_elm_access_info_get(ao),
189                              ELM_ACCESS_TYPE, E_("panel button"));
190         _elm_access_callback_set
191           (_elm_access_info_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
192      }
193 }
194
195 static void
196 _scrollable_layout_theme_set(Eo *obj, Elm_Panel_Data *sd)
197 {
198    switch (sd->orient)
199      {
200       case ELM_PANEL_ORIENT_TOP:
201          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/top",
202                                    elm_widget_style_get(obj)))
203            CRI("Failed to set layout!");
204          break;
205       case ELM_PANEL_ORIENT_BOTTOM:
206          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/bottom",
207                                    elm_widget_style_get(obj)))
208            CRI("Failed to set layout!");
209          break;
210       case ELM_PANEL_ORIENT_LEFT:
211          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/left",
212                                    elm_widget_style_get(obj)))
213            CRI("Failed to set layout!");
214          break;
215       case ELM_PANEL_ORIENT_RIGHT:
216          if (!elm_layout_theme_set(sd->scr_ly, "scroller", "panel/right",
217                                    elm_widget_style_get(obj)))
218            CRI("Failed to set layout!");
219          break;
220      }
221
222    /* access */
223    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
224      _access_obj_process(obj, EINA_TRUE);
225 }
226
227 EOLIAN static Elm_Theme_Apply
228 _elm_panel_elm_widget_theme_apply(Eo *obj, Elm_Panel_Data *sd)
229 {
230    const char *str;
231    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
232    //int w, h;
233    //
234    Evas_Coord minw = 0, minh = 0;
235
236    Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
237
238    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED);
239
240    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
241    if (!int_ret) return ELM_THEME_APPLY_FAILED;
242
243    _mirrored_set(obj, elm_widget_mirrored_get(obj));
244
245    if (sd->scrollable)
246      {
247         const char *handler_size;
248         elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
249                                     elm_widget_style_get(obj));
250         _scrollable_layout_theme_set(obj, sd);
251         // TIZEN_ONLY(20170316): set hidden property when panel is close/open
252         /*evas_object_geometry_get(obj, NULL, NULL, &w, &h);
253         if (!sd->hidden) _drawer_open(obj, w, h, EINA_FALSE);
254         else _drawer_close(obj, w, h, EINA_FALSE);*/
255         //
256         handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
257         if (handler_size)
258           sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
259      }
260    else
261      {
262         str = edje_object_data_get
263            (wd->resize_obj, "focus_highlight");
264         if ((str) && (!strcmp(str, "on")))
265           elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
266         else
267           elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
268
269         _orient_set_do(obj);
270
271         evas_object_hide(sd->event);
272         elm_coords_finger_size_adjust(1, &minw, 1, &minh);
273         evas_object_size_hint_min_set(sd->event, minw, minh);
274
275         if (edje_object_part_exists
276             (wd->resize_obj, "elm.swallow.event"))
277           eo_do_super(obj, MY_CLASS, elm_obj_container_content_set("elm.swallow.event", sd->event));
278      }
279
280    elm_layout_sizing_eval(obj);
281
282    return int_ret;
283 }
284
285 EOLIAN static Eina_Bool
286 _elm_panel_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Panel_Data *_pd EINA_UNUSED)
287 {
288    return EINA_TRUE;
289 }
290
291 EOLIAN static Eina_Bool
292 _elm_panel_elm_widget_focus_next(Eo *obj, Elm_Panel_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
293 {
294    Evas_Object *cur;
295    Eina_List *items = NULL;
296    Eina_Bool ret = EINA_FALSE;
297
298    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
299
300    if (!sd->content) return EINA_FALSE;
301
302    if (sd->scrollable)
303      {
304         if (sd->hidden) return EINA_FALSE;
305
306         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
307           {
308              Evas_Object *ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
309              if (ao) items = eina_list_append(items, ao);
310              items = eina_list_append(items, sd->content);
311
312              ret = elm_widget_focus_list_next_get
313                 (obj, items, eina_list_data_get, dir, next, next_item);
314              eina_list_free(items);
315
316              return ret;
317           }
318
319         return elm_widget_focus_next_get(sd->content, dir, next, next_item);
320      }
321
322    cur = sd->content;
323
324    /* Try to Focus cycle in subitem */
325    if (!sd->hidden) return elm_widget_focus_next_get(cur, dir, next, next_item);
326
327    /* access */
328    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
329      {
330         Evas_Object *ao, *po;
331         po = (Evas_Object *)edje_object_part_object_get
332                (wd->resize_obj, "btn_icon");
333         ao = evas_object_data_get(po, "_part_access_obj");
334         _elm_access_highlight_set(ao);
335      }
336
337    /* Return */
338    *next = (Evas_Object *)obj;
339    return !elm_widget_focus_get(obj);
340 }
341
342 static void
343 _box_layout_cb(Evas_Object *o,
344                Evas_Object_Box_Data *priv,
345                void *data EINA_UNUSED)
346 {
347    _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE);
348 }
349
350 static void
351 _handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
352 {
353    ELM_PANEL_DATA_GET(obj, sd);
354
355    if (sd->handler_size == 0) return;
356
357    switch (sd->orient)
358      {
359       case ELM_PANEL_ORIENT_TOP:
360          eo_do(obj, elm_interface_scrollable_region_bring_in
361                (0, (h * sd->content_size_ratio) - sd->handler_size, w, h));
362          break;
363       case ELM_PANEL_ORIENT_BOTTOM:
364          eo_do(obj, elm_interface_scrollable_region_bring_in
365                (0, sd->handler_size, w, h));
366          break;
367       case ELM_PANEL_ORIENT_LEFT:
368          eo_do(obj, elm_interface_scrollable_region_bring_in
369                ((w * sd->content_size_ratio) - sd->handler_size, 0, w, h));
370          break;
371       case ELM_PANEL_ORIENT_RIGHT:
372          eo_do(obj, elm_interface_scrollable_region_bring_in
373                (sd->handler_size, 0, w, h));
374          break;
375      }
376 }
377
378 static void
379 _drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
380 {
381    ELM_PANEL_DATA_GET(obj, sd);
382    int x = 0, y = 0;
383
384    if (sd->freeze)
385      {
386         eo_do(obj, elm_interface_scrollable_movement_block_set
387               (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
388         sd->freeze = EINA_FALSE;
389         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
390         // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
391         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
392         //
393      }
394
395    switch (sd->orient)
396      {
397       case ELM_PANEL_ORIENT_TOP:
398          break;
399       case ELM_PANEL_ORIENT_LEFT:
400          if (elm_widget_mirrored_get(obj))
401            x = w * sd->content_size_ratio;
402          break;
403
404       case ELM_PANEL_ORIENT_BOTTOM:
405          y = h * sd->content_size_ratio;
406          break;
407
408       case ELM_PANEL_ORIENT_RIGHT:
409          if (!elm_widget_mirrored_get(obj))
410            x = w * sd->content_size_ratio;
411          break;
412      }
413
414    if (anim)
415      eo_do(obj, elm_interface_scrollable_region_bring_in
416            (x, y, w, h));
417    else
418      eo_do(obj, elm_interface_scrollable_content_region_show
419            (x, y, w, h));
420
421    // TIZEN_ONLY(20170829): [atspi][panel] Adds accessibility support for the panel widget.
422    _accessible_panel_hidden_set(obj, EINA_FALSE);
423    //
424 }
425
426 static void
427 _drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
428 {
429    ELM_PANEL_DATA_GET(obj, sd);
430    int x = 0, y = 0;
431    Eina_Bool horizontal = EINA_FALSE;
432
433    elm_widget_tree_unfocusable_set(obj, EINA_TRUE);
434    switch (sd->orient)
435      {
436       case ELM_PANEL_ORIENT_TOP:
437          y = h * sd->content_size_ratio;
438          break;
439
440       case ELM_PANEL_ORIENT_LEFT:
441          if (!elm_widget_mirrored_get(obj))
442            x = w * sd->content_size_ratio;
443          horizontal = EINA_TRUE;
444          break;
445
446       case ELM_PANEL_ORIENT_BOTTOM:
447          break;
448
449       case ELM_PANEL_ORIENT_RIGHT:
450          if (elm_widget_mirrored_get(obj))
451            x = w * sd->content_size_ratio;
452          horizontal = EINA_TRUE;
453          break;
454      }
455
456    if (anim)
457      {
458         if (sd->freeze)
459           {
460              eo_do(obj, elm_interface_scrollable_movement_block_set
461                    (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
462              sd->freeze = EINA_FALSE;
463              elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
464              // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
465              elm_object_signal_emit(obj, "elm,state,unhold", "elm");
466              //
467           }
468         eo_do(obj, elm_interface_scrollable_region_bring_in(x, y, w, h));
469      }
470    else
471      {
472         eo_do(obj, elm_interface_scrollable_content_region_show(x, y, w, h));
473         if (!sd->freeze)
474           {
475              if (horizontal)
476                eo_do(obj, elm_interface_scrollable_movement_block_set
477                      (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
478              else
479                eo_do(obj, elm_interface_scrollable_movement_block_set
480                      (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
481              sd->freeze = EINA_TRUE;
482              elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
483              // TIZEN_ONLY(20170613): emit signal when panel is hidden
484              elm_object_signal_emit(obj, "elm,state,hold", "elm");
485              //
486           }
487      }
488    // TIZEN_ONLY(20170829) : [atspi][panel] Adds accessibility support for the panel widget.
489    _accessible_panel_hidden_set(obj, EINA_TRUE);
490    //
491 }
492
493 static void
494 _panel_toggle(void *data EINA_UNUSED,
495               Evas_Object *obj,
496               const char *emission EINA_UNUSED,
497               const char *source EINA_UNUSED)
498 {
499    ELM_PANEL_DATA_GET(obj, sd);
500    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
501    int w, h;
502
503    if (sd->scrollable)
504      {
505         if (elm_widget_disabled_get(obj)) return;
506
507         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
508         if (sd->hidden)
509           {
510              sd->hidden = EINA_FALSE;
511              _drawer_open(obj, w, h, EINA_TRUE);
512           }
513         else
514           {
515              sd->hidden = EINA_TRUE;
516              _drawer_close(obj, w, h, EINA_TRUE);
517           }
518      }
519    else
520      {
521         if (sd->hidden)
522           {
523              elm_layout_signal_emit(obj, "elm,action,show", "elm");
524              sd->hidden = EINA_FALSE;
525              evas_object_repeat_events_set(obj, EINA_FALSE);
526              // TIZEN_ONLY(20170829) : [atspi][panel] Adds accessibility support for the panel widget.
527              _accessible_panel_hidden_set(obj, sd->hidden);
528              //
529           }
530         else
531           {
532              elm_layout_signal_emit(obj, "elm,action,hide", "elm");
533              sd->hidden = EINA_TRUE;
534              evas_object_repeat_events_set(obj, EINA_TRUE);
535              if (sd->content && elm_widget_focus_get(sd->content))
536                {
537                   elm_widget_focused_object_clear(obj);
538                   elm_widget_focus_steal(obj, NULL);
539                }
540              // TIZEN_ONLY(20170829) : [atspi][panel] Adds accessibility support for the panel widget.
541              _accessible_panel_hidden_set(obj, sd->hidden);
542              //
543           }
544
545         edje_object_message_signal_process(wd->resize_obj);
546      }
547
548    eo_do(obj, eo_event_callback_call(ELM_PANEL_EVENT_TOGGLED, NULL));
549 }
550
551 static Eina_Bool
552 _state_sync(Evas_Object *obj)
553 {
554    ELM_PANEL_DATA_GET(obj, sd);
555    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
556    /*Evas_Object *ao;
557    Evas_Coord pos, panel_size, w, h;
558    Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE;*/
559    Evas_Coord pos, panel_size, w, h, threshold;
560    Eina_Bool horizontal = EINA_FALSE, reverse = EINA_FALSE;
561    //
562    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
563
564    if (!evas_object_visible_get(sd->bx)) return EINA_TRUE;
565
566    switch (sd->orient)
567      {
568       // TIZEN_ONLY(20170316): set hidden property when panel is close/open
569       /*case ELM_PANEL_ORIENT_TOP:
570          if (h <= 0) return EINA_TRUE;
571
572          panel_size = h * sd->content_size_ratio;
573          eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
574
575          if (pos == 0) open = EINA_TRUE;
576          else if (pos == panel_size) open = EINA_FALSE;
577          else return EINA_FALSE;
578          break;
579
580       case ELM_PANEL_ORIENT_BOTTOM:
581          if (h <= 0) return EINA_TRUE;
582
583          panel_size = h * sd->content_size_ratio;
584          eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
585
586          if (pos == panel_size) open = EINA_TRUE;
587          else if (pos == 0) open = EINA_FALSE;
588          else return EINA_FALSE;
589          break;
590
591       case ELM_PANEL_ORIENT_LEFT:
592          if (w <= 0) return EINA_TRUE;
593
594          panel_size = w * sd->content_size_ratio;
595          eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
596          horizontal = EINA_TRUE;
597
598          if (!elm_widget_mirrored_get(obj))
599            {
600               if (pos == 0) open = EINA_TRUE;
601               else if (pos == panel_size) open = EINA_FALSE;
602               else return EINA_FALSE;
603            }
604          else
605            {
606               if (pos == panel_size) open = EINA_TRUE;
607               else if (pos == 0) open = EINA_FALSE;
608               else return EINA_FALSE;
609            }
610          break;
611
612       case ELM_PANEL_ORIENT_RIGHT:
613          if (w <= 0) return EINA_TRUE;
614
615          panel_size = w * sd->content_size_ratio;
616          eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
617          horizontal = EINA_TRUE;
618
619          if (elm_widget_mirrored_get(obj))
620            {
621               if (pos == 0) open = EINA_TRUE;
622               else if (pos == panel_size) open = EINA_FALSE;
623               else return EINA_FALSE;
624            }
625          else
626            {
627               if (pos == panel_size) open = EINA_TRUE;
628               else if (pos == 0) open = EINA_FALSE;
629               else return EINA_FALSE;
630            }
631          break;*/
632        case ELM_PANEL_ORIENT_BOTTOM:
633           reverse = EINA_TRUE;
634        case ELM_PANEL_ORIENT_TOP:
635           break;
636
637        case ELM_PANEL_ORIENT_RIGHT:
638           reverse = EINA_TRUE;
639        case ELM_PANEL_ORIENT_LEFT:
640           horizontal = EINA_TRUE;
641           break;
642        //
643      }
644
645    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
646    /*if (open)
647      {
648         if (sd->hidden)
649           {
650              sd->hidden = EINA_FALSE;
651              eo_do(obj, eo_event_callback_call(ELM_PANEL_EVENT_TOGGLED, NULL));
652           }
653         eo_do(obj, elm_interface_scrollable_single_direction_set
654               (ELM_SCROLLER_SINGLE_DIRECTION_HARD));
655
656         //focus & access
657         elm_object_tree_focus_allow_set(obj, EINA_TRUE);
658         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
659           {
660              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
661              evas_object_show(ao);
662              _elm_access_highlight_set(ao);
663           }
664         else
665           elm_object_focus_set(obj, EINA_TRUE);
666      }
667    else
668      {
669         if (!sd->hidden)
670           {
671              sd->hidden = EINA_TRUE;
672              eo_do(obj, eo_event_callback_call(ELM_PANEL_EVENT_TOGGLED, NULL));
673           }
674
675         if (horizontal)
676           eo_do(obj, elm_interface_scrollable_movement_block_set
677                 (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
678         else
679           eo_do(obj, elm_interface_scrollable_movement_block_set
680                 (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
681         sd->freeze = EINA_TRUE;
682         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
683
684         eo_do(obj, elm_interface_scrollable_single_direction_set
685               (ELM_SCROLLER_SINGLE_DIRECTION_NONE));
686
687         //focus & access
688         elm_object_tree_focus_allow_set(obj, EINA_FALSE);
689         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
690           {
691              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
692              evas_object_hide(ao);
693           }
694      }
695
696    return EINA_TRUE;*/
697
698    if (horizontal)
699      {
700         if (w <= 0) return EINA_TRUE;
701
702         panel_size = w * sd->content_size_ratio;
703         eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
704         reverse ^= elm_widget_mirrored_get(obj);
705      }
706    else
707      {
708         if (h <= 0) return EINA_TRUE;
709
710         panel_size = h * sd->content_size_ratio;
711         eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
712      }
713    threshold = (sd->hidden) ? panel_size - (panel_size / 4) : (panel_size / 4);
714
715    if (reverse)
716      {
717         if (pos > panel_size - threshold) sd->hidden = EINA_FALSE;
718         else sd->hidden = EINA_TRUE;
719      }
720    else
721      {
722         if (pos < threshold) sd->hidden = EINA_FALSE;
723         else sd->hidden = EINA_TRUE;
724      }
725
726    return EINA_FALSE;
727    //
728 }
729
730 static Eina_Bool
731 _timer_cb(void *data)
732 {
733    ELM_PANEL_DATA_GET(data, sd);
734    Evas_Object *obj = data;
735    Evas_Coord w, h;
736
737    sd->timer = NULL;
738
739    if (sd->freeze)
740      {
741         eo_do(obj, elm_interface_scrollable_movement_block_set
742               (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
743         sd->freeze = EINA_FALSE;
744         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
745         // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
746         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
747         //
748         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
749         _handler_open(obj, w, h);
750      }
751
752    return ECORE_CALLBACK_CANCEL;
753 }
754
755 static void
756 _event_mouse_up(void *data,
757                 Evas *e EINA_UNUSED,
758                 Evas_Object *obj EINA_UNUSED,
759                 void *event_info)
760 {
761    ELM_PANEL_DATA_GET(data, sd);
762    Evas_Event_Mouse_Up *ev = event_info;
763    Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
764    evas_object_geometry_get(data, &x, &y, NULL, NULL);
765
766    up_x = ev->canvas.x - x;
767    up_y = ev->canvas.y - y;
768
769    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
770
771    if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
772      elm_panel_hidden_set(data, EINA_TRUE);
773 }
774
775 static void
776 _on_mouse_down(void *data,
777                Evas *e EINA_UNUSED,
778                Evas_Object *obj,
779                void *event_info)
780 {
781    Elm_Panel_Data *sd = data;
782    Evas_Event_Mouse_Down *ev = event_info;
783    Evas_Coord finger_size = elm_config_finger_size_get();
784    Evas_Coord x, y, w, h;
785    evas_object_geometry_get(obj, &x, &y, &w, &h);
786    Eina_Bool is_mirrored = elm_widget_mirrored_get(obj);
787
788    sd->down_x = ev->canvas.x - x;
789    sd->down_y = ev->canvas.y - y;
790
791    // if freeze state & mouse down on the edge
792    // then set timer for un-freeze
793    switch (sd->orient)
794      {
795       case ELM_PANEL_ORIENT_TOP:
796          if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
797            {
798               ecore_timer_del(sd->timer);
799               sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
800            }
801          break;
802       case ELM_PANEL_ORIENT_BOTTOM:
803          if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - finger_size)))
804            {
805               ecore_timer_del(sd->timer);
806               sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
807            }
808          break;
809       case ELM_PANEL_ORIENT_LEFT:
810          if ((!is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size)) ||
811               ((is_mirrored && (sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size)))))
812            {
813               ecore_timer_del(sd->timer);
814               sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
815            }
816          break;
817       case ELM_PANEL_ORIENT_RIGHT:
818          if ((is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x < finger_size)) ||
819               (!is_mirrored && (sd->freeze) && (sd->down_x <= w) && (sd->down_x > (w - finger_size))))
820            {
821               ecore_timer_del(sd->timer);
822               sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
823            }
824          break;
825      }
826 }
827
828 static void
829 _on_mouse_move(void *data,
830                Evas *e EINA_UNUSED,
831                Evas_Object *obj,
832                void *event_info)
833 {
834    Elm_Panel_Data *sd = data;
835    Evas_Event_Mouse_Move *ev = event_info;
836    Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
837    evas_object_geometry_get(obj, &x, &y, &w, &h);
838    finger_size = elm_config_finger_size_get();
839    Eina_Bool is_mirrored = elm_widget_mirrored_get(obj);
840
841    cur_x = ev->cur.canvas.x - x;
842    cur_y = ev->cur.canvas.y - y;
843
844    // if mouse down on the edge (it means sd->timer is not null)
845    //    and move more than finger size
846    // then un-freeze
847    switch (sd->orient)
848      {
849       case ELM_PANEL_ORIENT_TOP:
850          if (sd->timer && ((cur_y - sd->down_y) > finger_size))
851            {
852               eo_do(obj, elm_interface_scrollable_movement_block_set
853                     (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
854               sd->freeze = EINA_FALSE;
855               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
856               // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
857               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
858               //
859            }
860          break;
861       case ELM_PANEL_ORIENT_BOTTOM:
862          if (sd->timer && ((sd->down_y - cur_y) > finger_size))
863            {
864               eo_do(obj, elm_interface_scrollable_movement_block_set
865                     (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
866               sd->freeze = EINA_FALSE;
867               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
868               // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
869               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
870               //
871            }
872          break;
873       case ELM_PANEL_ORIENT_LEFT:
874          if ((!is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > finger_size)) ||
875               ((is_mirrored) && (sd->timer) && ((sd->down_x - cur_x) > finger_size)))
876            {
877               eo_do(obj, elm_interface_scrollable_movement_block_set
878                     (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
879               sd->freeze = EINA_FALSE;
880               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
881               // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
882               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
883               //
884            }
885          break;
886       case ELM_PANEL_ORIENT_RIGHT:
887          if ((is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > finger_size)) ||
888               (!is_mirrored && (sd->timer) && ((sd->down_x - cur_x) > finger_size)))
889            {
890               eo_do(obj, elm_interface_scrollable_movement_block_set
891                     (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
892               sd->freeze = EINA_FALSE;
893               elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
894               // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
895               elm_object_signal_emit(obj, "elm,state,unhold", "elm");
896               //
897            }
898          break;
899      }
900
901    if (!sd->freeze && sd->hidden)
902      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
903 }
904
905 static void
906 _on_mouse_up(void *data,
907              Evas *e EINA_UNUSED,
908              Evas_Object *obj,
909              void *event_info)
910 {
911    Elm_Panel_Data *sd = data;
912    Evas_Event_Mouse_Up *ev = event_info;
913    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
914    //Evas_Coord panel_size, threshold, pos, w, h;
915    Evas_Coord w, h;
916    Eina_Bool hidden;
917
918    hidden = sd->hidden;
919    //
920
921    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
922
923    ELM_SAFE_FREE(sd->timer, ecore_timer_del);
924
925    if (_state_sync(obj)) return;
926
927    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
928    /*switch (sd->orient)
929      {
930       case ELM_PANEL_ORIENT_TOP:
931          panel_size = h * sd->content_size_ratio;
932          threshold = panel_size / 4;
933          eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
934
935          if (sd->hidden)
936            {
937               if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
938               else _drawer_close(obj, w, h, EINA_TRUE);
939            }
940          else
941            {
942               if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
943               else _drawer_close(obj, w, h, EINA_TRUE);
944            }
945          break;
946
947       case ELM_PANEL_ORIENT_BOTTOM:
948          panel_size = h * sd->content_size_ratio;
949          threshold = panel_size / 4;
950          eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
951
952          if (sd->hidden)
953            {
954               if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
955               else _drawer_close(obj, w, h, EINA_TRUE);
956            }
957          else
958            {
959               if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
960               else _drawer_close(obj, w, h, EINA_TRUE);
961            }
962          break;
963
964       case ELM_PANEL_ORIENT_LEFT:
965          panel_size = w * sd->content_size_ratio;
966          threshold = panel_size / 4;
967          eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
968
969          if (elm_widget_mirrored_get(obj))
970            {
971               if (sd->hidden)
972                 {
973                    if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
974                    else _drawer_close(obj, w, h, EINA_TRUE);
975                 }
976               else
977                 {
978                    if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
979                    else _drawer_close(obj, w, h, EINA_TRUE);
980                 }
981            }
982          else
983            {
984               if (sd->hidden)
985                 {
986                    if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
987                    else _drawer_close(obj, w, h, EINA_TRUE);
988                 }
989               else
990                 {
991                    if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
992                    else _drawer_close(obj, w, h, EINA_TRUE);
993                 }
994            }
995          break;
996
997       case ELM_PANEL_ORIENT_RIGHT:
998          panel_size = w * sd->content_size_ratio;
999          threshold = panel_size / 4;
1000          eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
1001
1002          if (!elm_widget_mirrored_get(obj))
1003            {
1004               if (sd->hidden)
1005                 {
1006                    if (pos > threshold) _drawer_open(obj, w, h, EINA_TRUE);
1007                    else _drawer_close(obj, w, h, EINA_TRUE);
1008                 }
1009               else
1010                 {
1011                    if (pos > (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
1012                    else _drawer_close(obj, w, h, EINA_TRUE);
1013                 }
1014            }
1015          else
1016            {
1017               if (sd->hidden)
1018                 {
1019                    if (pos < (panel_size - threshold)) _drawer_open(obj, w, h, EINA_TRUE);
1020                    else _drawer_close(obj, w, h, EINA_TRUE);
1021                 }
1022               else
1023                 {
1024                    if (pos < threshold) _drawer_open(obj, w, h, EINA_TRUE);
1025                    else _drawer_close(obj, w, h, EINA_TRUE);
1026                 }
1027            }
1028          break;
1029      }*/
1030    if (sd->hidden) _drawer_close(obj, w, h, EINA_TRUE);
1031    else _drawer_open(obj, w, h, EINA_TRUE);
1032
1033    if (sd->hidden != hidden)
1034      eo_do(obj, eo_event_callback_call(ELM_PANEL_EVENT_TOGGLED, NULL));
1035    //
1036
1037    if (!sd->freeze && sd->hidden)
1038      ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1039 }
1040
1041 static Eina_Bool
1042 _key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED)
1043 {
1044    _panel_toggle(NULL, obj, NULL, NULL);
1045    return EINA_TRUE;
1046 }
1047
1048 EOLIAN static Eina_Bool
1049 _elm_panel_elm_widget_event(Eo *obj, Elm_Panel_Data *_pd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info)
1050 {
1051    Evas_Event_Key_Down *ev = event_info;
1052    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1053    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1054    if (src != obj) return EINA_FALSE;
1055
1056    if (!_elm_config_key_binding_call(obj, ev, key_actions)) return EINA_FALSE;
1057
1058    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1059    return EINA_TRUE;
1060 }
1061
1062 EOLIAN static Eina_Bool
1063 _elm_panel_elm_container_content_set(Eo *obj, Elm_Panel_Data *sd, const char *part, Evas_Object *content)
1064 {
1065    if (part)
1066      {
1067         // "elm.swallow.event" part is used for internal needs and should not be changed.
1068         if (!strcmp(part, "elm.swallow.event"))
1069           {
1070              ERR("elm.swallow.event is being used for panel internally. Don't touch this part!");
1071              return EINA_FALSE;
1072           }
1073         if (strcmp(part, "default"))
1074           {
1075              Eina_Bool int_ret = EINA_TRUE;
1076              eo_do_super(obj, MY_CLASS,
1077                          int_ret = elm_obj_container_content_set(part, content));
1078
1079              return int_ret;
1080           }
1081      }
1082
1083    if (sd->content == content) return EINA_TRUE;
1084    if (sd->content)
1085      evas_object_box_remove_all(sd->bx, EINA_TRUE);
1086    sd->content = content;
1087    if (content)
1088      {
1089         evas_object_box_append(sd->bx, sd->content);
1090         evas_object_show(sd->content);
1091         if (sd->scrollable)
1092           elm_widget_sub_object_add(sd->scr_ly, sd->content);
1093         else
1094           elm_widget_sub_object_add(obj, sd->content);
1095      }
1096
1097    elm_layout_sizing_eval(obj);
1098
1099    return EINA_TRUE;
1100 }
1101
1102 EOLIAN static Evas_Object*
1103 _elm_panel_elm_container_content_get(Eo *obj, Elm_Panel_Data *sd, const char *part)
1104 {
1105    if (part)
1106      {
1107         // "elm.swallow.event" part is used for internal needs and should not be changed.
1108         if (!strcmp(part, "elm.swallow.event"))
1109           {
1110              ERR("elm.swallow.event is being used for panel internally. Don't touch this part!");
1111              return NULL;
1112           }
1113         if (strcmp(part, "default"))
1114           {
1115              Evas_Object *ret = NULL;
1116              eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(part));
1117              return ret;
1118           }
1119      }
1120
1121    return sd->content;
1122 }
1123
1124 EOLIAN static Evas_Object*
1125 _elm_panel_elm_container_content_unset(Eo *obj, Elm_Panel_Data *sd, const char *part)
1126 {
1127    Evas_Object *ret = NULL;
1128
1129    if (part)
1130      {
1131         // "elm.swallow.event" part is used for internal needs and should not be changed.
1132         if (!strcmp(part, "elm.swallow.event"))
1133           {
1134              ERR("elm.swallow.event is being used for panel internally. Don't touch this part!");
1135              return NULL;
1136           }
1137         if (strcmp(part, "default"))
1138           {
1139              eo_do_super(obj, MY_CLASS,
1140                          ret = elm_obj_container_content_unset(part));
1141              return ret;
1142           }
1143      }
1144
1145    if (!sd->content) return NULL;
1146    ret = sd->content;
1147
1148    evas_object_box_remove_all(sd->bx, EINA_FALSE);
1149    if (sd->scrollable)
1150      _elm_widget_sub_object_redirect_to_top(sd->scr_ly, sd->content);
1151    sd->content = NULL;
1152
1153    return ret;
1154 }
1155
1156 EOLIAN static void
1157 _elm_panel_evas_object_smart_add(Eo *obj, Elm_Panel_Data *priv)
1158 {
1159    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1160
1161    eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1162    elm_widget_sub_object_parent_add(obj);
1163    elm_widget_can_focus_set(obj, EINA_TRUE);
1164
1165    priv->panel_edje = wd->resize_obj;
1166    // TIZEN_ONLY(20170105): scrollable panel content size ratio refactoring (for 2.4 UX)
1167    if ((elm_win_rotation_get(elm_widget_top_get(obj)) == 90) || (elm_win_rotation_get(elm_widget_top_get(obj)) == 270))
1168      priv->content_size_ratio = 0.45;
1169    else
1170      priv->content_size_ratio = 0.80;
1171    //
1172
1173    eo_do(obj, elm_obj_widget_theme_apply());
1174
1175    priv->bx = evas_object_box_add(evas_object_evas_get(obj));
1176    evas_object_box_layout_set(priv->bx, _box_layout_cb, priv, NULL);
1177    evas_object_show(priv->bx);
1178
1179    elm_layout_signal_callback_add
1180      (obj, "elm,action,panel,toggle", "*", _panel_toggle, obj);
1181
1182    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1183
1184    priv->event = evas_object_rectangle_add(evas_object_evas_get(obj));
1185    evas_object_color_set(priv->event, 0, 0, 0, 0);
1186    evas_object_pass_events_set(priv->event, EINA_TRUE);
1187    elm_widget_sub_object_add(obj, priv->event);
1188
1189    /* just to bootstrap and have theme hook to work */
1190    if (!elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj)))
1191      CRI("Failed to set layout!");
1192    else
1193      {
1194         elm_layout_content_set(obj, "elm.swallow.content", priv->bx);
1195
1196         if (edje_object_part_exists
1197             (wd->resize_obj, "elm.swallow.event"))
1198           {
1199              Evas_Coord minw = 0, minh = 0;
1200
1201              elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1202              evas_object_size_hint_min_set(priv->event, minw, minh);
1203              eo_do_super(obj, MY_CLASS, elm_obj_container_content_set("elm.swallow.event", priv->event));
1204           }
1205      }
1206
1207    elm_layout_sizing_eval(obj);
1208 }
1209
1210 EOLIAN static void
1211 _elm_panel_evas_object_smart_del(Eo *obj, Elm_Panel_Data *sd)
1212 {
1213    Evas_Object *child;
1214    Eina_List *l;
1215
1216    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1217
1218    sd->delete_me = EINA_TRUE;
1219
1220    ELM_SAFE_FREE(sd->timer, ecore_timer_del);
1221
1222    /* let's make our panel object the *last* to be processed, since it
1223     * may (smart) parent other sub objects here */
1224    EINA_LIST_FOREACH(wd->subobjs, l, child)
1225      {
1226         if (child == sd->bx)
1227           {
1228              wd->subobjs =
1229                eina_list_demote_list(wd->subobjs, l);
1230              break;
1231           }
1232      }
1233
1234    eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1235 }
1236
1237 EOLIAN static void
1238 _elm_panel_evas_object_smart_move(Eo *obj, Elm_Panel_Data *sd, Evas_Coord x, Evas_Coord y)
1239 {
1240    eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
1241
1242    evas_object_move(sd->hit_rect, x, y);
1243 }
1244
1245 static void
1246 _scrollable_layout_resize(Eo *obj, Elm_Panel_Data *sd, Evas_Coord w, Evas_Coord h)
1247 {
1248    switch (sd->orient)
1249      {
1250       case ELM_PANEL_ORIENT_TOP:
1251       case ELM_PANEL_ORIENT_BOTTOM:
1252          // vertical
1253          evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
1254          evas_object_size_hint_min_set(sd->scr_panel, w, (sd->content_size_ratio * h));
1255          evas_object_size_hint_min_set(sd->scr_event, w, h);
1256          break;
1257       case ELM_PANEL_ORIENT_LEFT:
1258       case ELM_PANEL_ORIENT_RIGHT:
1259          // horizontal
1260          evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
1261          evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio * w), h);
1262          evas_object_size_hint_min_set(sd->scr_event, w, h);
1263          break;
1264      }
1265
1266    elm_layout_sizing_eval(obj);
1267 }
1268
1269 EOLIAN static void
1270 _elm_panel_evas_object_smart_resize(Eo *obj, Elm_Panel_Data *sd, Evas_Coord w, Evas_Coord h)
1271 {
1272    eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
1273
1274    if (!sd->scrollable) return;
1275
1276    evas_object_resize(sd->hit_rect, w, h);
1277
1278    _scrollable_layout_resize(obj, sd, w, h);
1279 }
1280
1281 EOLIAN static void
1282 _elm_panel_evas_object_smart_member_add(Eo *obj, Elm_Panel_Data *sd, Evas_Object *member)
1283 {
1284    eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
1285
1286    if (sd->hit_rect) evas_object_raise(sd->hit_rect);
1287 }
1288
1289 // TIZEN_ONLY(20170105): scrollable panel content size ratio refactoring (for 2.4 UX)
1290 EOLIAN static void
1291 _elm_panel_elm_widget_orientation_set(Eo *obj, Elm_Panel_Data *sd, int orient_mode)
1292 {
1293    eo_do_super(obj, MY_CLASS, elm_obj_widget_orientation_set(orient_mode));
1294
1295    if (!sd->content_size_manual_set)
1296      {
1297         if (orient_mode == 90 || orient_mode == 270)
1298           sd->content_size_ratio = 0.45;
1299         else
1300           sd->content_size_ratio = 0.80;
1301      }
1302
1303    if (sd->scrollable)
1304      {
1305         Evas_Coord w, h;
1306         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1307
1308         _scrollable_layout_resize(obj, sd, w, h);
1309      }
1310 }
1311 //
1312
1313 EOLIAN static void
1314 _elm_panel_elm_widget_access(Eo *obj, Elm_Panel_Data *_pd, Eina_Bool is_access)
1315 {
1316    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1317    Elm_Panel_Data *sd = _pd;
1318
1319    if (sd->scrollable)
1320      {
1321         _access_obj_process(obj, is_access);
1322         return;
1323      }
1324
1325    if (is_access)
1326      _elm_access_edje_object_part_object_register
1327        (obj, wd->resize_obj, "btn_icon");
1328    else
1329      _elm_access_edje_object_part_object_unregister
1330        (obj, wd->resize_obj, "btn_icon");
1331 }
1332
1333 EAPI Evas_Object *
1334 elm_panel_add(Evas_Object *parent)
1335 {
1336    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1337    Evas_Object *obj = eo_add(MY_CLASS, parent);
1338
1339    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1340    wd->highlight_root = EINA_TRUE;
1341
1342    return obj;
1343 }
1344
1345 EOLIAN static Eo *
1346 _elm_panel_eo_base_constructor(Eo *obj, Elm_Panel_Data *_pd EINA_UNUSED)
1347 {
1348    obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
1349    eo_do(obj,
1350          evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1351          evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
1352          elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_PANEL));
1353
1354    return obj;
1355 }
1356
1357 EOLIAN static void
1358 _elm_panel_orient_set(Eo *obj, Elm_Panel_Data *sd, Elm_Panel_Orient orient)
1359 {
1360    if (sd->orient == orient) return;
1361    sd->orient = orient;
1362
1363    if (sd->scrollable)
1364      {
1365         _scrollable_layout_theme_set(obj, sd);
1366
1367         if (!sd->freeze)
1368           {
1369              switch (sd->orient)
1370                {
1371                   case ELM_PANEL_ORIENT_TOP:
1372                   case ELM_PANEL_ORIENT_BOTTOM:
1373                      eo_do(obj, elm_interface_scrollable_movement_block_set
1374                            (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
1375                      break;
1376                   case ELM_PANEL_ORIENT_LEFT:
1377                   case ELM_PANEL_ORIENT_RIGHT:
1378                      eo_do(obj, elm_interface_scrollable_movement_block_set
1379                            (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
1380                      break;
1381                }
1382
1383              sd->freeze = EINA_TRUE;
1384              elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
1385              // TIZEN_ONLY(20170613): emit signal when panel is hidden
1386              elm_object_signal_emit(obj, "elm,state,hold", "elm");
1387              //
1388           }
1389
1390         // TIZEN_ONLY(20170105): scrollable panel content size ratio refactoring (for 2.4 UX)
1391         //elm_panel_scrollable_content_size_set(obj, sd->content_size_ratio);
1392         Evas_Coord w, h;
1393         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1394
1395         _scrollable_layout_resize(obj, sd, w, h);
1396         //
1397      }
1398    else
1399      _orient_set_do(obj);
1400
1401    elm_layout_sizing_eval(obj);
1402 }
1403
1404 EOLIAN static Elm_Panel_Orient
1405 _elm_panel_orient_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd)
1406 {
1407    return sd->orient;
1408 }
1409
1410 EOLIAN static void
1411 _elm_panel_hidden_set(Eo *obj, Elm_Panel_Data *sd, Eina_Bool hidden)
1412 {
1413    if (sd->hidden == !!hidden)
1414      {
1415         if (sd->scrollable && sd->hidden && !sd->freeze)
1416           {
1417              Evas_Coord w, h;
1418              evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1419              _drawer_close(obj, w, h, EINA_TRUE);
1420           }
1421         return;
1422      }
1423
1424    _panel_toggle(NULL, obj, NULL, NULL);
1425 }
1426
1427 EOLIAN static Eina_Bool
1428 _elm_panel_hidden_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd)
1429 {
1430    return sd->hidden;
1431 }
1432
1433 EOLIAN static void
1434 _elm_panel_toggle(Eo *obj, Elm_Panel_Data *_pd EINA_UNUSED)
1435 {
1436    _panel_toggle(NULL, obj, NULL, NULL);
1437 }
1438
1439 EOLIAN static Eina_Bool
1440 _elm_panel_elm_widget_on_focus_region(Eo *obj,
1441                                       Elm_Panel_Data *sd,
1442                                       Evas_Coord *x,
1443                                       Evas_Coord *y,
1444                                       Evas_Coord *w,
1445                                       Evas_Coord *h)
1446 {
1447    eo_do(obj, elm_interface_scrollable_content_pos_get(x, y));
1448    evas_object_geometry_get(obj, NULL, NULL, w, h);
1449    switch (sd->orient)
1450      {
1451       case ELM_PANEL_ORIENT_TOP:
1452       case ELM_PANEL_ORIENT_BOTTOM:
1453          *h = *h * sd->content_size_ratio;
1454          break;
1455       case ELM_PANEL_ORIENT_LEFT:
1456       case ELM_PANEL_ORIENT_RIGHT:
1457          *w = *w * sd->content_size_ratio;
1458          break;
1459      }
1460    return EINA_TRUE;
1461 }
1462
1463 static void
1464 _anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED)
1465 {
1466    // TIZEN_ONLY(20170316): set hidden property when panel is close/open
1467    /*if (elm_widget_disabled_get(obj)) return;
1468    _state_sync(obj);*/
1469
1470    ELM_PANEL_DATA_GET(obj, sd);
1471    Evas_Object *ao;
1472    Evas_Coord pos, w, h, panel_size = 0;
1473    Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE, reverse = EINA_FALSE;
1474
1475    if (elm_widget_disabled_get(obj)) return;
1476
1477    switch (sd->orient)
1478      {
1479       case ELM_PANEL_ORIENT_BOTTOM:
1480          reverse = EINA_TRUE;
1481       case ELM_PANEL_ORIENT_TOP:
1482          break;
1483
1484       case ELM_PANEL_ORIENT_RIGHT:
1485          reverse = EINA_TRUE;
1486       case ELM_PANEL_ORIENT_LEFT:
1487          horizontal = EINA_TRUE;
1488          break;
1489      }
1490
1491    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1492    if (horizontal)
1493      {
1494          if (w <= 0) return;
1495
1496          panel_size = w * sd->content_size_ratio;
1497          eo_do(obj, elm_interface_scrollable_content_pos_get(&pos, NULL));
1498          reverse ^= elm_widget_mirrored_get(obj);
1499      }
1500    else
1501      {
1502          if (h <= 0) return;
1503
1504          panel_size = h * sd->content_size_ratio;
1505          eo_do(obj, elm_interface_scrollable_content_pos_get(NULL, &pos));
1506      }
1507
1508    if (pos == 0) open = !reverse;
1509    else if (pos == panel_size) open = reverse;
1510    else return;
1511
1512    if (open)
1513      {
1514         eo_do(obj, elm_interface_scrollable_single_direction_set
1515               (ELM_SCROLLER_SINGLE_DIRECTION_HARD));
1516
1517         //focus & access
1518         elm_object_tree_focus_allow_set(obj, EINA_TRUE);
1519         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1520           {
1521              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1522              evas_object_show(ao);
1523              _elm_access_highlight_set(ao);
1524           }
1525         else
1526           elm_object_focus_set(obj, EINA_TRUE);
1527      }
1528    else
1529      {
1530         if (horizontal)
1531           eo_do(obj, elm_interface_scrollable_movement_block_set
1532                 (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
1533         else
1534           eo_do(obj, elm_interface_scrollable_movement_block_set
1535                 (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
1536         sd->freeze = EINA_TRUE;
1537         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,hidden", "elm");
1538         // TIZEN_ONLY(20170613): emit signal when panel is hidden
1539         elm_object_signal_emit(obj, "elm,state,hold", "elm");
1540         //
1541
1542         eo_do(obj, elm_interface_scrollable_single_direction_set
1543               (ELM_SCROLLER_SINGLE_DIRECTION_NONE));
1544
1545         //focus & access
1546         elm_object_tree_focus_allow_set(obj, EINA_FALSE);
1547         if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
1548           {
1549              ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1550              evas_object_hide(ao);
1551           }
1552      }
1553    //
1554 }
1555
1556 static void
1557 _scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
1558 {
1559    ELM_PANEL_DATA_GET(obj, sd);
1560    Elm_Panel_Scroll_Info event;
1561    Evas_Coord x, y, w, h;
1562
1563    if (elm_widget_disabled_get(obj)) return;
1564    // in the case of
1565    // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
1566    if (sd->freeze)
1567      {
1568         eo_do(obj, elm_interface_scrollable_movement_block_set
1569               (ELM_SCROLLER_MOVEMENT_NO_BLOCK));
1570         sd->freeze = EINA_FALSE;
1571         elm_layout_signal_emit(sd->scr_ly, "elm,state,content,visible", "elm");
1572         // TIZEN_ONLY(20170613): emit signal when panel becomes draggable
1573         elm_object_signal_emit(obj, "elm,state,unhold", "elm");
1574         //
1575      }
1576
1577    eo_do(obj, elm_interface_scrollable_content_pos_get(&x, &y));
1578    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1579
1580    switch (sd->orient)
1581      {
1582       case ELM_PANEL_ORIENT_TOP:
1583          event.rel_x = 1;
1584          event.rel_y = 1 - ((double) y / (double) ((sd->content_size_ratio) * h));
1585         break;
1586       case ELM_PANEL_ORIENT_BOTTOM:
1587          event.rel_x = 1;
1588          event.rel_y = (double) y / (double) ((sd->content_size_ratio) * h);
1589         break;
1590       case ELM_PANEL_ORIENT_LEFT:
1591         if (!elm_widget_mirrored_get(obj))
1592           {
1593              event.rel_x = 1 - ((double) x / (double) ((sd->content_size_ratio) * w));
1594              event.rel_y = 1;
1595           }
1596         else
1597           {
1598              event.rel_x = (double) x / (double) ((sd->content_size_ratio) * w);
1599              event.rel_y = 1;
1600            }
1601         break;
1602       case ELM_PANEL_ORIENT_RIGHT:
1603         if (elm_widget_mirrored_get(obj))
1604           {
1605              event.rel_x = 1 - ((double) x / (double) ((sd->content_size_ratio) * w));
1606              event.rel_y = 1;
1607           }
1608         else
1609           {
1610              event.rel_x = (double) x / (double) ((sd->content_size_ratio) * w);
1611              event.rel_y = 1;
1612           }
1613         break;
1614      }
1615    eo_do(obj, eo_event_callback_call
1616      (EVAS_SCROLLABLE_INTERFACE_EVENT_SCROLL, (void *) &event));
1617 }
1618
1619 EOLIAN static Eina_Bool
1620 _elm_panel_elm_widget_disable(Eo *obj, Elm_Panel_Data *sd)
1621 {
1622    Eina_Bool int_ret = EINA_FALSE;
1623    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1624    if (!int_ret) return EINA_FALSE;
1625
1626    if (sd->scrollable)
1627      {
1628         if (elm_widget_disabled_get(obj) && sd->callback_added)
1629           {
1630              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
1631                                             _on_mouse_down);
1632              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
1633                                             _on_mouse_move);
1634              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
1635                                             _on_mouse_up);
1636              evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1637                                             _event_mouse_up);
1638
1639              sd->callback_added = EINA_FALSE;
1640           }
1641         else if (!elm_widget_disabled_get(obj) && !sd->callback_added)
1642           {
1643              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1644                                             _on_mouse_down, sd);
1645              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1646                                             _on_mouse_move, sd);
1647              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1648                                             _on_mouse_up, sd);
1649              evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1650                                             _event_mouse_up, obj);
1651
1652              sd->callback_added = EINA_TRUE;
1653           }
1654      }
1655
1656    return EINA_TRUE;
1657 }
1658
1659 EOLIAN static double
1660 _elm_panel_scrollable_content_size_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd)
1661 {
1662    return sd->content_size_ratio;
1663 }
1664
1665 EOLIAN static void
1666 _elm_panel_scrollable_content_size_set(Eo *obj, Elm_Panel_Data *sd, double ratio)
1667 {
1668    if (ratio < 0) ratio = 0;
1669    else if (ratio > 1.0) ratio = 1.0;
1670
1671    sd->content_size_ratio = ratio;
1672    // TIZEN_ONLY(20170105): scrollable panel content size ratio refactoring (for 2.4 UX)
1673    sd->content_size_manual_set = EINA_TRUE;
1674    //
1675
1676    if (sd->scrollable)
1677      {
1678         Evas_Coord w, h;
1679         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1680
1681         _scrollable_layout_resize(obj, sd, w, h);
1682      }
1683 }
1684
1685 EOLIAN static Eina_Bool
1686 _elm_panel_scrollable_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *sd)
1687 {
1688    return sd->scrollable;
1689 }
1690
1691 EOLIAN static void
1692 _elm_panel_scrollable_set(Eo *obj, Elm_Panel_Data *sd, Eina_Bool scrollable)
1693 {
1694    scrollable = !!scrollable;
1695    if (sd->scrollable == scrollable) return;
1696    sd->scrollable = scrollable;
1697
1698    if (scrollable)
1699      {
1700         // TIZEN_ONLY(20170309): initialize repeat_events when scrollable is set.
1701         evas_object_repeat_events_set(obj, EINA_FALSE);
1702         //
1703         elm_layout_content_unset(obj, "elm.swallow.content");
1704
1705         elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1706         elm_widget_sub_object_add(obj, sd->panel_edje);
1707         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1708         evas_object_hide(sd->panel_edje);
1709         //
1710
1711         if (!sd->scr_edje)
1712           {
1713              const char *handler_size;
1714
1715              sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
1716              elm_widget_theme_object_set(obj, sd->scr_edje, "scroller", "panel",
1717                                          elm_widget_style_get(obj));
1718              evas_object_size_hint_weight_set
1719                 (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1720              evas_object_size_hint_align_set
1721                 (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
1722
1723              handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
1724              if (handler_size)
1725                sd->handler_size = (int) (elm_object_scale_get(obj)) * (atoi(handler_size));
1726           }
1727
1728         elm_widget_resize_object_set(obj, sd->scr_edje, EINA_TRUE);
1729         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1730         evas_object_show(sd->scr_edje);
1731         //
1732
1733         if (!sd->hit_rect)
1734           {
1735              sd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
1736              evas_object_smart_member_add(sd->hit_rect, obj);
1737              elm_widget_sub_object_add(obj, sd->hit_rect);
1738              evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
1739              evas_object_show(sd->hit_rect);
1740              evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
1741
1742              eo_do(obj,
1743                    elm_interface_scrollable_objects_set(sd->scr_edje, sd->hit_rect),
1744                    elm_interface_scrollable_animate_stop_cb_set(_anim_stop_cb),
1745                    elm_interface_scrollable_scroll_cb_set(_scroll_cb));
1746           }
1747
1748         if (!sd->scr_ly)
1749           {
1750              sd->scr_ly = elm_layout_add(obj);
1751              evas_object_smart_member_add(sd->scr_ly, obj);
1752              elm_widget_sub_object_add(obj, sd->scr_ly);
1753              _scrollable_layout_theme_set(obj, sd);
1754
1755              sd->scr_panel = evas_object_rectangle_add(evas_object_evas_get(obj));
1756              evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
1757              elm_widget_sub_object_add(obj, sd->scr_panel);
1758              elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
1759
1760              sd->scr_event = evas_object_rectangle_add(evas_object_evas_get(obj));
1761              evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
1762              elm_widget_sub_object_add(obj, sd->scr_event);
1763              elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
1764           }
1765
1766         eo_do(obj,
1767               elm_interface_scrollable_content_set(sd->scr_ly));
1768         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1769         evas_object_show(sd->scr_ly);
1770         //
1771         sd->freeze = EINA_TRUE;
1772         elm_layout_content_set(sd->scr_ly, "elm.swallow.content", sd->bx);
1773         if (sd->content) elm_widget_sub_object_add(sd->scr_ly, sd->content);
1774
1775         // TIZEN_ONLY(20170105): scrollable panel content size ratio refactoring (for 2.4 UX)
1776         Evas_Coord w, h;
1777         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1778
1779         _scrollable_layout_resize(obj, sd, w, h);
1780         //
1781
1782         switch (sd->orient)
1783           {
1784            case ELM_PANEL_ORIENT_TOP:
1785            case ELM_PANEL_ORIENT_BOTTOM:
1786               eo_do(obj, elm_interface_scrollable_movement_block_set
1787                     (ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL));
1788               break;
1789            case ELM_PANEL_ORIENT_LEFT:
1790            case ELM_PANEL_ORIENT_RIGHT:
1791               eo_do(obj, elm_interface_scrollable_movement_block_set
1792                     (ELM_SCROLLER_MOVEMENT_BLOCK_HORIZONTAL));
1793               break;
1794           }
1795
1796         eo_do(obj, elm_interface_scrollable_single_direction_set
1797               (ELM_SCROLLER_SINGLE_DIRECTION_NONE));
1798
1799         if (!elm_widget_disabled_get(obj) && !sd->callback_added)
1800           {
1801              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
1802                                             _on_mouse_down, sd);
1803              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
1804                                             _on_mouse_move, sd);
1805              evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1806                                             _on_mouse_up, sd);
1807              evas_object_event_callback_add(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1808                                             _event_mouse_up, obj);
1809
1810              sd->callback_added = EINA_TRUE;
1811           }
1812
1813      }
1814    else
1815      {
1816         eo_do(obj, elm_interface_scrollable_content_set(NULL));
1817
1818         if (sd->callback_added)
1819           {
1820              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down);
1821              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _on_mouse_move);
1822              evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up);
1823              evas_object_event_callback_del(sd->scr_event, EVAS_CALLBACK_MOUSE_UP,
1824                                             _event_mouse_up);
1825
1826              sd->callback_added = EINA_FALSE;
1827           }
1828
1829         elm_widget_resize_object_set(obj, NULL, EINA_TRUE);
1830         elm_widget_sub_object_add(obj, sd->scr_edje);
1831         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1832         evas_object_hide(sd->scr_edje);
1833         //
1834
1835         elm_widget_resize_object_set(obj, sd->panel_edje, EINA_TRUE);
1836         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1837         evas_object_show(sd->panel_edje);
1838         //
1839
1840         elm_layout_content_unset(sd->scr_ly, "elm.swallow.content");
1841         // TIZEN_ONLY(20171109): show and hide necessary object when scrollable is set
1842         evas_object_hide(sd->scr_ly);
1843         //
1844         elm_layout_content_set(obj, "elm.swallow.content", sd->bx);
1845         if (sd->content) elm_widget_sub_object_add(obj, sd->content);
1846      }
1847 }
1848
1849 static void
1850 _elm_panel_class_constructor(Eo_Class *klass)
1851 {
1852    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1853 }
1854
1855 EOLIAN const Elm_Atspi_Action *
1856 _elm_panel_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Panel_Data *pd EINA_UNUSED)
1857 {
1858    static Elm_Atspi_Action atspi_actions[] = {
1859           { "toggle", "toggle", NULL, _key_action_toggle},
1860           { NULL, NULL, NULL, NULL }
1861    };
1862    return &atspi_actions[0];
1863 }
1864
1865 // TIZEN_ONLY(20170829) : [atspi][panel] Adds accessibility support for the panel widget.
1866 EOLIAN static Elm_Atspi_State_Set
1867 _elm_panel_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Panel_Data *sd EINA_UNUSED)
1868 {
1869    Elm_Atspi_State_Set ret;
1870    eo_do_super(obj, MY_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
1871
1872    if (!sd->hidden)
1873       STATE_TYPE_SET(ret, ELM_ATSPI_STATE_SHOWING);
1874    else
1875       STATE_TYPE_UNSET(ret, ELM_ATSPI_STATE_SHOWING);
1876
1877    STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MODAL);
1878
1879    return ret;
1880 }
1881 //
1882 #include "elm_panel.eo.c"