--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EFL_EXTENSION_PANEL_H__
+#define __EFL_EXTENSION_PANEL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup CAPI_EFL_EXTENSION_PANEL_MODULE Efl Extension Panel
+ * @ingroup CAPI_EFL_EXTENSION_COMMON_UI_MODULE
+ * @brief Eext_panel is composed of primary panel and assist panel.
+ * Assist panel becomes visible by dragging the edge of the screen.
+ *
+ * @{
+ */
+
+/**
+ * @WEARABLE_ONLY
+ * @brief Add a new Eext_Panel
+ * @details Because the return value is a handle of elm_layout object,
+ * the elm_layout APIs are applicable to eext_panel.
+ *
+ * This widget emits the following signals:
+ * @li "assist,panel,visible": When the assist panel becomes draggable
+ * and visible
+ * @li "assist,panel,hidden": When the assist panel becomes completely
+ * invisible and not draggable
+ *
+ * @param[in] parent The parent object
+ *
+ * @return A new eext_panel handle, otherwise @c NULL if it cannot be created
+ * @if WEARABLE @since_tizen 4.0
+ * @endif
+ */
+EAPI Evas_Object* eext_panel_add(Evas_Object *parent);
+
+
+/**
+ * @WEARABLE_ONLY
+ * @brief Set the content at a part of a given eext_panel widget
+ *
+ * @remarks Eext panel holds two (primary and assist) child objects as its
+ * contents in the given parts. This API sets a new content to a given
+ * part. If any object is already set as a content object in the given
+ * part, the previous object is automatically deleted with this call.
+ * If the @p content is NULL, this call will just delete the previous
+ * object.
+ *
+ * The part names works as follows:
+ * @li "primary": If you set an object as the content of this part,
+ * the object is visible by default before assist panel
+ * is dragged.
+ * @li "assist": If you set an object as the content of this part,
+ * the object is hidden by default and becomes visible
+ * by dragging the edge of the screen.
+ *
+ * @param[in] obj Eext panel
+ * @param[in] part_name Eext panel's part name to set
+ * @param[in] content The new content for that part
+ *
+ * @if WEARABLE @since_tizen 4.0
+ * @endif
+ */
+EAPI void eext_panel_part_content_set(Evas_Object *obj, const char *part_name, Evas_Object *content);
+
+/**
+ * @WEARABLE_ONLY
+ * @brief Get the content from the part of the given eext_panel widget
+ *
+ * @param[in] obj Eext panel
+ * @param[in] part_name Eext panel part name
+ * @return The content of the object at the given part, otherwise @c NULL in case of an error
+ *
+ * @if WEARABLE @since_tizen 4.0
+ * @endif
+ */
+EAPI Evas_Object* eext_panel_part_content_get(const Evas_Object *obj, const char *part_name);
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __EFL_EXTENSION_PANEL_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "efl_extension.h"
+#include "efl_extension_private.h"
+#include "wearable/circle/efl_extension_circle_private.h"
+#include "wearable/efl_extension_common_private.h"
+
+#define EEXT_PANEL_DATA_KEY "eext_panel_data"
+
+
+static Eext_Panel_Data *
+_eext_panel_data_init(Evas_Object *obj, Evas_Object *parent)
+{
+ Eext_Panel_Data *pd = NULL;
+
+ pd = (Eext_Panel_Data *)calloc(1, sizeof(Eext_Panel_Data));
+
+ if (!pd)
+ {
+ ERR("pd is NULL!!");
+ return NULL;
+ }
+
+ pd->parent = parent;
+ pd->eext_panel = obj;
+ pd->is_zoom_out = EINA_FALSE;
+ pd->is_mouse_down = EINA_FALSE;
+ pd->panel_hide_cb_added = EINA_FALSE;
+
+ return pd;
+}
+
+static Eext_Panel_Data *
+_eext_panel_data_get(const Evas_Object *eext_panel)
+{
+ if (!eext_panel)
+ {
+ ERR("eext_panel is NULL!!");
+ return NULL;
+ }
+
+ return evas_object_data_get(eext_panel, EEXT_PANEL_DATA_KEY);
+}
+
+static void
+_panel_hide_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+ if (!obj)
+ {
+ ERR("panel is NULL!!");
+ return;
+ }
+
+ if (!elm_panel_hidden_get(obj)) elm_panel_toggle(obj);
+}
+
+static void
+_panel_unhold_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Eext_Panel_Data *pd = data;
+ double curve[4] = {0.25, 0.46, 0.45, 1.0};
+ Evas_Map *map;
+ Elm_Transit *tran;
+
+ map = evas_map_new(4);
+ evas_map_util_points_populate_from_object(map, pd->primary_panel);
+ evas_object_map_set(pd->primary_panel, map);
+ evas_object_map_enable_set(pd->primary_panel, EINA_TRUE);
+ evas_map_free(map);
+
+ tran = elm_transit_add();
+ elm_transit_effect_zoom_add(tran, 1.0, 0.9);
+ elm_transit_object_add(tran, pd->primary_panel);
+ elm_transit_duration_set(tran, 0.25);
+ elm_transit_tween_mode_set(tran, ELM_TRANSIT_TWEEN_MODE_BEZIER_CURVE);
+ elm_transit_tween_mode_factor_n_set(tran, 4, curve);
+ elm_transit_objects_final_state_keep_set(tran, EINA_TRUE);
+ elm_transit_go(tran);
+
+ pd->is_zoom_out = EINA_TRUE;
+
+ if (!pd->panel_hide_cb_added)
+ {
+ eext_object_event_callback_add(pd->assist_panel, EEXT_CALLBACK_BACK,
+ _panel_hide_cb, NULL);
+ pd->panel_hide_cb_added = EINA_TRUE;
+ }
+
+ evas_object_smart_callback_call(pd->eext_panel, "assist,panel,visible", NULL);
+}
+
+static void
+_panel_hold_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Eext_Panel_Data *pd = data;
+ double curve[4] = {0.25, 0.46, 0.45, 1.0};
+ Evas_Map *map;
+ Elm_Transit *tran;
+
+ map = evas_map_new(4);
+ evas_map_util_points_populate_from_object(map, pd->primary_panel);
+ evas_object_map_set(pd->primary_panel, map);
+ evas_object_map_enable_set(pd->primary_panel, EINA_TRUE);
+ evas_map_free(map);
+
+ if (pd->is_zoom_out)
+ {
+ tran = elm_transit_add();
+ elm_transit_effect_zoom_add(tran, 0.9, 1.0);
+ elm_transit_object_add(tran, pd->primary_panel);
+ elm_transit_duration_set(tran, 0.25);
+ elm_transit_tween_mode_set(tran, ELM_TRANSIT_TWEEN_MODE_BEZIER_CURVE);
+ elm_transit_tween_mode_factor_n_set(tran, 4, curve);
+ elm_transit_objects_final_state_keep_set(tran, EINA_TRUE);
+ elm_transit_go(tran);
+
+ pd->is_zoom_out = EINA_FALSE;
+ }
+
+ if (pd->panel_hide_cb_added)
+ {
+ eext_object_event_callback_del(pd->assist_panel, EEXT_CALLBACK_BACK,
+ _panel_hide_cb);
+ pd->panel_hide_cb_added = EINA_FALSE;
+ }
+
+ evas_object_smart_callback_call(pd->eext_panel, "assist,panel,hidden", NULL);
+}
+
+static void
+_panel_scroll_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+ Eext_Panel_Data *pd = data;
+ Elm_Panel_Scroll_Info *ev = event_info;
+ double curve[4] = {0.25, 0.46, 0.45, 1.0};
+
+ int col = 229 * ev->rel_y;
+ evas_object_color_set(pd->panel_bg, 0, 0, 0, col);
+}
+
+static void
+_panel_mouse_up_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ Eext_Panel_Data *pd = data;
+
+ pd->is_mouse_down = EINA_FALSE;
+}
+
+static void
+_panel_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ Eext_Panel_Data *pd = data;
+
+ pd->is_mouse_down = EINA_TRUE;
+}
+
+static void
+_eext_panel_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ Eext_Panel_Data *pd = data;
+
+ free(pd);
+}
+
+EAPI Evas_Object *
+eext_panel_add(Evas_Object *parent)
+{
+ Evas_Object *layout, *primary_ly, *panel;
+ Eina_Bool ret;
+
+ if (!parent) return NULL;
+
+ Eext_Panel_Data *pd = NULL;
+
+ layout = elm_layout_add(parent);
+ if (!layout)
+ {
+ ERR("eext_panel is NULL!!");
+ return NULL;
+ }
+
+ pd = _eext_panel_data_init(layout, parent);
+ if (!pd)
+ {
+ evas_object_del(layout);
+ return NULL;
+ }
+
+ evas_object_data_set(layout, EEXT_PANEL_DATA_KEY, pd);
+
+ ret = elm_layout_theme_set(layout, "layout", "drawer", "panel");
+ if (!ret)
+ {
+ ERR("Failed to set theme!!");
+ evas_object_del(layout);
+ free(pd);
+ return NULL;
+ }
+
+ primary_ly = elm_layout_add(layout);
+ if (!primary_ly)
+ {
+ ERR("Primary layout is NULL!!");
+ evas_object_del(layout);
+ free(pd);
+ return NULL;
+ }
+
+ ret = elm_layout_theme_set(primary_ly, "layout", "panel", "primary");
+ if (!ret)
+ {
+ ERR("Failed to set primary layout theme!!");
+ evas_object_del(primary_ly);
+ evas_object_del(layout);
+ free(pd);
+ return NULL;
+ }
+
+ elm_object_part_content_set(layout, "elm.swallow.content", primary_ly);
+ evas_object_show(primary_ly);
+
+ pd->primary_panel = primary_ly;
+
+ panel = elm_panel_add(layout);
+ if (!panel)
+ {
+ ERR("Assist panel is NULL!!");
+ evas_object_del(primary_ly);
+ evas_object_del(layout);
+ free(pd);
+ return NULL;
+ }
+ elm_panel_scrollable_set(panel, EINA_TRUE);
+ elm_panel_scrollable_content_size_set(panel, 1.0);
+ elm_object_style_set(panel, "assist");
+ elm_panel_hidden_set(panel, EINA_TRUE);
+ elm_panel_orient_set(panel, ELM_PANEL_ORIENT_BOTTOM);
+ elm_object_part_content_set(layout, "elm.swallow.right", panel);
+
+ pd->assist_panel = panel;
+
+ pd->panel_bg = evas_object_rectangle_add(evas_object_evas_get(layout));
+ evas_object_color_set(pd->panel_bg, 0, 0, 0, 0);
+ elm_object_part_content_set(layout, "elm.swallow.bg", pd->panel_bg);
+
+ elm_object_signal_callback_add(panel, "elm,state,unhold", "elm",
+ (Edje_Signal_Cb)_panel_unhold_cb, pd);
+ elm_object_signal_callback_add(panel, "elm,state,hold", "elm",
+ (Edje_Signal_Cb)_panel_hold_cb, pd);
+ evas_object_smart_callback_add(panel, "scroll", _panel_scroll_cb, pd);
+ evas_object_event_callback_add(panel, EVAS_CALLBACK_MOUSE_UP,
+ _panel_mouse_up_cb, pd);
+ evas_object_event_callback_add(panel, EVAS_CALLBACK_MOUSE_DOWN,
+ _panel_mouse_down_cb, pd);
+ evas_object_event_callback_add(layout, EVAS_CALLBACK_DEL,
+ _eext_panel_del_cb, pd);
+
+ return layout;
+}
+
+EAPI void
+eext_panel_part_content_set(Evas_Object *obj, const char *part_name,
+ Evas_Object *content)
+{
+ Eext_Panel_Data *pd = NULL;
+
+ if (!obj)
+ {
+ ERR("obj is NULL!!");
+ return;
+ }
+ if (!part_name)
+ {
+ ERR("part_name is NULL!!");
+ return;
+ }
+ if (!content)
+ {
+ ERR("content is NULL!!");
+ return;
+ }
+
+ pd = _eext_panel_data_get(obj);
+ if (!pd)
+ {
+ ERR("pd is NULL!!");
+ return;
+ }
+
+ if (!strcmp(part_name, "primary"))
+ {
+ elm_object_part_content_set(pd->primary_panel, "elm.swallow.content",
+ content);
+ }
+ else if (!strcmp(part_name, "assist"))
+ {
+ elm_object_content_set(pd->assist_panel, content);
+ }
+ else
+ {
+ ERR("Not supported part name!!!");
+ return;
+ }
+}
+
+EAPI Evas_Object *
+eext_panel_part_content_get(const Evas_Object *obj, const char *part_name)
+{
+ Eext_Panel_Data *pd = NULL;
+
+ if (!obj)
+ {
+ ERR("obj is NULL!!");
+ return NULL;
+ }
+ if (!part_name)
+ {
+ ERR("part_name is NULL!!");
+ return NULL;
+ }
+
+ pd = _eext_panel_data_get(obj);
+ if (!pd)
+ {
+ ERR("pd is NULL!!");
+ return NULL;
+ }
+
+ if (!strcmp(part_name, "primary"))
+ {
+ return elm_object_part_content_get(pd->primary_panel,
+ "elm.swallow.content");
+ }
+ else if (!strcmp(part_name, "assist"))
+ {
+ return elm_object_content_get(pd->assist_panel);
+ }
+ else
+ {
+ ERR("Not supported part name!!!");
+ return NULL;
+ }
+}
+