forked from enlightenment/efl
Filter input text in entries.
Users can set filters of their own (text only, no format now) or use the predefined ones. SVN revision: 53141
This commit is contained in:
parent
4f3090af01
commit
4c8980e47e
|
@ -229,6 +229,8 @@ void
|
|||
test_entry_scrolled(void *data, Evas_Object *obj, void *event_info)
|
||||
{
|
||||
Evas_Object *win, *bg, *bx, *bx2, *bt, *en, *en_p, *sp;
|
||||
static Elm_Entry_Filter_Accept_Set digits_filter_data, digits_filter_data2;
|
||||
static Elm_Entry_Filter_Limit_Size limit_filter_data, limit_filter_data2;
|
||||
|
||||
win = elm_win_add(NULL, "entry-scrolled", ELM_WIN_BASIC);
|
||||
elm_win_title_set(win, "Entry Scrolled");
|
||||
|
@ -300,6 +302,62 @@ test_entry_scrolled(void *data, Evas_Object *obj, void *event_info)
|
|||
evas_object_show(en);
|
||||
elm_box_pack_end(bx, en);
|
||||
|
||||
/* Only digits entry */
|
||||
en = elm_scrolled_entry_add(win);
|
||||
evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
|
||||
elm_scrolled_entry_entry_set(en, "01234");
|
||||
elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
|
||||
elm_scrolled_entry_single_line_set(en, 1);
|
||||
evas_object_show(en);
|
||||
elm_box_pack_end(bx, en);
|
||||
|
||||
digits_filter_data.accepted = "0123456789";
|
||||
digits_filter_data.rejected = NULL;
|
||||
elm_scrolled_entry_text_filter_append(en, elm_entry_filter_accept_set, &digits_filter_data);
|
||||
|
||||
/* No digits entry */
|
||||
en = elm_scrolled_entry_add(win);
|
||||
evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
|
||||
elm_scrolled_entry_entry_set(en, "No numbers here");
|
||||
elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
|
||||
elm_scrolled_entry_single_line_set(en, 1);
|
||||
evas_object_show(en);
|
||||
elm_box_pack_end(bx, en);
|
||||
|
||||
digits_filter_data2.accepted = NULL;
|
||||
digits_filter_data2.rejected = "0123456789";
|
||||
elm_scrolled_entry_text_filter_append(en, elm_entry_filter_accept_set, &digits_filter_data2);
|
||||
|
||||
/* Size limited entry */
|
||||
en = elm_scrolled_entry_add(win);
|
||||
evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
|
||||
elm_scrolled_entry_entry_set(en, "Just 20 chars");
|
||||
elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
|
||||
elm_scrolled_entry_single_line_set(en, 1);
|
||||
evas_object_show(en);
|
||||
elm_box_pack_end(bx, en);
|
||||
|
||||
limit_filter_data.max_char_count = 20;
|
||||
limit_filter_data.max_byte_count = 0;
|
||||
elm_scrolled_entry_text_filter_append(en, elm_entry_filter_limit_size, &limit_filter_data);
|
||||
|
||||
/* Byte size limited entry */
|
||||
en = elm_scrolled_entry_add(win);
|
||||
evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0);
|
||||
evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5);
|
||||
elm_scrolled_entry_entry_set(en, "And now only 30 bytes");
|
||||
elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
|
||||
elm_scrolled_entry_single_line_set(en, 1);
|
||||
evas_object_show(en);
|
||||
elm_box_pack_end(bx, en);
|
||||
|
||||
limit_filter_data2.max_char_count = 0;
|
||||
limit_filter_data2.max_byte_count = 30;
|
||||
elm_scrolled_entry_text_filter_append(en, elm_entry_filter_limit_size, &limit_filter_data2);
|
||||
|
||||
/* Single line password entry */
|
||||
en_p = elm_scrolled_entry_add(win);
|
||||
evas_object_size_hint_weight_set(en_p, EVAS_HINT_EXPAND, 0.0);
|
||||
|
|
|
@ -866,8 +866,26 @@ extern "C" {
|
|||
EAPI void elm_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
EAPI void elm_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
EAPI void elm_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
EAPI char *elm_entry_markup_to_utf8(const char *s);
|
||||
EAPI char *elm_entry_utf8_to_markup(const char *s);
|
||||
/* pre-made filters for entries */
|
||||
typedef struct _Elm_Entry_Filter_Limit_Size Elm_Entry_Filter_Limit_Size;
|
||||
struct _Elm_Entry_Filter_Limit_Size
|
||||
{
|
||||
int max_char_count;
|
||||
int max_byte_count;
|
||||
};
|
||||
EAPI void elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text);
|
||||
typedef struct _Elm_Entry_Filter_Accept_Set Elm_Entry_Filter_Accept_Set;
|
||||
struct _Elm_Entry_Filter_Accept_Set
|
||||
{
|
||||
const char *accepted;
|
||||
const char *rejected;
|
||||
};
|
||||
EAPI void elm_entry_filter_accept_set(void *data, Evas_Object *entry, char **text);
|
||||
/* smart callbacks called:
|
||||
* "changed" - the text content changed
|
||||
* "selection,start" - the user started selecting text
|
||||
|
@ -1753,6 +1771,12 @@ extern "C" {
|
|||
EAPI const Evas_Object *elm_scrolled_entry_end_get(Evas_Object *obj);
|
||||
EAPI Evas_Object *elm_scrolled_entry_end_unset(Evas_Object *obj);
|
||||
EAPI void elm_scrolled_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting);
|
||||
EAPI void elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data);
|
||||
EAPI void elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
EAPI void elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
EAPI void elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data);
|
||||
|
||||
EAPI Evas_Object *elm_conformant_add(Evas_Object *parent);
|
||||
EAPI void elm_conformant_content_set(Evas_Object *obj, Evas_Object *content);
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
*/
|
||||
|
||||
typedef struct _Widget_Data Widget_Data;
|
||||
typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
|
||||
typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
|
||||
typedef struct _Elm_Entry_Text_Filter Elm_Entry_Text_Filter;
|
||||
|
||||
struct _Widget_Data
|
||||
{
|
||||
|
@ -39,9 +42,31 @@ struct _Widget_Data
|
|||
Evas_Object *icon;
|
||||
Evas_Object *end;
|
||||
Elm_Scroller_Policy policy_h, policy_v;
|
||||
Eina_List *items;
|
||||
Eina_List *item_providers;
|
||||
Eina_List *text_filters;
|
||||
Eina_Bool single_line : 1;
|
||||
};
|
||||
|
||||
struct _Elm_Entry_Context_Menu_Item
|
||||
{
|
||||
Evas_Object *obj;
|
||||
Evas_Smart_Cb func;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct _Elm_Entry_Item_Provider
|
||||
{
|
||||
Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct _Elm_Entry_Text_Filter
|
||||
{
|
||||
void (*func) (void *data, Evas_Object *entry, char **text);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static const char *widtype = NULL;
|
||||
|
||||
static const char SIG_CHANGED[] = "changed";
|
||||
|
@ -83,7 +108,19 @@ static const Evas_Smart_Cb_Description _signals[] = {
|
|||
static void
|
||||
_del_hook(Evas_Object *obj)
|
||||
{
|
||||
Elm_Entry_Context_Menu_Item *ci;
|
||||
Elm_Entry_Item_Provider *ip;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
|
||||
EINA_LIST_FREE(wd->items, ci)
|
||||
free(ci);
|
||||
EINA_LIST_FREE(wd->item_providers, ip)
|
||||
free(ip);
|
||||
EINA_LIST_FREE(wd->text_filters, tf)
|
||||
free(tf);
|
||||
|
||||
if (!wd) return;
|
||||
free(wd);
|
||||
}
|
||||
|
@ -256,6 +293,42 @@ _entry_unfocused(void *data, Evas_Object *obj __UNUSED__, void *event_info)
|
|||
evas_object_smart_callback_call(data, SIG_UNFOCUSED, event_info);
|
||||
}
|
||||
|
||||
static void
|
||||
_context_item_wrap_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
|
||||
{
|
||||
Elm_Entry_Context_Menu_Item *ci = data;
|
||||
ci->func(ci->data, ci->obj, event_info);
|
||||
}
|
||||
|
||||
static Evas_Object *
|
||||
_item_provider_wrap_cb(void *data, Evas_Object *obj __UNUSED__, const char *item)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(data);
|
||||
Eina_List *l;
|
||||
Elm_Entry_Item_Provider *ip;
|
||||
|
||||
EINA_LIST_FOREACH(wd->item_providers, l, ip)
|
||||
{
|
||||
Evas_Object *o;
|
||||
o = ip->func(ip->data, data, item);
|
||||
if (o) return o;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_text_filter_wrap_cb(void *data, Evas_Object *obj __UNUSED__, char **text)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(data);
|
||||
Eina_List *l;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
|
||||
EINA_LIST_FOREACH(wd->text_filters, l, tf)
|
||||
{
|
||||
tf->func(tf->data, data, text);
|
||||
if (!*text) break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds a scrolled entry to @p parent object.
|
||||
|
@ -302,7 +375,8 @@ elm_scrolled_entry_add(Evas_Object *parent)
|
|||
elm_scroller_content_set(wd->scroller, wd->entry);
|
||||
evas_object_show(wd->entry);
|
||||
|
||||
wd->icon = wd->end = NULL;
|
||||
elm_entry_text_filter_prepend(wd->entry, _text_filter_wrap_cb, obj);
|
||||
elm_entry_item_provider_prepend(wd->entry, _item_provider_wrap_cb, obj);
|
||||
|
||||
evas_object_smart_callback_add(wd->entry, "changed", _entry_changed, obj);
|
||||
evas_object_smart_callback_add(wd->entry, "activated", _entry_activated, obj);
|
||||
|
@ -1109,10 +1183,18 @@ elm_scrolled_entry_context_menu_clear(Evas_Object *obj)
|
|||
EAPI void
|
||||
elm_scrolled_entry_context_menu_item_add(Evas_Object *obj, const char *label, const char *icon_file, Elm_Icon_Type icon_type, Evas_Smart_Cb func, const void *data)
|
||||
{
|
||||
Elm_Entry_Context_Menu_Item *ci;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
if (!wd) return;
|
||||
elm_entry_context_menu_item_add(wd->entry, label, icon_file, icon_type, func, data);
|
||||
|
||||
ci = malloc(sizeof(Elm_Entry_Context_Menu_Item));
|
||||
if (!ci) return;
|
||||
ci->func = func;
|
||||
ci->data = (void *)data;
|
||||
ci->obj = obj;
|
||||
wd->items = eina_list_append(wd->items, ci);
|
||||
elm_entry_context_menu_item_add(wd->entry, label, icon_file, icon_type, _context_item_wrap_cb, ci);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1186,3 +1268,190 @@ elm_scrolled_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_
|
|||
if (!wd) return;
|
||||
elm_scroller_bounce_set(wd->scroller, h_bounce, v_bounce);
|
||||
}
|
||||
|
||||
/**
|
||||
* This appends a custom item provider to the list for that entry
|
||||
*
|
||||
* This appends the given callback. The list is walked from beginning to end
|
||||
* with each function called given the item href string in the text. If the
|
||||
* function returns an object handle other than NULL (it should create an
|
||||
* and object to do this), then this object is used to replace that item. If
|
||||
* not the next provider is called until one provides an item object, or the
|
||||
* default provider in entry does.
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function called to provide the item object
|
||||
* @param data The data passed to @p func
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
|
||||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
if (!wd) return;
|
||||
if (!func) return;
|
||||
Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
|
||||
if (!ip) return;
|
||||
ip->func = func;
|
||||
ip->data = data;
|
||||
wd->item_providers = eina_list_append(wd->item_providers, ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* This prepends a custom item provider to the list for that entry
|
||||
*
|
||||
* This prepends the given callback. See elm_scrolled_entry_item_provider_append() for
|
||||
* more information
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function called to provide the item object
|
||||
* @param data The data passed to @p func
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
|
||||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
if (!wd) return;
|
||||
if (!func) return;
|
||||
Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
|
||||
if (!ip) return;
|
||||
ip->func = func;
|
||||
ip->data = data;
|
||||
wd->item_providers = eina_list_prepend(wd->item_providers, ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* This removes a custom item provider to the list for that entry
|
||||
*
|
||||
* This removes the given callback. See elm_scrolled_entry_item_provider_append() for
|
||||
* more information
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function called to provide the item object
|
||||
* @param data The data passed to @p func
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
|
||||
{
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Eina_List *l;
|
||||
Elm_Entry_Item_Provider *ip;
|
||||
if (!wd) return;
|
||||
if (!func) return;
|
||||
EINA_LIST_FOREACH(wd->item_providers, l, ip)
|
||||
{
|
||||
if ((ip->func == func) && (ip->data == data))
|
||||
{
|
||||
wd->item_providers = eina_list_remove_list(wd->item_providers, l);
|
||||
free(ip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a filter function for text inserted in the entry
|
||||
*
|
||||
* Append the given callback to the list. This functions will be called
|
||||
* whenever any text is inserted into the entry, with the text to be inserted
|
||||
* as a parameter. The callback function is free to alter the text in any way
|
||||
* it wants, but it must remember to free the given pointer and update it.
|
||||
* If the new text is to be discarded, the function can free it and set it text
|
||||
* parameter to NULL. This will also prevent any following filters from being
|
||||
* called.
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function to use as text filter
|
||||
* @param data User data to pass to @p func
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
|
||||
if (!func) return;
|
||||
|
||||
tf = ELM_NEW(Elm_Entry_Text_Filter);
|
||||
if (!tf) return;
|
||||
tf->func = func;
|
||||
tf->data = data;
|
||||
wd->text_filters = eina_list_append(wd->text_filters, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a filter function for text insdrted in the entry
|
||||
*
|
||||
* Prepend the given callback to the list. See elm_scrolled_entry_text_filter_append()
|
||||
* for more information
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function to use as text filter
|
||||
* @param data User data to pass to @p func
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
|
||||
if (!func) return;
|
||||
|
||||
tf = ELM_NEW(Elm_Entry_Text_Filter);
|
||||
if (!tf) return;
|
||||
tf->func = func;
|
||||
tf->data = data;
|
||||
wd->text_filters = eina_list_prepend(wd->text_filters, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filter from the list
|
||||
*
|
||||
* Removes the given callback from the filter list. See elm_scrolled_entry_text_filter_append()
|
||||
* for more information.
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The filter function to remove
|
||||
* @param data The user data passed when adding the function
|
||||
*
|
||||
* @ingroup Scrolled_Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Eina_List *l;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
if (!func) return;
|
||||
|
||||
EINA_LIST_FOREACH(wd->text_filters, l, tf)
|
||||
{
|
||||
if ((tf->func == func) && (tf->data == data))
|
||||
{
|
||||
wd->text_filters = eina_list_remove_list(wd->text_filters, l);
|
||||
free(tf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ typedef struct _Mod_Api Mod_Api;
|
|||
typedef struct _Widget_Data Widget_Data;
|
||||
typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
|
||||
typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
|
||||
typedef struct _Elm_Entry_Text_Filter Elm_Entry_Text_Filter;
|
||||
|
||||
struct _Widget_Data
|
||||
{
|
||||
|
@ -108,6 +109,7 @@ struct _Widget_Data
|
|||
Evas_Coord cx, cy, cw, ch;
|
||||
Eina_List *items;
|
||||
Eina_List *item_providers;
|
||||
Eina_List *text_filters;
|
||||
Ecore_Job *hovdeljob;
|
||||
Mod_Api *api; // module api if supplied
|
||||
Eina_Bool changed : 1;
|
||||
|
@ -142,6 +144,12 @@ struct _Elm_Entry_Item_Provider
|
|||
void *data;
|
||||
};
|
||||
|
||||
struct _Elm_Entry_Text_Filter
|
||||
{
|
||||
void (*func) (void *data, Evas_Object *entry, char **text);
|
||||
void *data;
|
||||
};
|
||||
|
||||
static const char *widtype = NULL;
|
||||
|
||||
static Eina_Bool _drag_drop_cb(void *data, Evas_Object *obj, Elm_Drop_Data *);
|
||||
|
@ -231,6 +239,7 @@ _del_hook(Evas_Object *obj)
|
|||
Widget_Data *wd = elm_widget_data_get(obj);
|
||||
Elm_Entry_Context_Menu_Item *it;
|
||||
Elm_Entry_Item_Provider *ip;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
|
||||
if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
|
||||
if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj); // module - unhook
|
||||
|
@ -255,6 +264,10 @@ _del_hook(Evas_Object *obj)
|
|||
{
|
||||
free(ip);
|
||||
}
|
||||
EINA_LIST_FREE(wd->text_filters, tf)
|
||||
{
|
||||
free(tf);
|
||||
}
|
||||
free(wd);
|
||||
}
|
||||
|
||||
|
@ -1322,6 +1335,24 @@ _get_item(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__,
|
|||
return o;
|
||||
}
|
||||
|
||||
static void
|
||||
_text_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, Edje_Text_Filter_Type type, char **text)
|
||||
{
|
||||
Widget_Data *wd = elm_widget_data_get(data);
|
||||
Eina_List *l;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
|
||||
if (type == EDJE_TEXT_FILTER_FORMAT)
|
||||
return;
|
||||
|
||||
EINA_LIST_FOREACH(wd->text_filters, l, tf)
|
||||
{
|
||||
tf->func(tf->data, data, text);
|
||||
if (!*text)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds an entry to @p parent object.
|
||||
*
|
||||
|
@ -1363,6 +1394,7 @@ elm_entry_add(Evas_Object *parent)
|
|||
|
||||
wd->ent = edje_object_add(e);
|
||||
edje_object_item_provider_set(wd->ent, _get_item, obj);
|
||||
edje_object_text_insert_filter_callback_add(wd->ent,"elm.text", _text_filter, obj);
|
||||
evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOVE, _move, obj);
|
||||
evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_RESIZE, _resize, obj);
|
||||
evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_DOWN,
|
||||
|
@ -2220,6 +2252,105 @@ elm_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *dat
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a filter function for text inserted in the entry
|
||||
*
|
||||
* Append the given callback to the list. This functions will be called
|
||||
* whenever any text is inserted into the entry, with the text to be inserted
|
||||
* as a parameter. The callback function is free to alter the text in any way
|
||||
* it wants, but it must remember to free the given pointer and update it.
|
||||
* If the new text is to be discarded, the function can free it and set it text
|
||||
* parameter to NULL. This will also prevent any following filters from being
|
||||
* called.
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function to use as text filter
|
||||
* @param data User data to pass to @p func
|
||||
*
|
||||
* @ingroup Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
|
||||
if (!func) return;
|
||||
|
||||
tf = ELM_NEW(Elm_Entry_Text_Filter);
|
||||
if (!tf) return;
|
||||
tf->func = func;
|
||||
tf->data = data;
|
||||
wd->text_filters = eina_list_append(wd->text_filters, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend a filter function for text insdrted in the entry
|
||||
*
|
||||
* Prepend the given callback to the list. See elm_entry_text_filter_append()
|
||||
* for more information
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The function to use as text filter
|
||||
* @param data User data to pass to @p func
|
||||
*
|
||||
* @ingroup Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
|
||||
if (!func) return;
|
||||
|
||||
tf = ELM_NEW(Elm_Entry_Text_Filter);
|
||||
if (!tf) return;
|
||||
tf->func = func;
|
||||
tf->data = data;
|
||||
wd->text_filters = eina_list_prepend(wd->text_filters, tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a filter from the list
|
||||
*
|
||||
* Removes the given callback from the filter list. See elm_entry_text_filter_append()
|
||||
* for more information.
|
||||
*
|
||||
* @param obj The entry object
|
||||
* @param func The filter function to remove
|
||||
* @param data The user data passed when adding the function
|
||||
*
|
||||
* @ingroup Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
|
||||
{
|
||||
Widget_Data *wd;
|
||||
Eina_List *l;
|
||||
Elm_Entry_Text_Filter *tf;
|
||||
ELM_CHECK_WIDTYPE(obj, widtype);
|
||||
|
||||
wd = elm_widget_data_get(obj);
|
||||
if (!func) return;
|
||||
|
||||
EINA_LIST_FOREACH(wd->text_filters, l, tf)
|
||||
{
|
||||
if ((tf->func == func) && (tf->data == data))
|
||||
{
|
||||
wd->text_filters = eina_list_remove_list(wd->text_filters, l);
|
||||
free(tf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This converts a markup (HTML-like) string into UTF-8.
|
||||
*
|
||||
|
@ -2252,6 +2383,160 @@ elm_entry_utf8_to_markup(const char *s)
|
|||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter inserted text based on user defined character and byte limits
|
||||
*
|
||||
* Add this filter to an entry to limit the characters that it will accept
|
||||
* based the the contents of the provided Elm_Entry_Filter_Limit_Size.
|
||||
* The funtion works on the UTF-8 representation of the string, converting
|
||||
* it from the set markup, thus not accounting for any format in it.
|
||||
*
|
||||
* The user must create an Elm_Entry_Filter_Limit_Size structure and pass
|
||||
* it as data when setting the filter. In it it's possible to set limits
|
||||
* by character count or bytes (any of them is disabled if 0), and both can
|
||||
* be set at the same time. In that case, it first checks for characters,
|
||||
* then bytes.
|
||||
*
|
||||
* The function will cut the inserted text in order to allow only the first
|
||||
* number of characters that are still allowed. The cut is made in
|
||||
* characters, even when limiting by bytes, in order to always contain
|
||||
* valid ones and avoid half unicode characters making it in.
|
||||
*
|
||||
* @ingroup Entry
|
||||
*/
|
||||
EAPI void
|
||||
elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text)
|
||||
{
|
||||
Elm_Entry_Filter_Limit_Size *lim = data;
|
||||
char *current;
|
||||
int len, newlen;
|
||||
const char *(*text_get)(const Evas_Object *);
|
||||
const char *widget_type;
|
||||
|
||||
if (!lim) return;
|
||||
|
||||
/* hack. I don't want to copy the entire function to work with
|
||||
* scrolled_entry */
|
||||
widget_type = elm_widget_type_get(entry);
|
||||
if (!strcmp(widget_type, "entry"))
|
||||
text_get = elm_entry_entry_get;
|
||||
else if (!strcmp(widget_type, "scrolled_entry"))
|
||||
text_get = elm_scrolled_entry_entry_get;
|
||||
else /* huh? */
|
||||
return;
|
||||
|
||||
current = elm_entry_markup_to_utf8(text_get(entry));
|
||||
|
||||
if (lim->max_char_count > 0)
|
||||
{
|
||||
int cut;
|
||||
len = evas_string_char_len_get(current);
|
||||
if (len >= lim->max_char_count)
|
||||
{
|
||||
free(*text);
|
||||
free(current);
|
||||
*text = NULL;
|
||||
return;
|
||||
}
|
||||
newlen = evas_string_char_len_get(*text);
|
||||
cut = strlen(*text);
|
||||
while ((len + newlen) > lim->max_char_count)
|
||||
{
|
||||
cut = evas_string_char_prev_get(*text, cut, NULL);
|
||||
newlen--;
|
||||
}
|
||||
(*text)[cut] = 0;
|
||||
}
|
||||
|
||||
if (lim->max_byte_count > 0)
|
||||
{
|
||||
len = strlen(current);
|
||||
if (len >= lim->max_byte_count)
|
||||
{
|
||||
free(*text);
|
||||
free(current);
|
||||
*text = NULL;
|
||||
return;
|
||||
}
|
||||
newlen = strlen(*text);
|
||||
while ((len + newlen) > lim->max_byte_count)
|
||||
{
|
||||
int p = evas_string_char_prev_get(*text, newlen, NULL);
|
||||
newlen -= (newlen - p);
|
||||
}
|
||||
if (newlen)
|
||||
(*text)[newlen] = 0;
|
||||
else
|
||||
{
|
||||
free(*text);
|
||||
*text = NULL;
|
||||
}
|
||||
}
|
||||
free(current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter inserted text based on accepted or rejected sets of characters
|
||||
*
|
||||
* Add this filter to an entry to restrict the set of accepted characters
|
||||
* based on the sets in the provided Elm_Entry_Filter_Accept_Set.
|
||||
* This structure contains both accepted and rejected sets, but they are
|
||||
* mutually exclusive. If accepted is set, it will be used, otherwise it
|
||||
* goes on to the rejected set.
|
||||
*/
|
||||
EAPI void
|
||||
elm_entry_filter_accept_set(void *data, Evas_Object *entry, char **text)
|
||||
{
|
||||
Elm_Entry_Filter_Accept_Set *as = data;
|
||||
const char *set;
|
||||
char *insert;
|
||||
Eina_Bool goes_in;
|
||||
int read_idx, last_read_idx = 0, read_char, copy_count;
|
||||
|
||||
if (!as || (!as->accepted && !as->rejected))
|
||||
return;
|
||||
|
||||
if (as->accepted)
|
||||
{
|
||||
set = as->accepted;
|
||||
goes_in = EINA_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
set = as->rejected;
|
||||
goes_in = EINA_FALSE;
|
||||
}
|
||||
|
||||
insert = *text;
|
||||
read_idx = evas_string_char_next_get(*text, 0, &read_char);
|
||||
copy_count = read_idx;
|
||||
while (read_char)
|
||||
{
|
||||
int cmp_idx, cmp_char;
|
||||
Eina_Bool in_set = EINA_FALSE;
|
||||
|
||||
cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
|
||||
while (cmp_char)
|
||||
{
|
||||
if (read_char == cmp_char)
|
||||
{
|
||||
in_set = EINA_TRUE;
|
||||
break;
|
||||
}
|
||||
cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
|
||||
}
|
||||
if (in_set == goes_in)
|
||||
{
|
||||
int size = read_idx - last_read_idx;
|
||||
const char *src = (*text) + last_read_idx;
|
||||
if (src != insert)
|
||||
memcpy(insert, *text + last_read_idx, size);
|
||||
insert += size;
|
||||
}
|
||||
last_read_idx = read_idx;
|
||||
read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
|
||||
}
|
||||
*insert = 0;
|
||||
}
|
||||
|
||||
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
|
||||
|
|
Loading…
Reference in New Issue