inherit: "elm/scroller/base/default";
image: "bg_glow_in.png" COMP;
parts {
+ part { name: "validation_glow";
+ type: RECT;
+ insert_before: "bg";
+ mouse_events: 0;
+ description { state: "default" 0.0;
+ color: 0 0 0 0;
+ }
+ description { state: "pass" 0.0;
+ color: 0 255 0 90;
+ }
+ description { state: "fail" 0.0;
+ color: 255 0 0 90;
+ }
+ }
part { name: "bg";
description { state: "default" 0.0;
color: DARK_GREY_BG_COLOR;
transition: DECELERATE 0.3;
target: "glow";
}
+ program { name: "validation_fail";
+ signal: "validation,default,fail";
+ source: "elm";
+ action: STATE_SET "fail" 0.0;
+ target: "validation_glow";
+ }
+ program { name: "validation_pass";
+ signal: "validation,default,pass";
+ source: "elm";
+ action: STATE_SET "pass" 0.0;
+ target: "validation_glow";
+ }
+ program { name: "validation_off";
+ signal: "validation,default";
+ source: "elm";
+ action: STATE_SET "default" 0.0;
+ target: "validation_glow";
+ }
}
}
data.item: "focus_highlight" "on";
parts {
+ part { name: "validation_glow";
+ type: RECT;
+ insert_before: "bg";
+ mouse_events: 0;
+ description { state: "default" 0.0;
+ color: 0 0 0 0;
+ }
+ description { state: "pass" 0.0;
+ color: 0 255 0 90;
+ }
+ description { state: "fail" 0.0;
+ color: 255 0 0 90;
+ }
+ }
part { name: "sb_vbar_base"; type: RECT;
description { state: "default" 0.0;
fixed: 1 1;
transition: DECELERATE 0.3;
target: "glow";
}
+ program { name: "validation_fail";
+ signal: "validation,default,fail";
+ source: "elm";
+ action: STATE_SET "fail" 0.0;
+ target: "validation_glow";
+ }
+ program { name: "validation_pass";
+ signal: "validation,default,pass";
+ source: "elm";
+ action: STATE_SET "pass" 0.0;
+ target: "validation_glow";
+ }
+ program { name: "validation_off";
+ signal: "validation,default";
+ source: "elm";
+ action: STATE_SET "default" 0.0;
+ target: "validation_glow";
+ }
}
}
void test_entry6(void *data, Evas_Object *obj, void *event_info);
void test_entry7(void *data, Evas_Object *obj, void *event_info);
void test_entry8(void *data, Evas_Object *obj, void *event_info);
+void test_entry_regex(void *data, Evas_Object *obj, void *event_info);
void test_entry_notepad(void *data, Evas_Object *obj, void *event_info);
void test_multibuttonentry(void *data, Evas_Object *obj, void *event_info);
void test_entry_anchor2(void *data, Evas_Object *obj, void *event_info);
ADD_TEST(NULL, "Entries", "Entry 6", test_entry6);
ADD_TEST(NULL, "Entries", "Entry 7", test_entry7);
ADD_TEST(NULL, "Entries", "Entry 8", test_entry8);
+ ADD_TEST(NULL, "Entries", "Entry Regex", test_entry_regex);
ADD_TEST(NULL, "Entries", "Entry Notepad", test_entry_notepad);
ADD_TEST(NULL, "Entries", "Multibuttonentry", test_multibuttonentry);
ADD_TEST(NULL, "Entries", "Entry Anchor", test_entry_anchor);
evas_object_show(win);
}
+typedef struct {
+ Evas_Object *en_regex;
+ Evas_Object *lb_regex;
+ Evas_Object *en_single;
+ Evas_Object *en_multi;
+ Elm_Validator_Regexp *re;
+} _test_regex_data_t;
+
+static void
+_test_regex_data_del(void *data,
+ Evas *e EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ _test_regex_data_t *test_data = data;
+ if (test_data->re) elm_validator_regexp_free(test_data->re);
+ free(test_data);
+}
+
+static void
+_test_regex_bt_cb(void *data,
+ Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED)
+{
+ int status;
+ _test_regex_data_t *test_data = data;
+ Eina_Strbuf *tmp;
+
+ if (test_data->re)
+ {
+ eo_do(test_data->en_single, eo_event_callback_del(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+ eo_do(test_data->en_multi, eo_event_callback_del(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+ elm_validator_regexp_free(test_data->re);
+ }
+ test_data->re = elm_validator_regexp_new(elm_entry_entry_get(test_data->en_regex), NULL);
+
+ status = elm_validator_regexp_status_get(test_data->re);
+ tmp = eina_strbuf_manage_new(strdup("Regex error: "));
+ switch (status)
+ {
+ case ELM_REG_NOERROR:
+ {
+ eina_strbuf_append(tmp, "No error. Regex maches to the Entrys text.");
+ break;
+ }
+ case ELM_REG_BADPAT:
+ {
+ eina_strbuf_append(tmp, "Invalid regular expression.");
+ break;
+ }
+ default:
+ break;
+ }
+ if (!status)
+ {
+ eo_do(test_data->en_single, eo_event_callback_add(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+ eo_do(test_data->en_multi, eo_event_callback_add(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+ }
+
+ elm_object_text_set(test_data->lb_regex, eina_strbuf_string_get(tmp));
+ eina_strbuf_free(tmp);
+}
+
+static inline Evas_Object *
+_test_regex_entry_add(Evas_Object *parent, Eina_Bool is_singleline)
+{
+ Evas_Object *entry = elm_entry_add(parent);
+ elm_entry_scrollable_set(entry, EINA_TRUE);
+ elm_entry_single_line_set(entry, is_singleline);
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_entry_editable_set(entry, EINA_TRUE);
+ evas_object_show(entry);
+ return entry;
+}
+
+void
+test_entry_regex(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *win, *scr, *box;
+ Evas_Object *item, *label, *bt, *sep;
+ _test_regex_data_t *test_data;
+#define REGEX "^[0-9]*$"
+
+ test_data = malloc(sizeof(_test_regex_data_t));
+
+ win = elm_win_util_standard_add("Entry", "Entry Regex Test");
+ elm_win_autodel_set(win, EINA_TRUE);
+ evas_object_event_callback_add(win, EVAS_CALLBACK_DEL,
+ _test_regex_data_del, test_data);
+
+ scr = elm_scroller_add(win);
+ elm_scroller_bounce_set(scr, EINA_FALSE, EINA_TRUE);
+ elm_scroller_policy_set(scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
+ evas_object_size_hint_weight_set(scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, scr);
+ evas_object_show(scr);
+
+ box = elm_box_add(win);
+ evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_box_homogeneous_set(box, EINA_FALSE);
+ elm_object_content_set(scr, box);
+
+ evas_object_show(box);
+
+ label = elm_label_add(box);
+ elm_object_text_set(label, "Regular Expression");
+ elm_box_pack_end(box, label);
+ evas_object_show(label);
+
+ item = elm_box_add(win);
+ evas_object_size_hint_weight_set(item, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(item, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_horizontal_set(item, EINA_TRUE);
+ elm_box_homogeneous_set(item, EINA_FALSE);
+ evas_object_show(item);
+ elm_box_pack_end(box, item);
+
+ test_data->en_regex = _test_regex_entry_add(item, EINA_TRUE);
+ elm_box_pack_end(item, test_data->en_regex);
+
+ bt = elm_button_add(item);
+ elm_object_text_set(bt, "Set");
+ evas_object_smart_callback_add(bt, "clicked", _test_regex_bt_cb, test_data);
+ evas_object_show(bt);
+ elm_box_pack_end(item, bt);
+
+ test_data->lb_regex = elm_label_add(box);
+ elm_object_text_set(test_data->lb_regex, "Regex error: no error.");
+ elm_box_pack_end(box, test_data->lb_regex);
+ evas_object_show(test_data->lb_regex);
+
+ sep = elm_separator_add(box);
+ elm_separator_horizontal_set(sep, EINA_TRUE);
+ evas_object_show(sep);
+ elm_box_pack_end(box, sep);
+
+ label = elm_label_add(box);
+ elm_object_text_set(label, "Test regex in single line entry");
+ elm_box_pack_end(box, label);
+ evas_object_show(label);
+
+ test_data->en_single = _test_regex_entry_add(box, EINA_TRUE);
+ elm_box_pack_end(box, test_data->en_single);
+
+ label = elm_label_add(box);
+ elm_object_text_set(label, "Test regex in multi line entry");
+ elm_box_pack_end(box, label);
+ evas_object_show(label);
+
+ test_data->en_multi = _test_regex_entry_add(box, EINA_FALSE);
+ elm_box_pack_end(box, test_data->en_multi);
+
+ test_data->re = elm_validator_regexp_new(REGEX, NULL);
+ elm_entry_entry_set(test_data->en_regex, REGEX);
+ eo_do(test_data->en_single, eo_event_callback_add(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+ eo_do(test_data->en_multi, eo_event_callback_add(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, test_data->re));
+
+ evas_object_resize(win, 400, 400);
+ evas_object_show(win);
+
+#undef REGEX
+}
+
static void
_scrolled_entry_clear(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
/* include deprecated calls last of all */
#include <elm_deprecated.h>
+#include <elm_helper.h>
+
#ifdef __cplusplus
}
#endif
elm_win.h \
elm_win_common.h \
elm_win_eo.h \
-elm_win_legacy.h
+elm_win_legacy.h \
+elm_helper.h
includesubdir = $(includedir)/elementary-@VMAJ@/
libelementary_la_SOURCES = \
elm_web2.c \
elm_widget.c \
elm_win.c \
+elm_helper.c \
els_box.c \
els_cursor.c \
els_tooltip.c \
sd->has_text = has_text;
}
+static void
+_validate(Evas_Object *obj)
+{
+ ELM_ENTRY_DATA_GET(obj, sd);
+ Eina_Bool res;
+ Elm_Validate_Content vc;
+ Eina_Strbuf *buf;
+
+ if (sd->validators == 0) return;
+
+ vc.text = edje_object_part_text_get(sd->entry_edje, "elm.text");
+ eo_do(obj, res = eo_event_callback_call(ELM_ENTRY_EVENT_VALIDATE, (void *)&vc));
+ buf = eina_strbuf_new();
+ eina_strbuf_append_printf(buf, "validation,%s,%s", vc.signal, res == EO_CALLBACK_STOP ? "fail" : "pass");
+ edje_object_signal_emit(sd->scr_edje, eina_strbuf_string_get(buf), "elm");
+ eina_tmpstr_del(vc.signal);
+ eina_strbuf_free(buf);
+}
+
static Elm_Entry_Markup_Filter *
_filter_new(Elm_Entry_Filter_Cb func,
void *data)
elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
_return_key_enabled_check(obj);
+ _validate(obj);
}
else
{
edje_object_part_text_select_none(sd->entry_edje, "elm.text");
}
}
+ edje_object_signal_emit(sd->scr_edje, "validation,default", "elm");
}
return EINA_TRUE;
else
_elm_entry_guide_update(data, EINA_FALSE);
}
+ _validate(data);
+
/* callback - this could call callbacks that delete the
* entry... thus... any access to sd after this could be
* invalid */
return obj;
}
+static Eina_Bool
+_cb_added(void *data EINA_UNUSED,
+ Eo *obj,
+ const Eo_Event_Description *desc EINA_UNUSED,
+ void *event_info)
+{
+ const Eo_Callback_Array_Item *event = event_info;
+
+ ELM_ENTRY_DATA_GET(obj, sd);
+ if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
+ sd->validators++;
+ return EO_CALLBACK_CONTINUE;
+}
+
+static Eina_Bool
+_cb_deled(void *data EINA_UNUSED,
+ Eo *obj,
+ const Eo_Event_Description *desc EINA_UNUSED,
+ void *event_info)
+{
+ const Eo_Callback_Array_Item *event = event_info;
+
+ ELM_ENTRY_DATA_GET(obj, sd);
+ if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
+ sd->validators--;
+ return EO_CALLBACK_CONTINUE;
+
+}
+
EOLIAN static void
_elm_entry_eo_base_constructor(Eo *obj, Elm_Entry_Data *_pd EINA_UNUSED)
{
eo_do(obj,
evas_obj_type_set(MY_CLASS_NAME_LEGACY),
evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
- elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_ENTRY));
+ elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_ENTRY),
+ eo_event_callback_add(EO_EV_CALLBACK_ADD, _cb_added, NULL),
+ eo_event_callback_add(EO_EV_CALLBACK_DEL, _cb_deled, NULL));
}
EOLIAN static void
activated;
changed;
changed,user;
+ validate;
}
}
* @li "theme,changed": Called when the theme is changed.
* @li "undo,request": Called on undo request.
* @li "rejected": Called when some of inputs are rejected by the filter. (since 1.9)
+ * @li "validate": Called when entry text ready to validate. (since 1.14)
*
* Default content parts of the entry items that you can use for are:
* @li "icon" - An icon in the entry
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#include <Elementary.h>
+#include <regex.h>
+
+struct _Elm_Validator_Regexp
+{
+ Eina_Stringshare *signal;
+ int status;
+ regex_t regex;
+};
+
+EAPI Elm_Validator_Regexp *
+elm_validator_regexp_new(const char *pattern, const char *signal)
+{
+ Elm_Validator_Regexp *validator;
+
+ validator = calloc(1, sizeof(Elm_Validator_Regexp));
+ validator->signal = eina_stringshare_add(signal ? signal : "default");
+ validator->status = regcomp(&validator->regex, pattern, REG_EXTENDED | REG_NOSUB) ? ELM_REG_BADPAT : ELM_REG_NOERROR;
+
+ return validator;
+}
+
+EAPI void
+elm_validator_regexp_free(Elm_Validator_Regexp *validator)
+{
+ eina_stringshare_del(validator->signal);
+ regfree(&validator->regex);
+ free(validator);
+}
+
+EAPI Elm_Regexp_Status
+elm_validator_regexp_status_get(Elm_Validator_Regexp *validator)
+{
+ return validator->status;
+}
+
+EAPI Eina_Bool
+elm_validator_regexp_helper(void *data,
+ Eo *obj EINA_UNUSED,
+ const Eo_Event_Description *desc EINA_UNUSED,
+ void *event_info)
+{
+ Elm_Validate_Content *vc = event_info;
+ Elm_Validator_Regexp *validator = (Elm_Validator_Regexp *)data;
+
+ validator->status = regexec(&validator->regex, vc->text, (size_t)0, NULL, 0) ? ELM_REG_NOMATCH : ELM_REG_NOERROR;
+ vc->signal = validator->signal;
+ return validator->status ? EO_CALLBACK_STOP : EO_CALLBACK_CONTINUE;
+}
--- /dev/null
+/**
+ * @defgroup Helper Helper
+ * @ingroup Elementary
+ *
+ * The validation helper feature.
+ *
+ * @{
+ */
+
+struct _Elm_Validate_Content
+{
+ const char *text;
+ Eina_Tmpstr *signal;
+};
+/**
+ * Data for the elm_validator_regexp_helper()
+ */
+typedef struct _Elm_Validate_Content Elm_Validate_Content;
+
+/**
+ * The Regexp validator data.
+ */
+typedef struct _Elm_Validator_Regexp Elm_Validator_Regexp;
+
+/**
+ * @brief Enumeration that defines the regex error codes
+ * @since 1.14
+ */
+typedef enum
+{
+ /** Regex maches to the Entrys text. */
+ ELM_REG_NOERROR = 0,
+ /** Failed to match. */
+ ELM_REG_NOMATCH,
+ /** Invalid regular expression. */
+ ELM_REG_BADPAT,
+} Elm_Regexp_Status;
+
+/**
+ * @brief Create a new regex validator.
+ * General designed for validate inputed entry text.
+ *
+ * @param pattern The regex pattern
+ * @param signal The part of signal name, which will be emited to style
+ * @return The regex validator
+ *
+ * @see elm_validator_regexp_del()
+ * @see elm_validator_regex_regex_set()
+ * @see elm_validator_regexp_status_get()
+ * @see elm_validator_regexp_helper()
+ *
+ * @since 1.14
+ */
+EAPI Elm_Validator_Regexp *
+elm_validator_regexp_new(const char *pattern, const char *signal) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Delete the existing regex validator.
+ *
+ * @param validator The given validator
+ *
+ * @see elm_validator_regexp_add()
+ *
+ * @since 1.14
+ */
+EAPI void
+elm_validator_regexp_free(Elm_Validator_Regexp *validator) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief Get the validation status.
+ *
+ * @param The given validator
+ *
+ * @note All return value see here: http://www.gnu.org/software/libc/manual/html_node/Regular-Expressions.html
+ *
+ * @since 1.14
+ */
+EAPI Elm_Regexp_Status
+elm_validator_regexp_status_get(Elm_Validator_Regexp *validator) EINA_ARG_NONNULL(1);
+
+/**
+ * @brief The regex validator. Used as callback to validate event.
+ *
+ * Example:
+ * @code
+ * extern Evas_Object *parent;
+ * Evas_Object *entry;
+ * Elm_Validator_Regexp *re;
+ *
+ * //add validator
+ * entry = elm_entry_add(parent);
+ * re = elm_validator_regexp_add("^[0-9]*$");
+ * eo_do(entry, eo_event_callback_add(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, re));
+ *
+ * //delete validator
+ * eo_do(entry, eo_event_callback_del(ELM_ENTRY_EVENT_VALIDATE, elm_validator_regexp_helper, re));
+ * @endcode
+ *
+ * @see elm_validator_regexp_add()
+ * @see elm_validotor_regex_regex_set()
+ * @since 1.14
+ */
+EAPI Eina_Bool
+elm_validator_regexp_helper(void *data, Eo *obj, const Eo_Event_Description *desc, void *event_info);
+
+/**
+ * @}
+ */
void *input_panel_imdata;
int input_panel_imdata_len;
int input_panel_layout_variation;
+ int validators;
struct
{
Evas_Object *hover_parent; /**< hover parent object. entry is a hover parent object by default */