diff options
Diffstat (limited to 'src/lib/elementary/efl_ui_tab_bar.c')
-rw-r--r-- | src/lib/elementary/efl_ui_tab_bar.c | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/src/lib/elementary/efl_ui_tab_bar.c b/src/lib/elementary/efl_ui_tab_bar.c new file mode 100644 index 0000000000..ffbc1fdbce --- /dev/null +++ b/src/lib/elementary/efl_ui_tab_bar.c @@ -0,0 +1,392 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_UI_TAB_BAR_BETA + +#include <Elementary.h> +#include "elm_priv.h" +#include "efl_ui_tab_bar_private.h" +#include "els_box.h" + +#define MY_CLASS EFL_UI_TAB_BAR_CLASS + +static const char PART_NAME_TAB[] = "tab"; + +static void _tab_select(Efl_Ui_Tab_Bar_Data *sd, Tab_Info *ti); + +EOLIAN static void +_efl_ui_tab_bar_current_tab_set(Eo *obj EINA_UNUSED, Efl_Ui_Tab_Bar_Data *sd, int index) +{ + Tab_Info *ti; + ti = eina_list_nth(sd->tab_infos, index); + + _tab_select(sd, ti); +} + +EOLIAN static int +_efl_ui_tab_bar_current_tab_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tab_Bar_Data *sd) +{ + return sd->cur; +} + +EOLIAN static unsigned int +_efl_ui_tab_bar_tab_count(const Eo *obj EINA_UNUSED, Efl_Ui_Tab_Bar_Data *sd) +{ + return sd->cnt; +} + +static void +_tab_icon_update(Tab_Info *ti) +{ + Eo *old_icon = + efl_content_get(efl_part(ti->tab, "efl.icon")); + + _elm_widget_sub_object_redirect_to_top(ti->tab, old_icon); + efl_content_unset(efl_part(ti->tab, "efl.icon")); + efl_content_set(efl_part(ti->tab, "efl.icon"), ti->icon); + + if (ti->icon) + efl_layout_signal_emit(ti->tab, "efl,state,icon,visible", "efl"); + else + efl_layout_signal_emit(ti->tab, "efl,state,icon,hidden", "efl"); + + efl_del(old_icon); +} + +static void +_tab_icon_set_cb(void *data, + Eo *obj, + const char *emission, + const char *source) +{ + Tab_Info *ti = data; + _tab_icon_update(ti); + + efl_layout_signal_callback_del(obj, emission, source, _tab_icon_set_cb, NULL); + efl_layout_signal_emit(ti->tab, "efl,state,icon,reset", "efl"); +} + +static void +_tab_icon_obj_set(Eo *obj, + Tab_Info *ti, + Eo *icon_obj, + const char *icon_str, + const char *sig) +{ + Eo *old_icon; + const char *s; + + if (icon_str) + eina_stringshare_replace(&ti->icon_str, icon_str); + else + { + eina_stringshare_del(ti->icon_str); + ti->icon_str = NULL; + } + + ti->icon = icon_obj; + if (icon_obj) + { + efl_gfx_entity_visible_set(ti->icon, EINA_TRUE); + elm_widget_sub_object_add(obj, ti->icon); + } + + s = elm_layout_data_get(ti->tab, "transition_animation_on"); + if ((s) && (atoi(s))) + { + old_icon = efl_content_get + (efl_part(ti->tab, "efl.icon_new")); + if (old_icon) + { + _elm_widget_sub_object_redirect_to_top(ti->tab, old_icon); + efl_gfx_entity_visible_set(old_icon, EINA_FALSE); + } + efl_content_set + (efl_part(ti->tab, "efl.icon_new"), ti->icon); + efl_layout_signal_emit(ti->tab, sig, "efl"); + efl_layout_signal_callback_add + (ti->tab, "efl,state,icon_set,done", "efl", _tab_icon_set_cb, ti); + } + else + _tab_icon_update(ti); +} + +static Eina_Bool +_tab_icon_set(Eo *icon_obj, + const char *type, + const char *icon) +{ + char icon_str[512]; + + if ((!type) || (!*type)) goto end; + if ((!icon) || (!*icon)) return EINA_FALSE; + if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0) + && (elm_icon_standard_set(icon_obj, icon_str))) + return EINA_TRUE; +end: + if (elm_icon_standard_set(icon_obj, icon)) + return EINA_TRUE; + + WRN("couldn't find icon definition for '%s'", icon); + return EINA_FALSE; +} + +static void +_tab_unselect(Efl_Ui_Tab_Bar_Data *sd, Tab_Info *ti) +{ + if ((!ti->tab) || (!ti->selected)) return; + + ti->selected = EINA_FALSE; + + efl_layout_signal_emit(ti->tab, "efl,state,unselected", "efl"); + if (ti->icon) + elm_widget_signal_emit(ti->icon, "efl,state,unselected", "efl"); + + sd->cur = -1; +} + +static void +_tab_select(Efl_Ui_Tab_Bar_Data *sd, Tab_Info *ti) +{ + if (!ti->selected) + { + Eo *tp; + tp = efl_parent_get(ti->tab); + int index; + + _tab_unselect(sd, sd->selected_tab); + ti->selected = EINA_TRUE; + sd->selected_tab = ti; + + efl_layout_signal_emit(ti->tab, "efl,state,selected", "efl"); + if (ti->icon) + elm_widget_signal_emit(ti->icon, "efl,state,selected", "efl"); + + index = eina_list_data_idx(sd->tab_infos, ti); + + efl_event_callback_call(tp, EFL_UI_EVENT_SELECTED, (void *)(intptr_t)index); + + sd->cur = index; + } +} + +static void +_action_click_cb(void *data, + Eo *obj EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *tb; + Tab_Info *ti; + ti = data; + tb = efl_parent_get(ti->tab); + EFL_UI_TAB_BAR_DATA_GET(tb, sd); + + _tab_select(sd, ti); +} + +static Tab_Info * +_tab_add(Eo *obj, const char *label, const char *icon) +{ + Eo *tab, *icon_obj; + Tab_Info *ti; + Efl_Ui_Theme_Apply theme_apply; + + ti = calloc(1, sizeof(*ti)); + + ti->tab = NULL; + ti->label = eina_stringshare_add(label); + + tab = efl_add(EFL_UI_LAYOUT_OBJECT_CLASS, obj); + + icon_obj = elm_icon_add(tab); + + if (_tab_icon_set(icon_obj, "toolbar/", icon)) + { + ti->icon = icon_obj; + ti->icon_str = eina_stringshare_add(icon); + } + else + { + ti->icon = NULL; + ti->icon_str = NULL; + efl_del(icon_obj); + } + + theme_apply = elm_widget_element_update(obj, tab, PART_NAME_TAB); + + if (theme_apply == EFL_UI_THEME_APPLY_FAILED) + CRI("Failed to set layout!"); + + efl_layout_signal_callback_add + (tab, "efl,action,click", "efl", _action_click_cb, ti); + + if (ti->icon) + { + efl_content_set(efl_part(tab, "efl.icon"), ti->icon); + efl_layout_signal_emit(tab, "efl,state,icon,visible", "efl"); + efl_layout_signal_emit(tab, "efl,icon,visible", "efl"); + efl_gfx_entity_visible_set(ti->icon, EINA_TRUE); + } + else + { + efl_layout_signal_emit(tab, "efl,state,icon,hidden", "efl"); + efl_layout_signal_emit(tab, "efl,icon,hidden", "efl"); + } + + if (ti->label) + { + efl_text_set(efl_part(tab, "efl.text"), ti->label); + efl_layout_signal_emit(tab, "efl,state,text,visible", "efl"); + efl_layout_signal_emit(tab, "efl,text,visible", "efl"); + } + else + { + efl_layout_signal_emit(tab, "efl,state,text,hidden", "efl"); + efl_layout_signal_emit(tab, "efl,text,hidden", "efl"); + } + + efl_ui_widget_focus_allow_set(tab, EINA_TRUE); + + ti->tab = tab; + + return ti; +} + +EOLIAN static void +_efl_ui_tab_bar_tab_add(Eo *obj, Efl_Ui_Tab_Bar_Data *sd, + int index, const char *label, const char *icon) +{ + Tab_Info *ti; + ti = _tab_add(obj, label, icon); + + efl_parent_set(ti->tab, obj); + efl_ui_widget_sub_object_add(obj, ti->tab); + + if (sd->cnt > index) + { + Tab_Info *existing_ti; + existing_ti = eina_list_nth(sd->tab_infos, index); + + sd->tab_infos = eina_list_prepend_relative(sd->tab_infos, ti, existing_ti); + evas_object_box_insert_before(sd->bx, ti->tab, existing_ti->tab); + + if (sd->cur >= index) sd->cur ++; + } + else + { + sd->tab_infos = eina_list_append(sd->tab_infos, ti); + evas_object_box_append(sd->bx, ti->tab); + } + + sd->cnt ++; +} + +EOLIAN static void +_efl_ui_tab_bar_tab_remove(Eo *obj EINA_UNUSED, Efl_Ui_Tab_Bar_Data *sd, int index) +{ + if ((sd->cnt > 0) && (sd->cnt > index) && (index >= 0)) + { + Tab_Info *ti; + ti = eina_list_nth(sd->tab_infos, index); + + _tab_unselect(sd, ti); + evas_object_box_remove(sd->bx, ti->tab); + efl_del(ti->tab); + efl_del(ti->icon); + + sd->tab_infos = eina_list_remove(sd->tab_infos, ti); + sd->cnt --; + } +} + +EOLIAN static void +_efl_ui_tab_bar_tab_label_set(Eo *obj EINA_UNUSED, Efl_Ui_Tab_Bar_Data *sd, int index, const char *label) +{ + Tab_Info *ti; + ti = eina_list_nth(sd->tab_infos, index); + eina_stringshare_replace(&ti->label, label); + + efl_text_set(efl_part(ti->tab, "efl.text"), ti->label); +} + +EOLIAN static void +_efl_ui_tab_bar_tab_icon_set(Eo *obj, Efl_Ui_Tab_Bar_Data *sd, int index, const char *icon) +{ + Eo *icon_obj; + Tab_Info *ti; + ti = eina_list_nth(sd->tab_infos, index); + + if ((icon) && (ti->icon_str) && (!strcmp(icon, ti->icon_str))) return; + + icon_obj = elm_icon_add(obj); + if (!icon_obj) return; + if (_tab_icon_set(icon_obj, "toolbar/", icon)) + _tab_icon_obj_set(obj, ti, icon_obj, icon, "efl,state,icon_set"); + else + { + _tab_icon_obj_set(obj, ti, NULL, NULL, "efl,state,icon_set"); + efl_del(icon_obj); + } +} + +static void +_layout(Evas_Object *o, + Evas_Object_Box_Data *priv, + void *data) +{ + Evas_Object *obj = (Evas_Object *)data; + Eina_Bool horizontal; + + EFL_UI_TAB_BAR_DATA_GET(obj, sd); + + horizontal = efl_ui_dir_is_horizontal(sd->dir, EINA_TRUE); + + _els_box_layout + (o, priv, horizontal, EINA_TRUE, efl_ui_mirrored_get(obj)); +} + +EOLIAN static void +_efl_ui_tab_bar_efl_object_destructor(Eo *obj, Efl_Ui_Tab_Bar_Data *sd EINA_UNUSED) +{ + efl_destructor(efl_super(obj, MY_CLASS)); +} + +EOLIAN static Efl_Object * +_efl_ui_tab_bar_efl_object_constructor(Eo *obj, Efl_Ui_Tab_Bar_Data *sd) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); + + if (!elm_widget_theme_klass_get(obj)) + elm_widget_theme_klass_set(obj, "tab_bar"); + + obj = efl_constructor(efl_super(obj, MY_CLASS)); + + 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!"); + + elm_widget_sub_object_parent_add(obj); + + sd->dir = EFL_UI_DIR_HORIZONTAL; + sd->bx = evas_object_box_add(evas_object_evas_get(obj)); + evas_object_box_align_set(sd->bx, 0.5, 0.5); + evas_object_box_layout_set(sd->bx, _layout, obj, NULL); + + efl_ui_widget_focus_allow_set(obj, EINA_TRUE); + + efl_content_set(efl_part(obj, "efl.content"), sd->bx); + + sd->cnt = 0; + sd->cur = -1; + + Tab_Info *ti = calloc(1, sizeof(*ti)); + sd->selected_tab = ti; + + return obj; +} + +#include "efl_ui_tab_bar.eo.c" |