efl/src/lib/elementary/efl_ui_popup.c

402 lines
11 KiB
C

#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#define EFL_UI_POPUP_PROTECTED
#include <Elementary.h>
#include "elm_priv.h"
#include "efl_ui_popup_private.h"
#include "efl_ui_popup_part.eo.h"
#include "elm_part_helper.h"
#define MY_CLASS EFL_UI_POPUP_CLASS
#define MY_CLASS_NAME "Efl.Ui.Popup"
static const char PART_NAME_BACKWALL[] = "backwall";
static void
_backwall_clicked_cb(void *data,
Eo *o EINA_UNUSED,
const char *emission EINA_UNUSED,
const char *source EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_UI_POPUP_EVENT_BACKWALL_CLICKED, NULL);
}
EOLIAN static void
_efl_ui_popup_efl_gfx_position_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eina_Position2D pos)
{
pd->align = EFL_UI_POPUP_ALIGN_NONE;
efl_gfx_position_set(efl_super(obj, MY_CLASS), pos);
}
static void
_calc_align(Eo *obj)
{
Efl_Ui_Popup_Data *pd = efl_data_scope_get(obj, MY_CLASS);
Eina_Rect p_geom = efl_gfx_geometry_get(pd->win_parent);
Eina_Rect o_geom = efl_gfx_geometry_get(obj);
Evas_Coord pw, ph;
pw = p_geom.w;
ph = p_geom.h;
Evas_Coord ow, oh;
ow = o_geom.w;
oh = o_geom.h;
switch (pd->align)
{
case EFL_UI_POPUP_ALIGN_CENTER:
efl_gfx_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow ) / 2, (ph - oh) / 2));
break;
case EFL_UI_POPUP_ALIGN_LEFT:
efl_gfx_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D(0, (ph - oh) / 2));
break;
case EFL_UI_POPUP_ALIGN_RIGHT:
efl_gfx_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D(pw - ow, (ph - oh) / 2));
break;
case EFL_UI_POPUP_ALIGN_TOP:
efl_gfx_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow) / 2, 0));
break;
case EFL_UI_POPUP_ALIGN_BOTTOM:
efl_gfx_position_set(efl_super(obj, MY_CLASS), EINA_POSITION2D((pw - ow) / 2, ph - oh));
break;
default:
break;
}
}
EOLIAN static void
_efl_ui_popup_efl_gfx_size_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eina_Size2D size)
{
efl_gfx_size_set(efl_super(obj, MY_CLASS), size);
elm_layout_sizing_eval(obj);
}
static void
_parent_geom_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
Eo *obj = data;
EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, pd);
//Add align calc only
Eina_Bool needs_size_calc = pd->needs_size_calc;
elm_layout_sizing_eval(obj);
pd->needs_size_calc = needs_size_calc;
}
EOLIAN static void
_efl_ui_popup_efl_ui_widget_widget_parent_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eo *parent EINA_UNUSED)
{
pd->win_parent = efl_provider_find(obj, EFL_UI_WIN_CLASS);
if (!pd->win_parent)
{
ERR("Cannot find window parent");
return;
}
Eina_Rect p_geom = efl_gfx_geometry_get(pd->win_parent);
efl_gfx_position_set(pd->backwall, EINA_POSITION2D(p_geom.x, p_geom.y));
efl_gfx_size_set(pd->backwall, EINA_SIZE2D(p_geom.w, p_geom.h));
efl_event_callback_add(pd->win_parent, EFL_GFX_EVENT_RESIZE, _parent_geom_cb, obj);
efl_event_callback_add(pd->win_parent, EFL_GFX_EVENT_MOVE, _parent_geom_cb, obj);
}
EOLIAN static void
_efl_ui_popup_align_set(Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd, Efl_Ui_Popup_Align type)
{
pd->align = type;
//Add align calc only
Eina_Bool needs_size_calc = pd->needs_size_calc;
elm_layout_sizing_eval(obj);
pd->needs_size_calc = needs_size_calc;
}
EOLIAN static Efl_Ui_Popup_Align
_efl_ui_popup_align_get(Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd)
{
return pd->align;
}
EOLIAN static void
_efl_ui_popup_popup_size_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eina_Size2D size)
{
efl_gfx_size_set(obj, size);
}
EOLIAN static Eina_Size2D
_efl_ui_popup_popup_size_get(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED)
{
return efl_gfx_size_get(obj);
}
static Eina_Bool
_timer_cb(void *data)
{
Eo *popup = data;
efl_event_callback_call(popup, EFL_UI_POPUP_EVENT_TIMEOUT, NULL);
efl_del(popup);
return ECORE_CALLBACK_CANCEL;
}
static void
_timer_del(Efl_Ui_Popup_Data *pd)
{
if (pd->timer)
{
ecore_timer_del(pd->timer);
pd->timer = NULL;
}
}
static void
_timer_init(Eo *obj, Efl_Ui_Popup_Data *pd)
{
if (pd->timeout > 0.0)
pd->timer = ecore_timer_add(pd->timeout, _timer_cb, obj);
}
EOLIAN static void
_efl_ui_popup_efl_gfx_visible_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Bool v)
{
if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, v))
return;
efl_gfx_visible_set(efl_super(obj, MY_CLASS), v);
if (v)
{
_timer_del(pd);
_timer_init(obj, pd);
}
}
EOLIAN static void
_efl_ui_popup_timeout_set(Eo *obj, Efl_Ui_Popup_Data *pd, double time)
{
if (time < 0.0)
time = 0.0;
pd->timeout = time;
_timer_del(pd);
if (efl_gfx_visible_get(obj))
_timer_init(obj, pd);
}
EOLIAN static double
_efl_ui_popup_timeout_get(Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd)
{
return pd->timeout;
}
EOLIAN static Eo *
_efl_ui_popup_efl_object_constructor(Eo *obj, Efl_Ui_Popup_Data *pd)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "popup");
obj = efl_constructor(efl_super(obj, MY_CLASS));
efl_canvas_object_type_set(obj, MY_CLASS_NAME);
elm_widget_sub_object_parent_add(obj);
elm_widget_can_focus_set(obj, EINA_TRUE);
if (!elm_widget_theme_object_set(obj, wd->resize_obj,
elm_widget_theme_klass_get(obj),
elm_widget_theme_element_get(obj),
elm_widget_theme_style_get(obj)))
CRI("Failed to set layout!");
pd->backwall = edje_object_add(evas_object_evas_get(obj));
elm_widget_element_update(obj, pd->backwall, PART_NAME_BACKWALL);
evas_object_smart_member_add(pd->backwall, obj);
evas_object_stack_below(pd->backwall, wd->resize_obj);
edje_object_signal_callback_add(pd->backwall, "action,clicked", "*",
_backwall_clicked_cb, obj);
pd->align = EFL_UI_POPUP_ALIGN_CENTER;
return obj;
}
EOLIAN static void
_efl_ui_popup_efl_object_destructor(Eo *obj, Efl_Ui_Popup_Data *pd)
{
ELM_SAFE_DEL(pd->backwall);
efl_event_callback_del(pd->win_parent, EFL_GFX_EVENT_RESIZE, _parent_geom_cb,
obj);
efl_event_callback_del(pd->win_parent, EFL_GFX_EVENT_MOVE, _parent_geom_cb,
obj);
efl_destructor(efl_super(obj, MY_CLASS));
}
static void
_sizing_eval(Eo *obj)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
Evas_Coord minw = -1, minh = -1;
elm_coords_finger_size_adjust(1, &minw, 1, &minh);
edje_object_size_min_restricted_calc
(wd->resize_obj, &minw, &minh, minw, minh);
efl_gfx_size_hint_min_set(obj, EINA_SIZE2D(minw, minh));
Eina_Size2D size = efl_gfx_size_get(obj);
Eina_Size2D new_size;
new_size.w = (minw > size.w ? minw : size.w);
new_size.h = (minh > size.h ? minh : size.h);
efl_gfx_size_set(obj, new_size);
}
EOLIAN static void
_efl_ui_popup_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Popup_Data *pd)
{
if (pd->needs_group_calc) return;
pd->needs_group_calc = EINA_TRUE;
/* These flags can be modified by sub classes not to calculate size or align
* their super classes.
* e.g. Efl.Ui.Popup.Alert.Scroll class sets the flag as follows not to
* calculate size by its super class.
*
* ppd->needs_size_calc = EINA_FALSE;
* efl_canvas_group_calculate(efl_super(obj, MY_CLASS));
*/
pd->needs_size_calc = EINA_TRUE;
pd->needs_align_calc = EINA_TRUE;
evas_object_smart_changed(obj);
}
EOLIAN static void
_efl_ui_popup_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Popup_Data *pd)
{
/* When elm_layout_sizing_eval() is called, just flag is set instead of size
* calculation.
* The actual size calculation is done here when the object is rendered to
* avoid duplicate size calculations. */
if (pd->needs_group_calc)
{
if (pd->needs_size_calc)
{
_sizing_eval(obj);
pd->needs_size_calc = EINA_FALSE;
}
if (pd->needs_align_calc)
{
_calc_align(obj);
pd->needs_align_calc = EINA_FALSE;
}
Eina_Rect p_geom = efl_gfx_geometry_get(pd->win_parent);
efl_gfx_position_set(pd->backwall, EINA_POSITION2D(0, 0));
efl_gfx_size_set(pd->backwall, EINA_SIZE2D(p_geom.w, p_geom.h));
pd->needs_group_calc = EINA_FALSE;
}
}
/* Standard widget overrides */
ELM_PART_CONTENT_DEFAULT_GET(efl_ui_popup, "elm.swallow.content")
ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_popup, Efl_Ui_Popup_Data)
EOLIAN static Eo *
_efl_ui_popup_efl_part_part(const Eo *obj, Efl_Ui_Popup_Data *_pd EINA_UNUSED, const char *part)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
if (eina_streq(part, "backwall"))
return ELM_PART_IMPLEMENT(EFL_UI_POPUP_PART_CLASS, obj, part);
return efl_part(efl_super(obj, MY_CLASS), part);
}
EOLIAN static void
_efl_ui_popup_part_efl_canvas_object_repeat_events_set(Eo *obj, void *_pd EINA_UNUSED, Eina_Bool repeat)
{
Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
if (eina_streq(pd->part, "backwall"))
efl_canvas_object_repeat_events_set(sd->backwall, repeat);
else
efl_canvas_object_repeat_events_set(efl_part(efl_super(pd->obj, MY_CLASS), pd->part), repeat);
}
EOLIAN static Eina_Bool
_efl_ui_popup_part_efl_canvas_object_repeat_events_get(Eo *obj, void *_pd EINA_UNUSED)
{
Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
if (eina_streq(pd->part, "backwall"))
return efl_canvas_object_repeat_events_get(sd->backwall);
return efl_canvas_object_repeat_events_get(efl_part(efl_super(pd->obj, MY_CLASS), pd->part));
}
EOLIAN static Eina_Bool
_efl_ui_popup_part_efl_file_file_set(Eo *obj, void *_pd EINA_UNUSED, const char *file, const char *group)
{
Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS);
Efl_Ui_Popup_Data *sd = efl_data_scope_get(pd->obj, EFL_UI_POPUP_CLASS);
if (eina_streq(pd->part, "backwall"))
{
Eo *prev_obj = edje_object_part_swallow_get(sd->backwall, "elm.swallow.image");
if (prev_obj)
{
edje_object_part_unswallow(sd->backwall, prev_obj);
efl_del(prev_obj);
}
Eo *image = elm_image_add(pd->obj);
Eina_Bool ret = elm_image_file_set(image, file, group);
if (!ret)
{
edje_object_signal_emit(sd->backwall, "state,image,hidden", "efl");
efl_del(image);
return EINA_FALSE;
}
edje_object_part_swallow(sd->backwall, "elm.swallow.image", image);
edje_object_signal_emit(sd->backwall, "state,image,visible", "efl");
return EINA_TRUE;
}
return efl_file_set(efl_part(efl_super(pd->obj, MY_CLASS), pd->part), file, group);
}
#include "efl_ui_popup_part.eo.c"
/* Efl.Part end */
/* Internal EO APIs and hidden overrides */
#define EFL_UI_POPUP_EXTRA_OPS \
ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_popup), \
ELM_PART_CONTENT_DEFAULT_OPS(efl_ui_popup)
#include "efl_ui_popup.eo.c"