X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Flib%2Felm_button.c;h=7f784ea84cedfab3fe41cdd1c6130ad57c657f7f;hb=76315f85e6f98edbe7ffe8cc6f695308aff2f89c;hp=6ced31b08c7d32eafd57436e0458766f4900c14a;hpb=0ec4ccf5a48107a66b2dcd3f64102398abd43935;p=framework%2Fuifw%2Felementary.git diff --git a/src/lib/elm_button.c b/src/lib/elm_button.c index 6ced31b..7f784ea 100644 --- a/src/lib/elm_button.c +++ b/src/lib/elm_button.c @@ -1,30 +1,38 @@ #include #include "elm_priv.h" -/** - * @defgroup Button Button - * - * This is a push-button. Press it and run some function. It can contain - * a simple label and icon object. - */ - typedef struct _Widget_Data Widget_Data; +enum +{ + DEFAULT = 0, + HIGHLIGHTED, + FOCUSED, + DISABLED, +}; + struct _Widget_Data { Evas_Object *btn, *icon; const char *label; - Eina_Bool autorepeat; - Eina_Bool repeating; double ar_threshold; double ar_interval; Ecore_Timer *timer; + const char *statelabel[4]; + int statetype[4]; + Eina_Bool autorepeat : 1; + Eina_Bool repeating : 1; + Eina_Bool delete_me : 1; }; static const char *widtype = NULL; static void _del_hook(Evas_Object *obj); +static void _del_pre_hook(Evas_Object *obj); static void _theme_hook(Evas_Object *obj); static void _disable_hook(Evas_Object *obj); +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 _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); @@ -37,12 +45,17 @@ static void _activate_hook(Evas_Object *obj); static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info); +static void _set_label(Evas_Object *obj, const char *label); +static void _signal_default_text_set(void *data, Evas_Object *obj, const char *emission, const char *source); + static const char SIG_CLICKED[] = "clicked"; static const char SIG_REPEATED[] = "repeated"; +static const char SIG_PRESSED[] = "pressed"; static const char SIG_UNPRESSED[] = "unpressed"; static const Evas_Smart_Cb_Description _signals[] = { {SIG_CLICKED, ""}, {SIG_REPEATED, ""}, + {SIG_PRESSED, ""}, {SIG_UNPRESSED, ""}, {NULL, NULL} }; @@ -67,11 +80,23 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty } static void +_del_pre_hook(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + wd->delete_me = EINA_TRUE; +} + +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->statelabel[DEFAULT]) eina_stringshare_del(wd->statelabel[DEFAULT]); + if (wd->statelabel[HIGHLIGHTED]) eina_stringshare_del(wd->statelabel[HIGHLIGHTED]); + if (wd->statelabel[FOCUSED]) eina_stringshare_del(wd->statelabel[FOCUSED]); + if (wd->statelabel[DISABLED]) eina_stringshare_del(wd->statelabel[DISABLED]); free(wd); } @@ -82,11 +107,17 @@ _on_focus_hook(void *data __UNUSED__, Evas_Object *obj) if (!wd) return; if (elm_widget_focus_get(obj)) { + if (wd->statelabel[FOCUSED]) + { + _set_label(obj, wd->statelabel[FOCUSED]); + } edje_object_signal_emit(wd->btn, "elm,action,focus", "elm"); evas_object_focus_set(wd->btn, EINA_TRUE); } else { + if (wd->statelabel[DEFAULT]) + _set_label(obj, wd->statelabel[DEFAULT]); edje_object_signal_emit(wd->btn, "elm,action,unfocus", "elm"); evas_object_focus_set(wd->btn, EINA_FALSE); } @@ -109,6 +140,8 @@ _theme_hook(Evas_Object *obj) _elm_widget_mirrored_reload(obj); _mirrored_set(obj, elm_widget_mirrored_get(obj)); _elm_theme_object_set(obj, wd->btn, "button", "base", elm_widget_style_get(obj)); + if (elm_object_disabled_get(obj)) + edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm"); if (wd->icon) edje_object_part_swallow(wd->btn, "elm.swallow.content", wd->icon); if (wd->label) @@ -120,8 +153,6 @@ _theme_hook(Evas_Object *obj) else edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm"); edje_object_part_text_set(wd->btn, "elm.text", wd->label); - if (elm_object_disabled_get(obj)) - edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm"); edje_object_message_signal_process(wd->btn); edje_object_scale_set(wd->btn, elm_widget_scale_get(obj) * _elm_config->scale); str = edje_object_data_get(wd->btn, "focus_highlight"); @@ -138,9 +169,19 @@ _disable_hook(Evas_Object *obj) Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; if (elm_widget_disabled_get(obj)) - edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm"); + { + if (wd->statelabel[DISABLED] ) + { + _set_label(obj, wd->statelabel[DISABLED]); + } + edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm"); + } else - edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm"); + { + if (wd->statelabel[DEFAULT]) + _set_label(obj, wd->statelabel[DEFAULT]); + edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm"); + } } static void @@ -152,7 +193,7 @@ _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source) } static void -_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) +_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) { Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; @@ -160,7 +201,7 @@ _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *so } static void -_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, void (*func_cb) (void *data, Evas_Object *o, const char *emission, const char *source), void *data) +_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) { Widget_Data *wd = elm_widget_data_get(obj); edje_object_signal_callback_del_full(wd->btn, emission, source, func_cb, @@ -168,12 +209,60 @@ _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *so } static void +_content_set_hook(Evas_Object *obj, const char *part __UNUSED__, Evas_Object *content) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + if (wd->icon == content) return; + if (wd->icon) evas_object_del(wd->icon); + wd->icon = 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->btn, "elm.swallow.content", content); + edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm"); + edje_object_message_signal_process(wd->btn); + } + _sizing_eval(obj); +} + +static Evas_Object * +_content_get_hook(const Evas_Object *obj, const char *part __UNUSED__) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + return wd->icon; +} + +static Evas_Object * +_content_unset_hook(Evas_Object *obj, const char *part __UNUSED__) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + if (!wd->icon) return NULL; + Evas_Object *icon = wd->icon; + elm_widget_sub_object_del(obj, wd->icon); + evas_object_event_callback_del_full(wd->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _changed_size_hints, obj); + edje_object_part_unswallow(wd->btn, wd->icon); + wd->icon = NULL; + return icon; +} + +static void _sizing_eval(Evas_Object *obj) { Widget_Data *wd = elm_widget_data_get(obj); Evas_Coord minw = -1, minh = -1; if (!wd) return; + if (wd->delete_me) return; elm_coords_finger_size_adjust(1, &minw, 1, &minh); edje_object_size_min_restricted_calc(wd->btn, &minw, &minh, minw, minh); elm_coords_finger_size_adjust(1, &minw, 1, &minh); @@ -268,6 +357,10 @@ _signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __ Widget_Data *wd = elm_widget_data_get(data); if (!wd) return; + if (wd->statelabel[HIGHLIGHTED]) + { + _set_label(data, wd->statelabel[HIGHLIGHTED]); + } if ((wd->autorepeat) && (!wd->repeating)) { if (wd->ar_threshold <= 0.0) @@ -275,6 +368,8 @@ _signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __ else wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data); } + + evas_object_smart_callback_call(data, SIG_PRESSED, NULL); } static void @@ -282,6 +377,8 @@ _signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission { Widget_Data *wd = elm_widget_data_get(data); if (!wd) return; + if (wd->statelabel[DEFAULT]) + _set_label(data, wd->statelabel[DEFAULT]); if (wd->timer) { @@ -292,13 +389,50 @@ _signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission evas_object_smart_callback_call(data, SIG_UNPRESSED, NULL); } -/** - * Add a new button to the parent - * @param parent The parent object - * @return The new object or NULL if it cannot be created - * - * @ingroup Button - */ +static void +_signal_default_text_set(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) +{ + Widget_Data *wd = elm_widget_data_get(data); + if (!wd) return; + if (wd->statelabel[DEFAULT]) + _set_label(data, wd->statelabel[DEFAULT]); +} + +static void +_elm_button_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); + if (label) + edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm"); + else + edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm"); + edje_object_message_signal_process(wd->btn); + edje_object_part_text_set(wd->btn, "elm.text", label); + _sizing_eval(obj); +} + +static const char * +_elm_button_label_get(const Evas_Object *obj, const char *item) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (item && strcmp(item, "default")) return NULL; + if (!wd) return NULL; + return wd->label; +} + +static char * +_access_info_cb(const void *data, Evas_Object *obj, Elm_Widget_Item *item) +{ + const char *txt = _elm_button_label_get(obj, NULL); + if (txt) return strdup(txt); + return txt; +} + EAPI Evas_Object * elm_button_add(Evas_Object *parent) { @@ -306,18 +440,15 @@ elm_button_add(Evas_Object *parent) Evas *e; Widget_Data *wd; - EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); - wd = ELM_NEW(Widget_Data); - e = evas_object_evas_get(parent); - if (!e) return NULL; - obj = elm_widget_add(e); ELM_SET_WIDTYPE(widtype, "button"); elm_widget_type_set(obj, "button"); elm_widget_sub_object_add(parent, obj); - elm_widget_on_focus_hook_set( obj, _on_focus_hook, NULL ); + elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); elm_widget_data_set(obj, wd); elm_widget_del_hook_set(obj, _del_hook); + elm_widget_del_pre_hook_set(obj, _del_pre_hook); elm_widget_theme_hook_set(obj, _theme_hook); elm_widget_disable_hook_set(obj, _disable_hook); elm_widget_can_focus_set(obj, EINA_TRUE); @@ -326,15 +457,30 @@ elm_button_add(Evas_Object *parent) elm_widget_signal_emit_hook_set(obj, _signal_emit_hook); elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); + elm_widget_text_set_hook_set(obj, _elm_button_label_set); + elm_widget_text_get_hook_set(obj, _elm_button_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); wd->btn = edje_object_add(e); _elm_theme_object_set(obj, wd->btn, "button", "base", "default"); + wd->statetype[DEFAULT] = 0; + wd->statetype[HIGHLIGHTED] = 0; + wd->statetype[FOCUSED] = 0; + wd->statetype[DISABLED] = 0; + wd->statelabel[DEFAULT] = 0; + wd->statelabel[HIGHLIGHTED] = 0; + wd->statelabel[FOCUSED] = 0; + wd->statelabel[DISABLED] = 0; edje_object_signal_callback_add(wd->btn, "elm,action,click", "", _signal_clicked, obj); edje_object_signal_callback_add(wd->btn, "elm,action,press", "", _signal_pressed, obj); edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "", _signal_unpressed, obj); + edje_object_signal_callback_add(wd->btn, "elm,action,default,text,set", "", + _signal_default_text_set, obj); elm_widget_resize_object_set(obj, wd->btn); evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); @@ -344,126 +490,107 @@ elm_button_add(Evas_Object *parent) // TODO: convert Elementary to subclassing of Evas_Smart_Class // TODO: and save some bytes, making descriptions per-class and not instance! evas_object_smart_callbacks_descriptions_set(obj, _signals); + + _elm_access_object_register(obj, wd->btn); + _elm_access_text_set(_elm_access_object_get(obj), + ELM_ACCESS_TYPE, E_("Button")); + _elm_access_callback_set(_elm_access_object_get(obj), + ELM_ACCESS_INFO, _access_info_cb, obj); return obj; } -/** - * Set the label used in the button - * - * @param obj The button object - * @param label The text will be written on the button - * - * @ingroup Button - */ +static void +_set_label(Evas_Object *obj, const char *label) +{ + Widget_Data *wd = elm_widget_data_get(obj); + + edje_object_part_text_set(wd->btn, "elm.text", label); + _sizing_eval(obj); +} + EAPI void -elm_button_label_set(Evas_Object *obj, const char *label) +elm_button_label_set_for_state(Evas_Object *obj, const char *label, UIControlState state) { - ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; - eina_stringshare_replace(&wd->label, label); - if (label) - edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm"); + if (label == NULL) return; + + if (state == UIControlStateDefault) + { + wd->statetype[DEFAULT] = UIControlStateDefault; + eina_stringshare_replace(&wd->statelabel[DEFAULT], label); + return; + } + if (state == UIControlStateHighlighted) + { + wd->statetype[HIGHLIGHTED] = UIControlStateHighlighted; + eina_stringshare_replace(&wd->statelabel[HIGHLIGHTED], label); + return; + } + if (state == UIControlStateFocused) + { + wd->statetype[FOCUSED] = UIControlStateFocused; + eina_stringshare_replace(&wd->statelabel[FOCUSED], label); + return; + } + if (state == UIControlStateDisabled) + { + wd->statetype[DISABLED] = UIControlStateDisabled; + eina_stringshare_replace(&wd->statelabel[DISABLED], label); + return; + } +} + +EAPI const char* +elm_button_label_get_for_state(const Evas_Object *obj, UIControlState state) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + if (state == UIControlStateDefault) + return wd->statelabel[DEFAULT]; + else if (state == UIControlStateHighlighted) + return wd->statelabel[HIGHLIGHTED]; + else if (state == UIControlStateFocused) + return wd->statelabel[FOCUSED]; + else if (state == UIControlStateDisabled) + return wd->statelabel[DISABLED]; else - edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm"); - edje_object_message_signal_process(wd->btn); - edje_object_part_text_set(wd->btn, "elm.text", label); - _sizing_eval(obj); + return NULL; +} + +EAPI void +elm_button_label_set(Evas_Object *obj, const char *label) +{ + _elm_button_label_set(obj, NULL, label); } EAPI const char * elm_button_label_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - return wd->label; + return _elm_button_label_get(obj, NULL); } -/** - * Set the icon used for the button - * - * Once the icon object is set, a previously set one will be deleted - * If you want to keep that old content object, use the - * elm_button_icon_unset() function. - * - * @param obj The button object - * @param icon The icon object for the button - * - * @ingroup Button - */ + EAPI void elm_button_icon_set(Evas_Object *obj, Evas_Object *icon) { - ELM_CHECK_WIDTYPE(obj, widtype); - 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); - evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _changed_size_hints, obj); - edje_object_part_swallow(wd->btn, "elm.swallow.content", icon); - edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm"); - edje_object_message_signal_process(wd->btn); - } - _sizing_eval(obj); + _content_set_hook(obj, NULL, icon); } -/** - * Get the icon used for the button - * - * Return the icon object which is set for this widget. - * - * @param obj The button object - * @return The icon object that is being used - * - * @ingroup Button - */ EAPI Evas_Object * elm_button_icon_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - return wd->icon; + return _content_get_hook(obj, NULL); } -/** - * Unset the icon used for the button - * - * Unparent and return the icon object which was set for this widget. - * - * @param obj The button object - * @return The icon object that was being used - * - * @ingroup Button - */ EAPI Evas_Object * elm_button_icon_unset(Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) NULL; - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return NULL; - if (!wd->icon) return NULL; - Evas_Object *icon = wd->icon; - elm_widget_sub_object_del(obj, wd->icon); - edje_object_part_unswallow(wd->btn, wd->icon); - wd->icon = NULL; - return icon; + return _content_unset_hook(obj, NULL); } -/** - * Turn on/off the autorepeat event generated when the user keeps pressing on the button - * - * @param obj The button object - * @param on A bool to turn on/off the event - * - * @ingroup Button - */ EAPI void elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on) { @@ -479,14 +606,6 @@ elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on) wd->repeating = EINA_FALSE; } -/** - * Get if autorepeat event is on - * - * @param obj The button object - * @return If autorepeat is on - * - * @ingroup Button - */ EAPI Eina_Bool elm_button_autorepeat_get(const Evas_Object *obj) { @@ -496,14 +615,6 @@ elm_button_autorepeat_get(const Evas_Object *obj) return wd->autorepeat; } -/** - * Set the initial timeout before the autorepeat event is generated - * - * @param obj The button object - * @param t Timeout - * - * @ingroup Button - */ EAPI void elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t) { @@ -519,14 +630,6 @@ elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t) wd->ar_threshold = t; } -/** - * Get the initial timeout before the autorepeat event is generated - * - * @param obj The button object - * @return Timeout - * - * @ingroup Button - */ EAPI double elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj) { @@ -536,14 +639,6 @@ elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj) return wd->ar_threshold; } -/** - * Set the interval between each generated autorepeat event - * - * @param obj The button object - * @param t Interval - * - * @ingroup Button - */ EAPI void elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t) { @@ -556,14 +651,6 @@ elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t) if ((wd->repeating) && (wd->timer)) ecore_timer_interval_set(wd->timer, t); } -/** - * Get the interval between each generated autorepeat event - * - * @param obj The button object - * @return Interval - * - * @ingroup Button - */ EAPI double elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj) {