From 2308a021dedccf37c1b130544975b5a3db2cc71e Mon Sep 17 00:00:00 2001 From: Gustavo Lima Chaves Date: Wed, 2 May 2012 16:59:07 +0000 Subject: [PATCH] [Elm] Elm bubble is also an elm layout, now. SVN revision: 70642 --- .../elementary/data/themes/widgets/bubble.edc | 2 +- legacy/elementary/src/lib/elm_bubble.c | 452 ++++++------------ legacy/elementary/src/lib/elm_bubble.h | 8 +- 3 files changed, 159 insertions(+), 303 deletions(-) diff --git a/legacy/elementary/data/themes/widgets/bubble.edc b/legacy/elementary/data/themes/widgets/bubble.edc index 8348b07bd6..07ff9cba8a 100644 --- a/legacy/elementary/data/themes/widgets/bubble.edc +++ b/legacy/elementary/data/themes/widgets/bubble.edc @@ -569,7 +569,7 @@ group { name: "elm/bubble/bottom_right/default"; type: SWALLOW; description { state: "default" 0.0; fixed: 1 1; - visible: 0.0; + visible: 0; align: 1.0 1.0; aspect: 1.0 1.0; aspect_preference: VERTICAL; diff --git a/legacy/elementary/src/lib/elm_bubble.c b/legacy/elementary/src/lib/elm_bubble.c index 0f35578761..695c5b6904 100644 --- a/legacy/elementary/src/lib/elm_bubble.c +++ b/legacy/elementary/src/lib/elm_bubble.c @@ -1,368 +1,220 @@ #include #include "elm_priv.h" +#include "elm_widget_layout.h" -typedef struct _Widget_Data Widget_Data; +static const char BUBBLE_SMART_NAME[] = "elm_bubble"; -struct _Widget_Data +typedef struct _Elm_Bubble_Smart_Data Elm_Bubble_Smart_Data; + +struct _Elm_Bubble_Smart_Data { - Evas_Object *bbl; - Evas_Object *content, *icon; - const char *label, *info, *corner; - Elm_Bubble_Pos pos; -}; + Elm_Layout_Smart_Data base; -static const char *widtype = NULL; -static void _del_hook(Evas_Object *obj); -static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl); -static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content); -static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part); -static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part); -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); + Elm_Bubble_Pos pos; +}; static const char SIG_CLICKED[] = "clicked"; -static const Evas_Smart_Cb_Description _signals[] = +static const Elm_Layout_Part_Alias_Description _content_aliases[] = { - {SIG_CLICKED, ""}, - {NULL, NULL} + {"default", "elm.swallow.content"}, + {"icon", "elm.swallow.icon"}, + {NULL, NULL} +}; + +static const Elm_Layout_Part_Alias_Description _text_aliases[] = +{ + {"default", "elm.text"}, + {"info", "elm.info"}, + {NULL, NULL} +}; + +static const Evas_Smart_Cb_Description _smart_callbacks[] = +{ + {SIG_CLICKED, ""}, + {NULL, NULL} }; static const char *corner_string[] = { - "top_left", - "top_right", - "bottom_left", - "bottom_right" + "top_left", + "top_right", + "bottom_left", + "bottom_right" }; -static void -_del_hook(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->label) eina_stringshare_del(wd->label); - if (wd->info) eina_stringshare_del(wd->info); - if (wd->corner) eina_stringshare_del(wd->corner); - free(wd); -} +#define ELM_BUBBLE_DATA_GET(o, sd) \ + Elm_Bubble_Smart_Data * sd = evas_object_smart_data_get(o) + +#define ELM_BUBBLE_DATA_GET_OR_RETURN(o, ptr) \ + ELM_BUBBLE_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } + +#define ELM_BUBBLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + ELM_BUBBLE_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } + +#define ELM_BUBBLE_CHECK(obj) \ + if (!obj || !elm_widget_type_check((obj), BUBBLE_SMART_NAME, __func__)) \ + return + +/* Inheriting from elm_layout. Besides, we need no more than what is + * there */ +EVAS_SMART_SUBCLASS_NEW + (BUBBLE_SMART_NAME, _elm_bubble, Elm_Layout_Smart_Class, + Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks); static void -_mirrored_set(Evas_Object *obj, Eina_Bool rtl) +_elm_bubble_smart_sizing_eval(Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - edje_object_mirrored_set(wd->bbl, 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->bbl, "bubble", corner_string[wd->pos], - elm_widget_style_get(obj)); - edje_object_part_text_escaped_set(wd->bbl, "elm.text", wd->label); - if (wd->label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible", "elm"); - else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm"); - edje_object_part_text_escaped_set(wd->bbl, "elm.info", wd->info); - if (wd->info) edje_object_signal_emit(wd->bbl, "elm,state,info,visible", "elm"); - else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm"); - if (wd->content) - { - edje_object_part_swallow(wd->bbl, "elm.swallow.content", wd->content); - edje_object_message_signal_process(wd->bbl); - } - if (wd->icon) - edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm"); - else - edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm"); - edje_object_scale_set(wd->bbl, - elm_widget_scale_get(obj) * _elm_config->scale); - _sizing_eval(obj); -} - -static void -_content_set(Evas_Object *obj, Evas_Object *content) -{ - Widget_Data *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->bbl, "elm.swallow.content", content); - } - _sizing_eval(obj); -} - -static Evas_Object * -_content_unset(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Object *content; - if (!wd) return NULL; - if (!wd->content) return NULL; - content = wd->content; - elm_widget_sub_object_del(obj, content); - evas_object_event_callback_del_full(content, - EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - edje_object_part_unswallow(wd->bbl, content); - wd->content = NULL; - return content; -} - -static void -_icon_set(Evas_Object *obj, Evas_Object* icon) -{ - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (wd->icon == icon) return; - if (wd->icon) evas_object_del(wd->icon); - wd->icon = icon; - if (icon) - { - elm_widget_sub_object_add(obj, icon); - edje_object_part_swallow(wd->bbl, "elm.swallow.icon", icon); - evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm"); - edje_object_message_signal_process(wd->bbl); - } - _sizing_eval(obj); -} - -static Evas_Object * -_icon_unset(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Object *icon; - if (!wd) return NULL; - if (!wd->icon) return NULL; - icon = wd->icon; - elm_widget_sub_object_del(obj, icon); - evas_object_event_callback_del_full(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - edje_object_part_unswallow(wd->bbl, icon); - wd->icon = NULL; - return icon; -} - -static void -_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - - if (!part || !strcmp(part, "default")) - _content_set(obj, content); - else if (!strcmp(part, "icon")) - _icon_set(obj, content); -} - -static Evas_Object * -_content_get_hook(const Evas_Object *obj, const char *part) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - if (!part || !strcmp(part, "default")) - return wd->content; - else if (!strcmp(part, "icon")) - return wd->icon; - return NULL; -} - -static Evas_Object * -_content_unset_hook(Evas_Object *obj, const char *part) -{ - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - if (!part || !strcmp(part, "default")) - return _content_unset(obj); - else if (!strcmp(part, "icon")) - return _icon_unset(obj); - return NULL; -} - -static Eina_Bool -_elm_bubble_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) -{ - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Object *cur; - - if ((!wd) || (!wd->content)) - return EINA_FALSE; - - cur = wd->content; - - /* Try Focus cycle in subitem */ - return elm_widget_focus_next_get(cur, dir, next); -} - -static void -_sizing_eval(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; - if (!wd) return; + + ELM_BUBBLE_DATA_GET(obj, sd); + elm_coords_finger_size_adjust(1, &minw, 1, &minh); - edje_object_size_min_restricted_calc(wd->bbl, &minw, &minh, minw, minh); + edje_object_size_min_restricted_calc + (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh); evas_object_size_hint_min_set(obj, minw, minh); evas_object_size_hint_max_set(obj, maxw, maxh); } -static void -_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +/* overriding layout's focus_next() in order to just cycle through the + * content's tree */ +static Eina_Bool +_elm_bubble_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; - _sizing_eval(data); + Evas_Object *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 -_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; - evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - if (sub == wd->content) wd->content = NULL; - else if (sub == wd->icon) - { - edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm"); - wd->icon = NULL; - edje_object_message_signal_process(wd->bbl); - } - _sizing_eval(obj); -} - -static void -_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_on_mouse_up(void *data, + Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info) { Evas_Event_Mouse_Up *ev = event_info; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return; + evas_object_smart_callback_call(data, SIG_CLICKED, NULL); } -static void -_elm_bubble_label_set(Evas_Object *obj, const char *item, const char *label) +static Eina_Bool +_elm_bubble_smart_text_set(Evas_Object *obj, + const char *item, + const char *label) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; + if (!_elm_bubble_parent_sc->text_set(obj, item, label)) return EINA_FALSE; - if (!item || !strcmp(item, "default")) + if (item && (!strcmp(item, "info") || !strcmp(item, "elm.info"))) { - eina_stringshare_replace(&wd->label, label); - edje_object_part_text_escaped_set(wd->bbl, "elm.text", label); - if (label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible", - "elm"); - else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm"); - _sizing_eval(obj); - } - else if (!strcmp(item, "info")) - { - eina_stringshare_replace(&wd->info, label); - edje_object_part_text_escaped_set(wd->bbl, "elm.info", label); - if (label) edje_object_signal_emit(wd->bbl, "elm,state,info,visible", - "elm"); - else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm"); - _sizing_eval(obj); + if (label) + elm_layout_signal_emit(obj, "elm,state,info,visible", "elm"); + else + elm_layout_signal_emit(obj, "elm,state,info,hidden", "elm"); } + + elm_layout_sizing_eval(obj); + + return EINA_TRUE; } -static const char* -_elm_bubble_label_get(const Evas_Object *obj, const char *item) +static void +_elm_bubble_smart_add(Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; + EVAS_SMART_DATA_ALLOC(obj, Elm_Bubble_Smart_Data); - if (!item || !strcmp(item, "default")) - { - return wd->label; - } - else if (!strcmp(item, "info")) - { - return wd->info; - } + ELM_WIDGET_CLASS(_elm_bubble_parent_sc)->base.add(obj); - return NULL; + priv->pos = ELM_BUBBLE_POS_TOP_LEFT; //default + + elm_widget_can_focus_set(obj, EINA_FALSE); + + evas_object_event_callback_add + (ELM_WIDGET_DATA(priv)->resize_obj, EVAS_CALLBACK_MOUSE_UP, + _on_mouse_up, obj); + + elm_layout_theme_set(obj, "bubble", "base", elm_widget_style_get(obj)); +} + +static void +_elm_bubble_smart_set_user(Elm_Layout_Smart_Class *sc) +{ + ELM_WIDGET_CLASS(sc)->base.add = _elm_bubble_smart_add; + + ELM_WIDGET_CLASS(sc)->focus_next = _elm_bubble_smart_focus_next; + + sc->text_set = _elm_bubble_smart_text_set; + sc->sizing_eval = _elm_bubble_smart_sizing_eval; + + sc->content_aliases = _content_aliases; + sc->text_aliases = _text_aliases; } EAPI Evas_Object * elm_bubble_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, "bubble"); - elm_widget_type_set(obj, "bubble"); - 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_bubble_focus_next_hook); - elm_widget_can_focus_set(obj, EINA_FALSE); - elm_widget_text_set_hook_set(obj, _elm_bubble_label_set); - elm_widget_text_get_hook_set(obj, _elm_bubble_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->corner = eina_stringshare_add("base"); - wd->pos = ELM_BUBBLE_POS_TOP_LEFT; //default + obj = evas_object_smart_add(e, _elm_bubble_smart_class_new()); - wd->bbl = edje_object_add(e); - elm_widget_resize_object_set(obj, wd->bbl); + if (!elm_widget_sub_object_add(parent, obj)) + ERR("could not add %p as sub object of %p", obj, parent); - evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); - evas_object_event_callback_add(wd->bbl, EVAS_CALLBACK_MOUSE_UP, - _mouse_up, obj); + elm_layout_sizing_eval(obj); - evas_object_smart_callbacks_descriptions_set(obj, _signals); - _mirrored_set(obj, elm_widget_mirrored_get(obj)); - _elm_theme_object_set(obj, wd->bbl, "bubble", wd->corner, - elm_widget_style_get(obj)); - _sizing_eval(obj); return obj; } EAPI void -elm_bubble_pos_set(Evas_Object *obj, Elm_Bubble_Pos pos) +elm_bubble_pos_set(Evas_Object *obj, + Elm_Bubble_Pos pos) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - if (posELM_BUBBLE_POS_BOTTOM_RIGHT) return; - wd->pos = pos; - _theme_hook(obj); + ELM_BUBBLE_CHECK(obj); + ELM_BUBBLE_DATA_GET_OR_RETURN(obj, sd); + + if (pos < ELM_BUBBLE_POS_TOP_LEFT || pos > ELM_BUBBLE_POS_BOTTOM_RIGHT) + return; + + sd->pos = pos; + + eina_stringshare_replace + (&(ELM_LAYOUT_DATA(sd)->group), corner_string[sd->pos]); + + ELM_WIDGET_DATA(sd)->api->theme(obj); } EAPI Elm_Bubble_Pos elm_bubble_pos_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) ELM_BUBBLE_POS_INVALID; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return ELM_BUBBLE_POS_INVALID; - return wd->pos; + ELM_BUBBLE_CHECK(obj) ELM_BUBBLE_POS_INVALID; + ELM_BUBBLE_DATA_GET_OR_RETURN_VAL(obj, sd, ELM_BUBBLE_POS_INVALID); + + return sd->pos; } diff --git a/legacy/elementary/src/lib/elm_bubble.h b/legacy/elementary/src/lib/elm_bubble.h index 9f97ec1a47..8c21d9c49d 100644 --- a/legacy/elementary/src/lib/elm_bubble.h +++ b/legacy/elementary/src/lib/elm_bubble.h @@ -29,8 +29,12 @@ * @li "bottom_left" * @li "bottom_right" * - * Signals that you can add callbacks for are: - * @li "clicked" - This is called when a user has clicked the bubble. + * This widget inherits from the @ref Layout one, so that all the + * functions acting on it also work for bubble objects. + * + * This widget emits the following signals, besides the ones sent from + * @ref Layout: + * @li @c "clicked" - This is called when a user has clicked the bubble. * * Default content parts of the bubble that you can use for are: * @li "default" - A content of the bubble