2017-11-20 02:12:49 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "elementary_config.h"
|
|
|
|
#endif
|
|
|
|
|
2018-04-03 04:27:30 -07:00
|
|
|
#define EFL_ACCESS_OBJECT_PROTECTED
|
2017-11-20 02:12:49 -08:00
|
|
|
#define EFL_ACCESS_VALUE_PROTECTED
|
|
|
|
#define EFL_ACCESS_WIDGET_ACTION_PROTECTED
|
|
|
|
#define EFL_UI_FOCUS_COMPOSITION_PROTECTED
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
#define EFL_UI_FORMAT_PROTECTED
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
#include <Elementary.h>
|
|
|
|
|
|
|
|
#include "elm_priv.h"
|
|
|
|
#include "efl_ui_spin_button_private.h"
|
|
|
|
#include "efl_ui_spin_private.h"
|
2019-03-05 14:00:37 -08:00
|
|
|
#include "elm_entry_eo.h"
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
#define MY_CLASS EFL_UI_SPIN_BUTTON_CLASS
|
|
|
|
|
|
|
|
#define MY_CLASS_NAME "Efl.Ui.Spin_Button"
|
|
|
|
|
|
|
|
#define EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME 0.2
|
|
|
|
|
2019-07-05 09:18:33 -07:00
|
|
|
//when a item is pressed but not released, this time passes by
|
|
|
|
//until another step is added or removed from the current value.
|
|
|
|
//given in seconds
|
|
|
|
#define REPEAT_INTERVAL 0.85
|
|
|
|
|
2018-04-25 00:43:53 -07:00
|
|
|
static const char PART_NAME_ENTRY[] = "entry";
|
2017-12-07 21:52:08 -08:00
|
|
|
static const char PART_NAME_DEC_BUTTON[] = "dec_button";
|
|
|
|
static const char PART_NAME_TEXT_BUTTON[] = "text_button";
|
|
|
|
static const char PART_NAME_INC_BUTTON[] = "inc_button";
|
|
|
|
|
2017-11-20 02:12:49 -08:00
|
|
|
static void
|
|
|
|
_inc_dec_button_clicked_cb(void *data, const Efl_Event *event);
|
|
|
|
static void
|
|
|
|
_entry_activated_cb(void *data, const Efl_Event *event);
|
|
|
|
static void
|
|
|
|
_entry_focus_changed_cb(void *data, const Efl_Event *event);
|
|
|
|
static void
|
|
|
|
_access_increment_decrement_info_say(Evas_Object *obj, Eina_Bool is_incremented);
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_inc_dec_button_cb,
|
2019-07-29 02:42:34 -07:00
|
|
|
{ EFL_INPUT_EVENT_CLICKED, _inc_dec_button_clicked_cb},
|
2019-07-05 08:35:06 -07:00
|
|
|
{ EFL_UI_AUTOREPEAT_EVENT_REPEATED, _inc_dec_button_clicked_cb},
|
2017-11-20 02:12:49 -08:00
|
|
|
);
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_show(Evas_Object *obj)
|
|
|
|
{
|
2018-05-19 11:01:44 -07:00
|
|
|
char buf[32], fmt[32] = "%0.f";
|
|
|
|
|
2017-11-20 02:12:49 -08:00
|
|
|
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);
|
2018-05-19 11:01:44 -07:00
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
const char *format_string;
|
|
|
|
efl_ui_format_string_get(obj, &format_string, NULL);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
/* try to construct just the format from given label
|
|
|
|
* completely ignoring pre/post words
|
|
|
|
*/
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
if (format_string)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
const char *start = strchr(format_string, '%');
|
2017-11-20 02:12:49 -08:00
|
|
|
while (start)
|
|
|
|
{
|
|
|
|
/* handle %% */
|
|
|
|
if (start[1] != '%')
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
start = strchr(start + 2, '%');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start)
|
|
|
|
{
|
|
|
|
const char *itr, *end = NULL;
|
|
|
|
for (itr = start + 1; *itr != '\0'; itr++)
|
|
|
|
{
|
|
|
|
if ((*itr == 'd') || (*itr == 'u') || (*itr == 'i') || (*itr == 'o') ||
|
|
|
|
(*itr == 'x') || (*itr == 'X') || (*itr == 'f') || (*itr == 'F'))
|
|
|
|
{
|
|
|
|
end = itr + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((end) && ((size_t)(end - start + 1) < sizeof(fmt)))
|
|
|
|
{
|
|
|
|
memcpy(fmt, start, end - start);
|
|
|
|
fmt[end - start] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
snprintf(buf, sizeof(buf), fmt, pd->val);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
elm_object_text_set(sd->ent, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
Eina_Strbuf *strbuf = eina_strbuf_new();
|
|
|
|
Eina_Value val = eina_value_double_init(pd->val);
|
|
|
|
efl_ui_format_formatted_value_get(obj, strbuf, val);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
efl_text_set(sd->text_button, eina_strbuf_string_get(strbuf));
|
|
|
|
|
|
|
|
eina_value_flush(&val);
|
|
|
|
eina_strbuf_free(strbuf);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
2019-07-11 15:53:54 -07:00
|
|
|
static Eina_Value
|
|
|
|
_delay_change_timer_cb(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-07-31 08:49:44 -07:00
|
|
|
efl_event_callback_call(o, EFL_UI_RANGE_EVENT_STEADY, NULL);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2019-07-11 15:53:54 -07:00
|
|
|
return v;
|
|
|
|
}
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2019-07-11 15:53:54 -07:00
|
|
|
static void
|
|
|
|
_delay_change_timer_cleanup(Eo *o EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = data;
|
|
|
|
|
|
|
|
sd->delay_change_timer = NULL;
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_value_set(Evas_Object *obj,
|
|
|
|
double new_val)
|
|
|
|
{
|
|
|
|
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);
|
2019-07-11 15:53:54 -07:00
|
|
|
Eina_Future *f;
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2019-07-31 09:06:43 -07:00
|
|
|
if (sd->wraparound)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
if (new_val < pd->val_min)
|
|
|
|
new_val = pd->val_max;
|
|
|
|
else if (new_val > pd->val_max)
|
|
|
|
new_val = pd->val_min;
|
|
|
|
}
|
2019-07-07 07:58:01 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
new_val = MIN(pd->val_max, MAX(pd->val_min, new_val));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EINA_DBL_EQ(new_val, efl_ui_range_value_get(obj))) return EINA_TRUE;
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
efl_ui_range_value_set(obj, new_val);
|
2019-07-11 15:53:54 -07:00
|
|
|
if (sd->delay_change_timer) eina_future_cancel(sd->delay_change_timer);
|
|
|
|
f = efl_loop_timeout(efl_loop_get(obj), EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME);
|
|
|
|
sd->delay_change_timer = efl_future_then(obj, f,
|
|
|
|
.success = _delay_change_timer_cb,
|
|
|
|
.free = _delay_change_timer_cleanup,
|
|
|
|
.data = sd);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_hide(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_emit(obj, "efl,state,button,active", "efl");
|
|
|
|
efl_layout_signal_emit(obj, "efl,state,entry,inactive", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (sd->entry_visible && !evas_focus_state_get(evas_object_evas_get(obj)))
|
|
|
|
sd->entry_reactivate = EINA_TRUE;
|
|
|
|
|
|
|
|
sd->entry_visible = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_value_apply(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
const char *str;
|
2019-07-07 07:58:01 -07:00
|
|
|
double val;
|
2017-11-20 02:12:49 -08:00
|
|
|
char *end;
|
|
|
|
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
if (!sd->entry_visible) return;
|
|
|
|
|
|
|
|
efl_event_callback_del(sd->ent, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED,
|
|
|
|
_entry_focus_changed_cb, obj);
|
|
|
|
_entry_hide(obj);
|
|
|
|
str = elm_object_text_get(sd->ent);
|
|
|
|
if (!str) return;
|
|
|
|
|
|
|
|
val = strtod(str, &end);
|
2019-07-07 07:58:01 -07:00
|
|
|
_value_set(obj, val);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_invalid_input_validity_filter(void *data EINA_UNUSED, Evas_Object *obj, char **text)
|
|
|
|
{
|
|
|
|
char *insert = NULL;
|
|
|
|
const char *str = NULL;
|
|
|
|
int cursor_pos = 0;
|
|
|
|
int read_idx = 0, read_char, cmp_char;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(obj);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(text);
|
|
|
|
|
|
|
|
insert = *text;
|
|
|
|
str = elm_object_text_get(obj);
|
|
|
|
|
|
|
|
evas_string_char_next_get(*text, 0, &read_char);
|
|
|
|
cursor_pos = elm_entry_cursor_pos_get(obj);
|
|
|
|
if (read_char)
|
|
|
|
{
|
|
|
|
if (read_char == '-')
|
|
|
|
{
|
|
|
|
if (cursor_pos != 0)
|
|
|
|
{
|
|
|
|
goto invalid_input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (read_char == '.')
|
|
|
|
{
|
|
|
|
read_idx = evas_string_char_next_get(str, 0, &cmp_char);
|
|
|
|
while (cmp_char)
|
|
|
|
{
|
|
|
|
if (read_char == cmp_char)
|
|
|
|
{
|
|
|
|
goto invalid_input;
|
|
|
|
}
|
|
|
|
read_idx = evas_string_char_next_get(str, read_idx, &cmp_char);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_idx = evas_string_char_next_get(str, 0, &cmp_char);
|
|
|
|
if ((cmp_char == '-') && (cursor_pos == 0))
|
|
|
|
{
|
|
|
|
goto invalid_input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
invalid_input:
|
|
|
|
*insert = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_accept_filter_add(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
static Elm_Entry_Filter_Accept_Set digits_filter_data;
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
int decimal_places = efl_ui_format_decimal_places_get(obj);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (!sd->ent) return;
|
|
|
|
|
|
|
|
elm_entry_markup_filter_remove(sd->ent, elm_entry_filter_accept_set, &digits_filter_data);
|
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
if (decimal_places > 0)
|
2017-11-20 02:12:49 -08:00
|
|
|
digits_filter_data.accepted = "-.0123456789";
|
|
|
|
else
|
|
|
|
digits_filter_data.accepted = "-0123456789";
|
|
|
|
|
|
|
|
elm_entry_markup_filter_prepend(sd->ent, elm_entry_filter_accept_set, &digits_filter_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_text_insert(const char *text, const char *input, int pos)
|
|
|
|
{
|
|
|
|
char *result = NULL;
|
|
|
|
int text_len, input_len;
|
|
|
|
|
|
|
|
text_len = evas_string_char_len_get(text);
|
|
|
|
input_len = evas_string_char_len_get(input);
|
|
|
|
result = (char *)calloc(text_len + input_len + 1, sizeof(char));
|
|
|
|
if (!result) return NULL;
|
|
|
|
|
|
|
|
strncpy(result, text, pos);
|
|
|
|
strcpy(result + pos, input);
|
|
|
|
strcpy(result + pos + input_len, text + pos);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_min_max_validity_filter(void *data, Evas_Object *obj, char **text)
|
|
|
|
{
|
|
|
|
const char *str, *point;
|
|
|
|
char *insert, *new_str = NULL;
|
|
|
|
double val;
|
2017-12-17 20:23:32 -08:00
|
|
|
int max_len = 0, len;
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
int decimal_places = efl_ui_format_decimal_places_get(data);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(data);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(obj);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(text);
|
|
|
|
|
|
|
|
Efl_Ui_Spin_Data *pd = efl_data_scope_get(data, EFL_UI_SPIN_CLASS);
|
|
|
|
|
|
|
|
str = elm_object_text_get(obj);
|
|
|
|
if (!str) return;
|
|
|
|
|
|
|
|
insert = *text;
|
|
|
|
new_str = _text_insert(str, insert, elm_entry_cursor_pos_get(obj));
|
|
|
|
if (!new_str) return;
|
2017-12-17 20:23:32 -08:00
|
|
|
if (strchr(new_str, '-')) max_len++;
|
2017-11-20 02:12:49 -08:00
|
|
|
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
if (decimal_places > 0)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
point = strchr(new_str, '.');
|
|
|
|
if (point)
|
|
|
|
{
|
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.
2019-07-02 05:40:06 -07:00
|
|
|
if ((int) strlen(point + 1) > decimal_places)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
*insert = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-17 20:23:32 -08:00
|
|
|
max_len += (fabs(pd->val_max) > fabs(pd->val_min)) ?
|
|
|
|
(log10(fabs(pd->val_max)) + 1) : (log10(fabs(pd->val_min)) + 1);
|
|
|
|
len = strlen(new_str);
|
|
|
|
if (len < max_len) goto end;
|
|
|
|
|
2017-11-20 02:12:49 -08:00
|
|
|
val = strtod(new_str, NULL);
|
|
|
|
if ((val < pd->val_min) || (val > pd->val_max))
|
|
|
|
*insert = 0;
|
|
|
|
|
|
|
|
end:
|
|
|
|
free(new_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_show_cb(void *data,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS);
|
|
|
|
|
|
|
|
_entry_show(data);
|
|
|
|
elm_object_focus_set(obj, EINA_TRUE);
|
|
|
|
elm_entry_select_all(obj);
|
|
|
|
sd->entry_visible = EINA_TRUE;
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_emit(data, "efl,state,button,inactive", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_toggle_entry(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
2019-08-05 05:44:51 -07:00
|
|
|
if (efl_ui_widget_disabled_get(obj)) return;
|
2017-11-20 02:12:49 -08:00
|
|
|
if (!sd->editable) return;
|
|
|
|
if (sd->entry_visible) _entry_value_apply(obj);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!sd->ent)
|
|
|
|
{
|
2017-11-29 23:52:42 -08:00
|
|
|
//FIXME: elm_entry will be changed to efl_ui_text after
|
|
|
|
// filter feature implemented.
|
|
|
|
// (Current efl_ui_text has missed filter feature.)
|
2017-11-20 02:12:49 -08:00
|
|
|
sd->ent = elm_entry_add(obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->ent, EVAS_CALLBACK_SHOW, _entry_show_cb, obj);
|
|
|
|
elm_entry_single_line_set(sd->ent, EINA_TRUE);
|
2018-04-26 03:27:43 -07:00
|
|
|
elm_layout_content_set(obj, "efl.entry", sd->ent);
|
2017-11-20 02:12:49 -08:00
|
|
|
_entry_accept_filter_add(obj);
|
|
|
|
elm_entry_markup_filter_append(sd->ent, _invalid_input_validity_filter, NULL);
|
|
|
|
if (_elm_config->spinner_min_max_filter_enable)
|
|
|
|
elm_entry_markup_filter_append(sd->ent, _min_max_validity_filter, obj);
|
|
|
|
efl_event_callback_add(sd->ent, ELM_ENTRY_EVENT_ACTIVATED,
|
|
|
|
_entry_activated_cb, obj);
|
2019-07-05 10:09:43 -07:00
|
|
|
elm_widget_element_update(obj, sd->ent, "entry");
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
efl_event_callback_add(sd->ent, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED,
|
|
|
|
_entry_focus_changed_cb, obj);
|
|
|
|
sd->entry_visible = EINA_TRUE;
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_emit(obj, "efl,state,entry,active", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Eina_List *items = NULL;
|
|
|
|
|
|
|
|
items = eina_list_append(items, sd->dec_button);
|
|
|
|
items = eina_list_append(items, sd->text_button);
|
|
|
|
items = eina_list_append(items, sd->ent);
|
|
|
|
items = eina_list_append(items, sd->inc_button);
|
|
|
|
|
|
|
|
efl_ui_focus_composition_elements_set(obj, items);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_toggle_cb(void *data EINA_UNUSED,
|
|
|
|
Evas_Object *obj,
|
|
|
|
const char *emission EINA_UNUSED,
|
|
|
|
const char *source EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_toggle_entry(obj);
|
|
|
|
}
|
|
|
|
|
2019-07-05 09:18:33 -07:00
|
|
|
static void
|
|
|
|
_spin_value(Efl_Ui_Spin *obj, Eina_Bool inc)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-08-01 04:55:06 -07:00
|
|
|
Efl_Ui_Spin_Button_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_BUTTON_CLASS);
|
2019-07-08 07:17:38 -07:00
|
|
|
|
2019-07-05 09:18:33 -07:00
|
|
|
int absolut_value = efl_ui_range_value_get(obj) + (inc ? pd->step : -pd->step);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2019-07-07 07:58:01 -07:00
|
|
|
_value_set(obj, absolut_value);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_inc_dec_button_clicked_cb(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS);
|
|
|
|
|
2019-07-05 08:44:36 -07:00
|
|
|
if (sd->entry_visible) _entry_value_apply(data);
|
|
|
|
|
2019-07-05 09:18:33 -07:00
|
|
|
_spin_value(data, sd->inc_button == event->object);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (_elm_config->access_mode)
|
|
|
|
_access_increment_decrement_info_say(data, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-11-30 19:05:10 -08:00
|
|
|
_text_button_focus_changed_cb(void *data, const Efl_Event *event)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2017-11-30 19:05:10 -08:00
|
|
|
if (efl_ui_focus_object_focus_get(event->object))
|
|
|
|
_toggle_entry(data);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_activated_cb(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_toggle_entry(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-11-30 19:05:10 -08:00
|
|
|
_entry_focus_changed_cb(void *data, const Efl_Event *event)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS);
|
|
|
|
|
2019-07-05 09:08:02 -07:00
|
|
|
if (efl_ui_focus_object_focus_get(event->object) && sd->entry_visible) return;
|
|
|
|
_toggle_entry(data);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_key_action_toggle(Evas_Object *obj, const char *params EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
2019-07-05 08:35:06 -07:00
|
|
|
if (sd->entry_visible) _entry_toggle_cb(NULL, obj, NULL, NULL);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2019-03-04 10:37:18 -08:00
|
|
|
_efl_ui_spin_button_efl_ui_widget_widget_input_event_handler(Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED, const Efl_Event *eo_event, Evas_Object *src EINA_UNUSED)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Eo *ev = eo_event->info;
|
|
|
|
|
|
|
|
if (efl_input_processed_get(ev)) return EINA_FALSE;
|
2019-07-05 09:18:33 -07:00
|
|
|
if (eo_event->desc == EFL_EVENT_POINTER_WHEEL)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-07-05 09:18:33 -07:00
|
|
|
_spin_value(obj, efl_input_pointer_wheel_delta_get(ev) < 0);
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
else return EINA_FALSE;
|
|
|
|
|
|
|
|
efl_input_processed_set(ev, EINA_TRUE);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-01-19 00:25:47 -08:00
|
|
|
_efl_ui_spin_button_efl_ui_focus_object_on_focus_update(Eo *obj, Efl_Ui_Spin_Button_Data *sd)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Eina_Bool int_ret = EINA_FALSE;
|
|
|
|
|
2018-01-19 00:25:47 -08:00
|
|
|
int_ret = efl_ui_focus_object_on_focus_update(efl_super(obj, MY_CLASS));
|
2017-11-20 02:12:49 -08:00
|
|
|
if (!int_ret) return EINA_FALSE;
|
|
|
|
|
2019-07-07 07:58:01 -07:00
|
|
|
if (efl_ui_focus_object_focus_get(obj))
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
if (sd->entry_reactivate)
|
|
|
|
{
|
|
|
|
_toggle_entry(obj);
|
|
|
|
|
|
|
|
sd->entry_reactivate = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
|
|
|
|
{
|
|
|
|
const char *txt = NULL;
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS);
|
|
|
|
|
|
|
|
if (sd->entry_visible)
|
|
|
|
txt = elm_object_text_get(sd->ent);
|
|
|
|
else
|
2017-12-07 21:52:08 -08:00
|
|
|
txt = efl_text_get(sd->text_button);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (txt) return strdup(txt);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
_access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
|
|
|
|
{
|
2019-08-05 05:44:51 -07:00
|
|
|
if (efl_ui_widget_disabled_get(data))
|
2017-11-20 02:12:49 -08:00
|
|
|
return strdup(E_("State: Disabled"));
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_access_activate_spin_button_cb(void *data,
|
|
|
|
Evas_Object *part_obj EINA_UNUSED,
|
|
|
|
Elm_Object_Item *item EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(data, MY_CLASS);
|
|
|
|
|
2019-08-05 05:44:51 -07:00
|
|
|
if (efl_ui_widget_disabled_get(data)) return;
|
2017-11-20 02:12:49 -08:00
|
|
|
if (!sd->entry_visible)
|
|
|
|
_toggle_entry(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_access_increment_decrement_info_say(Evas_Object *obj,
|
|
|
|
Eina_Bool is_incremented)
|
|
|
|
{
|
|
|
|
Eina_Strbuf *buf;
|
|
|
|
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
|
|
|
buf = eina_strbuf_new();
|
|
|
|
if (is_incremented)
|
|
|
|
{
|
|
|
|
elm_object_signal_emit
|
2018-04-26 04:24:09 -07:00
|
|
|
(sd->inc_button, "efl,action,anim,activate", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
eina_strbuf_append(buf, E_("incremented"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
elm_object_signal_emit
|
2018-04-26 04:24:09 -07:00
|
|
|
(sd->dec_button, "efl,action,anim,activate", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
eina_strbuf_append(buf, E_("decremented"));
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_strbuf_append_printf
|
|
|
|
(buf, "%s", elm_object_text_get(sd->text_button));
|
|
|
|
|
|
|
|
_elm_access_say(eina_strbuf_string_get(buf));
|
|
|
|
eina_strbuf_free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_access_spinner_register(Evas_Object *obj, Eina_Bool is_access)
|
|
|
|
{
|
|
|
|
Evas_Object *ao;
|
|
|
|
Elm_Access_Info *ai;
|
|
|
|
|
|
|
|
Efl_Ui_Spin_Button_Data *sd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
|
|
|
if (!is_access)
|
|
|
|
{
|
|
|
|
/* unregister access */
|
|
|
|
_elm_access_edje_object_part_object_unregister
|
|
|
|
(obj, elm_layout_edje_get(obj), "access");
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_emit(obj, "efl,state,access,inactive", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
return;
|
|
|
|
}
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_emit(obj, "efl,state,access,active", "efl");
|
2017-11-20 02:12:49 -08:00
|
|
|
ao = _elm_access_edje_object_part_object_register
|
|
|
|
(obj, elm_layout_edje_get(obj), "access");
|
|
|
|
|
|
|
|
ai = _elm_access_info_get(ao);
|
|
|
|
_elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("spinner"));
|
|
|
|
_elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, obj);
|
|
|
|
_elm_access_activate_callback_set(ai, _access_activate_spin_button_cb, obj);
|
|
|
|
|
|
|
|
/*Do not register spinner buttons if widget is disabled*/
|
2019-08-05 05:44:51 -07:00
|
|
|
if (!efl_ui_widget_disabled_get(obj))
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
ai = _elm_access_info_get(sd->inc_button);
|
|
|
|
_elm_access_text_set(ai, ELM_ACCESS_TYPE,
|
|
|
|
E_("spinner increment button"));
|
|
|
|
ai = _elm_access_info_get(sd->dec_button);
|
|
|
|
_elm_access_text_set(ai, ELM_ACCESS_TYPE,
|
|
|
|
E_("spinner decrement button"));
|
|
|
|
ai = _elm_access_info_get(sd->text_button);
|
|
|
|
_elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("spinner text"));
|
|
|
|
_elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-05 10:09:43 -07:00
|
|
|
static void
|
|
|
|
_sync_widget_theme_klass(Eo *obj, Efl_Ui_Spin_Button_Data *pd)
|
2018-08-20 21:52:28 -07:00
|
|
|
{
|
2019-07-05 10:09:43 -07:00
|
|
|
if (efl_ui_layout_orientation_is_horizontal(pd->dir, EINA_TRUE))
|
|
|
|
elm_widget_theme_klass_set(obj, "spin_button/horizontal");
|
2018-08-20 21:52:28 -07:00
|
|
|
else
|
2019-07-05 10:09:43 -07:00
|
|
|
elm_widget_theme_klass_set(obj, "spin_button/vertical");
|
2018-08-20 21:52:28 -07:00
|
|
|
}
|
|
|
|
|
2019-03-04 10:37:07 -08:00
|
|
|
EOLIAN static Eina_Error
|
2018-01-07 20:55:35 -08:00
|
|
|
_efl_ui_spin_button_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-03-04 10:37:07 -08:00
|
|
|
Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
|
2018-08-20 21:52:28 -07:00
|
|
|
|
2019-07-05 10:09:43 -07:00
|
|
|
_sync_widget_theme_klass(obj, sd);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2017-12-07 21:52:08 -08:00
|
|
|
int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
|
2019-03-04 10:36:41 -08:00
|
|
|
if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (sd->ent)
|
2018-04-25 00:43:53 -07:00
|
|
|
elm_widget_element_update(obj, sd->ent, PART_NAME_ENTRY);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (sd->inc_button)
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, sd->inc_button, PART_NAME_INC_BUTTON);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (sd->text_button)
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, sd->text_button, PART_NAME_TEXT_BUTTON);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (sd->dec_button)
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, sd->dec_button, PART_NAME_DEC_BUTTON);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
if (_elm_config->access_mode)
|
|
|
|
_access_spinner_register(obj, EINA_TRUE);
|
|
|
|
|
2017-12-07 21:52:08 -08:00
|
|
|
_label_write(obj);
|
2019-03-04 10:36:41 -08:00
|
|
|
return EFL_UI_THEME_APPLY_ERROR_NONE;
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eo *
|
2017-12-07 21:52:08 -08:00
|
|
|
_efl_ui_spin_button_efl_object_constructor(Eo *obj, Efl_Ui_Spin_Button_Data *sd)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
|
2018-08-20 21:52:28 -07:00
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
2019-07-05 10:09:43 -07:00
|
|
|
_sync_widget_theme_klass(obj, sd);
|
2019-08-01 04:55:06 -07:00
|
|
|
sd->step = 1.0;
|
2018-08-20 21:52:28 -07:00
|
|
|
|
|
|
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
|
|
|
|
|
2019-03-04 10:36:41 -08:00
|
|
|
if (elm_widget_theme_object_set(obj, wd->resize_obj,
|
|
|
|
elm_widget_theme_klass_get(obj),
|
2019-07-05 10:09:43 -07:00
|
|
|
elm_widget_theme_element_get(obj),
|
2019-03-04 10:36:41 -08:00
|
|
|
elm_widget_theme_style_get(obj)) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
|
2018-08-20 21:52:28 -07:00
|
|
|
CRI("Failed to set layout!");
|
|
|
|
|
2019-03-04 10:36:41 -08:00
|
|
|
|
2017-11-29 23:52:42 -08:00
|
|
|
sd->inc_button = efl_add(EFL_UI_BUTTON_CLASS, obj,
|
2019-07-05 08:35:06 -07:00
|
|
|
efl_ui_autorepeat_enabled_set(efl_added, EINA_TRUE),
|
|
|
|
efl_ui_autorepeat_initial_timeout_set(efl_added, _elm_config->longpress_timeout),
|
2019-07-05 09:18:33 -07:00
|
|
|
efl_ui_autorepeat_gap_timeout_set(efl_added, REPEAT_INTERVAL),
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, efl_added, PART_NAME_INC_BUTTON),
|
2017-11-29 23:52:42 -08:00
|
|
|
efl_event_callback_array_add(efl_added, _inc_dec_button_cb(), obj),
|
2018-04-26 03:27:43 -07:00
|
|
|
efl_content_set(efl_part(obj, "efl.inc_button"), efl_added));
|
2017-11-29 23:52:42 -08:00
|
|
|
|
|
|
|
sd->text_button = efl_add(EFL_UI_BUTTON_CLASS, obj,
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, efl_added, PART_NAME_TEXT_BUTTON),
|
2017-11-29 23:52:42 -08:00
|
|
|
efl_event_callback_add(efl_added, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED,
|
|
|
|
_text_button_focus_changed_cb, obj),
|
2018-04-26 03:27:43 -07:00
|
|
|
efl_content_set(efl_part(obj, "efl.text_button"), efl_added));
|
2017-11-29 23:52:42 -08:00
|
|
|
|
|
|
|
sd->dec_button = efl_add(EFL_UI_BUTTON_CLASS, obj,
|
2019-07-05 08:35:06 -07:00
|
|
|
efl_ui_autorepeat_enabled_set(efl_added, EINA_TRUE),
|
|
|
|
efl_ui_autorepeat_initial_timeout_set(efl_added, _elm_config->longpress_timeout),
|
2019-07-05 09:18:33 -07:00
|
|
|
efl_ui_autorepeat_gap_timeout_set(efl_added, REPEAT_INTERVAL),
|
2017-12-07 21:52:08 -08:00
|
|
|
elm_widget_element_update(obj, efl_added, PART_NAME_DEC_BUTTON),
|
2017-11-29 23:52:42 -08:00
|
|
|
efl_event_callback_array_add(efl_added, _inc_dec_button_cb(), obj),
|
2018-04-26 03:27:43 -07:00
|
|
|
efl_content_set(efl_part(obj, "efl.dec_button"), efl_added));
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
{
|
|
|
|
Eina_List *items = NULL;
|
|
|
|
|
|
|
|
items = eina_list_append(items, sd->dec_button);
|
|
|
|
items = eina_list_append(items, sd->text_button);
|
|
|
|
items = eina_list_append(items, sd->inc_button);
|
|
|
|
|
|
|
|
efl_ui_focus_composition_elements_set(obj, items);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-05 05:44:51 -07:00
|
|
|
efl_layout_signal_callback_add
|
|
|
|
(obj, "efl,action,entry,toggle", "*", _entry_toggle_cb, NULL, NULL);
|
|
|
|
|
|
|
|
efl_ui_widget_focus_allow_set(obj, EINA_TRUE);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
2018-04-03 04:27:30 -07:00
|
|
|
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_SPIN_BUTTON);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2018-08-20 21:52:28 -07:00
|
|
|
EOLIAN static void
|
2019-05-24 09:30:31 -07:00
|
|
|
_efl_ui_spin_button_efl_ui_layout_orientable_orientation_set(Eo *obj, Efl_Ui_Spin_Button_Data *sd, Efl_Ui_Layout_Orientation dir)
|
2018-08-20 21:52:28 -07:00
|
|
|
{
|
2018-08-20 22:04:58 -07:00
|
|
|
if (sd->dir == dir) return;
|
|
|
|
|
2018-08-20 21:52:28 -07:00
|
|
|
sd->dir = dir;
|
|
|
|
|
|
|
|
efl_ui_widget_theme_apply(obj);
|
|
|
|
}
|
|
|
|
|
2019-05-24 09:30:31 -07:00
|
|
|
EOLIAN static Efl_Ui_Layout_Orientation
|
|
|
|
_efl_ui_spin_button_efl_ui_layout_orientable_orientation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd)
|
2018-08-20 21:52:28 -07:00
|
|
|
{
|
|
|
|
return sd->dir;
|
|
|
|
}
|
|
|
|
|
2017-11-20 02:12:49 -08:00
|
|
|
EOLIAN static void
|
2019-01-21 07:22:32 -08:00
|
|
|
_efl_ui_spin_button_efl_ui_range_display_range_value_set(Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED, double val)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
efl_ui_range_value_set(efl_super(obj, MY_CLASS), val);
|
|
|
|
|
|
|
|
_label_write(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-08-25 22:21:10 -07:00
|
|
|
_efl_ui_spin_button_direct_text_input_set(Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd, Eina_Bool editable)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
sd->editable = editable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2019-08-25 22:21:10 -07:00
|
|
|
_efl_ui_spin_button_direct_text_input_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
return sd->editable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-07-31 09:06:43 -07:00
|
|
|
_efl_ui_spin_button_wraparound_set(Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd, Eina_Bool wraparound)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-07-31 09:06:43 -07:00
|
|
|
sd->wraparound = wraparound;
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2019-07-31 09:06:43 -07:00
|
|
|
_efl_ui_spin_button_wraparound_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
2019-07-31 09:06:43 -07:00
|
|
|
return sd->wraparound;
|
2017-11-20 02:12:49 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const Efl_Access_Action_Data *
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_ui_spin_button_efl_access_widget_action_elm_actions_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
static Efl_Access_Action_Data atspi_actions[] = {
|
|
|
|
{ "toggle", "toggle", NULL, _key_action_toggle},
|
|
|
|
{ NULL, NULL, NULL, NULL }
|
|
|
|
};
|
|
|
|
return &atspi_actions[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
// A11Y Accessibility
|
|
|
|
|
|
|
|
EOLIAN static void
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_ui_spin_button_efl_access_value_value_and_text_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED, double *value, const char **text)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS);
|
|
|
|
|
|
|
|
if (value) *value = pd->val;
|
|
|
|
if (text) *text = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_ui_spin_button_efl_access_value_value_and_text_set(Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED, double value, const char *text EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS);
|
|
|
|
|
|
|
|
if (pd->val_min > value) return EINA_FALSE;
|
|
|
|
if (pd->val_max < value) return EINA_FALSE;
|
|
|
|
|
2019-08-01 04:29:06 -07:00
|
|
|
efl_ui_range_value_set(obj, value);
|
2017-11-20 02:12:49 -08:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_ui_spin_button_efl_access_value_range_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED, double *lower, double *upper, const char **descr)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
Efl_Ui_Spin_Data *pd = efl_data_scope_get(obj, EFL_UI_SPIN_CLASS);
|
|
|
|
|
|
|
|
if (lower) *lower = pd->val_min;
|
|
|
|
if (upper) *upper = pd->val_max;
|
|
|
|
if (descr) *descr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static double
|
2019-08-01 04:55:06 -07:00
|
|
|
_efl_ui_spin_button_efl_access_value_increment_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *pd)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
return pd->step;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const char*
|
2018-04-03 04:27:30 -07:00
|
|
|
_efl_ui_spin_button_efl_access_object_i18n_name_get(const Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED)
|
2017-11-20 02:12:49 -08:00
|
|
|
{
|
|
|
|
const char *name;
|
2018-04-03 04:27:30 -07:00
|
|
|
name = efl_access_object_i18n_name_get(efl_super(obj, EFL_UI_SPIN_BUTTON_CLASS));
|
2017-11-20 02:12:49 -08:00
|
|
|
if (name) return name;
|
2018-04-26 03:27:43 -07:00
|
|
|
const char *ret = elm_layout_text_get(obj, "efl.text");
|
2017-11-20 02:12:49 -08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-08-01 04:35:53 -07:00
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_spin_button_efl_ui_format_apply_formatted_value(Eo *obj, Efl_Ui_Spin_Button_Data *sd EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_label_write(obj);
|
|
|
|
efl_canvas_group_change(obj);
|
|
|
|
}
|
|
|
|
|
2019-08-01 04:55:06 -07:00
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_spin_button_efl_ui_range_interactive_range_step_set(Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd, double step)
|
|
|
|
{
|
|
|
|
if (step <= 0)
|
|
|
|
{
|
|
|
|
ERR("Wrong param. The step(%lf) should be bigger than 0.0", step);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sd->step = step;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static double
|
|
|
|
_efl_ui_spin_button_efl_ui_range_interactive_range_step_get(const Eo *obj EINA_UNUSED, Efl_Ui_Spin_Button_Data *sd)
|
|
|
|
{
|
|
|
|
return sd->step;
|
|
|
|
}
|
|
|
|
|
2017-11-20 02:12:49 -08:00
|
|
|
// A11Y Accessibility - END
|
|
|
|
|
|
|
|
#include "efl_ui_spin_button.eo.c"
|