diff --git a/data/elementary/themes/Makefile.am b/data/elementary/themes/Makefile.am index a52bd6538f..565e05046e 100644 --- a/data/elementary/themes/Makefile.am +++ b/data/elementary/themes/Makefile.am @@ -1022,6 +1022,7 @@ elementary/themes/edc/efl/uiclock.edc \ elementary/themes/edc/efl/cursor.edc \ elementary/themes/edc/efl/focus.edc \ elementary/themes/edc/efl/frame.edc \ +elementary/themes/edc/efl/navigation_bar.edc \ elementary/themes/edc/efl/navigation_layout.edc \ elementary/themes/edc/efl/multibuttonentry.edc \ elementary/themes/edc/efl/nstate.edc \ diff --git a/data/elementary/themes/default.edc b/data/elementary/themes/default.edc index 29733f6d1d..a677be44d5 100644 --- a/data/elementary/themes/default.edc +++ b/data/elementary/themes/default.edc @@ -168,6 +168,7 @@ collections { #include "edc/efl/bg.edc" #include "edc/efl/button.edc" #include "edc/efl/calendar.edc" +#include "edc/efl/navigation_bar.edc" #include "edc/efl/navigation_layout.edc" #include "edc/efl/nstate.edc" // XXX: mobile mode needs invisible scrollers... make signals that do this diff --git a/data/elementary/themes/edc/efl/navigation_bar.edc b/data/elementary/themes/edc/efl/navigation_bar.edc new file mode 100644 index 0000000000..212ddd8d76 --- /dev/null +++ b/data/elementary/themes/edc/efl/navigation_bar.edc @@ -0,0 +1,114 @@ +//Efl.Ui.Navigation_Bar Themes +group { "efl/navigation_bar"; + styles { + style { name: "navigation_bar_text"; + base: "font="FNBD" font_size=10 text_class=label align=center color=#fff color_class=navigation_bar_text style=shadow,bottom shadow_color=#00000080 ellipsis=1.0 wrap=mixed"; + tag: "br" "\n"; + tag: "hilight" "+ font="FNBD" text_class=label_light"; + tag: "b" "+ font="FNBD" text_class=label_light"; + tag: "whitecolor" "+ color=#fff"; + tag: "tab" "\t"; + } + } + parts { + spacer { "base"; + desc { "default"; + } + } + swallow { "back_button"; + desc { "default"; + fixed: 1 0; + min: 0 0; + max: 0 -1; + rel.to: "base"; + rel2.relative: 0.0 1.0; + align: 0.0 0.5; + hid; + } + desc { "visible"; + inherit: "default"; + min: 40 0; + max: 40 -1; + vis; + } + } + swallow { "left_content"; + desc { "default"; + rel.to: "base"; + rel2.relative: 0.0 1.0; + align: 0.0 0.5; + } + } + swallow { "right_content"; + desc { "default"; + rel.to: "base"; + rel1.relative: 1.0 0.0; + align: 1.0 0.5; + } + } + spacer { "text_base"; + desc { "default"; + rel1 { + to: "back_button"; + relative: 1.0 0.0; + } + rel2 { + to: "right_content"; + relative: 0.0 1.0; + } + } + desc { "left_content"; + inherit: "default"; + rel1 { + to: "left_content"; + relative: 1.0 0.0; + } + } + } + textblock { "text"; + scale; + desc { "default"; + text { + style: "navigation_bar_text"; + } + rel.to: "text_base"; + } + } + programs { + program { + signal: "elm,state,back_button,visible"; source: "elm"; + action: STATE_SET "visible" 0.0; + target: "back_button"; + } + program { + signal: "elm,state,back_button,hidden"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "back_button"; + } + program { + signal: "elm,state,left_content,visible"; source: "elm"; + action: STATE_SET "left_content" 0.0; + target: "text_base"; + } + program { + signal: "elm,state,left_content,hidden"; source: "elm"; + action: STATE_SET "default" 0.0; + target: "text_base"; + } + } + } +} + +group { name: "efl/navigation_bar/back_button"; + inherit: "efl/button"; + images.image: "icon_arrow_left.png" COMP; + parts { + image { name: "icon_arrow_left"; + insert_before: "elm.swallow.content"; + desc { "default"; + image.normal: "icon_arrow_left.png"; + fill.smooth: 0; + } + } + } +} diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am index e86f93d28f..b42a0ce6cf 100644 --- a/src/Makefile_Elementary.am +++ b/src/Makefile_Elementary.am @@ -16,6 +16,9 @@ elm_public_eolian_files = \ lib/elementary/efl_ui_image_zoomable.eo \ lib/elementary/efl_ui_layout.eo \ lib/elementary/efl_ui_nstate.eo \ + lib/elementary/efl_ui_navigation_bar.eo \ + lib/elementary/efl_ui_navigation_bar_part.eo \ + lib/elementary/efl_ui_navigation_bar_part_back_button.eo \ lib/elementary/efl_ui_navigation_layout.eo \ lib/elementary/efl_ui_panes.eo \ lib/elementary/efl_ui_progressbar.eo \ @@ -352,6 +355,7 @@ includesunstable_HEADERS = \ lib/elementary/elm_widget_menu.h \ lib/elementary/elm_widget_multibuttonentry.h \ lib/elementary/elm_widget_naviframe.h \ + lib/elementary/efl_ui_navigation_bar_private.h \ lib/elementary/efl_ui_navigation_layout_private.h \ lib/elementary/elm_widget_notify.h \ lib/elementary/elm_widget_panel.h \ @@ -627,6 +631,7 @@ lib_elementary_libelementary_la_SOURCES = \ lib/elementary/elc_hoversel.c \ lib/elementary/elc_multibuttonentry.c \ lib/elementary/elc_naviframe.c \ + lib/elementary/efl_ui_navigation_bar.c \ lib/elementary/efl_ui_navigation_layout.c \ lib/elementary/elc_player.c \ lib/elementary/elc_popup.c \ diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 38b814c3ba..76b9b0a39c 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -336,6 +336,9 @@ typedef Eo Efl_Ui_Focus_Manager; # include # include # include +# include +# include +# include # include # include #endif diff --git a/src/lib/elementary/efl_ui_navigation_bar.c b/src/lib/elementary/efl_ui_navigation_bar.c new file mode 100644 index 0000000000..911f3386ef --- /dev/null +++ b/src/lib/elementary/efl_ui_navigation_bar.c @@ -0,0 +1,210 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#include + +#include "elm_priv.h" +#include "efl_ui_navigation_bar_private.h" +#include "efl_ui_navigation_bar_part.eo.h" +#include "elm_part_helper.h" + +#define MY_CLASS EFL_UI_NAVIGATION_BAR_CLASS +#define MY_CLASS_NAME "Efl.Ui.Navigation_Bar" + +static void +_back_button_clicked_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Eo *navigation_bar = data; + + Eo *stack = efl_provider_find(navigation_bar, EFL_UI_STACK_CLASS); + if (!stack) + { + ERR("Cannot find EFL_UI_STACK_CLASS instance!"); + return; + } + + efl_ui_stack_pop(stack); +} + +EOLIAN static Eo * +_efl_ui_navigation_bar_efl_object_constructor(Eo *obj, Efl_Ui_Navigation_Bar_Data *pd) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); + + if (!elm_widget_theme_klass_get(obj)) + elm_widget_theme_klass_set(obj, "navigation_bar"); + 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!"); + + Eo *back_button = efl_add(EFL_UI_BUTTON_CLASS, obj, + elm_widget_element_update(obj, efl_added, "back_button"), + efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _back_button_clicked_cb, obj), + efl_gfx_visible_set(efl_added, EINA_FALSE)); + + pd->back_button = back_button; + + return obj; +} + + +/* Standard widget overrides */ +ELM_PART_CONTENT_DEFAULT_IMPLEMENT(efl_ui_navigation_bar, Efl_Ui_Navigation_Bar_Data) +ELM_PART_TEXT_DEFAULT_GET(efl_ui_navigation_bar, "text") +ELM_PART_TEXT_DEFAULT_IMPLEMENT(efl_ui_navigation_bar, Efl_Ui_Navigation_Bar_Data) + +#define EFL_UI_NAVIGATION_BAR_EXTRA_OPS \ +ELM_PART_TEXT_DEFAULT_OPS(efl_ui_navigation_bar) + +static Eina_Bool +_efl_ui_navigation_bar_content_set(Eo *obj, Efl_Ui_Navigation_Bar_Data *_pd EINA_UNUSED, const char *part, Efl_Gfx *content) +{ + if (eina_streq(part, "left_content")) + { + if (content) + efl_layout_signal_emit(obj, "elm,state,left_content,visible", "elm"); + else + efl_layout_signal_emit(obj, "elm,state,left_content,hidden", "elm"); + efl_layout_signal_process(obj, EINA_FALSE); + } + return efl_content_set(efl_part(efl_super(obj, MY_CLASS), part), content); +} + +static Efl_Gfx * +_efl_ui_navigation_bar_content_get(const Eo *obj, Efl_Ui_Navigation_Bar_Data *_pd EINA_UNUSED, const char *part) +{ + return efl_content_get(efl_part(efl_super(obj, MY_CLASS), part)); +} + +static Efl_Gfx * +_efl_ui_navigation_bar_content_unset(Eo *obj, Efl_Ui_Navigation_Bar_Data *_pd EINA_UNUSED, const char *part) +{ + if (eina_streq(part, "left_content")) + { + efl_layout_signal_emit(obj, "elm,state,left_content,hidden", "elm"); + efl_layout_signal_process(obj, EINA_FALSE); + } + return efl_content_unset(efl_part(efl_super(obj, MY_CLASS), part)); +} + + +/* Efl.Part begin */ +EOLIAN static Efl_Object * +_efl_ui_navigation_bar_efl_part_part(const Eo *obj, Efl_Ui_Navigation_Bar_Data *priv EINA_UNUSED, const char *part) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); + + if (eina_streq(part, "back_button")) + return ELM_PART_IMPLEMENT(EFL_UI_NAVIGATION_BAR_PART_BACK_BUTTON_CLASS, obj, part); + else if (eina_streq(part, "left_content") || eina_streq(part, "right_content")) + return ELM_PART_IMPLEMENT(EFL_UI_NAVIGATION_BAR_PART_CLASS, obj, part); + + return efl_part(efl_super(obj, MY_CLASS), part); +} + +EOLIAN static void +_efl_ui_navigation_bar_part_back_button_efl_gfx_visible_set(Eo *obj, void *_pd EINA_UNUSED, Eina_Bool visible) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd); + + if (visible) + { + if (!efl_content_set(efl_part(efl_super(pd->obj, MY_CLASS), "back_button"), ppd->back_button)) + ERR("Part for back button(i.e. \"back_button\") does not exist!"); + else + efl_layout_signal_emit(pd->obj, "elm,state,back_button,visible", "elm"); + } + else + { + efl_content_unset(efl_part(efl_super(pd->obj, MY_CLASS), "back_button")); + efl_gfx_visible_set(ppd->back_button, visible); + efl_layout_signal_emit(pd->obj, "elm,state,back_button,hidden", "elm"); + } + + efl_layout_signal_process(pd->obj, EINA_FALSE); +} + +EOLIAN static Eina_Bool +_efl_ui_navigation_bar_part_back_button_efl_gfx_visible_get(const Eo *obj, void *_pd EINA_UNUSED) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd, EINA_FALSE); + + return efl_gfx_visible_get(ppd->back_button); +} + +EOLIAN static void +_efl_ui_navigation_bar_part_back_button_efl_text_text_set(Eo *obj, void *_pd EINA_UNUSED, const char *label) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd); + + efl_text_set(ppd->back_button, label); +} + +EOLIAN static const char * +_efl_ui_navigation_bar_part_back_button_efl_text_text_get(const Eo *obj, void *_pd EINA_UNUSED) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd, EINA_FALSE); + + return efl_text_get(ppd->back_button); +} + +static Eina_Bool +_efl_ui_navigation_bar_part_back_button_efl_content_content_set(Eo *obj, void *_pd EINA_UNUSED, Efl_Gfx *content) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd, EINA_FALSE); + + if (content == ppd->back_button) return EINA_FALSE; + + efl_event_callback_add(content, EFL_UI_EVENT_CLICKED, _back_button_clicked_cb, pd->obj); + ppd->back_button = content; + + return _efl_ui_navigation_bar_content_set(pd->obj, ppd, pd->part, content); +} + +static Efl_Gfx* +_efl_ui_navigation_bar_part_back_button_efl_content_content_get(const Eo *obj, void *_pd EINA_UNUSED) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd, NULL); + + return _efl_ui_navigation_bar_content_get(pd->obj, ppd, pd->part); +} + +static Efl_Gfx* +_efl_ui_navigation_bar_part_back_button_efl_content_content_unset(Eo *obj, void *_pd EINA_UNUSED) +{ + Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); + EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(pd->obj, ppd, NULL); + + efl_event_callback_del(ppd->back_button, EFL_UI_EVENT_CLICKED, _back_button_clicked_cb, pd->obj); + ppd->back_button = NULL; + + return _efl_ui_navigation_bar_content_unset(pd->obj, ppd, pd->part); +} + +ELM_PART_OVERRIDE_CONTENT_SET(efl_ui_navigation_bar, EFL_UI_NAVIGATION_BAR, Efl_Ui_Navigation_Bar_Data) +ELM_PART_OVERRIDE_CONTENT_GET(efl_ui_navigation_bar, EFL_UI_NAVIGATION_BAR, Efl_Ui_Navigation_Bar_Data) +ELM_PART_OVERRIDE_CONTENT_UNSET(efl_ui_navigation_bar, EFL_UI_NAVIGATION_BAR, Efl_Ui_Navigation_Bar_Data) +#include "efl_ui_navigation_bar_part.eo.c" +/* Efl.Part end */ + + +/* Efl.Part Back_Button begin */ +#include "efl_ui_navigation_bar_part_back_button.eo.c" +/* Efl.Part Back_Button end */ + +#include "efl_ui_navigation_bar.eo.c" diff --git a/src/lib/elementary/efl_ui_navigation_bar.eo b/src/lib/elementary/efl_ui_navigation_bar.eo new file mode 100644 index 0000000000..764eaa8f20 --- /dev/null +++ b/src/lib/elementary/efl_ui_navigation_bar.eo @@ -0,0 +1,30 @@ +class Efl.Ui.Navigation_Bar (Efl.Ui.Layout, Efl.Content, Efl.Text, Efl.Ui.Translatable) +{ + [[Navigation_Bar widget. + + Navigation_Bar widget provides a bar form useful for navigation. + Navigation_Bar has a back button which is used to navigate to the previous + content in the stack. + ]] + parts { + back_button: Efl.Ui.Navigation_Bar.Part_Back_Button; + [[Back button to navigate to the previous content in the stack. + + The back button works only if the Navigation_Bar widget is contained + in the Stack widget(Efl.Ui.Stack class). + e.g. The Navigation_Bar widget is set in the Navigation_Layout widget + and the Navigation_Layout widget is pushed to the Stack widget. + + The back button is hidden by default and it can be visible. + e.g. efl_gfx_visible_set(efl_part(navigation_bar, "back_button"), EINA_TRUE); + ]] + } + implements { + Efl.Object.constructor; + Efl.Content.content { set; get; } + Efl.Content.content_unset; + Efl.Text.text { set; get; } + Efl.Ui.Translatable.translatable_text { set; get; } + Efl.Part.part; + } +} diff --git a/src/lib/elementary/efl_ui_navigation_bar_part.eo b/src/lib/elementary/efl_ui_navigation_bar_part.eo new file mode 100644 index 0000000000..461e82c799 --- /dev/null +++ b/src/lib/elementary/efl_ui_navigation_bar_part.eo @@ -0,0 +1,9 @@ +class Efl.Ui.Navigation_Bar.Part (Efl.Ui.Layout.Part_Content) +{ + [[Efl UI Navigation_Bar internal part class]] + data: null; + implements { + Efl.Content.content { set; get; } + Efl.Content.content_unset; + } +} diff --git a/src/lib/elementary/efl_ui_navigation_bar_part_back_button.eo b/src/lib/elementary/efl_ui_navigation_bar_part_back_button.eo new file mode 100644 index 0000000000..90017686c1 --- /dev/null +++ b/src/lib/elementary/efl_ui_navigation_bar_part_back_button.eo @@ -0,0 +1,11 @@ +class Efl.Ui.Navigation_Bar.Part_Back_Button (Efl.Ui.Widget.Part, Efl.Ui.Button) +{ + [[Efl Ui Navigation_Bar internal part back button class]] + data: null; + implements { + Efl.Gfx.visible { set; get; } + Efl.Text.text { set; get; } + Efl.Content.content { set; get; } + Efl.Content.content_unset; + } +} diff --git a/src/lib/elementary/efl_ui_navigation_bar_private.h b/src/lib/elementary/efl_ui_navigation_bar_private.h new file mode 100644 index 0000000000..a4ba779baa --- /dev/null +++ b/src/lib/elementary/efl_ui_navigation_bar_private.h @@ -0,0 +1,20 @@ +#ifndef EFL_UI_WIDGET_NAVIGATION_BAR_H +#define EFL_UI_WIDGET_NAVIGATION_BAR_H + +typedef struct _Efl_Ui_Navigation_Bar_Data Efl_Ui_Navigation_Bar_Data; +struct _Efl_Ui_Navigation_Bar_Data +{ + Eo *back_button; +}; + +#define EFL_UI_NAVIGATION_BAR_DATA_GET_OR_RETURN(o, ptr, ...) \ + Efl_Ui_Navigation_Bar_Data *ptr; \ + ptr = efl_data_scope_get(o, EFL_UI_NAVIGATION_BAR_CLASS); \ + if (EINA_UNLIKELY(!ptr)) \ + { \ + CRI("no ui frame navigation data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return __VA_ARGS__; \ + } + +#endif diff --git a/src/lib/elementary/efl_ui_navigation_layout.eo b/src/lib/elementary/efl_ui_navigation_layout.eo index aea7b8b2b8..846fbf68af 100644 --- a/src/lib/elementary/efl_ui_navigation_layout.eo +++ b/src/lib/elementary/efl_ui_navigation_layout.eo @@ -9,6 +9,7 @@ class Efl.Ui.Navigation_Layout (Efl.Ui.Layout, Efl.Content) methods { @property bar { [[The bar object which is located at the top area as a title. + e.g. Navigation_Bar widget(Efl.Ui.Navigation_Bar) can be used as $bar. ]] set { }