forked from enlightenment/efl
Efl.Ui.Format revamp
This class helps widgets which contain a numerical value and must display it, like Progressbar (units label), Spin, Spin_Button, Slider (both units and popup labels, in legacy), Tags (when in shrunk mode) or Calendar (year_month label). Previously this was a mix of interface and mixin: widgets had to support setting a formatting func, and the mixin offered support for formatting strings, by setting an internal formatting func. On top of that, the spinner widget supported "special values", a list of values that should be shown as certain strings instead. This has now been simplified and unified: Widgets including this mixin can use the formatted_value_get() method which accepts an Eina_Value and returns a string. Thats's it. The mixin adds three properties to the widget (format_values, format_func and format_string) which users can use to tailor formatting. The widget does not need to know which method has been used, it just retrieves the resulting string. This removes a lot of duplicated widget code, and adds functionality which was missing before. For example, all widgets support passing a list of values now. Widgets must implement the apply_formatted_value() method so they are notified of changes in the format and they can redraw anything they need. Tests have been added to the Elementary Spec suite for all cases. Legacy widgets behavior has not been modified, although a few needed some code changes.
This commit is contained in:
parent
87cfde51d3
commit
e776f5f0d7
|
@ -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));
|
||||
|
|
|
@ -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))
|
||||
);
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<tm>(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() {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
@ -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 <b>format
|
||||
string</b> 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.]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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',
|
||||
])
|
||||
|
|
|
@ -246,6 +246,7 @@ typedef Eo Efl_Ui_Active_View_Indicator;
|
|||
# include <efl_ui_navigation_layout.eo.h>
|
||||
# include <efl_ui_clickable.eo.h>
|
||||
# include <efl_ui_clickable_util.eo.h>
|
||||
# include <efl_ui_format.eo.h>
|
||||
|
||||
/**
|
||||
* Initialize Elementary
|
||||
|
|
|
@ -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 <Elementary.h>
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
@ -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<Efl.Ui.Format_Value>; [[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;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
#define ELM_LAYOUT_PROTECTED
|
||||
#define EFL_ACCESS_VALUE_PROTECTED
|
||||
#define EFL_PART_PROTECTED
|
||||
#define EFL_UI_FORMAT_PROTECTED
|
||||
|
||||
#include <Elementary.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 <Elementary.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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<ptr(Efl.Ui.Spin_Special_Value)>); [[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]]
|
||||
|
|
|
@ -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 <Elementary.h>
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#define EFL_UI_FORMAT_PROTECTED
|
||||
|
||||
#include <Elementary.h>
|
||||
#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), \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define EFL_ACCESS_VALUE_PROTECTED
|
||||
#define ELM_LAYOUT_PROTECTED
|
||||
#define EFL_PART_PROTECTED
|
||||
#define EFL_UI_FORMAT_PROTECTED
|
||||
|
||||
#include <Elementary.h>
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "elementary_config.h"
|
||||
#endif
|
||||
|
||||
#define EFL_UI_FORMAT_PROTECTED /* To access internal methods */
|
||||
|
||||
#include <Efl_Ui.h>
|
||||
#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, "<July 2019>");
|
||||
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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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([
|
||||
|
|
Loading…
Reference in New Issue