2018-05-02 01:23:25 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "elementary_config.h"
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
|
|
2018-05-02 01:23:25 -07:00
|
|
|
#include <Elementary.h>
|
|
|
|
#include "elm_priv.h"
|
|
|
|
#include "efl_ui_tags_private.h"
|
2019-03-05 14:00:37 -08:00
|
|
|
#include "elm_entry_eo.h"
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
#define MY_CLASS EFL_UI_TAGS_CLASS
|
|
|
|
|
|
|
|
#define MY_CLASS_NAME "Efl.Ui.Tags"
|
|
|
|
|
|
|
|
#define MIN_W_ENTRY 10
|
|
|
|
|
|
|
|
static const char PART_NAME_BUTTON[] = "btn";
|
|
|
|
static const char PART_NAME_LABEL[] = "label";
|
|
|
|
static const char PART_NAME_NUMBER[] = "number";
|
|
|
|
|
|
|
|
static Eina_Bool _efl_ui_tags_smart_focus_direction_enable = EINA_TRUE;
|
|
|
|
|
|
|
|
static void _entry_changed_cb(void *data, const Efl_Event *event);
|
|
|
|
static void _entry_focus_changed_cb(void *data, const Efl_Event *event);
|
|
|
|
static void _entry_clicked_cb(void *data, const Efl_Event *event);
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_tags_cb,
|
|
|
|
{ ELM_ENTRY_EVENT_CHANGED, _entry_changed_cb },
|
|
|
|
{ EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED , _entry_focus_changed_cb },
|
2019-07-29 02:42:34 -07:00
|
|
|
{ EFL_INPUT_EVENT_CLICKED, _entry_clicked_cb }
|
2018-05-02 01:23:25 -07:00
|
|
|
);
|
|
|
|
|
|
|
|
static void
|
|
|
|
_shrink_mode_set(Eo *obj,
|
|
|
|
Eina_Bool shrink)
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (!sd->layouts) return;
|
|
|
|
if (sd->view_state == TAGS_VIEW_ENTRY)
|
|
|
|
evas_object_hide(sd->entry);
|
|
|
|
else if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
evas_object_hide(sd->end);
|
|
|
|
|
|
|
|
if (shrink == EINA_TRUE)
|
|
|
|
{
|
|
|
|
Evas_Coord w = 0;
|
2019-10-02 03:04:12 -07:00
|
|
|
unsigned int box_inner_item_width_padding = 0;
|
2018-05-02 01:23:25 -07:00
|
|
|
Eina_Value val;
|
|
|
|
|
2019-10-02 03:04:12 -07:00
|
|
|
efl_gfx_arrangement_content_padding_get(sd->box, &box_inner_item_width_padding, NULL);
|
2018-05-02 01:23:25 -07:00
|
|
|
// unpack all items and entry
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack_all(sd->box);
|
2018-05-02 01:23:25 -07:00
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
{
|
|
|
|
evas_object_hide(layout);
|
|
|
|
}
|
|
|
|
// pack buttons only 1line
|
|
|
|
w = sd->w_box;
|
|
|
|
|
|
|
|
if (sd->label && sd->label_packed)
|
|
|
|
{
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
Eina_Size2D label_min =
|
2019-02-21 09:19:45 -08:00
|
|
|
efl_gfx_hint_size_combined_min_get(sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
w -= label_min.w;
|
2019-10-02 03:04:12 -07:00
|
|
|
w -= (Evas_Coord)box_inner_item_width_padding;
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
layout = NULL;
|
|
|
|
count = eina_list_count(sd->layouts);
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
{
|
|
|
|
Evas_Coord w_label_count = 0, h = 0;
|
|
|
|
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_show(layout);
|
|
|
|
|
|
|
|
Eina_Size2D item_min =
|
2019-02-21 09:19:45 -08:00
|
|
|
efl_gfx_hint_size_combined_min_get(layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
w -= item_min.w;
|
|
|
|
w -= box_inner_item_width_padding;
|
|
|
|
count--;
|
|
|
|
|
|
|
|
eina_value_setup(&val, EINA_VALUE_TYPE_INT);
|
|
|
|
|
|
|
|
if (count > 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
|
|
|
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);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
edje_object_size_min_calc(sd->end, &w_label_count, NULL);
|
|
|
|
elm_coords_finger_size_adjust(1, &w_label_count, 1, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((w < 0) || (w < w_label_count))
|
|
|
|
{
|
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();
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack(sd->box, layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_hide(layout);
|
|
|
|
count++;
|
|
|
|
|
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_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);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
edje_object_size_min_calc(sd->end, &w_label_count, &h);
|
|
|
|
elm_coords_finger_size_adjust(1, &w_label_count, 1, &h);
|
2019-08-01 06:20:34 -07:00
|
|
|
efl_gfx_hint_size_min_set(sd->end, EINA_SIZE2D(w_label_count, h));
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, sd->end);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_show(sd->end);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd->view_state != TAGS_VIEW_SHRINK)
|
|
|
|
{
|
|
|
|
sd->view_state = TAGS_VIEW_SHRINK;
|
|
|
|
efl_event_callback_call
|
2019-03-19 13:31:45 -07:00
|
|
|
(obj, EFL_UI_TAGS_EVENT_EXPAND_STATE_CHANGED, &shrink);
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
eina_value_flush(&val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// unpack all items and entry
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack_all(sd->box);
|
2018-05-02 01:23:25 -07:00
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
{
|
|
|
|
evas_object_hide(layout);
|
|
|
|
}
|
|
|
|
evas_object_hide(sd->end);
|
|
|
|
|
|
|
|
// pack buttons only 1line
|
|
|
|
|
2019-07-31 11:02:47 -07:00
|
|
|
if (sd->label && sd->label_packed) efl_pack(sd->box, sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
// pack remain btns
|
|
|
|
layout = NULL;
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
{
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_show(layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
{
|
|
|
|
sd->view_state = TAGS_VIEW_NONE;
|
|
|
|
efl_event_callback_call
|
2019-03-19 13:31:45 -07:00
|
|
|
(obj, EFL_UI_TAGS_EVENT_EXPAND_STATE_CHANGED, &shrink);
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
_efl_ui_tags_smart_focus_direction_enable = EINA_FALSE;
|
|
|
|
else
|
|
|
|
_efl_ui_tags_smart_focus_direction_enable = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_view_update(Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
Eo *obj = sd->parent;
|
|
|
|
|
|
|
|
if (sd->w_box <= 0) return;
|
|
|
|
|
|
|
|
// update buttons in shrink mode
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
_shrink_mode_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_current_item_state_change(Evas_Object *obj, Tags_It_State state)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
Eo *item = sd->selected_it;
|
|
|
|
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case TAGS_IT_STATE_SELECTED:
|
|
|
|
elm_layout_signal_emit(item, "efl,state,focused", "efl");
|
|
|
|
efl_event_callback_call
|
|
|
|
(obj, EFL_UI_TAGS_EVENT_ITEM_SELECTED, (void *)elm_object_part_text_get(item, "efl.btn.text"));
|
|
|
|
break;
|
|
|
|
case TAGS_IT_STATE_DEFAULT:
|
|
|
|
default:
|
|
|
|
elm_layout_signal_emit(item, "efl,state,default", "efl");
|
|
|
|
sd->selected_it = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_current_item_change(Evas_Object *obj, Evas_Object *it)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
// change the state of previous item to "default"
|
|
|
|
_current_item_state_change(obj, TAGS_IT_STATE_DEFAULT);
|
|
|
|
|
|
|
|
// change the current
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
{
|
|
|
|
if (layout == it)
|
|
|
|
{
|
|
|
|
sd->selected_it = it;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// change the state of current item to "focused"
|
|
|
|
_current_item_state_change(obj, TAGS_IT_STATE_SELECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_item_select(Evas_Object *obj, Evas_Object *it)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (it)
|
|
|
|
{
|
|
|
|
_current_item_change(obj, it);
|
|
|
|
|
|
|
|
if (efl_ui_focus_object_focus_get(obj))
|
|
|
|
{
|
|
|
|
elm_object_focus_set(sd->entry, EINA_FALSE);
|
|
|
|
elm_object_focus_set(it, EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_current_item_state_change
|
|
|
|
(obj, TAGS_IT_STATE_DEFAULT);
|
|
|
|
if (efl_ui_focus_object_focus_get(obj) && sd->editable)
|
|
|
|
elm_object_focus_set(sd->entry, EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_long_press_cb(void *data)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
sd->longpress_timer = NULL;
|
|
|
|
|
|
|
|
efl_event_callback_call
|
|
|
|
(data, EFL_UI_TAGS_EVENT_ITEM_LONGPRESSED,
|
|
|
|
(void *)elm_object_part_text_get(sd->downed_it, "efl.btn.text"));
|
|
|
|
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_mouse_down_cb(void *data,
|
|
|
|
Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *obj,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Evas_Event_Mouse_Down *ev = event_info;
|
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (ev->button != 1) return;
|
|
|
|
|
|
|
|
ecore_timer_del(sd->longpress_timer);
|
|
|
|
sd->downed_it = obj;
|
|
|
|
sd->longpress_timer = ecore_timer_add
|
|
|
|
(_elm_config->longpress_timeout, _long_press_cb, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_mouse_up_cb(void *data,
|
|
|
|
Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
sd->downed_it = NULL;
|
|
|
|
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_on_item_focused(void *data,
|
|
|
|
Evas_Object *obj,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
sd->focused_it = obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_on_item_unfocused(void *data,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
sd->focused_it = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_on_item_deleted(void *data,
|
|
|
|
Evas_Object *obj,
|
|
|
|
const char *emission EINA_UNUSED,
|
|
|
|
const char *source EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *item;
|
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
// change the current
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, item)
|
|
|
|
{
|
|
|
|
if (item == obj)
|
|
|
|
{
|
|
|
|
sd->layouts = eina_list_remove(sd->layouts, item);
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack(sd->box, item);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
if (sd->selected_it == item)
|
|
|
|
sd->selected_it = NULL;
|
|
|
|
|
|
|
|
if (sd->focused_it == item)
|
|
|
|
sd->focused_it = NULL;
|
|
|
|
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
_shrink_mode_set(data, EINA_TRUE);
|
|
|
|
|
|
|
|
if (!sd->item_setting)
|
|
|
|
efl_event_callback_call
|
|
|
|
(data, EFL_UI_TAGS_EVENT_ITEM_DELETED,
|
|
|
|
(void *)elm_object_part_text_get(obj, "efl.btn.text"));
|
|
|
|
|
|
|
|
efl_del(item);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_on_item_clicked(void *data,
|
|
|
|
Evas_Object *obj,
|
|
|
|
const char *emission EINA_UNUSED,
|
|
|
|
const char *source EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
_item_select(data, obj);
|
|
|
|
|
|
|
|
if (sd->selected_it)
|
|
|
|
efl_event_callback_call
|
|
|
|
(data, EFL_UI_TAGS_EVENT_ITEM_CLICKED, (void *)elm_object_part_text_get(obj, "efl.btn.text"));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eo *
|
|
|
|
_item_new(Efl_Ui_Tags_Data *sd,
|
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
Evas_Object *obj;
|
|
|
|
Eina_Size2D min;
|
|
|
|
Eina_Rect r;
|
|
|
|
Eo *layout;
|
|
|
|
|
|
|
|
obj = sd->parent;
|
|
|
|
|
|
|
|
if (!str) return NULL;
|
|
|
|
|
2018-11-16 01:45:05 -08:00
|
|
|
layout = efl_add(EFL_UI_LAYOUT_CLASS, obj);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-03-04 10:36:41 -08:00
|
|
|
if (elm_widget_element_update(obj, layout, PART_NAME_BUTTON) == EFL_UI_THEME_APPLY_ERROR_GENERIC)
|
2018-05-02 01:23:25 -07:00
|
|
|
CRI("Failed to set layout!");
|
|
|
|
|
|
|
|
efl_text_set(efl_part(layout, "efl.btn.text"), str);
|
|
|
|
|
|
|
|
//entry is cleared when text is made to button
|
|
|
|
efl_text_set(sd->entry, "");
|
|
|
|
|
|
|
|
elm_layout_signal_callback_add
|
|
|
|
(layout, "mouse,clicked,1", "*", _on_item_clicked, obj);
|
|
|
|
elm_layout_signal_callback_add
|
|
|
|
(layout, "efl,deleted", "efl", _on_item_deleted, obj);
|
|
|
|
evas_object_smart_callback_add
|
|
|
|
(layout, "focused", _on_item_focused, obj);
|
|
|
|
evas_object_smart_callback_add
|
|
|
|
(layout, "unfocused", _on_item_unfocused, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(layout,
|
|
|
|
EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(layout,
|
|
|
|
EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
|
|
|
|
|
2019-02-21 09:19:45 -08:00
|
|
|
efl_gfx_hint_align_set(layout, 0.5, 0.5);
|
|
|
|
efl_gfx_hint_weight_set(layout, 0.0, 0.0);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
evas_object_show(layout);
|
|
|
|
|
|
|
|
evas_object_smart_calculate(layout);
|
2019-02-21 09:19:45 -08:00
|
|
|
min = efl_gfx_hint_size_combined_min_get(layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
r = efl_gfx_entity_geometry_get(sd->box);
|
|
|
|
|
|
|
|
if (sd->w_box && min.w > r.w)
|
|
|
|
{
|
|
|
|
elm_coords_finger_size_adjust(1, &r.w, 1, &min.h);
|
2019-08-01 06:20:34 -07:00
|
|
|
efl_gfx_hint_size_min_set(layout, EINA_SIZE2D(r.w, min.h));
|
2018-05-02 01:23:25 -07:00
|
|
|
efl_gfx_entity_size_set(layout, EINA_SIZE2D(r.w, min.h));
|
|
|
|
}
|
|
|
|
|
|
|
|
elm_object_focus_allow_set(layout, EINA_TRUE);
|
|
|
|
|
|
|
|
sd->layouts = eina_list_append(sd->layouts, layout);
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
{
|
|
|
|
elm_widget_sub_object_add(obj, layout);
|
|
|
|
evas_object_hide(layout);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (sd->editable)
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_before(sd->box, layout, sd->entry);
|
2018-05-02 01:23:25 -07:00
|
|
|
else
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!efl_ui_focus_object_focus_get(obj) && sd->view_state == TAGS_VIEW_SHRINK && sd->w_box)
|
|
|
|
_shrink_mode_set(obj, EINA_TRUE);
|
|
|
|
|
|
|
|
if (!sd->item_setting)
|
|
|
|
efl_event_callback_call
|
|
|
|
(obj, EFL_UI_TAGS_EVENT_ITEM_ADDED, (void *)elm_object_part_text_get(layout, "efl.btn.text"));
|
|
|
|
|
|
|
|
return layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME: having an empty event handling function and reacting on Evas
|
|
|
|
//events on specific objects is crazy, someone should fix that.
|
|
|
|
EOLIAN static Eina_Bool
|
2019-03-04 10:37:18 -08:00
|
|
|
_efl_ui_tags_efl_ui_widget_widget_input_event_handler(Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd EINA_UNUSED, const Efl_Event *eo_event EINA_UNUSED, Evas_Object *src EINA_UNUSED)
|
2018-05-02 01:23:25 -07:00
|
|
|
{
|
|
|
|
//lets stop eating all events
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_mouse_clicked_signal_cb(void *data EINA_UNUSED,
|
|
|
|
Evas_Object *obj,
|
|
|
|
const char *emission EINA_UNUSED,
|
|
|
|
const char *source EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
Efl.Ui.Text : all related interfaces
Summary:
Change summary:
Removed :
- efl_ui_text_selectable.eo and add it functionality into efl_text_interactive.eo
- efl_ui_text_editable.eo because it is same as efl_ui_text.eo (just set one property by default)
Modifications:
- Move all Text Input enums and functionality from efl_ui_text class into its own interface, this interface will be implemented at efl_ui_internal_text_interactive class.
- Rename selection_allowed property to selectable (same as other "editable" property) in efl_text_interactive
- Add select_all function into efl_text_interactive interface
- Add have_selection property into efl_text_interactive interface
- Move user_change , selection_start/change/clear and undo/redo events into efl_text_interactive interface.
- Move methods and events of copy/paste/cut into efl_ui_text
- Fix password-related functionality
- Remove context menu clear and add_item methods. (these should be added later with better design)
- Remove Validation event from EFL_UI_TEXT. (these should be added later with better design)
Reviewers: woohyun, tasn, segfaultxavi, zmike, bu5hm4n
Subscribers: stefan_schmidt, a.srour, q66, zmike, segfaultxavi, cedric
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D10711
2019-12-08 17:58:39 -08:00
|
|
|
if (sd->editable) efl_input_text_input_panel_show(sd->entry);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
efl_event_callback_call(obj, EFL_INPUT_EVENT_CLICKED, NULL);
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_box_resize_cb(void *data,
|
|
|
|
Evas *evas EINA_UNUSED,
|
|
|
|
Evas_Object *obj,
|
|
|
|
void *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eina_Size2D min;
|
|
|
|
Eina_Rect r;
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
2019-10-02 03:04:12 -07:00
|
|
|
unsigned int hpad;
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
r = efl_gfx_entity_geometry_get(sd->box);
|
|
|
|
if ((r.w <= elm_config_finger_size_get()) || (r.h <= elm_config_finger_size_get())) return;
|
|
|
|
|
2019-10-02 03:04:12 -07:00
|
|
|
efl_gfx_arrangement_content_padding_get(obj, &hpad, NULL);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
if (sd->h_box < r.h)
|
|
|
|
efl_event_callback_call
|
|
|
|
(sd->parent, EFL_UI_TAGS_EVENT_EXPANDED, NULL);
|
|
|
|
else if (sd->h_box > r.h)
|
|
|
|
efl_event_callback_call
|
|
|
|
(sd->parent, EFL_UI_TAGS_EVENT_CONTRACTED, NULL);
|
|
|
|
|
|
|
|
if (sd->layouts && sd->w_box != r.w)
|
|
|
|
{
|
|
|
|
EINA_LIST_FOREACH (sd->layouts, l, layout)
|
|
|
|
{
|
2019-07-30 10:11:19 -07:00
|
|
|
efl_canvas_group_calculate(layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-02-21 09:19:45 -08:00
|
|
|
min = efl_gfx_hint_size_combined_min_get(layout);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-10-02 03:04:12 -07:00
|
|
|
if (min.w > r.w - (int)hpad)
|
2018-05-02 01:23:25 -07:00
|
|
|
{
|
2019-10-02 03:04:12 -07:00
|
|
|
min.w = r.w - (int)hpad;
|
2019-08-01 06:20:34 -07:00
|
|
|
efl_gfx_hint_size_min_set(layout, EINA_SIZE2D(min.w, min.h));
|
2018-05-02 01:23:25 -07:00
|
|
|
efl_gfx_entity_size_set(layout, EINA_SIZE2D(min.w, min.h));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sd->w_box = r.w;
|
|
|
|
sd->h_box = r.h;
|
|
|
|
|
|
|
|
if (sd->view_state == TAGS_VIEW_SHRINK)
|
|
|
|
_shrink_mode_set(data, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_resize_cb(void *data,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (efl_ui_focus_object_focus_get(sd->parent))
|
|
|
|
elm_widget_show_region_set(sd->entry, efl_gfx_entity_geometry_get(sd->entry), EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
str = efl_text_get(sd->entry);
|
|
|
|
sd->n_str = str ? strlen(str) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_focus_changed_cb(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (efl_ui_focus_object_focus_get(event->object))
|
|
|
|
{
|
|
|
|
Eo *item;
|
|
|
|
|
|
|
|
if (sd->selected_it)
|
|
|
|
{
|
|
|
|
item = sd->selected_it;
|
|
|
|
elm_object_focus_set(sd->entry, EINA_FALSE);
|
|
|
|
elm_object_focus_set(item, EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
str = efl_text_get(sd->entry);
|
|
|
|
if (str && str[0])
|
|
|
|
_item_new(sd, str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_clicked_cb(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
_current_item_state_change(sd->parent, TAGS_IT_STATE_DEFAULT);
|
|
|
|
elm_object_focus_set(sd->entry, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_layout_key_down_cb(void *data,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
|
|
|
|
|
|
|
|
if (!sd->box) return;
|
|
|
|
|
|
|
|
if (sd->last_it_select)
|
|
|
|
{
|
|
|
|
if (sd->selected_it &&
|
|
|
|
((!strcmp(ev->key, "BackSpace")) ||
|
|
|
|
(!strcmp(ev->key, "Delete"))))
|
|
|
|
{
|
|
|
|
Eo *item = sd->selected_it;
|
|
|
|
if (item && sd->editable)
|
|
|
|
{
|
|
|
|
_on_item_deleted(data, item, NULL, NULL);
|
|
|
|
elm_object_focus_set(sd->entry, EINA_TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sd->focused_it &&
|
|
|
|
((!strcmp(ev->key, "KP_Enter")) ||
|
|
|
|
(!strcmp(ev->key, "Return"))))
|
|
|
|
{
|
|
|
|
Eo *item = sd->focused_it;
|
|
|
|
if (item)
|
|
|
|
_on_item_clicked(item, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
else if (((!sd->selected_it && (sd->n_str == 0) &&
|
|
|
|
(!strcmp(ev->key, "BackSpace"))) ||
|
|
|
|
(!strcmp(ev->key, "Delete"))))
|
|
|
|
{
|
|
|
|
Eo *item = eina_list_data_get(eina_list_last(sd->layouts));
|
|
|
|
if (item)
|
|
|
|
{
|
|
|
|
_item_select(sd->parent, item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sd->last_it_select = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_key_down_cb(void *data,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
|
|
|
|
|
|
|
|
if (sd->n_str == 1 &&
|
|
|
|
(!strcmp(ev->key, "BackSpace") || !strcmp(ev->key, "Delete")))
|
|
|
|
sd->last_it_select = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_entry_key_up_cb(void *data,
|
|
|
|
Evas *e EINA_UNUSED,
|
|
|
|
Evas_Object *obj EINA_UNUSED,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
if (!sd->box) return;
|
|
|
|
|
|
|
|
str = efl_text_get(sd->entry);
|
|
|
|
if (!str) return;
|
|
|
|
|
|
|
|
if (strlen(str) &&
|
|
|
|
(!strcmp(ev->key, "KP_Enter") || !strcmp(ev->key, "Return")))
|
|
|
|
{
|
|
|
|
_item_new(sd, str);
|
|
|
|
sd->n_str = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_callbacks_register(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
|
|
|
|
|
|
|
|
elm_layout_signal_callback_add
|
|
|
|
(obj, "mouse,clicked,1", "*", _mouse_clicked_signal_cb, NULL);
|
|
|
|
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(wd->resize_obj, EVAS_CALLBACK_KEY_DOWN,
|
|
|
|
_layout_key_down_cb, obj);
|
|
|
|
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->box, EVAS_CALLBACK_RESIZE, _box_resize_cb, obj);
|
|
|
|
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->entry, EVAS_CALLBACK_RESIZE, _entry_resize_cb, obj);
|
|
|
|
efl_event_callback_array_add(sd->entry, _tags_cb(), obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_label_set(Evas_Object *obj,
|
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
Evas_Coord width, height;
|
|
|
|
|
|
|
|
Efl_Ui_Tags_Data *sd = efl_data_scope_get(obj, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
if (!str) return;
|
|
|
|
|
|
|
|
eina_stringshare_replace(&sd->label_str, str);
|
|
|
|
|
|
|
|
edje_object_part_text_escaped_set(sd->label, "efl.text", str);
|
|
|
|
|
|
|
|
if (!strlen(str))
|
|
|
|
{
|
|
|
|
sd->label_packed = EINA_FALSE;
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack(sd->box, sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_hide(sd->label);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (sd->label_packed)
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack(sd->box, sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
sd->label_packed = EINA_TRUE;
|
|
|
|
edje_object_size_min_calc(sd->label, &width, &height);
|
2019-08-05 06:13:05 -07:00
|
|
|
efl_gfx_hint_size_min_set(sd->label, EINA_SIZE2D(width, height));
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_begin(sd->box, sd->label);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_show(sd->label);
|
|
|
|
}
|
|
|
|
|
|
|
|
_view_update(sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_view_init(Evas_Object *obj, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
int hpad = 0, vpad = 0;
|
|
|
|
|
|
|
|
//FIXME: efl_ui_box doesn't support box_layout customizing.
|
|
|
|
// So i use legacy box here.
|
2019-07-31 11:02:47 -07:00
|
|
|
sd->box = efl_add(EFL_UI_BOX_FLOW_CLASS, obj,
|
|
|
|
efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL),
|
|
|
|
efl_gfx_arrangement_content_align_set(efl_added, 0, 0),
|
|
|
|
efl_gfx_hint_align_set(efl_added, 0, 0));
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
if (!sd->box) return;
|
|
|
|
|
|
|
|
str = elm_layout_data_get(obj, "horizontal_pad");
|
|
|
|
if (str) hpad = atoi(str);
|
|
|
|
str = elm_layout_data_get(obj, "vertical_pad");
|
|
|
|
if (str) vpad = atoi(str);
|
2019-10-02 03:04:12 -07:00
|
|
|
efl_gfx_arrangement_content_padding_set(sd->box, hpad, vpad);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_content_set(efl_part(obj, "efl.box"), sd->box);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
sd->label = edje_object_add(evas_object_evas_get(obj));
|
|
|
|
if (!sd->label) return;
|
|
|
|
elm_widget_element_update(obj, sd->label, PART_NAME_LABEL);
|
|
|
|
|
2019-12-10 16:47:50 -08:00
|
|
|
sd->entry = efl_add(EFL_UI_TEXTBOX_CLASS, sd->box,
|
2018-05-02 01:23:25 -07:00
|
|
|
efl_text_multiline_set(efl_added, EINA_FALSE),
|
|
|
|
efl_text_set(efl_added, ""),
|
2020-01-19 04:58:26 -08:00
|
|
|
efl_ui_textbox_cnp_dnd_mode_set(efl_added, EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP),
|
Efl.Ui.Text : all related interfaces
Summary:
Change summary:
Removed :
- efl_ui_text_selectable.eo and add it functionality into efl_text_interactive.eo
- efl_ui_text_editable.eo because it is same as efl_ui_text.eo (just set one property by default)
Modifications:
- Move all Text Input enums and functionality from efl_ui_text class into its own interface, this interface will be implemented at efl_ui_internal_text_interactive class.
- Rename selection_allowed property to selectable (same as other "editable" property) in efl_text_interactive
- Add select_all function into efl_text_interactive interface
- Add have_selection property into efl_text_interactive interface
- Move user_change , selection_start/change/clear and undo/redo events into efl_text_interactive interface.
- Move methods and events of copy/paste/cut into efl_ui_text
- Fix password-related functionality
- Remove context menu clear and add_item methods. (these should be added later with better design)
- Remove Validation event from EFL_UI_TEXT. (these should be added later with better design)
Reviewers: woohyun, tasn, segfaultxavi, zmike, bu5hm4n
Subscribers: stefan_schmidt, a.srour, q66, zmike, segfaultxavi, cedric
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D10711
2019-12-08 17:58:39 -08:00
|
|
|
efl_input_text_input_panel_autoshow_set(efl_added, EINA_FALSE),
|
2018-05-02 01:23:25 -07:00
|
|
|
efl_text_interactive_editable_set(efl_added, EINA_TRUE),
|
|
|
|
efl_composite_attach(obj, efl_added));
|
|
|
|
|
2019-08-01 06:20:34 -07:00
|
|
|
efl_gfx_hint_size_min_set(sd->entry, EINA_SIZE2D(MIN_W_ENTRY, 0));
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_gfx_hint_weight_set(sd->entry, EFL_GFX_HINT_EXPAND, 0);
|
2019-08-01 10:34:18 -07:00
|
|
|
efl_gfx_hint_fill_set(sd->entry, EINA_TRUE, EINA_TRUE);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, sd->entry);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
sd->view_state = TAGS_VIEW_ENTRY;
|
|
|
|
|
|
|
|
{
|
|
|
|
Evas_Coord button_min_width = 0, button_min_height = 0;
|
|
|
|
|
|
|
|
sd->end = edje_object_add(evas_object_evas_get(obj));
|
|
|
|
if (!sd->end) return;
|
|
|
|
elm_widget_element_update(obj, sd->end, PART_NAME_NUMBER);
|
|
|
|
|
|
|
|
edje_object_size_min_calc(sd->end, &button_min_width, &button_min_height);
|
|
|
|
elm_coords_finger_size_adjust(1, &button_min_width, 1, &button_min_height);
|
2019-08-01 06:20:34 -07:00
|
|
|
efl_gfx_hint_size_min_set(sd->end, EINA_SIZE2D(button_min_width, button_min_height));
|
2018-05-02 01:23:25 -07:00
|
|
|
elm_widget_sub_object_add(obj, sd->end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_legacy_focused(void *data, const Efl_Event *ev)
|
|
|
|
{
|
|
|
|
Efl_Ui_Focus_Object *new_focus;
|
|
|
|
Eina_Bool meaningful_focus_in = EINA_FALSE, meaningful_focus_out = EINA_FALSE;
|
|
|
|
Efl_Ui_Tags_Data *pd = efl_data_scope_get(data, EFL_UI_TAGS_CLASS);
|
|
|
|
|
|
|
|
new_focus = efl_ui_focus_manager_focus_get(ev->object);
|
|
|
|
|
|
|
|
if (efl_isa(ev->info, EFL_UI_WIDGET_CLASS) && elm_widget_parent_get(ev->info) == pd->box)
|
|
|
|
{
|
|
|
|
meaningful_focus_out = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (efl_isa(new_focus, EFL_UI_WIDGET_CLASS) && elm_widget_parent_get(new_focus) == pd->box)
|
|
|
|
{
|
|
|
|
meaningful_focus_in = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (meaningful_focus_in && !meaningful_focus_out)
|
|
|
|
{
|
|
|
|
evas_object_smart_callback_call(data, "focused", NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!meaningful_focus_in && meaningful_focus_out)
|
|
|
|
{
|
|
|
|
evas_object_smart_callback_call(data, "unfocused", NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_legacy_manager_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
|
|
|
|
{
|
2019-02-17 08:21:58 -08:00
|
|
|
efl_event_callback_del(ev->info, EFL_UI_FOCUS_MANAGER_EVENT_MANAGER_FOCUS_CHANGED, _legacy_focused, ev->object);
|
|
|
|
efl_event_callback_add(efl_ui_focus_object_focus_manager_get(ev->object), EFL_UI_FOCUS_MANAGER_EVENT_MANAGER_FOCUS_CHANGED, _legacy_focused, ev->object);
|
2018-05-02 01:23:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eo *
|
|
|
|
_efl_ui_tags_efl_object_constructor(Eo *obj, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
|
|
|
|
|
|
|
|
if (!elm_widget_theme_klass_get(obj))
|
|
|
|
elm_widget_theme_klass_set(obj, "tags");
|
|
|
|
|
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
|
|
|
|
2019-03-04 10:36:41 -08:00
|
|
|
if (elm_widget_theme_object_set(obj, wd->resize_obj,
|
2018-05-02 01:23:25 -07:00
|
|
|
elm_widget_theme_klass_get(obj),
|
|
|
|
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-05-02 01:23:25 -07:00
|
|
|
CRI("Failed to set layout!");
|
|
|
|
|
|
|
|
elm_widget_can_focus_set(obj, EINA_FALSE);
|
|
|
|
|
|
|
|
sd->last_it_select = EINA_TRUE;
|
|
|
|
sd->editable = EINA_TRUE;
|
|
|
|
sd->parent = obj;
|
|
|
|
sd->it_array = eina_array_new(4);
|
|
|
|
|
|
|
|
_view_init(obj, sd);
|
|
|
|
_callbacks_register(obj);
|
|
|
|
|
|
|
|
//listen to manager changes here
|
2019-02-21 12:35:34 -08:00
|
|
|
efl_event_callback_add(obj, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, _legacy_manager_changed_cb, NULL);
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_efl_object_destructor(Eo *obj, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
evas_object_del(layout);
|
|
|
|
|
|
|
|
sd->layouts = eina_list_free(sd->layouts);
|
|
|
|
eina_array_free(sd->it_array);
|
|
|
|
|
|
|
|
sd->selected_it = NULL;
|
|
|
|
sd->focused_it = NULL;
|
|
|
|
|
|
|
|
eina_stringshare_del(sd->label_str);
|
|
|
|
evas_object_del(sd->entry);
|
|
|
|
evas_object_del(sd->label);
|
|
|
|
evas_object_del(sd->end);
|
|
|
|
ecore_timer_del(sd->longpress_timer);
|
|
|
|
|
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_efl_text_text_set(Eo *obj, Efl_Ui_Tags_Data *sd EINA_UNUSED, const char *label)
|
|
|
|
{
|
|
|
|
if (label) _label_set(obj, label);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const char *
|
|
|
|
_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 Eina_Bool
|
|
|
|
_efl_ui_tags_expanded_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
return sd->view_state == TAGS_VIEW_SHRINK ?
|
|
|
|
EINA_FALSE : EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_expanded_set(Eo *obj, Efl_Ui_Tags_Data *sd, Eina_Bool expanded)
|
|
|
|
{
|
|
|
|
if (((sd->view_state == TAGS_VIEW_SHRINK) ?
|
|
|
|
EINA_FALSE : EINA_TRUE) == expanded) return;
|
|
|
|
|
|
|
|
if (expanded)
|
|
|
|
_shrink_mode_set(obj, EINA_FALSE);
|
|
|
|
else
|
|
|
|
_shrink_mode_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_editable_set(Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd, Eina_Bool editable)
|
|
|
|
{
|
|
|
|
editable = !!editable;
|
|
|
|
if (sd->editable == editable) return;
|
|
|
|
sd->editable = editable;
|
|
|
|
|
|
|
|
if (sd->editable && (sd->view_state != TAGS_VIEW_SHRINK))
|
|
|
|
{
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack(sd->box, sd->entry);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_show(sd->entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-07-31 11:02:47 -07:00
|
|
|
efl_pack_unpack(sd->box, sd->entry);
|
2018-05-02 01:23:25 -07:00
|
|
|
evas_object_hide(sd->entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_ui_tags_editable_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
return sd->editable;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_items_set(Eo *obj, Efl_Ui_Tags_Data *sd, const Eina_Array *items)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(items);
|
|
|
|
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
|
|
|
Eina_Array_Iterator iterator;
|
|
|
|
const char *it_text;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
sd->item_setting = EINA_TRUE;
|
|
|
|
|
|
|
|
if (sd->layouts)
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
_on_item_deleted(obj, layout, NULL, NULL);
|
|
|
|
|
|
|
|
if (eina_array_count(items))
|
|
|
|
EINA_ARRAY_ITER_NEXT(items, i, it_text, iterator)
|
|
|
|
_item_new(sd, it_text);
|
|
|
|
|
|
|
|
sd->item_setting = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static const Eina_Array*
|
|
|
|
_efl_ui_tags_items_get(const Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *sd)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Eo *layout;
|
|
|
|
|
|
|
|
eina_array_clean(sd->it_array);
|
|
|
|
|
|
|
|
if (sd->layouts)
|
|
|
|
EINA_LIST_FOREACH(sd->layouts, l, layout)
|
|
|
|
eina_array_push(sd->it_array, elm_object_part_text_get(layout, "efl.btn.text"));
|
|
|
|
|
|
|
|
return sd->it_array;
|
|
|
|
}
|
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
|
|
|
EOLIAN static void
|
|
|
|
_efl_ui_tags_efl_ui_format_apply_formatted_value(Eo *obj EINA_UNUSED, Efl_Ui_Tags_Data *pd)
|
|
|
|
{
|
|
|
|
_view_update(pd);
|
|
|
|
}
|
2018-05-02 01:23:25 -07:00
|
|
|
|
|
|
|
#include "efl_ui_tags.eo.c"
|