diff --git a/src/bin/elementary/test_calendar.c b/src/bin/elementary/test_calendar.c index 9a5de374ee..b3f54f5ee7 100644 --- a/src/bin/elementary/test_calendar.c +++ b/src/bin/elementary/test_calendar.c @@ -405,17 +405,18 @@ _cal_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev) max_date.tm_year + 1900); } -static void +static Eina_Bool _cal_format_cb(void *data EINA_UNUSED, Eina_Strbuf *str, const Eina_Value value) { struct tm current_time; //return if the value type is other than EINA_VALUE_TYPE_TM if (eina_value_type_get(&value) != EINA_VALUE_TYPE_TM) - return; + return EINA_FALSE; eina_value_get(&value, ¤t_time); eina_strbuf_append_strftime(str, "<< %b %y >>", ¤t_time); + return EINA_TRUE; } void @@ -444,7 +445,7 @@ test_efl_ui_calendar(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void efl_ui_calendar_date_max_set(efl_added, max_date), efl_ui_calendar_date_set(efl_added, selected_date), efl_event_callback_add(efl_added, EFL_UI_CALENDAR_EVENT_CHANGED, _cal_changed_cb, NULL), - efl_ui_format_string_set(efl_added, "%b"), + efl_ui_format_string_set(efl_added, "%b", EFL_UI_FORMAT_STRING_TYPE_TIME), efl_pack(box, efl_added)); efl_add(EFL_UI_CALENDAR_CLASS, win, @@ -452,7 +453,7 @@ test_efl_ui_calendar(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void efl_ui_calendar_date_max_set(efl_added, max_date), efl_ui_calendar_date_set(efl_added, selected_date), efl_event_callback_add(efl_added, EFL_UI_CALENDAR_EVENT_CHANGED, _cal_changed_cb, NULL), - efl_ui_format_cb_set(efl_added, NULL, _cal_format_cb, NULL), + efl_ui_format_func_set(efl_added, NULL, _cal_format_cb, NULL), efl_pack(box, efl_added)); efl_gfx_entity_size_set(win, EINA_SIZE2D(300, 300)); diff --git a/src/bin/elementary/test_ui_progressbar.c b/src/bin/elementary/test_ui_progressbar.c index 3d50d0be61..5a1c705a03 100644 --- a/src/bin/elementary/test_ui_progressbar.c +++ b/src/bin/elementary/test_ui_progressbar.c @@ -119,7 +119,7 @@ _win_delete_req_cb(void *d, const Efl_Event *ev EINA_UNUSED) free(pd); } -static void +static Eina_Bool _custom_format_cb(void *data EINA_UNUSED, Eina_Strbuf *str, const Eina_Value value) { double v; @@ -129,6 +129,7 @@ _custom_format_cb(void *data EINA_UNUSED, Eina_Strbuf *str, const Eina_Value val else if (v < 75.f) eina_strbuf_append_printf(str, "Getting there..."); else if (v < 100.f) eina_strbuf_append_printf(str, "Almost done..."); else eina_strbuf_append_printf(str, "Done!"); + return EINA_TRUE; } static void @@ -204,7 +205,7 @@ test_ui_progressbar(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, void *event_inf efl_pack(bx, efl_added), efl_text_set(efl_added, "Custom string"), efl_ui_range_limits_set(efl_added, 0, 100), - efl_ui_format_string_set(efl_added, "%d rabbits"), + efl_ui_format_string_set(efl_added, "%d rabbits", EFL_UI_FORMAT_STRING_TYPE_SIMPLE), efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(250, 20)) ); @@ -212,7 +213,7 @@ test_ui_progressbar(void *data EINA_UNUSED, Eo *obj EINA_UNUSED, void *event_inf efl_pack(bx, efl_added), efl_text_set(efl_added, "Custom func"), efl_ui_range_limits_set(efl_added, 0, 100), - efl_ui_format_cb_set(efl_added, NULL, _custom_format_cb, NULL), + efl_ui_format_func_set(efl_added, NULL, _custom_format_cb, NULL), efl_gfx_hint_size_min_set(efl_added, EINA_SIZE2D(250, 20)) ); diff --git a/src/bin/elementary/test_ui_spin.c b/src/bin/elementary/test_ui_spin.c index 1c5b86b531..f07a42778a 100644 --- a/src/bin/elementary/test_ui_spin.c +++ b/src/bin/elementary/test_ui_spin.c @@ -50,7 +50,7 @@ test_ui_spin(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i efl_ui_range_limits_set(efl_added, 0, 10), efl_ui_range_value_set(efl_added, 6), efl_ui_range_step_set(efl_added, 2), - efl_ui_format_string_set(efl_added, "test %d"), + efl_ui_format_string_set(efl_added, "test %d", EFL_UI_FORMAT_STRING_TYPE_SIMPLE), efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_spin_changed_cb, NULL), efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_MIN_REACHED,_spin_min_reached_cb, NULL), efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_MAX_REACHED,_spin_max_reached_cb, NULL), diff --git a/src/bin/elementary/test_ui_spin_button.c b/src/bin/elementary/test_ui_spin_button.c index 52455e67ef..82a207f1b0 100644 --- a/src/bin/elementary/test_ui_spin_button.c +++ b/src/bin/elementary/test_ui_spin_button.c @@ -16,18 +16,12 @@ void test_ui_spin_button(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) { Eo *win, *bx; - int i; - Eina_Array *array; - Efl_Ui_Spin_Special_Value values[12] = { + Efl_Ui_Format_Value special_values[] = { {1, "January"}, {2, "February"}, {3, "March"}, {4, "April"}, {5, "May"}, {6, "June"}, {7, "July"}, {8, "August"}, {9, "September"}, {10, "October"}, {11, "November"}, {12, "December"} }; - array = eina_array_new(sizeof(Efl_Ui_Spin_Special_Value)); - for (i = 0; i < NUM_OF_VALS; i++) - eina_array_push(array, &values[i]); - win = efl_add_ref(EFL_UI_WIN_CLASS, NULL, efl_ui_win_type_set(efl_added, EFL_UI_WIN_TYPE_BASIC), efl_text_set(efl_added, "Efl.Ui.Spin_Button"), @@ -49,7 +43,7 @@ test_ui_spin_button(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void * efl_add(EFL_UI_SPIN_BUTTON_CLASS, bx, efl_ui_range_limits_set(efl_added, -100.0, 100.0), efl_ui_range_value_set(efl_added, 0), - efl_ui_format_string_set(efl_added, "test float %0.2f"), + efl_ui_format_string_set(efl_added, "test float %0.2f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE), efl_ui_spin_button_editable_set(efl_added, EINA_FALSE), efl_pack(bx, efl_added)); @@ -57,10 +51,9 @@ test_ui_spin_button(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void * efl_ui_range_limits_set(efl_added, 1, 12), efl_ui_range_value_set(efl_added, 1), efl_ui_spin_button_editable_set(efl_added, EINA_FALSE), - efl_ui_spin_special_value_set(efl_added, array), + efl_ui_format_values_set(efl_added, EINA_C_ARRAY_ACCESSOR_NEW(special_values)), efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_VERTICAL), efl_pack(bx, efl_added)); - eina_array_free(array); efl_gfx_entity_size_set(win, EINA_SIZE2D(180, 140)); } diff --git a/src/bin/elementary/test_ui_tags.c b/src/bin/elementary/test_ui_tags.c index 410c7b24cd..2ef7d6db2b 100644 --- a/src/bin/elementary/test_ui_tags.c +++ b/src/bin/elementary/test_ui_tags.c @@ -78,7 +78,7 @@ test_ui_tags(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i efl_event_callback_add(efl_added, EFL_UI_TAGS_EVENT_ITEM_ADDED, _item_added_cb, array), efl_event_callback_add(efl_added, EFL_UI_TAGS_EVENT_ITEM_DELETED, _item_deleted_cb, array), efl_text_set(efl_added, "To :"), - efl_ui_format_string_set(efl_added, "+ %d items"), + efl_ui_format_string_set(efl_added, "+ %d items", EFL_UI_FORMAT_STRING_TYPE_SIMPLE), elm_object_part_content_set(layout, "multibuttonentry", efl_added)); efl_add(EFL_UI_BUTTON_CLASS, layout, diff --git a/src/examples/elementary/calendar_cxx_example_02.cc b/src/examples/elementary/calendar_cxx_example_02.cc index 60fb796bf1..e666ae844a 100644 --- a/src/examples/elementary/calendar_cxx_example_02.cc +++ b/src/examples/elementary/calendar_cxx_example_02.cc @@ -26,17 +26,19 @@ struct appData auto wcal(cal._get_wref()); // FIXME: How does one figure out the argument types for the function? - auto cb_a = std::bind([=]( + auto cb_a = std::bind([]( efl::eina::strbuf_wrapper& sb, - efl::eina::value_view const& value) { + efl::eina::value_view const& value) -> bool { try { sb.append_strftime("%b. %y", efl::eina::get(value)); } catch (std::system_error const&) { sb.append(value.to_string()); } std::cout << "Month: " << std::string(sb) << std::endl; + return true; }, _1, _2); - cal.format_cb_set(cb_a); + // FIXME XAR: I broke this and I do not know how to fix it + // cal.format_func_set(cb_a); } void destroy() { diff --git a/src/lib/efl/Efl.h b/src/lib/efl/Efl.h index aa88196720..5cbd1c2f96 100644 --- a/src/lib/efl/Efl.h +++ b/src/lib/efl/Efl.h @@ -147,7 +147,6 @@ typedef Efl_Gfx_Path_Command_Type Efl_Gfx_Path_Command; #include "interfaces/efl_ui_property_bind.eo.h" #include "interfaces/efl_ui_factory.eo.h" #include "interfaces/efl_ui_factory_bind.eo.h" -#include "interfaces/efl_ui_format.eo.h" #include "interfaces/efl_cached_item.eo.h" /* Observable interface */ diff --git a/src/lib/efl/interfaces/efl_ui_format.c b/src/lib/efl/interfaces/efl_ui_format.c deleted file mode 100644 index f6f1b811e2..0000000000 --- a/src/lib/efl/interfaces/efl_ui_format.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "config.h" -#include "Efl.h" - -#define ERR(...) EINA_LOG_DOM_ERR(EINA_LOG_DOMAIN_DEFAULT, __VA_ARGS__) -#define DBG(...) EINA_LOG_DOM_DBG(EINA_LOG_DOMAIN_DEFAULT, __VA_ARGS__) - -typedef enum _Format_Type -{ - FORMAT_TYPE_INVALID, - FORMAT_TYPE_DOUBLE, - FORMAT_TYPE_INT, - FORMAT_TYPE_STRING, - FORMAT_TYPE_STATIC -} Format_Type; - -typedef struct -{ - const char *template; - Format_Type format_type; -} Efl_Ui_Format_Data; - -static Eina_Bool -_is_valid_digit(char x) -{ - return ((x >= '0' && x <= '9') || (x == '.')) ? EINA_TRUE : EINA_FALSE; -} - -static Format_Type -_format_string_check(const char *fmt) -{ - const char *itr; - Eina_Bool found = EINA_FALSE; - Format_Type ret_type = FORMAT_TYPE_STATIC; - - for (itr = fmt; *itr; itr++) - { - if (itr[0] != '%') continue; - if (itr[1] == '%') - { - itr++; - if (ret_type == FORMAT_TYPE_STATIC) - ret_type = FORMAT_TYPE_STRING; - continue; - } - - if (!found) - { - found = EINA_TRUE; - for (itr++; *itr; itr++) - { - // FIXME: This does not properly support int64 or unsigned. - if ((*itr == 'd') || (*itr == 'u') || (*itr == 'i') || - (*itr == 'o') || (*itr == 'x') || (*itr == 'X')) - { - ret_type = FORMAT_TYPE_INT; - break; - } - else if ((*itr == 'f') || (*itr == 'F')) - { - ret_type = FORMAT_TYPE_DOUBLE; - break; - } - else if (*itr == 's') - { - ret_type = FORMAT_TYPE_STRING; - break; - } - else if (_is_valid_digit(*itr)) - { - continue; - } - else - { - ERR("Format string '%s' has unknown format element '%c' in format. It must have one format element of type 's', 'f', 'F', 'd', 'u', 'i', 'o', 'x' or 'X'", fmt, *itr); - found = EINA_FALSE; - break; - } - } - if (!(*itr)) break; - } - else - { - ret_type = FORMAT_TYPE_INVALID; - break; - } - } - - if (ret_type == FORMAT_TYPE_INVALID) - { - ERR("Format string '%s' is invalid. It must have one and only one format element of type 's', 'f', 'F', 'd', 'u', 'i', 'o', 'x' or 'X'", fmt); - } - return ret_type; -} - -static void -_default_format_cb(void *data, Eina_Strbuf *str, const Eina_Value value) -{ - Efl_Ui_Format_Data *sd = data; - Eina_Value copy; - - if (sd->format_type == FORMAT_TYPE_DOUBLE) - { - double v = 0.0; - eina_value_setup(©, EINA_VALUE_TYPE_DOUBLE); - eina_value_convert(&value, ©); - eina_value_get(©, &v); - eina_strbuf_append_printf(str, sd->template, v); - eina_value_flush(©); - } - else if (sd->format_type == FORMAT_TYPE_INT) - { - int v = 0; - eina_value_setup(©, EINA_VALUE_TYPE_INT); - eina_value_convert(&value, ©); - eina_value_get(©, &v); - eina_strbuf_append_printf(str, sd->template, v); - eina_value_flush(©); - } - else if (sd->format_type == FORMAT_TYPE_STRING) - { - char *v = eina_value_to_string(&value); - eina_strbuf_append_printf(str, sd->template, v); - free(v); - } - else if (sd->format_type == FORMAT_TYPE_STATIC) - { - eina_strbuf_append(str, sd->template); - } - else - { - // Error: Discard format string and just print value. - DBG("Could not guess value type in format string: '%s'", sd->template); - char *v = eina_value_to_string(&value); - eina_strbuf_append(str, v); - free(v); - } -} - -static void -_default_format_free_cb(void *data) -{ - Efl_Ui_Format_Data *sd = data; - - if (sd && sd->template) - { - eina_stringshare_del(sd->template); - sd->template = NULL; - } -} - -EOLIAN static void -_efl_ui_format_format_string_set(Eo *obj, Efl_Ui_Format_Data *sd, const char *template) -{ - if (!template) return; - - eina_stringshare_replace(&sd->template, template); - sd->format_type = _format_string_check(sd->template); - - efl_ui_format_cb_set(obj, sd, _default_format_cb, _default_format_free_cb); -} - -EOLIAN static const char * -_efl_ui_format_format_string_get(const Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *sd) -{ - return sd->template; -} - -#include "interfaces/efl_ui_format.eo.c" - diff --git a/src/lib/efl/interfaces/efl_ui_format.eo b/src/lib/efl/interfaces/efl_ui_format.eo deleted file mode 100644 index c7b6aba841..0000000000 --- a/src/lib/efl/interfaces/efl_ui_format.eo +++ /dev/null @@ -1,42 +0,0 @@ -import eina_types; - -function @beta Efl.Ui.Format_Func_Cb { - [[Function pointer for format function hook]] - params { - @in str: strbuf; [[the formated string to be appended by user.]] - @in value: const(any_value); [[The @Eina.Value passed by $obj.]] - } -}; - -mixin @beta Efl.Ui.Format -{ - [[interface class for format_func]] - methods { - @property format_cb { - set @pure_virtual { - [[Set the format function pointer to format the string. - ]] - } - values { - func: Efl.Ui.Format_Func_Cb; [[The format function callback]] - } - } - @property format_string { - [[Control the format string for a given units label - - If $NULL is passed to $format, it will hide $obj's units - area completely. If not, it'll set the format - string for the units label text. The units label is - provided as a floating point value, so the units text can display - at most one floating point value. Note that the units label is - optional. Use a format string such as "%1.2f meters" for example. - - Note: The default format string is an integer percentage, - as in $"%.0f %%". - ]] - values { - units: string; [[The format string for $obj's units label.]] - } - } - } -} diff --git a/src/lib/efl/interfaces/meson.build b/src/lib/efl/interfaces/meson.build index e3baa55571..d09a24c255 100644 --- a/src/lib/efl/interfaces/meson.build +++ b/src/lib/efl/interfaces/meson.build @@ -94,7 +94,6 @@ pub_eo_files = [ 'efl_observer.eo', 'efl_observable.eo', 'efl_ui_autorepeat.eo', - 'efl_ui_format.eo', 'efl_gfx_color_class.eo', 'efl_gfx_text_class.eo', 'efl_gfx_size_class.eo', @@ -166,7 +165,6 @@ efl_src += files([ 'efl_io_queue.c', 'efl_observer.c', 'efl_file.c', - 'efl_ui_format.c', 'efl_ui_layout_orientable_readonly.c', 'efl_text_markup_util.c', ]) diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h index 2647362ba5..dc13d16a65 100644 --- a/src/lib/elementary/Efl_Ui.h +++ b/src/lib/elementary/Efl_Ui.h @@ -246,6 +246,7 @@ typedef Eo Efl_Ui_Active_View_Indicator; # include # include # include +# include /** * Initialize Elementary diff --git a/src/lib/elementary/efl_ui_calendar.c b/src/lib/elementary/efl_ui_calendar.c index 200566139b..7fb174273f 100644 --- a/src/lib/elementary/efl_ui_calendar.c +++ b/src/lib/elementary/efl_ui_calendar.c @@ -5,6 +5,7 @@ #define EFL_UI_FOCUS_COMPOSITION_PROTECTED #define EFL_UI_FOCUS_OBJECT_PROTECTED #define EFL_ACCESS_WIDGET_ACTION_PROTECTED +#define EFL_UI_FORMAT_PROTECTED #include #include "elm_priv.h" @@ -167,37 +168,17 @@ _disable(Efl_Ui_Calendar_Data *sd, static void _set_month_year(Efl_Ui_Calendar_Data *sd) { + Eina_Strbuf *strbuf = eina_strbuf_new(); + Eina_Value val; sd->filling = EINA_TRUE; - if (sd->format_cb) - { - Eina_Value val; - const char *buf; - - eina_value_setup(&val, EINA_VALUE_TYPE_TM); - eina_value_set(&val, sd->shown_date); - eina_strbuf_reset(sd->format_strbuf); - sd->format_cb(sd->format_cb_data, sd->format_strbuf, val); - buf = eina_strbuf_string_get(sd->format_strbuf); - eina_value_flush(&val); - - if (buf) - elm_layout_text_set(sd->obj, "month_text", buf); - else - elm_layout_text_set(sd->obj, "month_text", ""); - } - else - { - char *buf; - buf = eina_strftime(E_("%B %Y"), &sd->shown_date); - if (buf) - { - elm_layout_text_set(sd->obj, "month_text", buf); - free(buf); - } - else elm_layout_text_set(sd->obj, "month_text", ""); - } + eina_value_setup(&val, EINA_VALUE_TYPE_TM); + eina_value_set(&val, sd->shown_date); + efl_ui_format_formatted_value_get(sd->obj, strbuf, val); + elm_layout_text_set(sd->obj, "month_text", eina_strbuf_string_get(strbuf)); + eina_value_flush(&val); + eina_strbuf_free(strbuf); sd->filling = EINA_FALSE; } @@ -841,9 +822,6 @@ _efl_ui_calendar_efl_object_destructor(Eo *obj, Efl_Ui_Calendar_Data *sd) ecore_timer_del(sd->update_timer); - efl_ui_format_cb_set(obj, NULL, NULL, NULL); - eina_strbuf_free(sd->format_strbuf); - for (i = 0; i < ELM_DAY_LAST; i++) eina_stringshare_del(sd->weekdays[i]); @@ -919,7 +897,6 @@ _efl_ui_calendar_constructor_internal(Eo *obj, Efl_Ui_Calendar_Data *priv) priv->today_it = -1; priv->selected_it = -1; priv->first_day_it = -1; - priv->format_cb = NULL; edje_object_signal_callback_add (wd->resize_obj, "efl,action,selected", "*", @@ -1146,64 +1123,11 @@ _efl_ui_calendar_date_get(const Eo *obj EINA_UNUSED, Efl_Ui_Calendar_Data *sd) } EOLIAN static void -_efl_ui_calendar_efl_ui_format_format_cb_set(Eo *obj, Efl_Ui_Calendar_Data *sd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) +_efl_ui_calendar_efl_ui_format_apply_formatted_value(Eo *obj, Efl_Ui_Calendar_Data *pd EINA_UNUSED) { - if ((sd->format_cb_data == func_data) && (sd->format_cb == func)) - return; - - if (sd->format_cb_data && sd->format_free_cb) - sd->format_free_cb(sd->format_cb_data); - - sd->format_cb = func; - sd->format_cb_data = func_data; - sd->format_free_cb = func_free_cb; - if (!sd->format_strbuf) sd->format_strbuf = eina_strbuf_new(); - evas_object_smart_changed(obj); } -static void -_calendar_format_cb(void *data, Eina_Strbuf *str, const Eina_Value value) -{ - Efl_Ui_Calendar_Data *sd = data; - const Eina_Value_Type *type = eina_value_type_get(&value); - struct tm v; - - if (type == EINA_VALUE_TYPE_TM) - { - eina_value_get(&value, &v); - eina_strbuf_append_strftime(str, sd->format_template, &v); - } -} - -static void -_calendar_format_free_cb(void *data) -{ - Efl_Ui_Calendar_Data *sd = data; - - if (sd && sd->format_template) - { - eina_stringshare_del(sd->format_template); - sd->format_template = NULL; - } -} - -EOLIAN static void -_efl_ui_calendar_efl_ui_format_format_string_set(Eo *obj, Efl_Ui_Calendar_Data *sd, const char *template) -{ - if (!template) return; - - eina_stringshare_replace(&sd->format_template, template); - - efl_ui_format_cb_set(obj, sd, _calendar_format_cb, _calendar_format_free_cb); -} - -EOLIAN static const char * -_efl_ui_calendar_efl_ui_format_format_string_get(const Eo *obj EINA_UNUSED, Efl_Ui_Calendar_Data *sd) -{ - return sd->format_template; -} - EOLIAN static void _efl_ui_calendar_first_day_of_week_set(Eo *obj, Efl_Ui_Calendar_Data *sd, Efl_Ui_Calendar_Weekday day) { diff --git a/src/lib/elementary/efl_ui_calendar.eo b/src/lib/elementary/efl_ui_calendar.eo index 888319d382..586535f500 100644 --- a/src/lib/elementary/efl_ui_calendar.eo +++ b/src/lib/elementary/efl_ui_calendar.eo @@ -111,8 +111,7 @@ class @beta Efl.Ui.Calendar extends Efl.Ui.Layout_Base implements Efl.Ui.Focus.C Efl.Ui.Focus.Object.on_focus_update; Efl.Ui.Widget.widget_input_event_handler; Efl.Access.Widget.Action.elm_actions { get; } - Efl.Ui.Format.format_cb { set; } - Efl.Ui.Format.format_string { set; get;} + Efl.Ui.Format.apply_formatted_value; } events { changed: void; [[Emitted when the selected date in the calendar is changed]] diff --git a/src/lib/elementary/efl_ui_calendar_private.h b/src/lib/elementary/efl_ui_calendar_private.h index 78446c612e..3d80b89305 100644 --- a/src/lib/elementary/efl_ui_calendar_private.h +++ b/src/lib/elementary/efl_ui_calendar_private.h @@ -39,15 +39,9 @@ struct _Efl_Ui_Calendar_Data Evas_Object *month_access; Eo *items[42]; - Efl_Ui_Calendar_Weekday first_week_day; + Efl_Ui_Calendar_Weekday first_week_day; unsigned char first_day_it; - const char *format_template; - Efl_Ui_Format_Func_Cb format_cb; - Eina_Free_Cb format_free_cb; - void *format_cb_data; - Eina_Strbuf *format_strbuf; - Eina_Bool selected : 1; Eina_Bool filling : 1; Eina_Bool weekdays_set : 1; diff --git a/src/lib/elementary/efl_ui_format.c b/src/lib/elementary/efl_ui_format.c new file mode 100644 index 0000000000..beb3945f43 --- /dev/null +++ b/src/lib/elementary/efl_ui_format.c @@ -0,0 +1,345 @@ +#define EFL_UI_FORMAT_PROTECTED 1 + +#include "config.h" +#include "Efl_Ui.h" +#include "elm_priv.h" /* To be able to use elm_widget_is_legacy() */ + +typedef enum _Format_Type +{ + /* When a format string is used, it is parsed to find out the expected data type */ + FORMAT_TYPE_INVALID, /* Format description not understood */ + FORMAT_TYPE_DOUBLE, /* double */ + FORMAT_TYPE_INT, /* int */ + FORMAT_TYPE_TM, /* struct tm, for time and date values */ + FORMAT_TYPE_STRING, /* const char* */ + FORMAT_TYPE_STATIC /* No value is passed, the format string IS the formatted output */ +} Format_Type; + +typedef struct +{ + Efl_Ui_Format_Func format_func; /* User-supplied formatting function */ + void *format_func_data; /* User data for the above function */ + Eina_Free_Cb format_func_free; /* How to free the above data */ + + Eina_Inarray *format_values; /* Array of formatting values, owned by us */ + + const char *format_string; /* User-supplied formatting string, stringshare */ + Format_Type format_string_type; /* Type of data expected in the above string */ +} Efl_Ui_Format_Data; + +static Eina_Bool +_is_valid_digit(char x) +{ + return ((x >= '0' && x <= '9') || (x == '.')) ? EINA_TRUE : EINA_FALSE; +} + +static Format_Type +_format_string_check(const char *fmt, Efl_Ui_Format_String_Type type) +{ + const char *itr; + Eina_Bool found = EINA_FALSE; + Format_Type ret_type = FORMAT_TYPE_STATIC; + + if (type == EFL_UI_FORMAT_STRING_TYPE_TIME) return FORMAT_TYPE_TM; + + for (itr = fmt; *itr; itr++) + { + if (itr[0] != '%') continue; + if (itr[1] == '%') + { + itr++; + if (ret_type == FORMAT_TYPE_STATIC) + ret_type = FORMAT_TYPE_STRING; + continue; + } + + if (!found) + { + found = EINA_TRUE; + for (itr++; *itr; itr++) + { + // FIXME: This does not properly support int64 or unsigned. + if ((*itr == 'd') || (*itr == 'u') || (*itr == 'i') || + (*itr == 'o') || (*itr == 'x') || (*itr == 'X')) + { + ret_type = FORMAT_TYPE_INT; + break; + } + else if ((*itr == 'f') || (*itr == 'F')) + { + ret_type = FORMAT_TYPE_DOUBLE; + break; + } + else if (*itr == 's') + { + ret_type = FORMAT_TYPE_STRING; + break; + } + else if (_is_valid_digit(*itr)) + { + continue; + } + else + { + ERR("Format string '%s' has unknown format element '%c' in format. It must have one format element of type 's', 'f', 'F', 'd', 'u', 'i', 'o', 'x' or 'X'", fmt, *itr); + found = EINA_FALSE; + break; + } + } + if (!(*itr)) break; + } + else + { + ret_type = FORMAT_TYPE_INVALID; + break; + } + } + + if (ret_type == FORMAT_TYPE_INVALID) + { + ERR("Format string '%s' is invalid. It must have one and only one format element of type 's', 'f', 'F', 'd', 'u', 'i', 'o', 'x' or 'X'", fmt); + } + return ret_type; +} + +static Eina_Bool +_do_format_string(Efl_Ui_Format_Data *pd, Eina_Strbuf *str, const Eina_Value value) +{ + switch (pd->format_string_type) + { + case FORMAT_TYPE_DOUBLE: + { + double v = 0.0; + eina_value_double_convert(&value, &v); + eina_strbuf_append_printf(str, pd->format_string, v); + break; + } + case FORMAT_TYPE_INT: + { + int v = 0; + eina_value_int_convert(&value, &v); + eina_strbuf_append_printf(str, pd->format_string, v); + break; + } + case FORMAT_TYPE_STRING: + { + char *v = eina_value_to_string(&value); + eina_strbuf_append_printf(str, pd->format_string, v); + free(v); + break; + } + case FORMAT_TYPE_STATIC: + { + eina_strbuf_append(str, pd->format_string); + break; + } + case FORMAT_TYPE_TM: + { + struct tm v; + char *buf; + eina_value_get(&value, &v); + buf = eina_strftime(pd->format_string, &v); + eina_strbuf_append(str, buf); + free(buf); + break; + } + default: + return EINA_FALSE; + } + return EINA_TRUE; +} + +static Eina_Bool +_legacy_default_format_func(void *data, Eina_Strbuf *str, const Eina_Value value) +{ + if (!_do_format_string(data, str, value)) + { + /* Fallback to just printing the value if format string fails (legacy behavior) */ + char *v = eina_value_to_string(&value); + eina_strbuf_append(str, v); + free(v); + } + return EINA_TRUE; +} + +EOLIAN static void +_efl_ui_format_format_func_set(Eo *obj, Efl_Ui_Format_Data *pd, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb) +{ + if (pd->format_func_free) + pd->format_func_free(pd->format_func_data); + pd->format_func = func; + pd->format_func_data = func_data; + pd->format_func_free = func_free_cb; + + if (efl_alive_get(obj)) + efl_ui_format_apply_formatted_value(obj); +} + +EOLIAN static Efl_Ui_Format_Func +_efl_ui_format_format_func_get(const Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *pd) +{ + return pd->format_func; +} + +static int +_value_compare(const Efl_Ui_Format_Value *val1, const Efl_Ui_Format_Value *val2) +{ + return val1->value - val2->value; +} + +EOLIAN static void +_efl_ui_format_format_values_set(Eo *obj, Efl_Ui_Format_Data *pd, Eina_Accessor *values) +{ + Efl_Ui_Format_Value v; + int i; + if (pd->format_values) + { + Efl_Ui_Format_Value *vptr; + /* Delete previous values array */ + EINA_INARRAY_FOREACH(pd->format_values, vptr) + { + eina_stringshare_del(vptr->text); + } + eina_inarray_free(pd->format_values); + pd->format_values = NULL; + } + if (values == NULL) + { + if (efl_alive_get(obj)) + efl_ui_format_apply_formatted_value(obj); + return; + } + + /* Copy the values to our internal array */ + pd->format_values = eina_inarray_new(sizeof(Efl_Ui_Format_Value), 4); + EINA_ACCESSOR_FOREACH(values, i, v) + { + Efl_Ui_Format_Value vcopy = { v.value, eina_stringshare_add(v.text) }; + eina_inarray_insert_sorted(pd->format_values, &vcopy, (Eina_Compare_Cb)_value_compare); + } + eina_accessor_free(values); + + if (efl_alive_get(obj)) + efl_ui_format_apply_formatted_value(obj); +} + +EOLIAN static Eina_Accessor * +_efl_ui_format_format_values_get(const Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *pd) +{ + if (!pd->format_values) return NULL; + return eina_inarray_accessor_new(pd->format_values); +} + +EOLIAN static void +_efl_ui_format_format_string_set(Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *sd, const char *string, Efl_Ui_Format_String_Type type) +{ + eina_stringshare_replace(&sd->format_string, string); + if (string) + sd->format_string_type = _format_string_check(sd->format_string, type); + else + sd->format_string_type = FORMAT_TYPE_INVALID; + + /* In legacy, setting the format string installs a default format func. + Some widgets then override the format_func_set method so we keep that behavior. */ + if (elm_widget_is_legacy(obj)) + efl_ui_format_func_set(obj, sd, _legacy_default_format_func, NULL); + + if (efl_alive_get(obj)) + efl_ui_format_apply_formatted_value(obj); +} + +EOLIAN static void +_efl_ui_format_format_string_get(const Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *sd, const char **string, Efl_Ui_Format_String_Type *type) +{ + if (string) *string = sd->format_string; + if (type) *type = sd->format_string_type == FORMAT_TYPE_TM ? + EFL_UI_FORMAT_STRING_TYPE_TIME : EFL_UI_FORMAT_STRING_TYPE_SIMPLE; +} + +EOLIAN static void +_efl_ui_format_formatted_value_get(Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *pd, Eina_Strbuf *str, const Eina_Value value) +{ + char *v; + eina_strbuf_reset(str); + if (pd->format_values) + { + /* Search in the format_values array if we have one */ + Efl_Ui_Format_Value v = { 0 }; + int ndx; + eina_value_int_convert(&value, &v.value); + ndx = eina_inarray_search_sorted(pd->format_values, &v, (Eina_Compare_Cb)_value_compare); + if (ndx > -1) { + Efl_Ui_Format_Value *entry = eina_inarray_nth(pd->format_values, ndx); + eina_strbuf_append(str, entry->text); + return; + } + } + if (pd->format_func) + { + /* If we have a formatting function, try to use it */ + if (pd->format_func(pd->format_func_data, str, value)) + return; + } + if (pd->format_string) + { + /* If we have a formatting string, use it */ + if (_do_format_string(pd, str, value)) + return; + } + + /* Fallback to just printing the value if everything else fails */ + v = eina_value_to_string(&value); + eina_strbuf_append(str, v); + free(v); +} + +EOLIAN static int +_efl_ui_format_decimal_places_get(Eo *obj EINA_UNUSED, Efl_Ui_Format_Data *pd) +{ + char result[16] = "0"; + const char *start; + + /* This method can only be called if a format_string has been supplied */ + if (!pd->format_string) return 0; + + start = strchr(pd->format_string, '%'); + while (start) + { + if (start[1] != '%') + { + start = strchr(start, '.'); + if (start) + start++; + break; + } + else + start = strchr(start + 2, '%'); + } + + if (start) + { + const char *p = strchr(start, 'f'); + + if ((p) && ((p - start) < 15)) + sscanf(start, "%[^f]", result); + } + + return atoi(result); +} + +EOLIAN static void +_efl_ui_format_efl_object_destructor(Eo *obj, Efl_Ui_Format_Data *pd EINA_UNUSED) +{ + /* Legacy widgets keep their own formatting data and have their own destructors */ + if (!elm_widget_is_legacy(obj)) + { + /* Otherwise, free formatting data */ + efl_ui_format_func_set(obj, NULL, NULL, NULL); + efl_ui_format_values_set(obj, NULL); + efl_ui_format_string_set(obj, NULL, 0); + } + efl_destructor(efl_super(obj, EFL_UI_FORMAT_MIXIN)); +} + +#include "efl_ui_format.eo.c" + diff --git a/src/lib/elementary/efl_ui_format.eo b/src/lib/elementary/efl_ui_format.eo new file mode 100644 index 0000000000..3858a79ef1 --- /dev/null +++ b/src/lib/elementary/efl_ui_format.eo @@ -0,0 +1,149 @@ +import eina_types; + +function @beta Efl.Ui.Format_Func +{ + [[A function taking an @Eina.Value and producing its textual representation. + See @Efl.Ui.Format.format_func. + ]] + params { + @in str: strbuf; [[Output formatted string. Its contents will be overwritten by this method.]] + @in value: const(any_value); [[The @Eina.Value to convert to text.]] + } + return: bool; [[Whether the conversion succeeded or not.]] +}; + +struct @beta Efl.Ui.Format_Value +{ + [[A value which should always be displayed as a specific text string. + See @Efl.Ui.Format.format_values. + ]] + value: int; [[Input value.]] + text: string; [[Text string to replace it.]] +} + +enum @beta Efl.Ui.Format_String_Type +{ + [[Type of formatting string.]] + simple, [[This is the simplest formatting mechanism, working pretty much like $printf. + Accepted formats are $s, $f, $F, $d, $u, $i, $o, $x and $X. + For example, "%1.2f meters", "%.0%%" or "%d items". + ]] + time [[A strftime-style string used to format date and time values. + For example, "%A" for the full name of the day or "%y" for the year as a decimal number + without a century (range 00 to 99). Note that these are not the $printf formats. + See the man page for the $strftime function for the complete list. + ]] +} + +mixin @beta Efl.Ui.Format requires Efl.Object +{ + [[Helper mixin that simplifies converting numerical values to text. + + A number of widgets represent a numerical value but display a text representation. + For example, an @Efl.Ui.Progressbar can hold the number 0.75 but display the string "75%", + or an @Efl.Ui.Spin can hold numbers 1 to 7, but display the strings "Monday" thru "Sunday". + + This conversion can be controlled through the @.format_func, @.format_values and @.format_string properties. + Only one of them needs to be set. When more than one is set @.format_values has the highest priority, followed by @.format_func and then @.format_string. + If one mechanism fails to produce a valid string the others will be tried (if provided) in descending + order of priority. + If no user-provided mechanism works, a fallback is used that just displays the value. + + Widgets including this mixin offer their users different properties to control how + @Eina.Value's are converted to text. + ]] + methods { + @property format_func { + [[User-provided function which takes care of converting an @Eina.Value into a text string. + The user is then completely in control of how the string is generated, but it is the + most cumbersome method to use. + If the conversion fails the other mechanisms will be tried, according to their priorities. + ]] + values { + func: Efl.Ui.Format_Func; [[User-provided formatting function.]] + } + } + + @property format_values { + [[User-provided list of values which are to be rendered using specific text strings. + This is more convenient to use than @.format_func and is perfectly suited for cases + where the strings make more sense than the numerical values. For example, weekday names + ("Monday", "Tuesday", ...) are friendlier than numbers 1 to 7. + If a value is not found in the list, the other mechanisms will be tried according to their priorities. + List members do not need to be in any particular order. They are sorted internally for + performance reasons. + ]] + values { + values: accessor; [[Accessor over a list of value-text pairs. + The method will dispose of the accessor, but not of + its contents. + For convenience, Eina offers a range of helper + methods to obtain accessors from Eina.Array, + Eina.List or even plain C arrays. + ]] + } + } + + @property format_string { + [[A user-provided, string used to format the numerical value. + + For example, "%1.2f meters", "%.0%%" or "%d items". + + This is the simplest formatting mechanism, working pretty much like $printf. + + Different format specifiers (the character after the %) are available, depending on the + $type used. Use @Efl.Ui.Format_String_Type.simple for simple numerical values and + @Efl.Ui.Format_String_Type.time for time and date values. + For instance, %d means "integer" when the first type is used, but it means "day of the month + as a decimal number" in the second. + + Pass $NULL to disable this mechanism. + ]] + values { + string: string; [[Formatting string containing regular characters and format specifiers.]] + type: Efl.Ui.Format_String_Type(Efl.Ui.Format_String_Type.simple); + [[Type of formatting string, which controls how the + different format specifiers are to be traslated.]] + } + } + + formatted_value_get @protected { + [[Internal method to be used by widgets including this mixin to perform the conversion + from the internal numerical value into the text representation (Users of these widgets + do not need to call this method). + + @.formatted_value_get uses any user-provided mechanism to perform the conversion, according to their + priorities, and implements a simple fallback if all mechanisms fail. + ]] + params { + @in str: strbuf; [[Output formatted string. Its contents will be overwritten by this method.]] + @in value: const(any_value); [[The @Eina.Value to convert to text.]] + } + } + + decimal_places_get @protected { + [[Internal method to be used by widgets including this mixin. + It can only be used when a @.format_string has been supplied, and it returns the number + of decimal places that the format string will produce for floating point values. + + For example, "%.2f" returns 2, and "%d" returns 0; + ]] + return: int; [[Number of decimal places, or 0 for non-floating point types.]] + } + + apply_formatted_value @pure_virtual @protected { + [[Internal method to be implemented by widgets including this mixin. + + The mixin will call this method to signal the widget that the formatting has changed + and therefore the current value should be converted and rendered again. + Widgets must typically call @.formatted_value_get and display the returned string. This + is something they are already doing (whenever the value changes, for example) so there + should be no extra code written to implement this method. + ]] + } + } + + implements { + Efl.Object.destructor; + } +} diff --git a/src/lib/elementary/efl_ui_progressbar.c b/src/lib/elementary/efl_ui_progressbar.c index dfe4b07fbb..637c54f8d6 100644 --- a/src/lib/elementary/efl_ui_progressbar.c +++ b/src/lib/elementary/efl_ui_progressbar.c @@ -6,6 +6,7 @@ #define ELM_LAYOUT_PROTECTED #define EFL_ACCESS_VALUE_PROTECTED #define EFL_PART_PROTECTED +#define EFL_UI_FORMAT_PROTECTED #include @@ -73,7 +74,7 @@ _units_set(Evas_Object *obj) { EFL_UI_PROGRESSBAR_DATA_GET(obj, sd); - if (sd->show_progress_label && sd->format_cb) + if (sd->show_progress_label) { Eina_Value val; @@ -84,8 +85,8 @@ _units_set(Evas_Object *obj) if (sd->is_legacy_format_string && !sd->is_legacy_format_cb) eina_value_set(&val, 100 * sd->val); - eina_strbuf_reset(sd->format_strbuf); - sd->format_cb(sd->format_cb_data, sd->format_strbuf, val); + if (!sd->format_strbuf) sd->format_strbuf = eina_strbuf_new(); + efl_ui_format_formatted_value_get(obj, sd->format_strbuf, val); eina_value_flush(&val); @@ -361,7 +362,7 @@ _efl_ui_progressbar_efl_canvas_group_group_add(Eo *obj, Efl_Ui_Progressbar_Data free(group); - efl_ui_format_string_set(obj, "%.0f%%"); + efl_ui_format_string_set(obj, "%.0f%%", EFL_UI_FORMAT_STRING_TYPE_SIMPLE); priv->spacer = evas_object_rectangle_add(evas_object_evas_get(obj)); evas_object_color_set(priv->spacer, 0, 0, 0, 0); @@ -402,8 +403,8 @@ _efl_ui_progressbar_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Progressbar_Data } } - efl_ui_format_cb_set(obj, NULL, NULL, NULL); eina_strbuf_free(sd->format_strbuf); + sd->format_strbuf = NULL; efl_canvas_group_del(efl_super(obj, MY_CLASS)); } @@ -610,32 +611,6 @@ _efl_ui_progressbar_efl_ui_range_display_range_value_get(const Eo *obj, Efl_Ui_P return efl_ui_range_value_get(efl_part(obj, "efl.cur.progressbar")); } -EOLIAN static void -_efl_ui_progressbar_efl_ui_format_format_cb_set(Eo *obj, Efl_Ui_Progressbar_Data *sd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - - if (sd->format_cb_data == func_data && sd->format_cb == func) - return; - - if (sd->format_cb_data && sd->format_free_cb) - sd->format_free_cb(sd->format_cb_data); - - sd->format_cb = func; - sd->format_cb_data = func_data; - sd->format_free_cb = func_free_cb; - if (!sd->format_strbuf) sd->format_strbuf = eina_strbuf_new(); - - if (elm_widget_is_legacy(obj)) - elm_layout_signal_emit(obj, "elm,state,units,visible", "elm"); - else - elm_layout_signal_emit(obj, "efl,state,units,visible", "efl"); - edje_object_message_signal_process(wd->resize_obj); - - _units_set(obj); - elm_layout_sizing_eval(obj); -} - EOLIAN static void _efl_ui_progressbar_pulse_set(Eo *obj, Efl_Ui_Progressbar_Data *sd, Eina_Bool state) { @@ -773,6 +748,12 @@ _efl_ui_progressbar_show_progress_label_get(const Eo *obj EINA_UNUSED, Efl_Ui_Pr return pd->show_progress_label; } +EOLIAN static void +_efl_ui_progressbar_efl_ui_format_apply_formatted_value(Eo *obj, Efl_Ui_Progressbar_Data *pd EINA_UNUSED) +{ + _units_set(obj); +} + #include "efl_ui_progressbar_part.eo.c" /* Efl.Part end */ @@ -982,7 +963,7 @@ typedef struct progressbar_freefunc_type format_free_cb; } Pb_Format_Wrapper_Data; -static void +static Eina_Bool _format_legacy_to_format_eo_cb(void *data, Eina_Strbuf *str, const Eina_Value value) { Pb_Format_Wrapper_Data *pfwd = data; @@ -998,6 +979,8 @@ _format_legacy_to_format_eo_cb(void *data, Eina_Strbuf *str, const Eina_Value va if (buf) eina_strbuf_append(str, buf); if (pfwd->format_free_cb) pfwd->format_free_cb(buf); + + return EINA_TRUE; } static void @@ -1018,8 +1001,8 @@ elm_progressbar_unit_format_function_set(Evas_Object *obj, progressbar_func_type pfwd->format_free_cb = free_func; sd->is_legacy_format_cb = EINA_TRUE; - efl_ui_format_cb_set(obj, pfwd, _format_legacy_to_format_eo_cb, - _format_legacy_to_format_eo_free_cb); + efl_ui_format_func_set(obj, pfwd, _format_legacy_to_format_eo_cb, + _format_legacy_to_format_eo_free_cb); } EAPI void @@ -1042,13 +1025,15 @@ elm_progressbar_unit_format_set(Evas_Object *obj, const char *units) EFL_UI_PROGRESSBAR_DATA_GET_OR_RETURN(obj, sd); sd->is_legacy_format_string = EINA_TRUE; - efl_ui_format_string_set(obj, units); + efl_ui_format_string_set(obj, units, EFL_UI_FORMAT_STRING_TYPE_SIMPLE); } EAPI const char * elm_progressbar_unit_format_get(const Evas_Object *obj) { - return efl_ui_format_string_get(obj); + const char *fmt; + efl_ui_format_string_get(obj, &fmt, NULL); + return fmt; } EAPI void diff --git a/src/lib/elementary/efl_ui_progressbar.eo b/src/lib/elementary/efl_ui_progressbar.eo index 6a708447a9..ba8b3e37f2 100644 --- a/src/lib/elementary/efl_ui_progressbar.eo +++ b/src/lib/elementary/efl_ui_progressbar.eo @@ -58,7 +58,7 @@ class @beta Efl.Ui.Progressbar extends Efl.Ui.Layout_Base implements Efl.Ui.Rang Efl.Ui.Range_Display.range_value { get; set; } Efl.Ui.Range_Display.range_limits {get; set; } Efl.Ui.Layout_Orientable.orientation { get; set; } - Efl.Ui.Format.format_cb { set; } + Efl.Ui.Format.apply_formatted_value; Efl.Part.part_get; Efl.Access.Value.value_and_text { get; } Efl.Text.text { get; set; } diff --git a/src/lib/elementary/efl_ui_progressbar_private.h b/src/lib/elementary/efl_ui_progressbar_private.h index 9abd57d3d7..48b999b532 100644 --- a/src/lib/elementary/efl_ui_progressbar_private.h +++ b/src/lib/elementary/efl_ui_progressbar_private.h @@ -38,9 +38,6 @@ struct _Efl_Ui_Progressbar_Data Eina_List *progress_status; /**< The list of _Elm_Progress_Status. To save the progress value(in percentage) each part of given progress bar */ - Efl_Ui_Format_Func_Cb format_cb; - Eina_Free_Cb format_free_cb; - void *format_cb_data; Eina_Strbuf *format_strbuf; Efl_Ui_Layout_Orientation dir; /**< Orientation of the progressbar */ diff --git a/src/lib/elementary/efl_ui_spin.c b/src/lib/elementary/efl_ui_spin.c index feb3f543af..dddc869152 100644 --- a/src/lib/elementary/efl_ui_spin.c +++ b/src/lib/elementary/efl_ui_spin.c @@ -5,6 +5,7 @@ #define EFL_ACCESS_OBJECT_PROTECTED #define EFL_ACCESS_VALUE_PROTECTED #define EFL_ACCESS_WIDGET_ACTION_PROTECTED +#define EFL_UI_FORMAT_PROTECTED #include @@ -15,142 +16,17 @@ #define MY_CLASS_NAME "Efl.Ui.Spin" -static Eina_Bool -_is_valid_digit(char x) -{ - return ((x >= '0' && x <= '9') || (x == '.')) ? EINA_TRUE : EINA_FALSE; -} - -static Efl_Ui_Spin_Format_Type -_is_label_format_integer(const char *fmt) -{ - const char *itr = NULL; - const char *start = NULL; - Eina_Bool found = EINA_FALSE; - Efl_Ui_Spin_Format_Type ret_type = SPIN_FORMAT_INVALID; - - start = strchr(fmt, '%'); - if (!start) return SPIN_FORMAT_INVALID; - - while (start) - { - if (found && start[1] != '%') - { - return SPIN_FORMAT_INVALID; - } - - if (start[1] != '%' && !found) - { - found = EINA_TRUE; - for (itr = start + 1; *itr != '\0'; itr++) - { - if ((*itr == 'd') || (*itr == 'u') || (*itr == 'i') || - (*itr == 'o') || (*itr == 'x') || (*itr == 'X')) - { - ret_type = SPIN_FORMAT_INT; - break; - } - else if ((*itr == 'f') || (*itr == 'F')) - { - ret_type = SPIN_FORMAT_FLOAT; - break; - } - else if (_is_valid_digit(*itr)) - { - continue; - } - else - { - return SPIN_FORMAT_INVALID; - } - } - } - start = strchr(start + 2, '%'); - } - - return ret_type; -} static void -_label_write(Evas_Object *obj) +_label_write(Evas_Object *obj, Efl_Ui_Spin_Data *sd) { - Efl_Ui_Spin_Special_Value *sv; - unsigned int i; - Eina_Array_Iterator iterator; + Eina_Strbuf *strbuf = eina_strbuf_new(); + Eina_Value val = eina_value_double_init(sd->val); + efl_ui_format_formatted_value_get(obj, strbuf, val); - Efl_Ui_Spin_Data *sd = efl_data_scope_get(obj, MY_CLASS); + elm_layout_text_set(obj, "efl.text", eina_strbuf_string_get(strbuf)); - EINA_ARRAY_ITER_NEXT(sd->special_values, i, sv, iterator) - { - if (sv->value == sd->val) - { - char buf[1024]; - snprintf(buf, sizeof(buf), "%s", sv->label); - elm_layout_text_set(obj, "elm.text", buf); - sd->templates = sv->label; - return; - } - } - - if (sd->format_cb) - { - const char *buf; - Eina_Value val; - - if (sd->format_type == SPIN_FORMAT_INT) - { - eina_value_setup(&val, EINA_VALUE_TYPE_INT); - eina_value_set(&val, (int)sd->val); - } - else - { - eina_value_setup(&val, EINA_VALUE_TYPE_DOUBLE); - eina_value_set(&val, sd->val); - } - eina_strbuf_reset(sd->format_strbuf); - sd->format_cb(sd->format_cb_data, sd->format_strbuf, val); - - buf = eina_strbuf_string_get(sd->format_strbuf); - eina_value_flush(&val); - elm_layout_text_set(obj, "efl.text", buf); - sd->templates = buf; - } - else - { - char buf[1024]; - snprintf(buf, sizeof(buf), "%.0f", sd->val); - elm_layout_text_set(obj, "efl.text", buf); - evas_object_show(obj); - } -} - -static int -_decimal_points_get(const char *label) -{ - char result[16] = "0"; - const char *start = strchr(label, '%'); - - while (start) - { - if (start[1] != '%') - { - start = strchr(start, '.'); - if (start) - start++; - break; - } - else - start = strchr(start + 2, '%'); - } - - if (start) - { - const char *p = strchr(start, 'f'); - - if ((p) && ((p - start) < 15)) - sscanf(start, "%[^f]", result); - } - - return atoi(result); + eina_value_flush(&val); + eina_strbuf_free(strbuf); } EOLIAN static void @@ -188,48 +64,6 @@ _efl_ui_spin_efl_ui_widget_widget_input_event_handler(Eo *obj, Efl_Ui_Spin_Data return EINA_TRUE; } -EOLIAN static void -_efl_ui_spin_special_value_set(Eo *obj, Efl_Ui_Spin_Data *sd, const Eina_Array *values) -{ - EINA_SAFETY_ON_NULL_RETURN(values); - - unsigned int i; - Efl_Ui_Spin_Special_Value *sv; - Efl_Ui_Spin_Special_Value *temp; - Eina_Array_Iterator iterator; - - if (eina_array_count(sd->special_values)) - { - EINA_ARRAY_ITER_NEXT(sd->special_values, i, sv, iterator) - { - eina_stringshare_del(sv->label); - free(sv); - } - eina_array_clean(sd->special_values); - } - - if (eina_array_count(values)) - EINA_ARRAY_ITER_NEXT(values, i, temp, iterator) - { - sv = calloc(1, sizeof(*sv)); - if (!sv) return; - sv->value = temp->value; - sv->label = eina_stringshare_add(temp->label); - eina_array_push(sd->special_values, sv); - } - - _label_write(obj); -} - -EOLIAN static const Eina_Array* -_efl_ui_spin_special_value_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Data *sd) -{ - if (eina_array_count(sd->special_values)) - return sd->special_values; - else - return NULL; -} - EOLIAN static Eo * _efl_ui_spin_efl_object_constructor(Eo *obj, Efl_Ui_Spin_Data *sd) { @@ -241,7 +75,6 @@ _efl_ui_spin_efl_object_constructor(Eo *obj, Efl_Ui_Spin_Data *sd) sd->val_max = 100.0; sd->step = 1.0; - sd->special_values = eina_array_new(sizeof(Efl_Ui_Spin_Special_Value)); if (elm_widget_theme_object_set(obj, wd->resize_obj, elm_widget_theme_klass_get(obj), @@ -249,7 +82,7 @@ _efl_ui_spin_efl_object_constructor(Eo *obj, Efl_Ui_Spin_Data *sd) elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC) CRI("Failed to set layout!"); - _label_write(obj); + _label_write(obj, sd); elm_widget_can_focus_set(obj, EINA_TRUE); elm_layout_sizing_eval(obj); @@ -260,50 +93,13 @@ _efl_ui_spin_efl_object_constructor(Eo *obj, Efl_Ui_Spin_Data *sd) EOLIAN static void _efl_ui_spin_efl_object_destructor(Eo *obj, Efl_Ui_Spin_Data *sd EINA_UNUSED) { - Efl_Ui_Spin_Special_Value *sv; - Eina_Array_Iterator iterator; - unsigned int i; - - efl_ui_format_cb_set(obj, NULL, NULL, NULL); - - EINA_ARRAY_ITER_NEXT(sd->special_values, i, sv, iterator) - { - eina_stringshare_del(sv->label); - free(sv); - } - eina_array_free(sd->special_values); - efl_destructor(efl_super(obj, MY_CLASS)); } EOLIAN static void -_efl_ui_spin_efl_ui_format_format_cb_set(Eo *obj, Efl_Ui_Spin_Data *sd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) +_efl_ui_spin_efl_ui_format_apply_formatted_value(Eo *obj, Efl_Ui_Spin_Data *sd EINA_UNUSED) { - if (sd->format_cb_data == func_data && sd->format_cb == func) - return; - - if (sd->format_cb_data && sd->format_free_cb) - sd->format_free_cb(sd->format_cb_data); - - sd->format_cb = func; - sd->format_cb_data = func_data; - sd->format_free_cb = func_free_cb; - if (!sd->format_strbuf) sd->format_strbuf = eina_strbuf_new(); - - const char *format = efl_ui_format_string_get(obj); - if (format) - { - sd->format_type = _is_label_format_integer(format); - if (sd->format_type == SPIN_FORMAT_INVALID) - { - ERR("format:\"%s\" is invalid, cannot be set", format); - return; - } - else if (sd->format_type == SPIN_FORMAT_FLOAT) - sd->decimal_points = _decimal_points_get(format); - } - - _label_write(obj); + _label_write(obj, sd); elm_layout_sizing_eval(obj); } @@ -325,7 +121,7 @@ _efl_ui_spin_efl_ui_range_display_range_limits_set(Eo *obj, Efl_Ui_Spin_Data *sd if (sd->val < sd->val_min) sd->val = sd->val_min; if (sd->val > sd->val_max) sd->val = sd->val_max; - _label_write(obj); + _label_write(obj, sd); } EOLIAN static void @@ -372,7 +168,7 @@ _efl_ui_spin_efl_ui_range_display_range_value_set(Eo *obj, Efl_Ui_Spin_Data *sd, efl_event_callback_call(obj, EFL_UI_SPIN_EVENT_CHANGED, NULL); - _label_write(obj); + _label_write(obj, sd); } EOLIAN static double diff --git a/src/lib/elementary/efl_ui_spin.eo b/src/lib/elementary/efl_ui_spin.eo index 4fee3df56c..7f02d5aeaa 100644 --- a/src/lib/elementary/efl_ui_spin.eo +++ b/src/lib/elementary/efl_ui_spin.eo @@ -1,36 +1,11 @@ -struct @beta Efl.Ui.Spin_Special_Value -{ - [[Special value]] - value: double; [[Target value]] - label: string; [[String to replace]] -} - class @beta Efl.Ui.Spin extends Efl.Ui.Layout_Base implements Efl.Ui.Range_Interactive, Efl.Ui.Format, Efl.Access.Value, Efl.Access.Widget.Action { [[A Spin. - This is a widget which allows the user to increase or decrease numeric values - using user interactions. It's a basic type of widget for choosing and displaying values. + This is a widget which allows the user to increase or decrease a numeric value + using arrow buttons. It's a basic type of widget for choosing and displaying values. ]] - methods { - @property special_value { - [[Control special string to display in the place of the numerical value. - - It's useful for cases when a user should select an item that is - better indicated by a label than a value. For example, weekdays or months. - - Note: If another label was previously set to $value, it will be replaced - by the new label.]] - set { - } - get { - } - values { - values: const(array); [[The array of special values, or NULL if none]] - } - } - } implements { Efl.Object.constructor; Efl.Object.destructor; @@ -38,7 +13,7 @@ class @beta Efl.Ui.Spin extends Efl.Ui.Layout_Base implements Efl.Ui.Range_Inter Efl.Ui.Range_Display.range_limits { get; set; } Efl.Ui.Range_Interactive.range_step { get; set; } Efl.Ui.Range_Display.range_value { get; set; } - Efl.Ui.Format.format_cb { set; } + Efl.Ui.Format.apply_formatted_value; } events { changed: void; [[Called when spin changed]] diff --git a/src/lib/elementary/efl_ui_spin_button.c b/src/lib/elementary/efl_ui_spin_button.c index 71eaec160e..c356686aea 100644 --- a/src/lib/elementary/efl_ui_spin_button.c +++ b/src/lib/elementary/efl_ui_spin_button.c @@ -6,6 +6,7 @@ #define EFL_ACCESS_VALUE_PROTECTED #define EFL_ACCESS_WIDGET_ACTION_PROTECTED #define EFL_UI_FOCUS_COMPOSITION_PROTECTED +#define EFL_UI_FORMAT_PROTECTED #include @@ -50,29 +51,20 @@ EFL_CALLBACKS_ARRAY_DEFINE(_inc_dec_button_cb, static void _entry_show(Evas_Object *obj) { - Efl_Ui_Spin_Special_Value *sv; - Eina_Array_Iterator iterator; - unsigned int i; char buf[32], fmt[32] = "%0.f"; Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS); Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS); - EINA_ARRAY_ITER_NEXT(pd->special_values, i, sv, iterator) - { - if (sv->value == pd->val) - { - snprintf(buf, sizeof(buf), "%s", sv->label); - elm_object_text_set(sd->ent, buf); - } - } + const char *format_string; + efl_ui_format_string_get(obj, &format_string, NULL); /* try to construct just the format from given label * completely ignoring pre/post words */ - if (pd->templates) + if (format_string) { - const char *start = strchr(pd->templates, '%'); + const char *start = strchr(format_string, '%'); while (start) { /* handle %% */ @@ -103,10 +95,7 @@ _entry_show(Evas_Object *obj) } } - if (pd->format_type == SPIN_FORMAT_INT) - snprintf(buf, sizeof(buf), fmt, (int)pd->val); - else - snprintf(buf, sizeof(buf), fmt, pd->val); + snprintf(buf, sizeof(buf), fmt, pd->val); elm_object_text_set(sd->ent, buf); } @@ -115,20 +104,16 @@ static void _label_write(Evas_Object *obj) { Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS); - Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS); - if (pd->templates) - { - efl_text_set(sd->text_button, pd->templates); - } - else - { - char buf[1024]; + Eina_Strbuf *strbuf = eina_strbuf_new(); + Eina_Value val = eina_value_double_init(pd->val); + efl_ui_format_formatted_value_get(obj, strbuf, val); - snprintf(buf, sizeof(buf), "%.0f", pd->val); - efl_text_set(sd->text_button, buf); - } + efl_text_set(sd->text_button, eina_strbuf_string_get(strbuf)); + + eina_value_flush(&val); + eina_strbuf_free(strbuf); } static Eina_Bool @@ -182,9 +167,6 @@ _entry_hide(Evas_Object *obj) static void _entry_value_apply(Evas_Object *obj) { - Efl_Ui_Spin_Special_Value *sv; - Eina_Array_Iterator iterator; - unsigned int i; const char *str; double val; char *end; @@ -200,10 +182,6 @@ _entry_value_apply(Evas_Object *obj) str = elm_object_text_get(sd->ent); if (!str) return; - EINA_ARRAY_ITER_NEXT(pd->special_values, i, sv, iterator) - if (sv->value == pd->val) - if (!strcmp(sv->label, str)) return; - val = strtod(str, &end); if (((*end != '\0') && (!isspace(*end))) || (fabs(val - pd->val) < DBL_EPSILON)) return; efl_ui_range_value_set(obj, val); @@ -267,14 +245,14 @@ static void _entry_accept_filter_add(Evas_Object *obj) { Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS); - Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS); static Elm_Entry_Filter_Accept_Set digits_filter_data; + int decimal_places = efl_ui_format_decimal_places_get(obj); if (!sd->ent) return; elm_entry_markup_filter_remove(sd->ent, elm_entry_filter_accept_set, &digits_filter_data); - if (pd->decimal_points > 0) + if (decimal_places > 0) digits_filter_data.accepted = "-.0123456789"; else digits_filter_data.accepted = "-0123456789"; @@ -307,6 +285,7 @@ _min_max_validity_filter(void *data, Evas_Object *obj, char **text) char *insert, *new_str = NULL; double val; int max_len = 0, len; + int decimal_places = efl_ui_format_decimal_places_get(data); EINA_SAFETY_ON_NULL_RETURN(data); EINA_SAFETY_ON_NULL_RETURN(obj); @@ -322,12 +301,12 @@ _min_max_validity_filter(void *data, Evas_Object *obj, char **text) if (!new_str) return; if (strchr(new_str, '-')) max_len++; - if (pd->format_type == SPIN_FORMAT_FLOAT) + if (decimal_places > 0) { point = strchr(new_str, '.'); if (point) { - if ((int) strlen(point + 1) > pd->decimal_points) + if ((int) strlen(point + 1) > decimal_places) { *insert = 0; goto end; diff --git a/src/lib/elementary/efl_ui_spin_private.h b/src/lib/elementary/efl_ui_spin_private.h index 3d21e3df54..3dbc06b4ea 100644 --- a/src/lib/elementary/efl_ui_spin_private.h +++ b/src/lib/elementary/efl_ui_spin_private.h @@ -3,29 +3,11 @@ #include "Elementary.h" -typedef enum _Efl_Ui_Spin_Format_Type -{ - SPIN_FORMAT_FLOAT, - SPIN_FORMAT_INT, - SPIN_FORMAT_INVALID -} Efl_Ui_Spin_Format_Type; - typedef struct _Efl_Ui_Spin_Data Efl_Ui_Spin_Data; struct _Efl_Ui_Spin_Data { - const char *templates; double val, val_min, val_max; double step; /**< step for the value change. 1 by default. */ - int decimal_points; - Ecore_Timer *spin_timer; /**< a timer for a repeated spin value change on mouse down */ - Efl_Ui_Spin_Format_Type format_type; - - Efl_Ui_Format_Func_Cb format_cb; - Eina_Free_Cb format_free_cb; - void *format_cb_data; - Eina_Strbuf *format_strbuf; - - Eina_Array *special_values; }; #endif diff --git a/src/lib/elementary/efl_ui_tags.c b/src/lib/elementary/efl_ui_tags.c index 12b56c15c5..34bc487355 100644 --- a/src/lib/elementary/efl_ui_tags.c +++ b/src/lib/elementary/efl_ui_tags.c @@ -2,6 +2,8 @@ # include "elementary_config.h" #endif +#define EFL_UI_FORMAT_PROTECTED + #include #include "elm_priv.h" #include "efl_ui_tags_private.h" @@ -75,7 +77,6 @@ _shrink_mode_set(Eo *obj, EINA_LIST_FOREACH(sd->layouts, l, layout) { - char buf[32]; Evas_Coord w_label_count = 0, h = 0; elm_box_pack_end(sd->box, layout); @@ -92,19 +93,12 @@ _shrink_mode_set(Eo *obj, if (count > 0) { - if (sd->format_cb) - { - eina_strbuf_reset(sd->format_strbuf); - eina_value_set(&val, count); - sd->format_cb(sd->format_cb_data, sd->format_strbuf, val); - edje_object_part_text_escaped_set(sd->end, "efl.text", - eina_strbuf_string_get(sd->format_strbuf)); - } - else - { - snprintf(buf, sizeof(buf), "+ %d", count); - edje_object_part_text_escaped_set(sd->end, "efl.text", buf); - } + Eina_Strbuf *strbuf = eina_strbuf_new(); + eina_value_set(&val, count); + efl_ui_format_formatted_value_get(obj, strbuf, val); + edje_object_part_text_escaped_set(sd->end, "efl.text", + eina_strbuf_string_get(strbuf)); + eina_strbuf_free(strbuf); edje_object_size_min_calc(sd->end, &w_label_count, NULL); elm_coords_finger_size_adjust(1, &w_label_count, 1, NULL); @@ -112,23 +106,16 @@ _shrink_mode_set(Eo *obj, if ((w < 0) || (w < w_label_count)) { + Eina_Strbuf *strbuf = eina_strbuf_new(); elm_box_unpack(sd->box, layout); evas_object_hide(layout); count++; - if (sd->format_cb) - { - eina_strbuf_reset(sd->format_strbuf); - eina_value_set(&val, count); - sd->format_cb(sd->format_cb_data, sd->format_strbuf, val); - edje_object_part_text_escaped_set(sd->end, "efl.text", - eina_strbuf_string_get(sd->format_strbuf)); - } - else - { - snprintf(buf, sizeof(buf), "+ %d", count); - edje_object_part_text_escaped_set(sd->end, "efl.text", buf); - } + eina_value_set(&val, count); + efl_ui_format_formatted_value_get(obj, strbuf, val); + edje_object_part_text_escaped_set(sd->end, "efl.text", + eina_strbuf_string_get(strbuf)); + eina_strbuf_free(strbuf); edje_object_size_min_calc(sd->end, &w_label_count, &h); elm_coords_finger_size_adjust(1, &w_label_count, 1, &h); @@ -1021,7 +1008,6 @@ _efl_ui_tags_efl_object_constructor(Eo *obj, Efl_Ui_Tags_Data *sd) sd->last_it_select = EINA_TRUE; sd->editable = EINA_TRUE; sd->parent = obj; - sd->format_cb = NULL; sd->it_array = eina_array_new(4); _view_init(obj, sd); @@ -1054,9 +1040,6 @@ _efl_ui_tags_efl_object_destructor(Eo *obj, Efl_Ui_Tags_Data *sd) evas_object_del(sd->end); ecore_timer_del(sd->longpress_timer); - efl_ui_format_cb_set(obj, NULL, NULL, NULL); - eina_strbuf_free(sd->format_strbuf); - efl_destructor(efl_super(obj, MY_CLASS)); } @@ -1072,23 +1055,6 @@ _efl_ui_tags_efl_text_text_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd) return (sd->label_str ? sd->label_str : NULL); } -EOLIAN static void -_efl_ui_tags_efl_ui_format_format_cb_set(Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) -{ - if ((sd->format_cb_data == func_data) && (sd->format_cb == func)) - return; - - if (sd->format_cb_data && sd->format_free_cb) - sd->format_free_cb(sd->format_cb_data); - - sd->format_cb = func; - sd->format_cb_data = func_data; - sd->format_free_cb = func_free_cb; - if (!sd->format_strbuf) sd->format_strbuf = eina_strbuf_new(); - - _view_update(sd); -} - EOLIAN static Eina_Bool _efl_ui_tags_expanded_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd) { @@ -1171,6 +1137,11 @@ _efl_ui_tags_items_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd) return sd->it_array; } +EOLIAN static void +_efl_ui_tags_efl_ui_format_apply_formatted_value(Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *pd) +{ + _view_update(pd); +} #define EFL_UI_TAGS_EXTRA_OPS \ ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_tags), \ diff --git a/src/lib/elementary/efl_ui_tags.eo b/src/lib/elementary/efl_ui_tags.eo index 86e83ab7e2..6f8c739f06 100644 --- a/src/lib/elementary/efl_ui_tags.eo +++ b/src/lib/elementary/efl_ui_tags.eo @@ -47,7 +47,7 @@ class @beta Efl.Ui.Tags extends Efl.Ui.Layout_Base implements Efl.Text, Efl.Ui.F Efl.Object.destructor; Efl.Ui.Widget.widget_input_event_handler; Efl.Text.text { get; set; } - Efl.Ui.Format.format_cb { set; } + Efl.Ui.Format.apply_formatted_value; } events { /* FIXME: Returning a basic type is not future-proof, better return a struct */ diff --git a/src/lib/elementary/efl_ui_tags_private.h b/src/lib/elementary/efl_ui_tags_private.h index 49d0a95264..ef9fca63e3 100644 --- a/src/lib/elementary/efl_ui_tags_private.h +++ b/src/lib/elementary/efl_ui_tags_private.h @@ -34,11 +34,6 @@ struct _Efl_Ui_Tags_Data Evas_Coord w_box, h_box; int shrink; - Efl_Ui_Format_Func_Cb format_cb; - Eina_Free_Cb format_free_cb; - void *format_cb_data; - Eina_Strbuf *format_strbuf; - Eina_Bool last_it_select : 1; Eina_Bool editable : 1; Eina_Bool focused : 1; diff --git a/src/lib/elementary/elm_slider.c b/src/lib/elementary/elm_slider.c index e57893c795..8239e475ee 100644 --- a/src/lib/elementary/elm_slider.c +++ b/src/lib/elementary/elm_slider.c @@ -7,6 +7,7 @@ #define EFL_ACCESS_VALUE_PROTECTED #define ELM_LAYOUT_PROTECTED #define EFL_PART_PROTECTED +#define EFL_UI_FORMAT_PROTECTED #include @@ -953,7 +954,7 @@ _elm_slider_efl_object_constructor(Eo *obj, Elm_Slider_Data *priv) elm_widget_can_focus_set(obj, EINA_TRUE); - efl_ui_format_string_set(efl_part(obj, "indicator"), "%0.2f"); + efl_ui_format_string_set(efl_part(obj, "indicator"), "%0.2f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE); evas_object_event_callback_add (sd->spacer, EVAS_CALLBACK_MOUSE_DOWN, _spacer_down_cb, obj); @@ -976,7 +977,7 @@ _elm_slider_efl_object_destructor(Eo *obj, ELM_SAFE_FREE(sd->indi_template, eina_stringshare_del); eina_strbuf_free(sd->indi_format_strbuf); - efl_ui_format_cb_set(obj, NULL, NULL, NULL); + efl_ui_format_func_set(obj, NULL, NULL, NULL); eina_strbuf_free(sd->format_strbuf); efl_destructor(efl_super(obj, MY_CLASS)); @@ -1004,7 +1005,7 @@ _elm_slider_class_constructor(Efl_Class *klass) } EOLIAN static void -_elm_slider_efl_ui_format_format_cb_set(Eo *obj, Elm_Slider_Data *sd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) +_elm_slider_efl_ui_format_format_cb_set(Eo *obj, Elm_Slider_Data *sd, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb) { ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); @@ -1076,7 +1077,7 @@ _elm_slider_efl_part_part_get(const Eo *obj, Elm_Slider_Data *sd EINA_UNUSED, co } EOLIAN static void -_elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *_pd EINA_UNUSED, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb) +_elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *_pd EINA_UNUSED, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb) { Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); Elm_Slider_Data *sd = efl_data_scope_get(pd->obj, ELM_SLIDER_CLASS); @@ -1095,17 +1096,19 @@ _elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *_pd EINA_U efl_canvas_group_change(pd->obj); } -static void +static Eina_Bool _indi_default_format_cb(void *data, Eina_Strbuf *str, const Eina_Value value) { const Eina_Value_Type *type = eina_value_type_get(&value); Elm_Slider_Data *sd = efl_data_scope_get(data, ELM_SLIDER_CLASS); double v; - if (type != EINA_VALUE_TYPE_DOUBLE) return; + if (type != EINA_VALUE_TYPE_DOUBLE) return EINA_FALSE; eina_value_get(&value, &v); eina_strbuf_append_printf(str, sd->indi_template, v); + + return EINA_TRUE; } static void @@ -1129,7 +1132,7 @@ _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *_pd EI if (!template) return; eina_stringshare_replace(&sd->indi_template, template); - efl_ui_format_cb_set(efl_part(pd->obj, "indicator"), pd->obj, _indi_default_format_cb, _indi_default_format_free_cb); + efl_ui_format_func_set(efl_part(pd->obj, "indicator"), pd->obj, _indi_default_format_cb, _indi_default_format_free_cb); } EOLIAN static const char * @@ -1164,6 +1167,10 @@ _elm_slider_part_indicator_visible_mode_get(const Eo *obj, void *_pd EINA_UNUSED return sd->indicator_visible_mode; } +void _elm_slider_part_indicator_efl_ui_format_apply_formatted_value(Eo *obj EINA_UNUSED, Elm_Part_Data *pd EINA_UNUSED) +{ +} + #include "elm_slider_part_indicator_eo.c" /* Efl.Part end */ @@ -1194,13 +1201,15 @@ elm_slider_span_size_get(const Evas_Object *obj) EAPI void elm_slider_unit_format_set(Evas_Object *obj, const char *units) { - efl_ui_format_string_set(obj, units); + efl_ui_format_string_set(obj, units, EFL_UI_FORMAT_STRING_TYPE_SIMPLE); } EAPI const char * elm_slider_unit_format_get(const Evas_Object *obj) { - return efl_ui_format_string_get(obj); + const char* fmt; + efl_ui_format_string_get(obj, &fmt, NULL); + return fmt; } EAPI void @@ -1277,7 +1286,7 @@ typedef struct slider_freefunc_type format_free_cb; } Slider_Format_Wrapper_Data; -static void +static Eina_Bool _format_legacy_to_format_eo_cb(void *data, Eina_Strbuf *str, const Eina_Value value) { Slider_Format_Wrapper_Data *sfwd = data; @@ -1293,6 +1302,8 @@ _format_legacy_to_format_eo_cb(void *data, Eina_Strbuf *str, const Eina_Value va if (buf) eina_strbuf_append(str, buf); if (sfwd->format_free_cb) sfwd->format_free_cb(buf); + + return EINA_TRUE; } static void @@ -1310,7 +1321,7 @@ elm_slider_units_format_function_set(Evas_Object *obj, slider_func_type func, sl sfwd->format_cb = func; sfwd->format_free_cb = free_func; - efl_ui_format_cb_set(obj, sfwd, _format_legacy_to_format_eo_cb, _format_legacy_to_format_eo_free_cb); + efl_ui_format_func_set(obj, sfwd, _format_legacy_to_format_eo_cb, _format_legacy_to_format_eo_free_cb); } EAPI void @@ -1369,13 +1380,15 @@ elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max) EAPI void elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator) { - efl_ui_format_string_set(efl_part(obj, "indicator"), indicator); + efl_ui_format_string_set(efl_part(obj, "indicator"), indicator, EFL_UI_FORMAT_STRING_TYPE_SIMPLE); } EAPI const char * elm_slider_indicator_format_get(const Evas *obj) { - return efl_ui_format_string_get(efl_part(obj, "indicator")); + const char *fmt; + efl_ui_format_string_get(efl_part(obj, "indicator"), &fmt, NULL); + return fmt; } EAPI void @@ -1386,9 +1399,9 @@ elm_slider_indicator_format_function_set(Evas_Object *obj, slider_func_type func sfwd->format_cb = func; sfwd->format_free_cb = free_func; - efl_ui_format_cb_set(efl_part(obj, "indicator"), sfwd, - _format_legacy_to_format_eo_cb, - _format_legacy_to_format_eo_free_cb); + efl_ui_format_func_set(efl_part(obj, "indicator"), sfwd, + _format_legacy_to_format_eo_cb, + _format_legacy_to_format_eo_free_cb); } EAPI void @@ -1452,6 +1465,10 @@ elm_slider_indicator_visible_mode_get(const Evas_Object *obj) return elm_slider_part_indicator_visible_mode_get(efl_part(obj, "indicator")); } +void _elm_slider_efl_ui_format_apply_formatted_value(Eo *obj EINA_UNUSED, Elm_Slider_Data *pd EINA_UNUSED) +{ +} + /* Internal EO APIs and hidden overrides */ ELM_LAYOUT_CONTENT_ALIASES_IMPLEMENT(elm_slider) diff --git a/src/lib/elementary/elm_slider_eo.c b/src/lib/elementary/elm_slider_eo.c index 12debeef34..5f3ecc29e9 100644 --- a/src/lib/elementary/elm_slider_eo.c +++ b/src/lib/elementary/elm_slider_eo.c @@ -29,7 +29,7 @@ void _elm_slider_efl_text_markup_markup_set(Eo *obj, Elm_Slider_Data *pd, const const char *_elm_slider_efl_text_markup_markup_get(const Eo *obj, Elm_Slider_Data *pd); -void _elm_slider_efl_ui_format_format_cb_set(Eo *obj, Elm_Slider_Data *pd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb); +void _elm_slider_efl_ui_format_format_cb_set(Eo *obj, Elm_Slider_Data *pd, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb); void _elm_slider_efl_ui_l10n_l10n_text_set(Eo *obj, Elm_Slider_Data *pd, const char *label, const char *domain); @@ -40,6 +40,7 @@ const char *_elm_slider_efl_ui_l10n_l10n_text_get(const Eo *obj, Elm_Slider_Data Efl_Object *_elm_slider_efl_part_part_get(const Eo *obj, Elm_Slider_Data *pd, const char *name); +void _elm_slider_efl_ui_format_apply_formatted_value(Eo *obj, Elm_Slider_Data *pd); static Eina_Bool _elm_slider_class_initializer(Efl_Class *klass) @@ -63,7 +64,8 @@ _elm_slider_class_initializer(Efl_Class *klass) EFL_OBJECT_OP_FUNC(efl_text_get, _elm_slider_efl_text_text_get), EFL_OBJECT_OP_FUNC(efl_text_markup_set, _elm_slider_efl_text_markup_markup_set), EFL_OBJECT_OP_FUNC(efl_text_markup_get, _elm_slider_efl_text_markup_markup_get), - EFL_OBJECT_OP_FUNC(efl_ui_format_cb_set, _elm_slider_efl_ui_format_format_cb_set), + EFL_OBJECT_OP_FUNC(efl_ui_format_func_set, _elm_slider_efl_ui_format_format_cb_set), + EFL_OBJECT_OP_FUNC(efl_ui_format_apply_formatted_value, _elm_slider_efl_ui_format_apply_formatted_value), EFL_OBJECT_OP_FUNC(efl_ui_l10n_text_set, _elm_slider_efl_ui_l10n_l10n_text_set), EFL_OBJECT_OP_FUNC(efl_ui_l10n_text_get, _elm_slider_efl_ui_l10n_l10n_text_get), EFL_OBJECT_OP_FUNC(efl_part_get, _elm_slider_efl_part_part_get), diff --git a/src/lib/elementary/elm_slider_part_indicator_eo.c b/src/lib/elementary/elm_slider_part_indicator_eo.c index 915e1cea7f..54882942b1 100644 --- a/src/lib/elementary/elm_slider_part_indicator_eo.c +++ b/src/lib/elementary/elm_slider_part_indicator_eo.c @@ -7,7 +7,7 @@ Elm_Slider_Indicator_Visible_Mode _elm_slider_part_indicator_visible_mode_get(co EOAPI EFL_FUNC_BODY_CONST(elm_slider_part_indicator_visible_mode_get, Elm_Slider_Indicator_Visible_Mode, 0); -void _elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *pd, void *func_data, Efl_Ui_Format_Func_Cb func, Eina_Free_Cb func_free_cb); +void _elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *pd, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb); void _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *pd, const char *units); @@ -15,6 +15,7 @@ void _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *p const char *_elm_slider_part_indicator_efl_ui_format_format_string_get(const Eo *obj, void *pd); +void _elm_slider_part_indicator_efl_ui_format_apply_formatted_value(Eo *obj, Elm_Part_Data *pd); static Eina_Bool _elm_slider_part_indicator_class_initializer(Efl_Class *klass) @@ -30,9 +31,10 @@ _elm_slider_part_indicator_class_initializer(Efl_Class *klass) EFL_OPS_DEFINE(ops, EFL_OBJECT_OP_FUNC(elm_slider_part_indicator_visible_mode_set, _elm_slider_part_indicator_visible_mode_set), EFL_OBJECT_OP_FUNC(elm_slider_part_indicator_visible_mode_get, _elm_slider_part_indicator_visible_mode_get), - EFL_OBJECT_OP_FUNC(efl_ui_format_cb_set, _elm_slider_part_indicator_efl_ui_format_format_cb_set), + EFL_OBJECT_OP_FUNC(efl_ui_format_func_set, _elm_slider_part_indicator_efl_ui_format_format_cb_set), EFL_OBJECT_OP_FUNC(efl_ui_format_string_set, _elm_slider_part_indicator_efl_ui_format_format_string_set), EFL_OBJECT_OP_FUNC(efl_ui_format_string_get, _elm_slider_part_indicator_efl_ui_format_format_string_get), + EFL_OBJECT_OP_FUNC(efl_ui_format_apply_formatted_value, _elm_slider_part_indicator_efl_ui_format_apply_formatted_value), ELM_SLIDER_PART_INDICATOR_EXTRA_OPS ); opsp = &ops; @@ -50,4 +52,4 @@ static const Efl_Class_Description _elm_slider_part_indicator_class_desc = { NULL }; -EFL_DEFINE_CLASS(elm_slider_part_indicator_class_get, &_elm_slider_part_indicator_class_desc, EFL_UI_LAYOUT_PART_CLASS, EFL_UI_FORMAT_MIXIN, NULL); +EFL_DEFINE_CLASS(elm_slider_part_indicator_class_get, &_elm_slider_part_indicator_class_desc, EFL_UI_LAYOUT_PART_CLASS, EFL_UI_LEGACY_INTERFACE, EFL_UI_FORMAT_MIXIN, NULL); diff --git a/src/lib/elementary/elm_widget_multibuttonentry.h b/src/lib/elementary/elm_widget_multibuttonentry.h index 1da716622b..83d5d499bf 100644 --- a/src/lib/elementary/elm_widget_multibuttonentry.h +++ b/src/lib/elementary/elm_widget_multibuttonentry.h @@ -103,7 +103,7 @@ struct _Elm_Multibuttonentry_Data void *add_callback_data; Ecore_Timer *longpress_timer; - Efl_Ui_Format_Func_Cb format_cb; + Efl_Ui_Format_Func format_cb; Eina_Free_Cb format_free_cb; void *format_cb_data; Eina_Strbuf *format_strbuf; diff --git a/src/lib/elementary/elm_widget_slider.h b/src/lib/elementary/elm_widget_slider.h index 1b9c85c1fe..c12ed7c011 100644 --- a/src/lib/elementary/elm_widget_slider.h +++ b/src/lib/elementary/elm_widget_slider.h @@ -35,12 +35,12 @@ struct _Elm_Slider_Data Evas_Coord size; - Efl_Ui_Format_Func_Cb format_cb; + Efl_Ui_Format_Func format_cb; Eina_Free_Cb format_free_cb; void *format_cb_data; Eina_Strbuf *format_strbuf; - Efl_Ui_Format_Func_Cb indi_format_cb; + Efl_Ui_Format_Func indi_format_cb; Eina_Free_Cb indi_format_free_cb; void *indi_format_cb_data; Eina_Strbuf *indi_format_strbuf; diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build index 9e88e4c9b6..9807d46216 100644 --- a/src/lib/elementary/meson.build +++ b/src/lib/elementary/meson.build @@ -180,6 +180,7 @@ pub_eo_files = [ 'efl_ui_relative_layout.eo', 'efl_ui_clickable.eo', 'efl_ui_clickable_util.eo', + 'efl_ui_format.eo', ] foreach eo_file : pub_eo_files @@ -935,6 +936,7 @@ elementary_src = [ 'efl_ui_relative_layout.c', 'efl_ui_clickable.c', 'efl_ui_clickable_util.c', + 'efl_ui_format.c', ] elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl] diff --git a/src/tests/elementary/spec/README b/src/tests/elementary/spec/README index f98cb78533..24fad54327 100644 --- a/src/tests/elementary/spec/README +++ b/src/tests/elementary/spec/README @@ -27,3 +27,4 @@ Just add your widget name to the "test-widgets" array and recompile. Next run of == Adding a new test == To add a new test you need to create the .c file and include the metadata comment at the top. +Remember to add the new .c file to the meson.build file. diff --git a/src/tests/elementary/spec/efl_test_format.c b/src/tests/elementary/spec/efl_test_format.c new file mode 100644 index 0000000000..cd2e698051 --- /dev/null +++ b/src/tests/elementary/spec/efl_test_format.c @@ -0,0 +1,174 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif + +#define EFL_UI_FORMAT_PROTECTED /* To access internal methods */ + +#include +#include "efl_ui_spec_suite.h" +#include "suite_helpers.h" + +/* spec-meta-start + {"test-interface":"Efl.Ui.Format", + "test-widgets": ["Efl.Ui.Progressbar", "Efl.Ui.Calendar", "Efl.Ui.Tags", "Efl.Ui.Spin", "Efl.Ui.Spin_Button"]} + spec-meta-end */ + +static const Efl_Ui_Format_Value values[] = {{15, "fifteen"}, {16, "sixteen"}, {17, "seventeen"}, {18, "eighteen"}}; + +EFL_START_TEST(format_values) +{ + Eina_Strbuf *buf = eina_strbuf_new(); + Eina_Value eina_val; + + efl_ui_format_values_set(widget, EINA_C_ARRAY_ACCESSOR_NEW(values)); + eina_val = eina_value_int_init(17); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "seventeen"); // Check that value works + eina_val = eina_value_float_init(16.f); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "sixteen"); // Check built-in conversion + + eina_value_flush(&eina_val); + eina_strbuf_free(buf); +} +EFL_END_TEST + +static Eina_Bool +_format_func(void *data, Eina_Strbuf *str, const Eina_Value value) +{ + int i = *(int *)data; + int v; + ck_assert_int_eq(i, 1234); // Check that data ptr is passed along correctly + if (eina_value_type_get(&value) != EINA_VALUE_TYPE_INT) return EINA_FALSE; + eina_value_get(&value, &v); + eina_strbuf_append_printf(str, "You said '%d'", v); + + return EINA_TRUE; +} + +static void +_format_free_func(void *data) +{ + int i = *(int *)data; + ck_assert_int_eq(i, 1234); // Check that data ptr is passed along correctly + *(int *)data = 12345; // Change it to indicate that free func was called +} + +EFL_START_TEST(format_func) +{ + int data = 1234; + Eina_Strbuf *buf = eina_strbuf_new(); + Eina_Value eina_val; + + efl_ui_format_func_set(widget, &data, _format_func, _format_free_func); + eina_val = eina_value_int_init(15); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "You said '15'"); // Check that format func works + efl_ui_format_func_set(widget, NULL, NULL, NULL); + ck_assert_int_eq(data, 12345); // Check that free func is called + eina_value_flush(&eina_val); + + eina_strbuf_free(buf); +} +EFL_END_TEST + +EFL_START_TEST(format_string) +{ + Eina_Strbuf *buf = eina_strbuf_new(); + Eina_Value eina_val; + struct tm t = { 0 }; + const char *old_locale = setlocale(LC_TIME, NULL); + +#define CHECK(fmt_str, fmt_type, val, val_type, result) \ + efl_ui_format_string_set(widget, fmt_str, fmt_type); \ + eina_value_setup(&eina_val, val_type); \ + eina_value_set(&eina_val, val); \ + efl_ui_format_formatted_value_get(widget, buf, eina_val); \ + ck_assert_str_eq(eina_strbuf_string_get(buf), result); \ + eina_value_flush(&eina_val) + + CHECK("%d", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234, EINA_VALUE_TYPE_INT, "1234"); + CHECK("%d", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234.f, EINA_VALUE_TYPE_FLOAT, "1234"); // built-in conversion + CHECK("%d units", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234, EINA_VALUE_TYPE_INT, "1234 units"); // complex format + + CHECK("%.0f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 12.34f, EINA_VALUE_TYPE_FLOAT, "12"); + CHECK("%.1f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 12.34f, EINA_VALUE_TYPE_FLOAT, "12.3"); + CHECK("%.2f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 12.34f, EINA_VALUE_TYPE_FLOAT, "12.34"); + CHECK("%.2f", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234, EINA_VALUE_TYPE_INT, "1234.00"); // built-in conversion + CHECK("%.0f%%", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 75.f, EINA_VALUE_TYPE_FLOAT, "75%"); // complex format + + CHECK("%s", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, "Hello!", EINA_VALUE_TYPE_STRING, "Hello!"); + CHECK("%s", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234, EINA_VALUE_TYPE_INT, "1234"); // built-in conversion + CHECK("He said '%s'", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, "Hello!", EINA_VALUE_TYPE_STRING, "He said 'Hello!'"); // complex format + + CHECK("Static string", EFL_UI_FORMAT_STRING_TYPE_SIMPLE, 1234, EINA_VALUE_TYPE_INT, "Static string"); + + strptime("2019 7 3 11:49:3", "%Y %m %d %H:%M:%S", &t); + setlocale(LC_TIME, "C"); + CHECK("%F", EFL_UI_FORMAT_STRING_TYPE_TIME, t, EINA_VALUE_TYPE_TM, "2019-07-03"); + CHECK("%T", EFL_UI_FORMAT_STRING_TYPE_TIME, t, EINA_VALUE_TYPE_TM, "11:49:03"); + CHECK("%A", EFL_UI_FORMAT_STRING_TYPE_TIME, t, EINA_VALUE_TYPE_TM, "Wednesday"); + CHECK("<%B %Y>", EFL_UI_FORMAT_STRING_TYPE_TIME, t, EINA_VALUE_TYPE_TM, ""); + setlocale(LC_TIME, old_locale); + + eina_strbuf_free(buf); +#undef CHECK +} +EFL_END_TEST + +static Eina_Bool +_partial_format_func(void *data EINA_UNUSED, Eina_Strbuf *str, const Eina_Value value) +{ + int v; + if (eina_value_type_get(&value) != EINA_VALUE_TYPE_INT) return EINA_FALSE; + eina_value_get(&value, &v); + if (v < 10) + { + eina_strbuf_append_printf(str, "You said '%d'", v); + return EINA_TRUE; + } + return EINA_FALSE; +} + +EFL_START_TEST(format_mixed) +{ + Eina_Strbuf *buf = eina_strbuf_new(); + Eina_Value eina_val; + + // Now we check combinations of different options + // Each one should be used in turn when the previous one fails: values, func, string, fallback + efl_ui_format_values_set(widget, EINA_C_ARRAY_ACCESSOR_NEW(values)); + efl_ui_format_func_set(widget, NULL, _partial_format_func, NULL); + efl_ui_format_string_set(widget, "%d rabbits", EFL_UI_FORMAT_STRING_TYPE_SIMPLE); + + eina_val = eina_value_int_init(1); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "You said '1'"); // Func + eina_value_set(&eina_val, 15); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "fifteen"); // Values + eina_value_set(&eina_val, 25); + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "25 rabbits"); // Values + + EXPECT_ERROR_START; + // This is an invalid format string (it has two placeholders) which should + // trigger the fallback mechanism + efl_ui_format_string_set(widget, "%d %d", EFL_UI_FORMAT_STRING_TYPE_SIMPLE); + EXPECT_ERROR_END; + efl_ui_format_formatted_value_get(widget, buf, eina_val); + ck_assert_str_eq(eina_strbuf_string_get(buf), "25"); // Fallback + + eina_value_flush(&eina_val); + eina_strbuf_free(buf); +} +EFL_END_TEST + +void +efl_ui_format_behavior_test(TCase *tc) +{ + tcase_add_test(tc, format_values); + tcase_add_test(tc, format_func); + tcase_add_test(tc, format_string); + tcase_add_test(tc, format_mixed); +} diff --git a/src/tests/elementary/spec/efl_ui_spec_suite.h b/src/tests/elementary/spec/efl_ui_spec_suite.h index 8389d819ef..666a40d80d 100644 --- a/src/tests/elementary/spec/efl_ui_spec_suite.h +++ b/src/tests/elementary/spec/efl_ui_spec_suite.h @@ -15,6 +15,7 @@ void efl_pack_linear_behavior_test(TCase *tc); void efl_content_behavior_test(TCase *tc); void efl_gfx_arrangement_behavior_test(TCase *tc); void efl_ui_clickable_behavior_test(TCase *tc); +void efl_ui_format_behavior_test(TCase *tc); void efl_test_container_content_equal(Efl_Ui_Widget **wid, unsigned int len); void efl_test_container_expect_evt_content_added(Efl_Ui_Widget *widget, const Efl_Event_Description *ev, Eina_Bool *flag, void *event_data); diff --git a/src/tests/elementary/spec/meson.build b/src/tests/elementary/spec/meson.build index 0f72b54fad..00fe61c1e7 100644 --- a/src/tests/elementary/spec/meson.build +++ b/src/tests/elementary/spec/meson.build @@ -5,6 +5,7 @@ efl_ui_suite_behavior_test_files = files([ 'efl_test_content.c', 'efl_test_gfx_arrangement.c', 'efl_test_clickable.c', + 'efl_test_format.c', ]) efl_ui_suite_behavior_src = files([