jaehyun pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=d9a222ecf59622ec9cf80a908b0a987d18f87b0f

commit d9a222ecf59622ec9cf80a908b0a987d18f87b0f
Author: Woochanlee <[email protected]>
Date:   Thu Dec 20 11:32:28 2018 +0900

    Intruduce Efl.Ui.Panel (Create Efl Ui Widget from elm widget(elm_panel))
    
    Summary: Create Efl Ui Widget from elm widget(elm_panel)
    
    Test Plan: elementary_test -> efl_ui_panel
    
    Reviewers: woohyun, Jaehyun_Cho, segfaultxavi
    
    Reviewed By: Jaehyun_Cho, segfaultxavi
    
    Subscribers: segfaultxavi, cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D7238
---
 data/elementary/themes/Makefile.am        |    1 +
 data/elementary/themes/default.edc        |    1 +
 data/elementary/themes/edc/efl/panel.edc  |  831 +++++++++++++++++
 src/Makefile_Elementary.am                |    4 +
 src/bin/elementary/Makefile.am            |    1 +
 src/bin/elementary/meson.build            |    1 +
 src/bin/elementary/test.c                 |    4 +
 src/bin/elementary/test_ui_panel.c        |  159 ++++
 src/lib/elementary/Elementary.h           |    1 +
 src/lib/elementary/efl_ui_panel.c         | 1386 +++++++++++++++++++++++++++++
 src/lib/elementary/efl_ui_panel.eo        |   95 ++
 src/lib/elementary/efl_ui_panel_private.h |   81 ++
 src/lib/elementary/meson.build            |    3 +
 13 files changed, 2568 insertions(+)

diff --git a/data/elementary/themes/Makefile.am 
b/data/elementary/themes/Makefile.am
index 2e176633f7..7116e63b0c 100644
--- a/data/elementary/themes/Makefile.am
+++ b/data/elementary/themes/Makefile.am
@@ -1026,6 +1026,7 @@ elementary/themes/edc/efl/grid.edc \
 elementary/themes/edc/efl/navigation_bar.edc \
 elementary/themes/edc/efl/navigation_layout.edc \
 elementary/themes/edc/efl/tags.edc \
+elementary/themes/edc/efl/panel.edc \
 elementary/themes/edc/efl/nstate.edc \
 elementary/themes/edc/efl/panes.edc \
 elementary/themes/edc/efl/photocam.edc \
diff --git a/data/elementary/themes/default.edc 
b/data/elementary/themes/default.edc
index d0e7126fd4..95f879a8a8 100644
--- a/data/elementary/themes/default.edc
+++ b/data/elementary/themes/default.edc
@@ -186,6 +186,7 @@ collections {
 #include "edc/efl/video.edc"
 #include "edc/efl/focus.edc"
 #include "edc/efl/tags.edc"
+#include "edc/efl/panel.edc"
 #include "edc/efl/tooltip.edc"
 #include "edc/efl/photocam.edc"
 #include "edc/efl/progress.edc"
diff --git a/data/elementary/themes/edc/efl/panel.edc 
b/data/elementary/themes/edc/efl/panel.edc
new file mode 100644
index 0000000000..aee2e31f6f
--- /dev/null
+++ b/data/elementary/themes/edc/efl/panel.edc
@@ -0,0 +1,831 @@
+group { name: "efl/panel";
+   data {
+      item: "handler_size" "30";
+   }
+   parts {
+      part { name: "efl.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+         }
+      }
+   }
+}
+group { name: "efl/panel/scrollable/left";
+   parts {
+      part { name: "efl.panel_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel2.relative: 0.0 1.0;
+            align: 0.0 0.5;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.event_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1 {
+               relative: 1.0 0.0;
+               to: "efl.panel_area";
+            }
+            rel2 {
+               relative: 1.0 1.0;
+               to: "efl.panel_area";
+            }
+            align: 0.0 0.5;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "access.outline";
+         type: RECT;
+         repeat_events: 1;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "bg";
+         type: RECT;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 64 64 64 255;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+   }
+   programs {
+      program { name: "active";
+         signal: "efl,state,content,visible";
+         source: "efl";
+         action: STATE_SET "visible" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+      program { name: "inactive";
+         signal: "efl,state,content,hidden";
+         source: "efl";
+         action: STATE_SET "default" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+   }
+}
+
+group { name: "efl/panel/scrollable/right";
+   parts {
+      part { name: "efl.event_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel2.relative: 0.0 1.0;
+            align: 0.0 0.5;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.panel_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1 {
+               relative: 1.0 0.0;
+               to: "efl.event_area";
+            }
+            rel2 {
+               relative: 1.0 1.0;
+               to: "efl.event_area";
+            }
+            align: 0.0 0.5;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "access.outline";
+         type: RECT;
+         repeat_events: 1;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "bg";
+         type: RECT;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 64 64 64 255;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+   }
+   programs {
+      program { name: "active";
+         signal: "efl,state,content,visible";
+         source: "efl";
+         action: STATE_SET "visible" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+      program { name: "inactive";
+         signal: "efl,state,content,hidden";
+         source: "efl";
+         action: STATE_SET "default" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+   }
+}
+
+group { name: "efl/panel/scrollable/top";
+   parts {
+      part { name: "efl.panel_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel2.relative: 1.0 0.0;
+            align: 0.5 0.0;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.event_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1 {
+               relative: 0.0 1.0;
+               to: "efl.panel_area";
+            }
+            rel2 {
+               relative: 1.0 1.0;
+               to: "efl.panel_area";
+            }
+            align: 0.5 0.0;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "access.outline";
+         type: RECT;
+         repeat_events: 1;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "bg";
+         type: RECT;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 64 64 64 255;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+   }
+   programs {
+      program { name: "active";
+         signal: "efl,state,content,visible";
+         source: "efl";
+         action: STATE_SET "visible" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+      program { name: "inactive";
+         signal: "efl,state,content,hidden";
+         source: "efl";
+         action: STATE_SET "default" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+   }
+}
+
+group { name: "efl/panel/scrollable/bottom";
+   parts {
+      part { name: "efl.event_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel2.relative: 1.0 0.0;
+            align: 0.5 0.0;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.panel_area";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1 {
+               relative: 0.0 1.0;
+               to: "efl.event_area";
+            }
+            rel2 {
+               relative: 1.0 1.0;
+               to: "efl.event_area";
+            }
+            align: 0.5 0.0;
+            fixed: 1 1;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "access.outline";
+         type: RECT;
+         repeat_events: 1;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 0 0 0 0;
+         }
+      }
+      part { name: "bg";
+         type: RECT;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            color: 64 64 64 255;
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+      part { name: "efl.content";
+         type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1.to: "efl.panel_area";
+            rel2.to: "efl.panel_area";
+            visible: 0;
+         }
+         description { state: "visible" 0.0;
+            inherit: "default" 0.0;
+            visible: 1;
+         }
+      }
+   }
+   programs {
+      program { name: "active";
+         signal: "efl,state,content,visible";
+         source: "efl";
+         action: STATE_SET "visible" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+      program { name: "inactive";
+         signal: "efl,state,content,hidden";
+         source: "efl";
+         action: STATE_SET "default" 0.0;
+         target: "efl.panel_area";
+         target: "efl.event_area";
+         target: "bg";
+         target: "efl.content";
+      }
+   }
+}
+
+group { name: "efl/panel/left";
+   images.image: "bevel_out.png" COMP;
+   images.image: "shine.png" COMP;
+   images.image: "shadow_square_tiny.png" COMP;
+   images.image: "holes_tiny_glow_vert.png" COMP;
+   images.image: "holes_tiny_glow_horiz.png" COMP;
+   images.image: "win_glow.png" COMP;
+   images.image: "icon_arrow_right.png" COMP;
+   images.image: "icon_arrow_left.png" COMP;
+   images.image: "icon_arrow_up.png" COMP;
+   images.image: "icon_arrow_down.png" COMP;
+   data.item: "focus_highlight" "on";
+   script {
+      public is_rtl = 0;
+   }
+   parts {
+      part { name: "shadow"; mouse_events: 0;
+         description { state: "default" 0.0;
+            rel1.offset: -3 -2;
+            rel1.to: "base";
+            rel2.offset: 2 4;
+            rel2.to: "base";
+            image.normal: "shadow_square_tiny.png";
+            image.border: 6 6 6 6;
+            fill.smooth: 0;
+         }
+      }
+      part { name: "glow"; mouse_events: 0;
+         description { state: "default" 0.0;
+            image.normal: "win_glow.png";
+            image.border: 9 9 9 9;
+            image.middle: 0;
+            rel1.offset: -5  -5;
+            rel1.to: "base";
+            rel2.offset: 4 4;
+            rel2.to: "base";
+            fill.smooth: 0;
+            color: 255 255 255 0;
+            visible: 0;
+         }
+         description { state: "focused" 0.0;
+            inherit: "default" 0.0;
+            color: 255 255 255 255;
+            visible: 1;
+         }
+      }
+      part { name: "all"; type: SPACER;
+         description { state: "default" 0.0;
+         }
+      }
+      part { name: "base"; type: RECT;
+         description { state: "default" 0.0;
+            rel1.to_x: "all";
+            rel2.to_x: "efl.swallow.event";
+            rel2.relative: 0.0 1.0;
+            rel2.offset: -4 -1;
+            color: 64 64 64 255;
+         }
+      }
+      part { name: "efl.content"; type: SWALLOW;
+         description { state: "default" 0.0;
+            rel1.offset: 4 4;
+            rel1.to: "base";
+            rel2.offset: -5 -5;
+            rel2.to: "base";
+         }
+      }
+      part { name: "bevel"; mouse_events: 0;
+         description { state: "default" 0.0;
+            rel1.to: "base";
+            rel2.to: "base";
+            image.normal: "bevel_out.png";
+            image.border: 1 1 1 1;
+            image.middle: 0;
+            fill.smooth: 0;
+         }
+      }
+      part { name: "shine"; mouse_events: 0;
+         description { state: "default" 0.0;
+            image.normal: "shine.png";
+            rel1.offset: 0 -2;
+            rel1.to: "base";
+            rel2.relative: 1.0 0.0;
+            rel2.offset: -1 2;
+            rel2.to: "base";
+            FIXED_SIZE(69, 5)
+         }
+      }
+      part { name: "efl.swallow.event"; type: SWALLOW;
+         description { state: "default" 0.0;
+            fixed: 1 1;
+            min: 20 20;
+            max: 20 20;
+            align: 1.0 0.5;
+            rel1.relative: 1.0 0.0;
+            rel2.relative: 1.0 1.0;
+            color: 0 0 0 0;
+         }
+         description { state: "hidden" 0.0;
+            inherit: "default" 0.0;
+            align: 0.0 0.5;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 0.0 1.0;
+         }
+      }
+      part { name: "btn"; type: RECT;
+         description { state: "default" 0.0;
+            rel1.to: "efl.swallow.event";
+            rel2.to: "efl.swallow.event";
+            color: 0 0 0 0;
+         }
+         description { state: "hidden" 0.0;
+            rel1.to: "efl.swallow.event";
+            rel2.to: "efl.swallow.event";
+         }
+      }
+      part { name: "dots"; mouse_events: 0;
+         description { state: "default" 0.0;
+            rel1.to: "icn";
+            rel2.to: "icn";
+            align: 0.0 0.5;
+            image.normal: "holes_tiny_glow_vert.png";
+            FIXED_SIZE(11, 17)
+         }
+      }
+      part { name: "icn"; mouse_events: 0;
+         scale: 1;
+         description { state: "default" 0.0;
+            fixed: 1 1;
+            min: 20 20;
+            max: 20 20;
+            rel1.to: "btn";
+            rel2.to: "btn";
+            image.normal: "icon_arrow_left.png";
+         }
+         description { state: "hidden" 0.0;
+            inherit: "default" 0.0;
+            image.normal: "icon_arrow_right.png";
+         }
+      }
+   }
+   programs {
+      program {
+         signal: "mouse,clicked,1"; source: "btn";
+         action: SIGNAL_EMIT "efl,action,panel,toggle" "efl";
+      }
+      program {
+         signal: "efl,action,show"; source: "efl";
+         action: STATE_SET "default" 0.0;
+         transition: DECELERATE 0.3;
+         target: "efl.swallow.event";
+         target: "base";
+      }
+      program {
+         signal: "efl,action,show"; source: "efl";
+         script {
+            if (get_int(is_rtl) == 0)
+              set_state(PART:"icn", "default", 0.0);
+            else
+              set_state(PART:"icn", "hidden", 0.0);
+         }
+      }
+      program {
+         signal: "edje,state,rtl";
+         source: "edje";
+         script {
+            new st[31];
+            new Float:vl;
+            get_state(PART:"efl.swallow.event", st, 30, vl);
+            if (!strcmp(st, "default"))
+              set_state(PART:"icn", "hidden", 0.0);
+            else
+              set_state(PART:"icn", "default", 0.0);
+            set_int(is_rtl, 1);
+         }
+      }
+      program {
+         signal: "edje,state,ltr"; 
+         source: "edje";
+         script {
+            new st[31];
+            new Float:vl;
+            get_state(PART:"efl.swallow.event", st, 30, vl);
+            if (!strcmp(st, "default"))
+              set_state(PART:"icn", "default", 0.0);
+            else
+              set_state(PART:"icn", "hidden", 0.0);
+            set_int(is_rtl, 0);
+         }
+      }
+      program {
+         signal: "efl,action,hide"; source: "efl";
+         action: STATE_SET "hidden" 0.0;
+         transition: ACCELERATE 0.3;
+         target: "efl.swallow.event";
+      }
+      program {
+         signal: "efl,action,hide"; source: "efl";
+         script {
+            if (get_int(is_rtl) == 0)
+              set_state(PART:"icn", "hidden", 0.0);
+            else
+              set_state(PART:"icn", "default", 0.0);
+         }
+      }
+      program { name: "hide1";
+         signal: "efl,action,hide"; source: "efl";
+         script {
+            new x, y, w, h;
+            if (get_int(is_rtl) == 0)
+              {
+                 custom_state(PART:"base", "default", 0.0);
+                 set_state_val(PART:"base", STATE_REL1, -1.0, 0.0);
+                 get_geometry(PART:"efl.swallow.event", x, y, w, h);
+                 set_state_val(PART:"base", STATE_REL1_OFFSET, w, 0);
+               }
+            else
+              {
+                 custom_state(PART:"base", "default", 0.0);
+                 set_state_val(PART:"base", STATE_REL1, -1.0, 0.0);
+                 set_state_val(PART:"base", STATE_REL2, -2.0, 1.0);
+                 get_geometry(PART:"efl.swallow.event", x, y, w, h);
+                 set_state_val(PART:"base", STATE_REL2_OFFSET, -w, 0);
+              }
+         }
+         after: "hide2";
+      }
+      program { name: "hide2";
+         action: STATE_SET "custom" 0.0;
+         transition: ACCELERATE 0.3;
+         target: "base";
+      }
+      program {
+         signal: "efl,action,focus_highlight,show"; source: "efl";
+         action: STATE_SET "focused" 0.0;
+         transition: ACCELERATE 0.2;
+         target: "glow";
+      }
+      program {
+         signal: "efl,action,focus_highlight,hide"; source: "efl";
+         action: STATE_SET "default" 0.0;
+         transition: DECELERATE 0.5;
+         target: "glow";
+      }
+   }
+}
+
+group { name: "efl/panel/right";
+   inherit: "efl/panel/left";
+   parts {
+      part { name: "base";
+         description { state: "default" 0.0;
+            rel1.relative: 1.0 0.0;
+            rel1.to_x: "efl.swallow.event";
+            rel1.offset: 3 0;
+            rel2.relative: 1.0 1.0;
+            rel2.to_x: "all";
+            rel2.offset: -1 -1;
+         }
+      }
+      part { name: "efl.swallow.event";
+         description { state: "default" 0.0;
+            align: 0.0 0.5;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 0.0 1.0;
+         }
+         description { state: "hidden" 0.0;
+            align: 1.0 0.5;
+            rel1.relative: 1.0 0.0;
+            rel2.relative: 1.0 1.0;
+         }
+      }
+      part { name: "dots";
+         description { state: "default" 0.0;
+            align: 1.0 0.5;
+         }
+      }
+      part { name: "icn";
+         description { state: "default" 0.0;
+            image.normal: "icon_arrow_right.png";
+         }
+         description { state: "hidden" 0.0;
+            image.normal: "icon_arrow_left.png";
+         }
+      }
+   }
+   programs {
+      program { name: "hide1";
+         script {
+            new x, y, w, h;
+    
+            custom_state(PART:"base", "default", 0.0);
+            set_state_val(PART:"base", STATE_REL1, 1.0, 0.0);
+            set_state_val(PART:"base", STATE_REL2, 2.0, 1.0);
+            get_geometry(PART:"efl.swallow.event", x, y, w, h);
+            set_state_val(PART:"base", STATE_REL2_OFFSET, -w, 0);
+         }
+      }
+   }
+}
+
+group { name: "efl/panel/top";
+   inherit: "efl/panel/left";
+   parts {
+      part { name: "base";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 0.0;
+            rel1.to_x: "all";
+            rel1.to_y: "all";
+            rel1.offset: 0 0;
+            rel2.relative: 1.0 0.0;
+            rel2.to_x: "all";
+            rel2.to_y: "efl.swallow.event";
+            rel2.offset: -1 -4;
+         }
+      }
+      part { name: "efl.swallow.event";
+         description { state: "default" 0.0;
+            align: 0.5 1.0;
+            rel1.relative: 0.0 1.0;
+            rel2.relative: 1.0 1.0;
+         }
+         description { state: "hidden" 0.0;
+            align: 0.5 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 0.0;
+         }
+      }
+      part { name: "dots";
+         description { state: "default" 0.0;
+            align: 0.5 0.0;
+            image.normal: "holes_tiny_glow_horiz.png";
+            FIXED_SIZE(17, 11)
+         }
+      }
+      part { name: "icn";
+         description { state: "default" 0.0;
+            image.normal: "icon_arrow_up.png";
+         }
+         description { state: "hidden" 0.0;
+            image.normal: "icon_arrow_down.png";
+         }
+      }
+   }
+   programs {
+      program { name: "hide1";
+         script {
+            new x, y, w, h;
+            
+            custom_state(PART:"base", "default", 0.0);
+            set_state_val(PART:"base", STATE_REL1, 0.0, -1.0);
+            set_state_val(PART:"base", STATE_REL2, 1.0, 0.0);
+            get_geometry(PART:"efl.swallow.event", x, y, w, h);
+            set_state_val(PART:"base", STATE_REL1_OFFSET, 0, h);
+         }
+      }
+      program {
+         signal: "efl,action,show"; source: "efl";
+         action: STATE_SET "default" 0.0;
+         target: "icn";
+      }
+      program {
+         signal: "edje,state,rtl";
+         source: "edje";
+         script {
+            new st[31];
+            new Float:vl;
+            get_state(PART:"efl.swallow.event", st, 30, vl);
+            if (!strcmp(st, "default"))
+              set_state(PART:"icn", "default", 0.0);
+            else
+              set_state(PART:"icn", "hidden", 0.0);
+         }
+      }
+      program {
+         signal: "edje,state,ltr";
+         source: "edje";
+         script {
+            new st[31];
+            new Float:vl;
+            get_state(PART:"efl.swallow.event", st, 30, vl);
+            if (!strcmp(st, "default"))
+              set_state(PART:"icn", "default", 0.0);
+            else
+              set_state(PART:"icn", "hidden", 0.0);
+         }
+      }
+      program {
+         signal: "efl,action,hide"; source: "efl";
+         action: STATE_SET "hidden" 0.0;
+         target: "icn";
+      }
+   }
+}
+
+group { name: "efl/panel/bottom";
+   inherit: "efl/panel/top";
+   parts {
+      part { name: "base";
+         description { state: "default" 0.0;
+            rel1.relative: 0.0 1.0;
+            rel1.to_x: "all";
+            rel1.to_y: "efl.swallow.event";
+            rel1.offset: 0 3;
+            rel2.relative: 1.0 1.0;
+            rel2.to_x: "all";
+            rel2.to_y: "all";
+            rel2.offset: -1 -1;
+         }
+      }
+      part { name: "efl.swallow.event";
+         description { state: "default" 0.0;
+            align: 0.5 0.0;
+            rel1.relative: 0.0 0.0;
+            rel2.relative: 1.0 0.0;
+         }
+         description { state: "hidden" 0.0;
+            align: 0.5 1.0;
+            rel1.relative: 0.0 1.0;
+            rel2.relative: 1.0 1.0;
+         }
+      }
+      part { name: "dots";
+         description { state: "default" 0.0;
+            align: 0.5 0.0;
+            image.normal: "holes_tiny_glow_horiz.png";
+            FIXED_SIZE(17, 11)
+         }
+      }
+      part { name: "icn";
+         description { state: "default" 0.0;
+            image.normal: "icon_arrow_down.png";
+         }
+         description { state: "hidden" 0.0;
+            image.normal: "icon_arrow_up.png";
+         }
+      }
+   }
+   programs {
+      program { name: "hide1";
+         script {
+            new x, y, w, h;
+            custom_state(PART:"base", "default", 0.0);
+            set_state_val(PART:"base", STATE_REL1, 0.0, 1.0);
+            set_state_val(PART:"base", STATE_REL2, 1.0, 2.0);
+            get_geometry(PART:"efl.swallow.event", x, y, w, h);
+            set_state_val(PART:"base", STATE_REL2_OFFSET, 0, -h);
+         }
+      }
+   }
+}
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index 0c75466680..af5d06abfe 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -29,6 +29,7 @@ elm_public_eolian_files = \
        lib/elementary/efl_ui_datepicker.eo \
        lib/elementary/efl_ui_timepicker.eo \
        lib/elementary/efl_ui_tags.eo \
+       lib/elementary/efl_ui_panel.eo \
        lib/elementary/efl_ui_video.eo \
        lib/elementary/efl_ui_win.eo \
        lib/elementary/efl_ui_win_inlined.eo \
@@ -414,6 +415,7 @@ includesunstable_HEADERS = \
        lib/elementary/efl_ui_datepicker_private.h \
        lib/elementary/efl_ui_timepicker_private.h \
        lib/elementary/efl_ui_tags_private.h \
+       lib/elementary/efl_ui_panel_private.h \
        lib/elementary/elm_widget_table.h \
        lib/elementary/elm_widget_thumb.h \
        lib/elementary/elm_widget_toolbar.h \
@@ -787,6 +789,7 @@ lib_elementary_libelementary_la_SOURCES = \
        lib/elementary/efl_ui_datepicker.c \
        lib/elementary/efl_ui_timepicker.c \
        lib/elementary/efl_ui_tags.c \
+       lib/elementary/efl_ui_panel.c \
        lib/elementary/elm_slideshow.c \
        lib/elementary/elm_spinner.c \
        lib/elementary/elm_store.c \
@@ -1064,6 +1067,7 @@ bin/elementary/test_ui_spin_button.c \
 bin/elementary/test_ui_datepicker.c \
 bin/elementary/test_ui_timepicker.c \
 bin/elementary/test_ui_tags.c \
+bin/elementary/test_ui_panel.c \
 bin/elementary/test_slideshow.c \
 bin/elementary/test_spinner.c \
 bin/elementary/test_store.c \
diff --git a/src/bin/elementary/Makefile.am b/src/bin/elementary/Makefile.am
index 8828276e26..290ea0e110 100644
--- a/src/bin/elementary/Makefile.am
+++ b/src/bin/elementary/Makefile.am
@@ -136,6 +136,7 @@ test_ui_buttonspin.c \
 test_ui_datepicker.c \
 test_ui_timepicker.c \
 test_ui_tags.c \
+test_ui_panel.c \
 test_store.c \
 test_sys_notify.c \
 test_systray.c \
diff --git a/src/bin/elementary/meson.build b/src/bin/elementary/meson.build
index ddc778ba2c..f8ca71e9c8 100644
--- a/src/bin/elementary/meson.build
+++ b/src/bin/elementary/meson.build
@@ -98,6 +98,7 @@ elementary_test_src = [
   'test_panel.c',
   'test_panes.c',
   'test_ui_panes.c',
+  'test_ui_panel.c',
   'test_part_bg.c',
   'test_part_shadow.c',
   'test_photo.c',
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index 9298e9b2e2..de66b96582 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -189,6 +189,8 @@ void test_ui_spin_button(void *data, Evas_Object *obj, void 
*event_info);
 void test_ui_datepicker(void *data, Evas_Object *obj, void *event_info);
 void test_ui_timepicker(void *data, Evas_Object *obj, void *event_info);
 void test_ui_tags(void *data, Evas_Object *obj, void *event_info);
+void test_ui_panel(void *data, Evas_Object *obj, void *event_info);
+void test_ui_panel2(void *data, Evas_Object *obj, void *event_info);
 void test_index(void *data, Evas_Object *obj, void *event_info);
 void test_index2(void *data, Evas_Object *obj, void *event_info);
 void test_index3(void *data, Evas_Object *obj, void *event_info);
@@ -1165,6 +1167,8 @@ add_tests:
    ADD_TEST(NULL, "Dividers", "Panel Scrollable", test_panel2);
    ADD_TEST(NULL, "Dividers", "Panes", test_panes);
    ADD_TEST_EO(NULL, "Dividers", "Efl.Ui.Panes", test_panes_minsize);
+   ADD_TEST_EO(NULL, "Dividers", "Efl.Ui.Panel", test_ui_panel);
+   ADD_TEST_EO(NULL, "Dividers", "Efl.Ui.Panel Scrollable", test_ui_panel2);
 
    //------------------------------//
    ADD_TEST(NULL, "Standardization", "Conformant", test_conformant);
diff --git a/src/bin/elementary/test_ui_panel.c 
b/src/bin/elementary/test_ui_panel.c
new file mode 100644
index 0000000000..eed8d14759
--- /dev/null
+++ b/src/bin/elementary/test_ui_panel.c
@@ -0,0 +1,159 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+
+void
+test_ui_panel(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   char buf[PATH_MAX] = {0};
+   Eo *win, *table, *panel;
+
+   win = efl_add_ref(EFL_UI_WIN_CLASS, NULL,
+                     efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
+                     efl_text_set(efl_added, "Efl.Ui.Panel"),
+                     efl_ui_win_autodel_set(efl_added, EINA_TRUE));
+
+   table = efl_add(EFL_UI_TABLE_CLASS, win,
+                   efl_content_set(win, efl_added));
+
+   snprintf(buf, sizeof(buf), "%s/images/plant_01.jpg", 
elm_app_data_dir_get());
+   efl_add(EFL_UI_IMAGE_CLASS, table,
+           efl_file_set(efl_added, buf, NULL),
+           efl_gfx_size_hint_weight_set(efl_added, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND),
+           efl_gfx_size_hint_align_set(efl_added, EVAS_HINT_FILL, 
EVAS_HINT_FILL),
+           efl_pack_table(table, efl_added, 0, 0, 4, 5));
+
+   // Top Panel
+   panel = efl_add(EFL_UI_PANEL_CLASS, table,
+           efl_ui_panel_orient_set(efl_added, EFL_UI_PANEL_ORIENT_TOP),
+           efl_pack_table(table, efl_added, 0, 0, 4, 1));
+
+   efl_add(EFL_UI_BUTTON_CLASS, panel,
+           efl_text_set(efl_added, "Top Panel"),
+           efl_content_set(panel, efl_added));
+
+   // Left Panel
+   panel = efl_add(EFL_UI_PANEL_CLASS, table,
+           efl_ui_panel_orient_set(efl_added, EFL_UI_PANEL_ORIENT_LEFT),
+           efl_pack_table(table, efl_added, 0, 2, 2, 1));
+
+   efl_add(EFL_UI_BUTTON_CLASS, panel,
+           efl_text_set(efl_added, "Left Panel"),
+           efl_content_set(panel, efl_added));
+
+   // Right Panel
+   panel = efl_add(EFL_UI_PANEL_CLASS, table,
+           efl_ui_panel_orient_set(efl_added, EFL_UI_PANEL_ORIENT_RIGHT),
+           efl_pack_table(table, efl_added, 2, 2, 2, 1));
+
+   efl_add(EFL_UI_BUTTON_CLASS, panel,
+           efl_text_set(efl_added, "Right Panel"),
+           efl_content_set(panel, efl_added));
+
+   // Bottom Panel
+   panel = efl_add(EFL_UI_PANEL_CLASS, table,
+           efl_ui_panel_orient_set(efl_added, EFL_UI_PANEL_ORIENT_BOTTOM),
+           efl_pack_table(table, efl_added, 0, 4, 4, 1));
+
+   efl_add(EFL_UI_BUTTON_CLASS, panel,
+           efl_text_set(efl_added, "Bottom Panel"),
+           efl_content_set(panel, efl_added));
+
+   efl_gfx_entity_size_set(win, EINA_SIZE2D(280, 320));
+}
+
+static void
+_check_changed(void *data EINA_UNUSED, const Efl_Event *ev)
+{
+   
elm_config_scroll_thumbscroll_enabled_set(efl_ui_nstate_value_get(ev->object));
+}
+
+static void
+_panel_toggled(void *data, const Efl_Event *ev)
+{
+   Evas_Object *list;
+   int i;
+
+   if (!efl_ui_nstate_value_get(data)) return;
+
+   list = efl_content_get(ev->object);
+   evas_object_del(list);
+
+   list = elm_list_add(ev->object);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   for (i = 0; i < 7; i++)
+     elm_list_item_append(list, "panel list item", NULL, NULL, NULL, NULL);
+   efl_content_set(ev->object, list);
+
+   printf("Panel toggled:%s\n", efl_ui_panel_hidden_get(ev->object) ? "hidden" 
: "visible");
+}
+
+static void
+_btn_clicked(void *data, const Efl_Event *ev EINA_UNUSED)
+{
+   Eo *panel = data;
+   efl_ui_panel_toggle(panel);
+}
+void
+test_ui_panel2(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void 
*event_info EINA_UNUSED)
+{
+   int i;
+   Eo *win, *box, *check, *btn, *table, *list, *panel;
+
+   win = efl_add_ref(EFL_UI_WIN_CLASS, NULL,
+                     efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
+                     efl_text_set(efl_added, "Efl.Ui.Panel"),
+                     efl_ui_win_autodel_set(efl_added, EINA_TRUE));
+
+   box = efl_add(EFL_UI_BOX_CLASS, win,
+                 efl_content_set(win, efl_added));
+
+   efl_add(EFL_UI_CHECK_CLASS, box,
+           efl_ui_check_selected_set(efl_added, 
elm_config_scroll_thumbscroll_enabled_get()),
+           efl_text_set(efl_added, "Enable thumb scroll (temporarily"),
+           efl_event_callback_add(efl_added, EFL_UI_NSTATE_EVENT_CHANGED, 
_check_changed, NULL),
+           efl_gfx_size_hint_weight_set(efl_added, EVAS_HINT_EXPAND, 0),
+           efl_pack(box, efl_added));
+
+   check = efl_add(EFL_UI_CHECK_CLASS, box,
+                   efl_text_set(efl_added, "Reset content on toggle"),
+                   efl_gfx_size_hint_weight_set(efl_added, EVAS_HINT_EXPAND, 
0),
+                   efl_pack(box, efl_added));
+
+   btn = efl_add(EFL_UI_BUTTON_CLASS, box,
+                 efl_text_set(efl_added, "toggle"),
+                 efl_gfx_size_hint_weight_set(efl_added, EVAS_HINT_EXPAND, 0),
+                 efl_pack(box, efl_added));
+
+   table = efl_add(EFL_UI_TABLE_CLASS, box,
+                   efl_pack(box, efl_added));
+
+   list = elm_list_add(table);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_show(list);
+   for (i = 0; i < 20; i++)
+     elm_list_item_append(list, "center list item", NULL, NULL, NULL, NULL);
+   efl_pack_table(table, list, 0, 0, 1, 1);
+
+   panel = efl_add(EFL_UI_PANEL_CLASS, table,
+                   efl_ui_panel_orient_set(efl_added, 
EFL_UI_PANEL_ORIENT_LEFT),
+                   efl_ui_panel_scrollable_set(efl_added, EINA_TRUE),
+                   efl_ui_panel_hidden_set(efl_added, EINA_TRUE),
+                   efl_ui_panel_scrollable_content_size_set(efl_added, 0.75),
+                   efl_pack_table(table, efl_added, 0, 0, 1, 1));
+
+   list = elm_list_add(panel);
+   evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   for (i = 0; i < 7; i++)
+     elm_list_item_append(list, "left panel item", NULL, NULL, NULL, NULL);
+   efl_content_set(panel, list);
+
+   efl_event_callback_add(panel, EFL_UI_PANEL_EVENT_TOGGLED, _panel_toggled, 
check);
+   efl_event_callback_add(btn, EFL_UI_EVENT_CLICKED, _btn_clicked, panel);
+
+   efl_gfx_entity_size_set(win, EINA_SIZE2D(320, 400));
+}
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 9bd33c4feb..99798e77cd 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -323,6 +323,7 @@ typedef Eo Efl_Ui_Focus_Manager;
 # include <efl_ui_datepicker.eo.h>
 # include <efl_ui_timepicker.eo.h>
 # include <efl_ui_tags.eo.h>
+# include <efl_ui_panel.eo.h>
 # include <efl_ui_image_factory.eo.h>
 # include <efl_ui_slider.eo.h>
 # include <efl_ui_slider_interval.eo.h>
diff --git a/src/lib/elementary/efl_ui_panel.c 
b/src/lib/elementary/efl_ui_panel.c
new file mode 100644
index 0000000000..06d33235a5
--- /dev/null
+++ b/src/lib/elementary/efl_ui_panel.c
@@ -0,0 +1,1386 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#define EFL_ACCESS_OBJECT_PROTECTED
+#define EFL_ACCESS_WIDGET_ACTION_PROTECTED
+#define EFL_UI_FOCUS_LAYER_PROTECTED
+#define EFL_PART_PROTECTED
+
+#include <Elementary.h>
+
+#include "elm_priv.h"
+#include "efl_ui_panel_private.h"
+
+#include "els_box.h"
+
+#include "elm_part_helper.h"
+
+#define MY_CLASS EFL_UI_PANEL_CLASS
+
+#define MY_CLASS_NAME "Efl.Ui.Panel"
+
+static const char ACCESS_OUTLINE_PART[] = "access.outline";
+static const char SIG_TOGGLED[] = "toggled";
+static const char SIG_SCROLL[] = "scroll";
+
+static const Evas_Smart_Cb_Description _smart_callbacks[] = {
+   {SIG_TOGGLED, ""},
+   {SIG_SCROLL, ""},
+   {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
+   {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
+   {NULL, NULL}
+};
+static void _panel_toggle(void *, Evas_Object *, const char *,const char *);
+static Eina_Bool _key_action_toggle(Evas_Object *obj, const char *params);
+static void _drawer_open(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool );
+static void _drawer_close(Evas_Object *, Evas_Coord , Evas_Coord , Eina_Bool);
+
+static const Elm_Action key_actions[] = {
+   {"toggle", _key_action_toggle},
+   {NULL, NULL}
+};
+
+static void
+_mirrored_set(Evas_Object *obj,
+              Eina_Bool rtl)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+
+   if ((sd->content) && (efl_isa(sd->content, EFL_UI_WIDGET_CLASS)))
+     efl_ui_mirrored_set(sd->content, rtl);
+   efl_ui_panel_orient_set(obj, efl_ui_panel_orient_get(obj));
+}
+
+EOLIAN static void
+_efl_ui_panel_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Panel_Data *sd)
+{
+   Evas_Coord mw = 0, mh = 0;
+
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+
+   if (sd->delete_me) return;
+
+   if (sd->scrollable)
+     {
+        if (sd->hidden) _drawer_close(obj, wd->w, wd->h, EINA_FALSE);
+        else _drawer_open(obj, wd->w, wd->h, EINA_FALSE);
+     }
+
+   evas_object_smart_calculate(sd->bx);
+   edje_object_size_min_calc(wd->resize_obj, &mw, &mh);
+   evas_object_size_hint_min_set(obj, mw, mh);
+   evas_object_size_hint_max_set(obj, -1, -1);
+}
+
+static char *
+_access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
+{
+   EFL_UI_PANEL_DATA_GET(data, sd);
+
+   if (!sd->hidden) return strdup(E_("state: opened"));
+   else return strdup(E_("state: closed"));
+
+   return NULL;
+}
+
+static Evas_Object *
+_access_object_get(const Evas_Object *obj, const char *part)
+{
+   Evas_Object *po, *ao, *o;
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+
+   o = elm_layout_edje_get(sd->scr_ly);
+   edje_object_freeze(o);
+   po = (Evas_Object *)edje_object_part_object_get(o, part);
+   edje_object_thaw(o);
+   ao = evas_object_data_get(po, "_part_access_obj");
+
+   return ao;
+}
+
+static void
+_access_activate_cb(void *data,
+                    Evas_Object *part_obj EINA_UNUSED,
+                    Elm_Object_Item *item EINA_UNUSED)
+{
+   efl_ui_panel_hidden_set(data, EINA_TRUE);
+}
+
+static void
+_access_obj_process(Evas_Object *obj, Eina_Bool is_access)
+{
+   Evas_Object *ao;
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+
+   if (is_access)
+     {
+        ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
+        if (!ao)
+          {
+             ao = _elm_access_edje_object_part_object_register
+                (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
+             _elm_access_text_set(_elm_access_info_get(ao),
+                                  ELM_ACCESS_TYPE, E_("A panel is open"));
+             _elm_access_text_set(_elm_access_info_get(ao),
+                                  ELM_ACCESS_CONTEXT_INFO, E_("Double tap to 
close panel menu"));
+             _elm_access_activate_callback_set
+                (_elm_access_info_get(ao), _access_activate_cb, obj);
+          }
+     }
+   else
+     {
+        _elm_access_edje_object_part_object_unregister
+           (obj, elm_layout_edje_get(sd->scr_ly), ACCESS_OUTLINE_PART);
+     }
+}
+
+static void
+_orient_set_do(Evas_Object *obj)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         elm_widget_theme_element_set(obj, "top");
+         break;
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         elm_widget_theme_element_set(obj, "bottom");
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         elm_widget_theme_element_set(obj, "left");
+         break;
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         elm_widget_theme_element_set(obj, "right");
+         break;
+     }
+
+   efl_ui_widget_theme_apply(obj);
+
+   /* access */
+   if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
+     {
+        Evas_Object *ao;
+        ao = _elm_access_edje_object_part_object_register
+            (obj, wd->resize_obj, "btn_icon");
+        _elm_access_text_set(_elm_access_info_get(ao),
+                             ELM_ACCESS_TYPE, E_("panel button"));
+        _elm_access_callback_set
+          (_elm_access_info_get(ao), ELM_ACCESS_STATE, _access_state_cb, obj);
+     }
+}
+
+static void
+_scrollable_layout_theme_set(Eo *obj, Efl_Ui_Panel_Data *sd)
+{
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         elm_widget_theme_element_set(sd->scr_ly, "scrollable/top");
+         break;
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         elm_widget_theme_element_set(sd->scr_ly, "scrollable/bottom");
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         elm_widget_theme_element_set(sd->scr_ly, "scrollable/left");
+         break;
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         elm_widget_theme_element_set(sd->scr_ly, "scrollable/right");
+         break;
+     }
+
+   efl_ui_widget_theme_apply(sd->scr_ly);
+
+   /* access */
+   if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
+     _access_obj_process(obj, EINA_TRUE);
+}
+
+EOLIAN static Efl_Ui_Theme_Apply_Result
+_efl_ui_panel_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Panel_Data *sd)
+{
+   const char *str;
+   Evas_Coord minw = 0, minh = 0;
+
+   Efl_Ui_Theme_Apply_Result int_ret = EFL_UI_THEME_APPLY_RESULT_FAIL;
+
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EFL_UI_THEME_APPLY_RESULT_FAIL);
+
+   int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
+   if (!int_ret) return EFL_UI_THEME_APPLY_RESULT_FAIL;
+
+   _mirrored_set(obj, efl_ui_mirrored_get(obj));
+
+   if (sd->scrollable)
+     {
+        const char *handler_size;
+        elm_widget_theme_object_set(obj, sd->scr_edje, "panel", NULL,
+                                    elm_widget_style_get(obj));
+        handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
+        if (handler_size)
+          sd->handler_size = (int) (elm_object_scale_get(obj)) * 
(atoi(handler_size));
+     }
+   else
+     {
+        str = edje_object_data_get
+           (wd->resize_obj, "focus_highlight");
+        if ((str) && (!strcmp(str, "on")))
+          elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
+        else
+          elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
+
+        evas_object_hide(sd->event);
+        elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+        evas_object_size_hint_min_set(sd->event, minw, minh);
+
+        if (edje_object_part_exists(wd->resize_obj, "efl.swallow.event"))
+          efl_content_set(efl_part(efl_super(obj, MY_CLASS), 
"efl.swallow.event"), sd->event);
+     }
+
+   if (efl_finalized_get(obj))
+     elm_layout_sizing_eval(obj);
+
+   return int_ret;
+}
+
+static void
+_box_layout_cb(Evas_Object *o,
+               Evas_Object_Box_Data *_pd,
+               void *data EINA_UNUSED)
+{
+   _els_box_layout(o, _pd, EINA_TRUE, EINA_FALSE, EINA_FALSE);
+}
+
+static void
+_handler_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+
+   if (sd->handler_size == 0) return;
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         elm_interface_scrollable_region_bring_in
+               (obj, 0, (h * sd->content_size_ratio) - sd->handler_size, w, h);
+         break;
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         elm_interface_scrollable_region_bring_in
+               (obj, 0, sd->handler_size, w, h);
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         elm_interface_scrollable_region_bring_in
+               (obj, (w * sd->content_size_ratio) - sd->handler_size, 0, w, h);
+         break;
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         elm_interface_scrollable_region_bring_in
+               (obj, sd->handler_size, 0, w, h);
+         break;
+     }
+}
+
+static void
+_drawer_open(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   int x = 0, y = 0;
+
+   if (sd->freeze)
+     {
+        elm_interface_scrollable_movement_block_set
+              (obj, EFL_UI_SCROLL_BLOCK_NONE);
+        sd->freeze = EINA_FALSE;
+        elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
+     }
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         if (efl_ui_mirrored_get(obj))
+           x = w * sd->content_size_ratio;
+         break;
+
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         y = h * sd->content_size_ratio;
+         break;
+
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         if (!efl_ui_mirrored_get(obj))
+           x = w * sd->content_size_ratio;
+         break;
+     }
+
+   if (anim)
+     elm_interface_scrollable_region_bring_in
+           (obj, x, y, w, h);
+   else
+     elm_interface_scrollable_content_region_show
+           (obj, x, y, w, h);
+}
+
+static void
+_drawer_close(Evas_Object *obj, Evas_Coord w, Evas_Coord h, Eina_Bool anim)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   int x = 0, y = 0, cx, cy;
+   Eina_Bool horizontal = EINA_FALSE;
+
+   elm_widget_tree_unfocusable_set(obj, EINA_TRUE);
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         y = h * sd->content_size_ratio;
+         break;
+
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         if (!efl_ui_mirrored_get(obj))
+           x = w * sd->content_size_ratio;
+         horizontal = EINA_TRUE;
+         break;
+
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         break;
+
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         if (efl_ui_mirrored_get(obj))
+           x = w * sd->content_size_ratio;
+         horizontal = EINA_TRUE;
+         break;
+     }
+
+   elm_interface_scrollable_content_pos_get(obj, &cx, &cy);
+
+   if ((x == cx) && (y == cy))
+     {
+        if (!sd->freeze)
+          {
+             if (horizontal)
+               elm_interface_scrollable_movement_block_set
+                  (obj, EFL_UI_SCROLL_BLOCK_HORIZONTAL);
+             else
+               elm_interface_scrollable_movement_block_set
+                  (obj, EFL_UI_SCROLL_BLOCK_VERTICAL);
+             sd->freeze = EINA_TRUE;
+             elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", 
"efl");
+          }
+
+        return;
+     }
+
+   if (anim)
+     {
+        if (sd->freeze)
+          {
+             elm_interface_scrollable_movement_block_set
+                   (obj, EFL_UI_SCROLL_BLOCK_NONE);
+             sd->freeze = EINA_FALSE;
+             elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", 
"efl");
+          }
+        elm_interface_scrollable_region_bring_in(obj, x, y, w, h);
+     }
+   else
+     {
+        elm_interface_scrollable_content_region_show(obj, x, y, w, h);
+        if (!sd->freeze)
+          {
+             if (horizontal)
+               elm_interface_scrollable_movement_block_set
+                     (obj, EFL_UI_SCROLL_BLOCK_HORIZONTAL);
+             else
+               elm_interface_scrollable_movement_block_set
+                     (obj, EFL_UI_SCROLL_BLOCK_VERTICAL);
+             sd->freeze = EINA_TRUE;
+             elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", 
"efl");
+          }
+     }
+}
+
+static void
+_panel_toggle(void *data EINA_UNUSED,
+              Evas_Object *obj,
+              const char *emission EINA_UNUSED,
+              const char *source EINA_UNUSED)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+   int w, h;
+
+   if (sd->scrollable)
+     {
+        if (elm_widget_disabled_get(obj)) return;
+
+        evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+        if (sd->hidden)
+          {
+             sd->hidden = EINA_FALSE;
+             _drawer_open(obj, w, h, EINA_TRUE);
+          }
+        else
+          {
+             sd->hidden = EINA_TRUE;
+             _drawer_close(obj, w, h, EINA_TRUE);
+          }
+     }
+   else
+     {
+        if (sd->hidden)
+          {
+             elm_layout_signal_emit(obj, "efl,action,show", "efl");
+             sd->hidden = EINA_FALSE;
+             evas_object_repeat_events_set(obj, EINA_FALSE);
+          }
+        else
+          {
+             elm_layout_signal_emit(obj, "efl,action,hide", "efl");
+             sd->hidden = EINA_TRUE;
+             evas_object_repeat_events_set(obj, EINA_TRUE);
+          }
+
+        //if the panel is hidden, make this thing unfocusable
+        elm_widget_tree_unfocusable_set(obj, sd->hidden);
+        edje_object_message_signal_process(wd->resize_obj);
+     }
+
+   efl_ui_focus_layer_enable_set(obj, !sd->hidden);
+   efl_event_callback_call(obj, EFL_UI_PANEL_EVENT_TOGGLED, NULL);
+}
+
+static Eina_Bool
+_state_sync(Evas_Object *obj)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   Evas_Coord pos, panel_size, w, h, threshold;
+   Eina_Bool horizontal = EINA_FALSE, reverse = EINA_FALSE;
+
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+   if (!evas_object_visible_get(sd->bx)) return EINA_TRUE;
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         reverse = EINA_TRUE;
+      case EFL_UI_PANEL_ORIENT_TOP:
+         break;
+
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         reverse = EINA_TRUE;
+         EINA_FALLTHROUGH;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         horizontal = EINA_TRUE;
+         break;
+     }
+
+   if (horizontal)
+     {
+         if (w <= 0) return EINA_TRUE;
+
+         panel_size = w * sd->content_size_ratio;
+         elm_interface_scrollable_content_pos_get(obj, &pos, NULL);
+         reverse ^= efl_ui_mirrored_get(obj);
+     }
+   else
+     {
+         if (h <= 0) return EINA_TRUE;
+
+         panel_size = h * sd->content_size_ratio;
+         elm_interface_scrollable_content_pos_get(obj, NULL, &pos);
+     }
+   threshold = (sd->hidden) ? panel_size - (panel_size / 4) : (panel_size / 4);
+
+   if (reverse)
+     {
+         if (pos > panel_size - threshold) sd->hidden = EINA_FALSE;
+         else sd->hidden = EINA_TRUE;
+     }
+   else
+     {
+         if (pos < threshold) sd->hidden = EINA_FALSE;
+         else sd->hidden = EINA_TRUE;
+     }
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+_timer_cb(void *data)
+{
+   EFL_UI_PANEL_DATA_GET(data, sd);
+   Evas_Object *obj = data;
+   Evas_Coord w, h;
+
+   sd->timer = NULL;
+
+   if (sd->freeze)
+     {
+        elm_interface_scrollable_movement_block_set
+              (obj, EFL_UI_SCROLL_BLOCK_NONE);
+        sd->freeze = EINA_FALSE;
+        elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
+        evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+        _handler_open(obj, w, h);
+     }
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_event_mouse_up(void *data,
+                Evas *e EINA_UNUSED,
+                Evas_Object *obj EINA_UNUSED,
+                void *event_info)
+{
+   EFL_UI_PANEL_DATA_GET(data, sd);
+   Evas_Event_Mouse_Up *ev = event_info;
+   Evas_Coord x, y, up_x, up_y, minw = 0, minh = 0;
+   evas_object_geometry_get(data, &x, &y, NULL, NULL);
+
+   up_x = ev->canvas.x - x;
+   up_y = ev->canvas.y - y;
+
+   elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+
+   if ((!sd->hidden) && (up_x == sd->down_x) && (up_y == sd->down_y))
+     efl_ui_panel_hidden_set(data, EINA_TRUE);
+}
+
+static void
+_on_mouse_down(void *data,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Efl_Ui_Panel_Data *sd = data;
+   Evas_Event_Mouse_Down *ev = event_info;
+   Evas_Coord finger_size = elm_config_finger_size_get();
+   Evas_Coord x, y, w, h;
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   Eina_Bool is_mirrored = efl_ui_mirrored_get(obj);
+
+   sd->down_x = ev->canvas.x - x;
+   sd->down_y = ev->canvas.y - y;
+
+   // if freeze state & mouse down on the edge
+   // then set timer for un-freeze
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         if ((sd->freeze) && (sd->down_y >= 0) && (sd->down_y < finger_size))
+           {
+              ecore_timer_del(sd->timer);
+              sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
+           }
+         break;
+         case EFL_UI_PANEL_ORIENT_BOTTOM:
+         if ((sd->freeze) && (sd->down_y <= h) && (sd->down_y > (h - 
finger_size)))
+           {
+              ecore_timer_del(sd->timer);
+              sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
+           }
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         if ((!is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x 
< finger_size)) ||
+              ((is_mirrored && (sd->freeze) && (sd->down_x <= w) && 
(sd->down_x > (w - finger_size)))))
+           {
+              ecore_timer_del(sd->timer);
+              sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
+           }
+         break;
+         case EFL_UI_PANEL_ORIENT_RIGHT:
+         if ((is_mirrored && (sd->freeze) && (sd->down_x >= 0) && (sd->down_x 
< finger_size)) ||
+              (!is_mirrored && (sd->freeze) && (sd->down_x <= w) && 
(sd->down_x > (w - finger_size))))
+           {
+              ecore_timer_del(sd->timer);
+              sd->timer = ecore_timer_add(0.2, _timer_cb, obj);
+           }
+         break;
+     }
+}
+
+static void
+_on_mouse_move(void *data,
+               Evas *e EINA_UNUSED,
+               Evas_Object *obj,
+               void *event_info)
+{
+   Efl_Ui_Panel_Data *sd = data;
+   Evas_Event_Mouse_Move *ev = event_info;
+   Evas_Coord x, y, w, h, cur_x, cur_y, finger_size;
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   finger_size = elm_config_finger_size_get();
+   Eina_Bool is_mirrored = efl_ui_mirrored_get(obj);
+
+   cur_x = ev->cur.canvas.x - x;
+   cur_y = ev->cur.canvas.y - y;
+
+   // if mouse down on the edge (it means sd->timer is not null)
+   //    and move more than finger size
+   // then un-freeze
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         if (sd->timer && ((cur_y - sd->down_y) > finger_size))
+           {
+              elm_interface_scrollable_movement_block_set
+                 (obj, EFL_UI_SCROLL_BLOCK_NONE);
+              sd->freeze = EINA_FALSE;
+              elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", 
"efl");
+           }
+         break;
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         if (sd->timer && ((sd->down_y - cur_y) > finger_size))
+           {
+              elm_interface_scrollable_movement_block_set
+                 (obj, EFL_UI_SCROLL_BLOCK_NONE);
+              sd->freeze = EINA_FALSE;
+              elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", 
"efl");
+           }
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         if ((!is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > 
finger_size)) ||
+              ((is_mirrored) && (sd->timer) && ((sd->down_x - cur_x) > 
finger_size)))
+           {
+              elm_interface_scrollable_movement_block_set
+                 (obj, EFL_UI_SCROLL_BLOCK_NONE);
+              sd->freeze = EINA_FALSE;
+              elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", 
"efl");
+           }
+         break;
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         if ((is_mirrored && (sd->timer) && ((cur_x - sd->down_x) > 
finger_size)) ||
+              (!is_mirrored && (sd->timer) && ((sd->down_x - cur_x) > 
finger_size)))
+           {
+              elm_interface_scrollable_movement_block_set
+                 (obj, EFL_UI_SCROLL_BLOCK_NONE);
+              sd->freeze = EINA_FALSE;
+              elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", 
"efl");
+           }
+         break;
+     }
+
+   if (!sd->freeze && sd->hidden)
+     ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+}
+
+static void
+_on_mouse_up(void *data,
+             Evas *e EINA_UNUSED,
+             Evas_Object *obj,
+             void *event_info)
+{
+   Efl_Ui_Panel_Data *sd = data;
+   Evas_Event_Mouse_Up *ev = event_info;
+   Evas_Coord w, h;
+   Eina_Bool hidden;
+
+   hidden = sd->hidden;
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+   ELM_SAFE_FREE(sd->timer, ecore_timer_del);
+
+   if (_state_sync(obj)) return;
+
+   if (sd->hidden) _drawer_close(obj, w, h, EINA_TRUE);
+   else _drawer_open(obj, w, h, EINA_TRUE);
+
+   if (sd->hidden != hidden)
+     efl_event_callback_legacy_call(obj, EFL_UI_PANEL_EVENT_TOGGLED, NULL);
+
+   if (!sd->freeze && sd->hidden)
+     ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+}
+
+static Eina_Bool
+_key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED)
+{
+   _panel_toggle(NULL, obj, NULL, NULL);
+   return EINA_TRUE;
+}
+
+// _panel_elm_widget_widget_event
+ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(panel, Efl_Ui_Panel_Data)
+
+EOLIAN static Eina_Bool
+_efl_ui_panel_efl_ui_widget_widget_event(Eo *obj, Efl_Ui_Panel_Data *pd, const 
Efl_Event *eo_event, Evas_Object *src)
+{
+   if (src != obj) return EINA_FALSE;
+   return _panel_efl_ui_widget_widget_event(obj, pd, eo_event, src);
+}
+
+static Eina_Bool
+_efl_ui_panel_efl_content_content_set(Eo *obj, Efl_Ui_Panel_Data *sd, 
Efl_Gfx_Entity *content)
+{
+   if (sd->content == content) return EINA_TRUE;
+   if (sd->content)
+     evas_object_box_remove_all(sd->bx, EINA_TRUE);
+   sd->content = content;
+   if (content)
+     {
+        evas_object_box_append(sd->bx, sd->content);
+        evas_object_show(sd->content);
+        if (sd->scrollable)
+          elm_widget_sub_object_add(sd->scr_ly, sd->content);
+        else
+          elm_widget_sub_object_add(obj, sd->content);
+     }
+
+   if (efl_finalized_get(obj))
+     elm_layout_sizing_eval(obj);
+
+   return EINA_TRUE;
+}
+
+static Efl_Gfx_Entity*
+_efl_ui_panel_efl_content_content_get(const Eo *obj EINA_UNUSED, 
Efl_Ui_Panel_Data *sd)
+{
+   return sd->content;
+}
+
+static Efl_Gfx_Entity*
+_efl_ui_panel_efl_content_content_unset(Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data 
*sd)
+{
+   Efl_Gfx_Entity *ret = NULL;
+
+   if (!sd->content) return NULL;
+   ret = sd->content;
+
+   evas_object_box_remove_all(sd->bx, EINA_FALSE);
+   if (sd->scrollable)
+     _elm_widget_sub_object_redirect_to_top(sd->scr_ly, sd->content);
+   sd->content = NULL;
+
+   return ret;
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Panel_Data *sd, 
Eina_Position2D pos)
+{
+   if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, 
pos.x, pos.y))
+     return;
+
+   efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
+   efl_gfx_entity_position_set(sd->hit_rect, pos);
+}
+
+static void
+_scrollable_layout_resize(Eo *obj, Efl_Ui_Panel_Data *sd, Evas_Coord w, 
Evas_Coord h)
+{
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         // vertical
+         evas_object_resize(sd->scr_ly, w, (1 + sd->content_size_ratio) * h);
+         evas_object_size_hint_min_set(sd->scr_panel, w, 
(sd->content_size_ratio * h));
+         evas_object_size_hint_min_set(sd->scr_event, w, h);
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         // horizontal
+         evas_object_resize(sd->scr_ly, (1 + sd->content_size_ratio) * w, h);
+         evas_object_size_hint_min_set(sd->scr_panel, (sd->content_size_ratio 
* w), h);
+         evas_object_size_hint_min_set(sd->scr_event, w, h);
+         break;
+     }
+   if (efl_finalized_get(obj))
+     elm_layout_sizing_eval(obj);
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Panel_Data *sd, 
Eina_Size2D sz)
+{
+   if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, 
sz.w, sz.h))
+     return;
+
+   efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
+
+   if (!sd->scrollable) return;
+
+   efl_gfx_entity_size_set(sd->hit_rect, sz);
+   _scrollable_layout_resize(obj, sd, sz.w, sz.h);
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_Panel_Data 
*sd, Evas_Object *member)
+{
+   efl_canvas_group_member_add(efl_super(obj, MY_CLASS), member);
+
+   if (sd->hit_rect) evas_object_raise(sd->hit_rect);
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_ui_widget_on_access_update(Eo *obj, Efl_Ui_Panel_Data *_pd, 
Eina_Bool is_access)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+   Efl_Ui_Panel_Data *sd = _pd;
+
+   if (sd->scrollable)
+     {
+        _access_obj_process(obj, is_access);
+        return;
+     }
+
+   if (is_access)
+     _elm_access_edje_object_part_object_register
+       (obj, wd->resize_obj, "btn_icon");
+   else
+     _elm_access_edje_object_part_object_unregister
+       (obj, wd->resize_obj, "btn_icon");
+}
+
+EOLIAN static Eo *
+_efl_ui_panel_efl_object_constructor(Eo *obj, Efl_Ui_Panel_Data *_pd)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
+
+   obj = efl_constructor(efl_super(obj, MY_CLASS));
+   elm_widget_sub_object_parent_add(obj);
+   elm_widget_can_focus_set(obj, EINA_TRUE);
+
+   _pd->panel_edje = wd->resize_obj;
+
+   efl_ui_widget_theme_apply(obj);
+
+   _pd->bx = evas_object_box_add(evas_object_evas_get(obj));
+   evas_object_box_layout_set(_pd->bx, _box_layout_cb, _pd, NULL);
+   evas_object_show(_pd->bx);
+
+   elm_layout_signal_callback_add
+     (obj, "efl,action,panel,toggle", "*", _panel_toggle, obj);
+
+   _mirrored_set(obj, efl_ui_mirrored_get(obj));
+
+   _pd->event = evas_object_rectangle_add(evas_object_evas_get(obj));
+   evas_object_color_set(_pd->event, 0, 0, 0, 0);
+   evas_object_pass_events_set(_pd->event, EINA_TRUE);
+   elm_widget_sub_object_add(obj, _pd->event);
+
+   /* just to bootstrap and have theme hook to work */
+   if (!elm_layout_theme_set(obj, "panel", "top", elm_widget_style_get(obj)))
+     CRI("Failed to set layout!");
+   else
+     {
+        elm_layout_content_set(obj, "efl.content", _pd->bx);
+
+        if (edje_object_part_exists
+            (wd->resize_obj, "efl.swallow.event"))
+          {
+             Evas_Coord minw = 0, minh = 0;
+
+             elm_coords_finger_size_adjust(1, &minw, 1, &minh);
+             evas_object_size_hint_min_set(_pd->event, minw, minh);
+             efl_content_set(efl_part(efl_super(obj, MY_CLASS), 
"efl.swallow.event"), _pd->event);
+          }
+     }
+
+   evas_object_smart_callbacks_descriptions_set(obj, _smart_callbacks);
+   efl_access_object_role_set(obj, EFL_ACCESS_ROLE_PANEL);
+
+   efl_ui_focus_layer_behaviour_set(obj, EINA_FALSE, EINA_FALSE);
+
+   return obj;
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_object_destructor(Eo *obj, Efl_Ui_Panel_Data *sd)
+{
+   Evas_Object *child;
+   Eina_List *l;
+
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+
+   sd->delete_me = EINA_TRUE;
+
+   ELM_SAFE_FREE(sd->timer, ecore_timer_del);
+
+   /* let's make our panel object the *last* to be processed, since it
+    * may (smart) parent other sub objects here */
+   EINA_LIST_FOREACH(wd->subobjs, l, child)
+     {
+        if (child == sd->bx)
+          {
+             wd->subobjs =
+               eina_list_demote_list(wd->subobjs, l);
+             break;
+          }
+     }
+
+   efl_destructor(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static void
+_efl_ui_panel_orient_set(Eo *obj, Efl_Ui_Panel_Data *sd, Efl_Ui_Panel_Orient 
orient)
+{
+   if (sd->orient == orient) return;
+   sd->orient = orient;
+
+   if (sd->scrollable)
+     {
+        _scrollable_layout_theme_set(obj, sd);
+
+        if (!sd->freeze)
+          {
+             switch (sd->orient)
+               {
+                  case EFL_UI_PANEL_ORIENT_TOP:
+                  case EFL_UI_PANEL_ORIENT_BOTTOM:
+                     elm_interface_scrollable_movement_block_set
+                           (obj, EFL_UI_SCROLL_BLOCK_VERTICAL);
+                     break;
+                  case EFL_UI_PANEL_ORIENT_LEFT:
+                  case EFL_UI_PANEL_ORIENT_RIGHT:
+                     elm_interface_scrollable_movement_block_set
+                           (obj, EFL_UI_SCROLL_BLOCK_HORIZONTAL);
+                     break;
+               }
+
+             sd->freeze = EINA_TRUE;
+             elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", 
"efl");
+          }
+
+        efl_ui_panel_scrollable_content_size_set(obj, sd->content_size_ratio);
+     }
+   else
+     _orient_set_do(obj);
+
+   if (efl_finalized_get(obj))
+     elm_layout_sizing_eval(obj);
+}
+
+EOLIAN static Efl_Ui_Panel_Orient
+_efl_ui_panel_orient_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
+{
+   return sd->orient;
+}
+
+EOLIAN static void
+_efl_ui_panel_hidden_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool hidden)
+{
+   if (sd->hidden == !!hidden)
+     {
+        if (sd->scrollable && sd->hidden && !sd->freeze)
+          {
+             Evas_Coord w, h;
+             evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+             _drawer_close(obj, w, h, EINA_TRUE);
+          }
+        return;
+     }
+
+   _panel_toggle(NULL, obj, NULL, NULL);
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_panel_hidden_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
+{
+   return sd->hidden;
+}
+
+EOLIAN static void
+_efl_ui_panel_toggle(Eo *obj, Efl_Ui_Panel_Data *_pd EINA_UNUSED)
+{
+   _panel_toggle(NULL, obj, NULL, NULL);
+}
+
+EOLIAN static Eina_Rect
+_efl_ui_panel_efl_ui_widget_interest_region_get(const Eo *obj, 
Efl_Ui_Panel_Data *sd)
+{
+   Eina_Rect r = {};
+
+   elm_interface_scrollable_content_pos_get(obj, &r.x, &r.y);
+   evas_object_geometry_get(obj, NULL, NULL, &r.w, &r.h);
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         r.h *= sd->content_size_ratio;
+         break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         r.w *= sd->content_size_ratio;
+         break;
+     }
+   if (r.w < 1) r.w = 1;
+   if (r.h < 1) r.h = 1;
+
+   return r;
+}
+
+static void
+_anim_stop_cb(Evas_Object *obj, void *data EINA_UNUSED)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   Evas_Object *ao;
+   Evas_Coord pos, w, h, panel_size = 0;
+   Eina_Bool open = EINA_FALSE, horizontal = EINA_FALSE, reverse = EINA_FALSE;
+
+   if (elm_widget_disabled_get(obj)) return;
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         reverse = EINA_TRUE;
+      case EFL_UI_PANEL_ORIENT_TOP:
+         break;
+
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+         reverse = EINA_TRUE;
+         EINA_FALLTHROUGH;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+         horizontal = EINA_TRUE;
+         break;
+     }
+
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+   if (horizontal)
+     {
+         if (w <= 0) return;
+
+         panel_size = w * sd->content_size_ratio;
+         elm_interface_scrollable_content_pos_get(obj, &pos, NULL);
+         reverse ^= efl_ui_mirrored_get(obj);
+     }
+   else
+     {
+         if (h <= 0) return;
+
+         panel_size = h * sd->content_size_ratio;
+         elm_interface_scrollable_content_pos_get(obj, NULL, &pos);
+     }
+
+   if (pos == 0) open = !reverse;
+   else if (pos == panel_size) open = reverse;
+   else return;
+
+   if (open)
+     {
+        elm_interface_scrollable_single_direction_set
+              (obj, ELM_SCROLLER_SINGLE_DIRECTION_HARD);
+
+        //focus & access
+        elm_object_tree_focus_allow_set(obj, EINA_TRUE);
+        if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
+          {
+             ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
+             evas_object_show(ao);
+             _elm_access_highlight_set(ao);
+          }
+        else
+          elm_object_focus_set(obj, EINA_TRUE);
+     }
+   else
+     {
+        if (horizontal)
+          elm_interface_scrollable_movement_block_set
+                (obj, EFL_UI_SCROLL_BLOCK_HORIZONTAL);
+        else
+          elm_interface_scrollable_movement_block_set
+                (obj, EFL_UI_SCROLL_BLOCK_VERTICAL);
+        sd->freeze = EINA_TRUE;
+        elm_layout_signal_emit(sd->scr_ly, "efl,state,content,hidden", "efl");
+
+        elm_interface_scrollable_single_direction_set
+              (obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
+
+        //focus & access
+        elm_object_tree_focus_allow_set(obj, EINA_FALSE);
+        if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
+          {
+             ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
+             evas_object_hide(ao);
+          }
+     }
+}
+
+static void
+_scroll_cb(Evas_Object *obj, void *data EINA_UNUSED)
+{
+   EFL_UI_PANEL_DATA_GET(obj, sd);
+   Efl_Ui_Panel_Scroll_Info event;
+   Evas_Coord x, y, w, h;
+
+   if (elm_widget_disabled_get(obj)) return;
+   // in the case of
+   // freeze_set(FALSE) -> mouse_up -> freeze_set(TRUE) -> scroll
+   if (sd->freeze)
+     {
+        elm_interface_scrollable_movement_block_set
+              (obj, EFL_UI_SCROLL_BLOCK_NONE);
+        sd->freeze = EINA_FALSE;
+        elm_layout_signal_emit(sd->scr_ly, "efl,state,content,visible", "efl");
+     }
+
+   elm_interface_scrollable_content_pos_get(obj, &x, &y);
+   evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+   switch (sd->orient)
+     {
+      case EFL_UI_PANEL_ORIENT_TOP:
+         event.rel_x = 1;
+         event.rel_y = 1 - ((double) y / (double) ((sd->content_size_ratio) * 
h));
+        break;
+      case EFL_UI_PANEL_ORIENT_BOTTOM:
+         event.rel_x = 1;
+         event.rel_y = (double) y / (double) ((sd->content_size_ratio) * h);
+        break;
+      case EFL_UI_PANEL_ORIENT_LEFT:
+        if (!efl_ui_mirrored_get(obj))
+          {
+             event.rel_x = 1 - ((double) x / (double) 
((sd->content_size_ratio) * w));
+             event.rel_y = 1;
+          }
+        else
+          {
+             event.rel_x = (double) x / (double) ((sd->content_size_ratio) * 
w);
+             event.rel_y = 1;
+           }
+        break;
+      case EFL_UI_PANEL_ORIENT_RIGHT:
+        if (efl_ui_mirrored_get(obj))
+          {
+             event.rel_x = 1 - ((double) x / (double) 
((sd->content_size_ratio) * w));
+             event.rel_y = 1;
+          }
+        else
+          {
+             event.rel_x = (double) x / (double) ((sd->content_size_ratio) * 
w);
+             event.rel_y = 1;
+          }
+        break;
+     }
+   efl_event_callback_legacy_call
+     (obj, EFL_UI_EVENT_SCROLL, (void *) &event);
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_panel_efl_ui_widget_on_disabled_update(Eo *obj, Efl_Ui_Panel_Data *sd, 
Eina_Bool disabled)
+{
+   if (!efl_ui_widget_on_disabled_update(efl_super(obj, MY_CLASS), disabled))
+     return EINA_FALSE;
+
+   if (sd->scrollable)
+     {
+        if (disabled && sd->callback_added)
+          {
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                            _on_mouse_down);
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                            _on_mouse_move);
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP,
+                                            _on_mouse_up);
+             evas_object_event_callback_del(sd->scr_event, 
EVAS_CALLBACK_MOUSE_UP,
+                                            _event_mouse_up);
+
+             sd->callback_added = EINA_FALSE;
+          }
+        else if (!disabled && !sd->callback_added)
+          {
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                            _on_mouse_down, sd);
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                            _on_mouse_move, sd);
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                            _on_mouse_up, sd);
+             evas_object_event_callback_add(sd->scr_event, 
EVAS_CALLBACK_MOUSE_UP,
+                                            _event_mouse_up, obj);
+
+             sd->callback_added = EINA_TRUE;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+EOLIAN static double
+_efl_ui_panel_scrollable_content_size_get(const Eo *obj EINA_UNUSED, 
Efl_Ui_Panel_Data *sd)
+{
+   return sd->content_size_ratio;
+}
+
+EOLIAN static void
+_efl_ui_panel_scrollable_content_size_set(Eo *obj, Efl_Ui_Panel_Data *sd, 
double ratio)
+{
+   if (ratio < 0) ratio = 0;
+   else if (ratio > 1.0) ratio = 1.0;
+
+   sd->content_size_ratio = ratio;
+
+   if (sd->scrollable)
+     {
+        Evas_Coord w, h;
+        evas_object_geometry_get(obj, NULL, NULL, &w, &h);
+
+        _scrollable_layout_resize(obj, sd, w, h);
+     }
+}
+
+EOLIAN static Eina_Bool
+_efl_ui_panel_scrollable_get(const Eo *obj EINA_UNUSED, Efl_Ui_Panel_Data *sd)
+{
+   return sd->scrollable;
+}
+
+EOLIAN static void
+_efl_ui_panel_scrollable_set(Eo *obj, Efl_Ui_Panel_Data *sd, Eina_Bool 
scrollable)
+{
+   scrollable = !!scrollable;
+   if (sd->scrollable == scrollable) return;
+   sd->scrollable = scrollable;
+
+   if (scrollable)
+     {
+        elm_layout_content_unset(obj, "efl.content");
+
+        elm_widget_resize_object_set(obj, NULL);
+        elm_widget_sub_object_add(obj, sd->panel_edje);
+
+        if (!sd->scr_edje)
+          {
+             const char *handler_size;
+
+             sd->scr_edje = edje_object_add(evas_object_evas_get(obj));
+             elm_widget_theme_object_set(obj, sd->scr_edje, "panel", NULL,
+                                         elm_widget_style_get(obj));
+             evas_object_size_hint_weight_set
+                (sd->scr_edje, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+             evas_object_size_hint_align_set
+                (sd->scr_edje, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+             handler_size = edje_object_data_get(sd->scr_edje, "handler_size");
+             if (handler_size)
+               sd->handler_size = (int) (elm_object_scale_get(obj)) * 
(atoi(handler_size));
+          }
+
+        elm_widget_resize_object_set(obj, sd->scr_edje);
+
+        if (!sd->hit_rect)
+          {
+             sd->hit_rect = 
evas_object_rectangle_add(evas_object_evas_get(obj));
+             evas_object_smart_member_add(sd->hit_rect, obj);
+             elm_widget_sub_object_add(obj, sd->hit_rect);
+             evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
+             evas_object_show(sd->hit_rect);
+             evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
+
+             elm_interface_scrollable_objects_set(obj, sd->scr_edje, 
sd->hit_rect);
+             elm_interface_scrollable_animate_stop_cb_set(obj, _anim_stop_cb);
+             elm_interface_scrollable_scroll_cb_set(obj, _scroll_cb);
+          }
+
+        if (!sd->scr_ly)
+          {
+             sd->scr_ly = efl_add(EFL_UI_LAYOUT_CLASS, obj,
+                                  elm_layout_theme_set(efl_added,
+                                                       "panel",
+                                                       "scrollable/left",
+                                                       
elm_widget_style_get(obj)));
+
+             evas_object_smart_member_add(sd->scr_ly, obj);
+             elm_widget_sub_object_add(obj, sd->scr_ly);
+             _scrollable_layout_theme_set(obj, sd);
+
+             sd->scr_panel = 
evas_object_rectangle_add(evas_object_evas_get(obj));
+             evas_object_color_set(sd->scr_panel, 0, 0, 0, 0);
+             elm_widget_sub_object_add(obj, sd->scr_panel);
+             if (!elm_layout_content_set(sd->scr_ly, "efl.panel_area", 
sd->scr_panel))
+               elm_layout_content_set(sd->scr_ly, "panel_area", sd->scr_panel);
+
+             sd->scr_event = 
evas_object_rectangle_add(evas_object_evas_get(obj));
+             evas_object_color_set(sd->scr_event, 0, 0, 0, 0);
+             elm_widget_sub_object_add(obj, sd->scr_event);
+             if (!elm_layout_content_set(sd->scr_ly, "efl.event_area", 
sd->scr_event))
+               elm_layout_content_set(sd->scr_ly, "event_area", sd->scr_event);
+          }
+
+        elm_interface_scrollable_content_set(obj, sd->scr_ly);
+        sd->freeze = EINA_TRUE;
+        efl_content_set(efl_part(sd->scr_ly, "efl.content"), sd->bx);
+        if (sd->content) elm_widget_sub_object_add(sd->scr_ly, sd->content);
+
+        switch (sd->orient)
+          {
+           case EFL_UI_PANEL_ORIENT_TOP:
+           case EFL_UI_PANEL_ORIENT_BOTTOM:
+              elm_interface_scrollable_movement_block_set
+                    (obj, EFL_UI_SCROLL_BLOCK_VERTICAL);
+              break;
+           case EFL_UI_PANEL_ORIENT_LEFT:
+           case EFL_UI_PANEL_ORIENT_RIGHT:
+              elm_interface_scrollable_movement_block_set
+                    (obj, EFL_UI_SCROLL_BLOCK_HORIZONTAL);
+              break;
+          }
+
+        elm_interface_scrollable_single_direction_set
+              (obj, ELM_SCROLLER_SINGLE_DIRECTION_NONE);
+
+        if (!elm_widget_disabled_get(obj) && !sd->callback_added)
+          {
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+                                            _on_mouse_down, sd);
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
+                                            _on_mouse_move, sd);
+             evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
+                                            _on_mouse_up, sd);
+             evas_object_event_callback_add(sd->scr_event, 
EVAS_CALLBACK_MOUSE_UP,
+                                            _event_mouse_up, obj);
+
+             sd->callback_added = EINA_TRUE;
+          }
+
+     }
+   else
+     {
+        elm_interface_scrollable_content_set(obj, NULL);
+
+        if (sd->callback_added)
+          {
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_DOWN, 
_on_mouse_down);
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, 
_on_mouse_move);
+             evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, 
_on_mouse_up);
+             evas_object_event_callback_del(sd->scr_event, 
EVAS_CALLBACK_MOUSE_UP,
+                                            _event_mouse_up);
+
+             sd->callback_added = EINA_FALSE;
+          }
+
+        elm_widget_resize_object_set(obj, NULL);
+        elm_widget_sub_object_add(obj, sd->scr_edje);
+
+        elm_widget_resize_object_set(obj, sd->panel_edje);
+
+        elm_layout_content_unset(sd->scr_ly, "efl.content");
+        elm_layout_content_set(obj, "efl.content", sd->bx);
+        if (sd->content) elm_widget_sub_object_add(obj, sd->content);
+     }
+}
+
+EOLIAN static void
+_efl_ui_panel_efl_ui_base_mirrored_set(Eo *obj, Efl_Ui_Panel_Data *sd, 
Eina_Bool mirrored)
+{
+   if (sd->scrollable)
+     efl_ui_mirrored_set(efl_cast(obj, ELM_INTERFACE_SCROLLABLE_MIXIN), 
mirrored);
+   else
+     efl_ui_mirrored_set(efl_cast(obj, EFL_UI_WIDGET_CLASS), mirrored);
+}
+
+EOLIAN const Efl_Access_Action_Data *
+_efl_ui_panel_efl_access_widget_action_elm_actions_get(const Eo *obj 
EINA_UNUSED, Efl_Ui_Panel_Data *pd EINA_UNUSED)
+{
+   static Efl_Access_Action_Data atspi_actions[] = {
+          { "toggle", "toggle", NULL, _key_action_toggle},
+          { NULL, NULL, NULL, NULL }
+   };
+   return &atspi_actions[0];
+}
+
+/* Internal EO APIs and hidden overrides */
+
+#define EFL_UI_PANEL_EXTRA_OPS \
+   ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_panel)
+
+#include "efl_ui_panel.eo.c"
diff --git a/src/lib/elementary/efl_ui_panel.eo 
b/src/lib/elementary/efl_ui_panel.eo
new file mode 100644
index 0000000000..8fb5c1d359
--- /dev/null
+++ b/src/lib/elementary/efl_ui_panel.eo
@@ -0,0 +1,95 @@
+enum Efl.Ui.Panel_Orient
+{
+   [[Panel orientation mode]]
+
+   top, [[Panel (dis)appears from the top]]
+   bottom, [[Panel (dis)appears from the bottom]]
+   left, [[Panel (dis)appears from the left]]
+   right [[Panel (dis)appears from the right]]
+}
+
+struct Efl.Ui.Panel_Scroll_Info
+{
+   [[Panel scroll information]]
+   rel_x: double; [[content scrolled position (0.0 ~ 1.0) in the panel]]
+   rel_y: double; [[content scrolled position (0.0 ~ 1.0) in the panel]]
+}
+
+class Efl.Ui.Panel (Efl.Ui.Layout, Efl.Ui.Focus.Layer, 
Elm.Interface_Scrollable, Efl.Content,
+                    Efl.Access.Widget.Action)
+{
+   [[Elementary panel class]]
+   methods {
+      @property orient {
+         set {
+            [[Sets the orientation of the panel
+
+              Sets from where the panel will (dis)appear.
+            ]]
+         }
+         get {
+            [[Gets the orientation of the panel.]]
+         }
+         values {
+            orient: Efl.Ui.Panel_Orient; [[The panel orientation.]]
+         }
+      }
+      @property hidden {
+         set {
+            [[Sets the state of the panel.]]
+         }
+         get {
+            [[Gets the state of the panel.]]
+         }
+         values {
+            hidden: bool; [[If $true, the panel will run the animation to 
disappear.]]
+         }
+      }
+      @property scrollable {
+         set {
+            [[Sets the scrollability of the panel.]]
+         }
+         get {
+            [[Gets the state of the scrollability.
+            ]]
+         }
+         values {
+            scrollable: bool; [[The scrollable state.]]
+         }
+      }
+      @property scrollable_content_size {
+         set {
+            [[Sets the size of the scrollable panel.]]
+         }
+         get {
+            [[Gets the size of the scrollable panel.
+            ]]
+         }
+         values {
+            ratio: double; [[Size ratio]]
+         }
+      }
+      toggle {
+         [[Toggle the hidden state of the panel from code]]
+      }
+   }
+   implements {
+      Efl.Object.constructor;
+      Efl.Object.destructor;
+      Efl.Gfx.Entity.position { set; }
+      Efl.Gfx.Entity.size { set; }
+      Efl.Canvas.Group.group_member_add;
+      Efl.Ui.Widget.theme_apply;
+      Efl.Ui.Widget.on_disabled_update;
+      Efl.Ui.Widget.on_access_update;
+      Efl.Ui.Widget.widget_event;
+      Efl.Ui.Widget.interest_region { get; }
+      Efl.Access.Widget.Action.elm_actions { get; }
+      Efl.Ui.Base.mirrored { set; }
+      Efl.Content.content { get; set; }
+      Efl.Content.content_unset;
+   }
+   events {
+      toggled: void; [[Called when the hidden state was toggled]]
+   }
+}
diff --git a/src/lib/elementary/efl_ui_panel_private.h 
b/src/lib/elementary/efl_ui_panel_private.h
new file mode 100644
index 0000000000..18a32735b3
--- /dev/null
+++ b/src/lib/elementary/efl_ui_panel_private.h
@@ -0,0 +1,81 @@
+#ifndef EFL_UI_PANEL_H
+#define EFL_UI_PANEL_H
+
+#include "elm_interface_scrollable.h"
+#include "elm_widget_layout.h"
+#include "efl_ui_panel.eo.h"
+
+/* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR
+ * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT
+ * FINAL. CALL elm_widget_api_check(EFL_UI_INTERNAL_API_VERSION) TO CHECK
+ * IT AT RUNTIME.
+ */
+
+/**
+ * @addtogroup Widget
+ * @{
+ *
+ * @section elm-panel-class The Elementary Panel Class
+ *
+ * Elementary, besides having the @ref Panel widget, exposes its
+ * foundation -- the Elementary Panel Class -- in order to create other
+ * widgets which are a panel with some more logic on top.
+ */
+
+/**
+ * Base layout smart data extended with panel instance data.
+ */
+typedef struct _Efl_Ui_Panel_Data Efl_Ui_Panel_Data;
+struct _Efl_Ui_Panel_Data
+{
+   Evas_Object                          *bx, *content;
+   Evas_Object                          *event;
+   Evas_Object                          *scr_ly;
+   Evas_Object                          *hit_rect, *panel_edje, *scr_edje;
+   Evas_Object                          *scr_panel, *scr_event;
+
+
+   Efl_Ui_Panel_Orient                   orient;
+
+   double                                content_size_ratio;
+   Evas_Coord                            down_x, down_y;
+   Evas_Coord                            handler_size;
+   Ecore_Timer                          *timer;
+
+   Eina_Bool                             hidden : 1;
+   Eina_Bool                             delete_me : 1;
+   Eina_Bool                             scrollable : 1;
+   Eina_Bool                             freeze: 1;
+   Eina_Bool                             callback_added: 1;
+};
+
+/**
+ * @}
+ */
+
+#define EFL_UI_PANEL_DATA_GET(o, sd) \
+  Efl_Ui_Panel_Data * sd = efl_data_scope_get(o, EFL_UI_PANEL_CLASS)
+
+#define EFL_UI_PANEL_DATA_GET_OR_RETURN(o, ptr)         \
+  EFL_UI_PANEL_DATA_GET(o, ptr);                        \
+  if (EINA_UNLIKELY(!ptr))                           \
+    {                                                \
+       ERR("No widget data for object %p (%s)",      \
+           o, evas_object_type_get(o));              \
+       return;                                       \
+    }
+
+#define EFL_UI_PANEL_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
+  EFL_UI_PANEL_DATA_GET(o, ptr);                         \
+  if (EINA_UNLIKELY(!ptr))                            \
+    {                                                 \
+       ERR("No widget data for object %p (%s)",       \
+           o, evas_object_type_get(o));               \
+       return val;                                    \
+    }
+
+#define EFL_UI_PANEL_CHECK(obj)                              \
+  if (EINA_UNLIKELY(!efl_isa((obj), EFL_UI_PANEL_CLASS))) \
+    return
+
+#endif
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 335b8f581b..6b34dce2cb 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -154,6 +154,7 @@ pub_eo_files = [
   'efl_ui_slider_interval.eo',
   'efl_ui_spin.eo',
   'efl_ui_spin_button.eo',
+  'efl_ui_panel.eo',
   'efl_ui_datepicker.eo',
   'efl_ui_timepicker.eo',
   'efl_ui_tags.eo',
@@ -437,6 +438,7 @@ elementary_headers_unstable = [
   'elm_widget_spinner.h',
   'efl_ui_spin_private.h',
   'efl_ui_spin_button_private.h',
+  'efl_ui_panel_private.h',
   'efl_ui_datepicker_private.h',
   'efl_ui_timepicker_private.h',
   'efl_ui_tags_private.h',
@@ -806,6 +808,7 @@ elementary_src = [
   'efl_ui_slider_interval.c',
   'efl_ui_spin.c',
   'efl_ui_spin_button.c',
+  'efl_ui_panel.c',
   'efl_ui_datepicker.c',
   'efl_ui_timepicker.c',
   'efl_ui_tags.c',

-- 


Reply via email to