From 77831157d177531c2e4b52377d4a8f9fdea52f40 Mon Sep 17 00:00:00 2001 From: Gustavo Lima Chaves Date: Wed, 2 May 2012 16:58:36 +0000 Subject: [PATCH] [Elm] One more widget on elm layout: frame. SVN revision: 70636 --- legacy/elementary/src/lib/elm_frame.c | 438 +++++++++++--------------- legacy/elementary/src/lib/elm_frame.h | 6 +- 2 files changed, 196 insertions(+), 248 deletions(-) diff --git a/legacy/elementary/src/lib/elm_frame.c b/legacy/elementary/src/lib/elm_frame.c index 0d32c16b7c..63867430b3 100644 --- a/legacy/elementary/src/lib/elm_frame.c +++ b/legacy/elementary/src/lib/elm_frame.c @@ -1,325 +1,269 @@ #include #include "elm_priv.h" +#include "elm_widget_layout.h" -typedef struct _Widget_Data Widget_Data; +static const char FRAME_SMART_NAME[] = "elm_frame"; -struct _Widget_Data +typedef struct _Elm_Frame_Smart_Data Elm_Frame_Smart_Data; + +struct _Elm_Frame_Smart_Data { - Evas_Object *frm; - Evas_Object *content; - const char *label; - unsigned int recalc_count; - Eina_Bool collapsed : 1; - Eina_Bool collapsible : 1; - Eina_Bool anim : 1; + Elm_Layout_Smart_Data base; + + Eina_Bool collapsed : 1; + Eina_Bool collapsible : 1; + Eina_Bool anim : 1; }; static const char SIG_CLICKED[] = "clicked"; -static const Evas_Smart_Cb_Description _signals[] = { +static const Evas_Smart_Cb_Description _smart_callbacks[] = { {SIG_CLICKED, ""}, {NULL, NULL} }; -static const char *widtype = NULL; -static void _del_hook(Evas_Object *obj); -static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl); -static void _theme_hook(Evas_Object *obj); -static void _sizing_eval(Evas_Object *obj); -static void _changed_size_hints(void *data, - Evas *e, Evas_Object *obj, - void *event_info); -static void _sub_del(void *data, Evas_Object *obj, void *event_info); +#define ELM_FRAME_DATA_GET(o, sd) \ + Elm_Frame_Smart_Data * sd = evas_object_smart_data_get(o) + +#define ELM_FRAME_DATA_GET_OR_RETURN(o, ptr) \ + ELM_FRAME_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } + +#define ELM_FRAME_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + ELM_FRAME_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } + +#define ELM_FRAME_CHECK(obj) \ + if (!obj || !elm_widget_type_check((obj), FRAME_SMART_NAME, __func__)) \ + return + +static const Elm_Layout_Part_Alias_Description _content_aliases[] = +{ + {"default", "elm.swallow.content"}, + {NULL, NULL} +}; + +static const Elm_Layout_Part_Alias_Description _text_aliases[] = +{ + {"default", "elm.text"}, + {NULL, NULL} +}; + +/* Inheriting from elm_layout. Besides, we need no more than what is + * there */ +EVAS_SMART_SUBCLASS_NEW + (FRAME_SMART_NAME, _elm_frame, Elm_Layout_Smart_Class, + Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks); static void -_del_hook(Evas_Object *obj) +_sizing_eval(Evas_Object *obj, + Elm_Frame_Smart_Data *sd) { - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->label) eina_stringshare_del(wd->label); - free(wd); -} - -static void -_mirrored_set(Evas_Object *obj, Eina_Bool rtl) -{ - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - edje_object_mirrored_set(wd->frm, rtl); -} - -static void -_theme_hook(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - _elm_widget_mirrored_reload(obj); - _mirrored_set(obj, elm_widget_mirrored_get(obj)); - _elm_theme_object_set(obj, wd->frm, "frame", "base", - elm_widget_style_get(obj)); - edje_object_part_text_escaped_set(wd->frm, "elm.text", wd->label); - if (wd->content) - edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content); - edje_object_scale_set(wd->frm, - elm_widget_scale_get(obj) * _elm_config->scale); - _sizing_eval(obj); -} - -static Eina_Bool -_elm_frame_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) -{ - Widget_Data *wd = elm_widget_data_get(obj); - - if ((!wd) || (!wd->content)) - return EINA_FALSE; - - /* Try Focus cycle in subitem */ - return elm_widget_focus_next_get(wd->content, dir, next); -} - -static void -_sizing_eval(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); Evas_Coord minw = -1, minh = -1; Evas_Coord cminw = -1, cminh = -1; - if (!wd) return; - edje_object_size_min_calc(wd->frm, &minw, &minh); + + edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh); evas_object_size_hint_min_get(obj, &cminw, &cminh); if ((minw == cminw) && (minh == cminh)) return; + evas_object_size_hint_min_set(obj, minw, minh); evas_object_size_hint_max_set(obj, -1, -1); } -static void -_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +static Eina_Bool +_elm_frame_smart_focus_next(const Evas_Object *obj, + Elm_Focus_Direction dir, + Evas_Object **next) { - Widget_Data *wd = elm_widget_data_get(data); - if (!wd) return; - if (wd->anim) return; - // FIXME: why is this needed? how does edje get this unswallowed or - // lose its callbacks to edje - edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content); - _sizing_eval(data); -} - -static void -_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info) -{ - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Object *sub = event_info; - if (!wd) return; - if (sub == wd->content) - { - evas_object_event_callback_del_full(sub, - EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - wd->content = NULL; - _sizing_eval(obj); - } -} - -static void -_elm_frame_label_set(Evas_Object *obj, const char *item, const char *label) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (item && strcmp(item, "default")) return; - if (!wd) return; - eina_stringshare_replace(&(wd->label), label); - edje_object_part_text_escaped_set(wd->frm, "elm.text", wd->label); - _sizing_eval(obj); -} - -static const char * -_elm_frame_label_get(const Evas_Object *obj, const char *item) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - if (item && strcmp(item, "default")) return NULL; - return wd->label; -} - -static void -_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd; - - if (part && strcmp(part, "default")) return; - wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->content == content) return; - if (wd->content) evas_object_del(wd->content); - wd->content = content; - if (content) - { - elm_widget_sub_object_add(obj, content); - evas_object_event_callback_add(content, - EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - edje_object_part_swallow(wd->frm, "elm.swallow.content", content); - } - _sizing_eval(obj); -} - -static Evas_Object * -_content_get_hook(const Evas_Object *obj, const char *part) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd; - - if (part && strcmp(part, "default")) return NULL; - wd = elm_widget_data_get(obj); - if (!wd) return NULL; - - return wd->content; -} - -static Evas_Object * -_content_unset_hook(Evas_Object *obj, const char *part) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd; Evas_Object *content; - if (part && strcmp(part, "default")) return NULL; - wd = elm_widget_data_get(obj); - if (!wd || !wd->content) return NULL; - content = wd->content; - elm_widget_sub_object_del(obj, wd->content); - edje_object_part_unswallow(wd->frm, content); - return content; + + content = elm_layout_content_get(obj, NULL); + + if (!content) return EINA_FALSE; + + /* attempt to follow focus cycle into sub-object */ + return elm_widget_focus_next_get(content, dir, next); } static void -_recalc(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_recalc(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) { - _sizing_eval(data); + elm_layout_sizing_eval(data); } static void -_recalc_done(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__) +_on_recalc_done(void *data, + Evas_Object *obj __UNUSED__, + const char *sig __UNUSED__, + const char *src __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); - if (!wd) return; - evas_object_smart_callback_del(wd->frm, "recalc", _recalc); - wd->anim = EINA_FALSE; - _sizing_eval(data); + ELM_FRAME_DATA_GET(data, sd); + + evas_object_smart_callback_del + (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc); + sd->anim = EINA_FALSE; + + elm_layout_sizing_eval(data); } static void -_signal_click(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__) +_on_frame_clicked(void *data, + Evas_Object *obj __UNUSED__, + const char *sig __UNUSED__, + const char *src __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); - if (!wd) return; - if (wd->anim) return; - if (wd->collapsible) + ELM_FRAME_DATA_GET(data, sd); + + if (sd->anim) return; + + if (sd->collapsible) { - evas_object_smart_callback_add(wd->frm, "recalc", _recalc, data); - edje_object_signal_emit(wd->frm, "elm,action,toggle", "elm"); - wd->collapsed++; - wd->anim = EINA_TRUE; + evas_object_smart_callback_add + (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc, data); + elm_layout_signal_emit(data, "elm,action,toggle", "elm"); + sd->collapsed++; + sd->anim = EINA_TRUE; } evas_object_smart_callback_call(data, SIG_CLICKED, NULL); } +/* using deferred sizing evaluation, just like the parent */ +static void +_elm_frame_smart_calculate(Evas_Object *obj) +{ + ELM_FRAME_DATA_GET(obj, sd); + + if (ELM_LAYOUT_DATA(sd)->needs_size_calc) + { + /* calling OWN sizing evaluate code here */ + _sizing_eval(obj, sd); + ELM_LAYOUT_DATA(sd)->needs_size_calc = EINA_FALSE; + } +} + +static void +_elm_frame_smart_add(Evas_Object *obj) +{ + EVAS_SMART_DATA_ALLOC(obj, Elm_Frame_Smart_Data); + + ELM_WIDGET_CLASS(_elm_frame_parent_sc)->base.add(obj); + + edje_object_signal_callback_add + (ELM_WIDGET_DATA(priv)->resize_obj, "elm,anim,done", "elm", + _on_recalc_done, obj); + edje_object_signal_callback_add + (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,click", "elm", + _on_frame_clicked, obj); + + elm_widget_can_focus_set(obj, EINA_FALSE); + + elm_layout_theme_set(obj, "frame", "base", elm_widget_style_get(obj)); +} + +static void +_elm_frame_smart_set_user(Elm_Layout_Smart_Class *sc) +{ + ELM_WIDGET_CLASS(sc)->base.add = _elm_frame_smart_add; + ELM_WIDGET_CLASS(sc)->base.calculate = _elm_frame_smart_calculate; + + ELM_WIDGET_CLASS(sc)->focus_next = _elm_frame_smart_focus_next; + + sc->content_aliases = _content_aliases; + sc->text_aliases = _text_aliases; +} + EAPI Evas_Object * elm_frame_add(Evas_Object *parent) { - Evas_Object *obj; Evas *e; - Widget_Data *wd; + Evas_Object *obj; - ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); - ELM_SET_WIDTYPE(widtype, "frame"); - elm_widget_type_set(obj, "frame"); - elm_widget_sub_object_add(parent, obj); - elm_widget_data_set(obj, wd); - elm_widget_del_hook_set(obj, _del_hook); - elm_widget_theme_hook_set(obj, _theme_hook); - elm_widget_focus_next_hook_set(obj, _elm_frame_focus_next_hook); - elm_widget_can_focus_set(obj, EINA_FALSE); - elm_widget_text_set_hook_set(obj, _elm_frame_label_set); - elm_widget_text_get_hook_set(obj, _elm_frame_label_get); - elm_widget_content_set_hook_set(obj, _content_set_hook); - elm_widget_content_get_hook_set(obj, _content_get_hook); - elm_widget_content_unset_hook_set(obj, _content_unset_hook); + e = evas_object_evas_get(parent); + if (!e) return NULL; - wd->frm = edje_object_add(e); - _elm_theme_object_set(obj, wd->frm, "frame", "base", "default"); - elm_widget_resize_object_set(obj, wd->frm); + obj = evas_object_smart_add(e, _elm_frame_smart_class_new()); - evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); - edje_object_signal_callback_add(wd->frm, "elm,anim,done", "elm", - _recalc_done, obj); - edje_object_signal_callback_add(wd->frm, "elm,action,click", "elm", - _signal_click, obj); - evas_object_smart_callbacks_descriptions_set(obj, _signals); + if (!elm_widget_sub_object_add(parent, obj)) + ERR("could not add %p as sub object of %p", obj, parent); + + elm_layout_sizing_eval(obj); - _mirrored_set(obj, elm_widget_mirrored_get(obj)); - _sizing_eval(obj); return obj; } EAPI void -elm_frame_autocollapse_set(Evas_Object *obj, Eina_Bool autocollapse) +elm_frame_autocollapse_set(Evas_Object *obj, + Eina_Bool autocollapse) { - Widget_Data *wd; - ELM_CHECK_WIDTYPE(obj, widtype); - wd = elm_widget_data_get(obj); - if (!wd) return; - wd->collapsible = !!autocollapse; + ELM_FRAME_CHECK(obj); + ELM_FRAME_DATA_GET_OR_RETURN(obj, sd); + + sd->collapsible = !!autocollapse; } EAPI Eina_Bool elm_frame_autocollapse_get(const Evas_Object *obj) { - Widget_Data *wd; - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->collapsible; + ELM_FRAME_CHECK(obj) EINA_FALSE; + ELM_FRAME_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); + + return sd->collapsible; } EAPI void -elm_frame_collapse_set(Evas_Object *obj, Eina_Bool collapse) +elm_frame_collapse_set(Evas_Object *obj, + Eina_Bool collapse) { - Widget_Data *wd; - ELM_CHECK_WIDTYPE(obj, widtype); - wd = elm_widget_data_get(obj); - if (!wd) return; + ELM_FRAME_CHECK(obj); + ELM_FRAME_DATA_GET_OR_RETURN(obj, sd); + collapse = !!collapse; - if (wd->collapsed == collapse) return; - edje_object_signal_emit(wd->frm, "elm,action,switch", "elm"); - edje_object_message_signal_process(wd->frm); - wd->collapsed = !!collapse; - wd->anim = EINA_FALSE; - _sizing_eval(obj); + if (sd->collapsed == collapse) return; + + elm_layout_signal_emit(obj, "elm,action,switch", "elm"); + edje_object_message_signal_process(ELM_WIDGET_DATA(sd)->resize_obj); + sd->collapsed = !!collapse; + sd->anim = EINA_FALSE; + + _sizing_eval(obj, sd); } EAPI void -elm_frame_collapse_go(Evas_Object *obj, Eina_Bool collapse) +elm_frame_collapse_go(Evas_Object *obj, + Eina_Bool collapse) { - Widget_Data *wd; - ELM_CHECK_WIDTYPE(obj, widtype); - wd = elm_widget_data_get(obj); - if (!wd) return; + ELM_FRAME_CHECK(obj); + ELM_FRAME_DATA_GET_OR_RETURN(obj, sd); + collapse = !!collapse; - if (wd->collapsed == collapse) return; - edje_object_signal_emit(wd->frm, "elm,action,toggle", "elm"); - evas_object_smart_callback_add(wd->frm, "recalc", _recalc, obj); - wd->collapsed = collapse; - wd->anim = EINA_TRUE; + if (sd->collapsed == collapse) return; + + elm_layout_signal_emit(obj, "elm,action,toggle", "elm"); + evas_object_smart_callback_add + (ELM_WIDGET_DATA(sd)->resize_obj, "recalc", _recalc, obj); + sd->collapsed = collapse; + sd->anim = EINA_TRUE; } EAPI Eina_Bool elm_frame_collapse_get(const Evas_Object *obj) { - Widget_Data *wd; - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - wd = elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->collapsed; + ELM_FRAME_CHECK(obj) EINA_FALSE; + ELM_FRAME_DATA_GET_OR_RETURN_VAL(obj, sd, EINA_FALSE); + + return sd->collapsed; } diff --git a/legacy/elementary/src/lib/elm_frame.h b/legacy/elementary/src/lib/elm_frame.h index 58c3d933fb..b02efd9ddf 100644 --- a/legacy/elementary/src/lib/elm_frame.h +++ b/legacy/elementary/src/lib/elm_frame.h @@ -19,7 +19,11 @@ * * Of all this styles only default shows the title. * - * Smart callbacks one can listen to: + * This widget inherits from the @ref Layout one, so that all the + * functions acting on it also work for frame objects. + * + * This widget emits the following signals, besides the ones sent from + * @ref Layout: * - @c "clicked" - The user has clicked the frame's label * * Default content parts of the frame widget that you can use for are: