efl/src/modules/elementary/prefs/elm_entry.c

294 lines
7.3 KiB
C

#include "private.h"
#include "elm_widget.h"
#include <sys/types.h>
#include <regex.h>
#include "elm_entry_eo.h"
#define BLINK_INTERVAL 0.1
static Elm_Prefs_Item_Type supported_types[] =
{
ELM_PREFS_TYPE_TEXT,
ELM_PREFS_TYPE_TEXTAREA,
ELM_PREFS_TYPE_UNKNOWN
};
static Eina_Bool
_color_change_do(void *data)
{
Evas_Object *obj = data;
int color;
color = (int)(uintptr_t)evas_object_data_get(obj, "current_color");
switch (color)
{
case 0:
evas_object_data_set(obj, "current_color", (void *)1);
evas_object_color_set(obj, 255, 0, 0, 255); /* 1st red */
goto renew;
case 1:
evas_object_data_set(obj, "current_color", (void *)2);
evas_object_color_set(obj, 255, 255, 255, 255); /* 2nd white */
goto renew;
case 2:
evas_object_data_set(obj, "current_color", (void *)3);
evas_object_color_set(obj, 255, 0, 0, 255); /* 2nd red */
goto renew;
case 3:
default:
evas_object_data_set(obj, "current_color", (void *)0);
evas_object_color_set(obj, 255, 255, 255, 255); /* back to white */
goto end;
}
renew:
return ECORE_CALLBACK_RENEW;
end:
evas_object_data_del(obj, "timer");
return ECORE_CALLBACK_CANCEL;
}
static Eina_Bool
elm_prefs_entry_value_validate(Evas_Object *obj)
{
Ecore_Timer *timer;
const char *val;
regex_t *regex;
size_t min;
val = elm_entry_entry_get(obj);
if (!val) return EINA_FALSE;
regex = evas_object_data_get(obj, "accept_regex");
if (regex)
{
if (regexec(regex, val, 0, NULL, 0)) goto mismatch;
}
regex = evas_object_data_get(obj, "deny_regex");
if (regex)
{
/* we want tokens *out* of the deny language */
if (!regexec(regex, val, 0, NULL, 0)) goto mismatch;
}
min = (size_t) evas_object_data_get(obj, "min_size");
if (min)
{
if (strlen(val) < min) goto mismatch;
}
return EINA_TRUE;
mismatch:
evas_object_color_set(obj, 255, 0, 0, 255);
timer = evas_object_data_get(obj, "timer");
if (timer) ecore_timer_del(timer);
evas_object_data_set
(obj, "timer", ecore_timer_add(BLINK_INTERVAL, _color_change_do, obj));
return EINA_FALSE;
}
static void
_item_changed_cb(void *data, const Efl_Event *event)
{
Elm_Prefs_Item_Changed_Cb prefs_it_changed_cb = data;
if (efl_ui_focus_object_focus_get(event->object))
prefs_it_changed_cb(event->object);
}
static void
_entry_del_cb(void *data EINA_UNUSED,
Evas *evas EINA_UNUSED,
Evas_Object *obj,
void *event_info EINA_UNUSED)
{
regex_t *regex;
Ecore_Timer *timer;
regex = evas_object_data_del(obj, "accept_regex");
if (regex)
{
regfree(regex);
free(regex);
}
regex = evas_object_data_del(obj, "deny_regex");
if (regex)
{
regfree(regex);
free(regex);
}
timer = evas_object_data_del(obj, "timer");
if (timer) ecore_timer_del(timer);
evas_object_data_del(obj, "min_size");
}
static Evas_Object *
elm_prefs_entry_add(const Elm_Prefs_Item_Iface *iface EINA_UNUSED,
Evas_Object *prefs,
const Elm_Prefs_Item_Type type,
const Elm_Prefs_Item_Spec spec,
Elm_Prefs_Item_Changed_Cb cb)
{
Evas_Object *obj = elm_entry_add(prefs);
regex_t *regex = NULL;
char buf[256];
Elm_Entry_Filter_Limit_Size limit = {
.max_char_count = spec.s.length.max
};
evas_object_data_set(obj, "prefs_type", (void *)type);
/* FIXME: have this warning animation on the theme, later */
/* 0: orig. white; 1: 1st red; 2: 2nd white; 3: 2o red */
evas_object_data_set(obj, "current_color", 0);
/* FIXME: is it worth to ERR with the item's name, too, here? */
efl_event_callback_add
(obj, ELM_ENTRY_EVENT_ACTIVATED, _item_changed_cb, cb);
efl_event_callback_add
(obj, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_CHANGED, _item_changed_cb, cb);
if (spec.s.accept)
{
int ret;
regex = calloc(1, sizeof(regex_t));
ret = regcomp(regex, spec.s.accept, REG_EXTENDED | REG_NOSUB);
if (ret)
{
regerror(ret, regex, buf, sizeof(buf));
regfree(regex);
free(regex);
ERR("bad regular expression (%s) on item's 'accept' tag (%s)."
" Because of that, the 'accept' tag will be dropped for the "
"item.", spec.s.accept, buf);
}
else
evas_object_data_set(obj, "accept_regex", regex);
}
if (spec.s.deny)
{
int ret;
regex = calloc(1, sizeof(regex_t));
ret = regcomp(regex, spec.s.deny, REG_EXTENDED | REG_NOSUB);
if (ret)
{
regerror(ret, regex, buf, sizeof(buf));
regfree(regex);
free(regex);
ERR("bad regular expression (%s) on item's 'deny' tag (%s)."
" Because of that, the 'deny' tag will be dropped for the "
"item.", spec.s.deny, buf);
}
else
evas_object_data_set(obj, "deny_regex", regex);
}
if (spec.s.length.min) /* zero makes no sense */
{
size_t min = (size_t) spec.s.length.min;
evas_object_data_set(obj, "min_size", (void *) min);
}
evas_object_event_callback_add
(obj, EVAS_CALLBACK_DEL, _entry_del_cb, NULL);
elm_entry_scrollable_set(obj, EINA_TRUE);
if (type == ELM_PREFS_TYPE_TEXT)
elm_entry_single_line_set(obj, EINA_TRUE);
elm_entry_markup_filter_append(obj, elm_entry_filter_limit_size, &limit);
elm_layout_text_set(obj, NULL, spec.s.placeholder);
return obj;
}
/* already expects an EINA_VALUE_TYPE_STRINGSHARE one */
static Eina_Bool
elm_prefs_entry_value_set(Evas_Object *obj,
Eina_Value *value)
{
const char *val;
eina_value_get(value, &val);
return elm_layout_text_set(obj, NULL, val);
}
static Eina_Bool
elm_prefs_entry_value_get(Evas_Object *obj,
Eina_Value *value)
{
const char *val;
val = elm_layout_text_get(obj, NULL);
if (!eina_value_setup(value, EINA_VALUE_TYPE_STRINGSHARE))
return EINA_FALSE;
if (!eina_value_set(value, val)) return EINA_FALSE;
return EINA_TRUE;
}
static Eina_Bool
elm_prefs_entry_icon_set(Evas_Object *obj,
const char *icon)
{
Evas_Object *ic = elm_icon_add(obj);
elm_icon_standard_set(ic, icon);
return elm_layout_content_set(obj, "icon", ic);
}
static Eina_Bool
elm_prefs_entry_editable_set(Evas_Object *obj,
Eina_Bool editable)
{
elm_entry_editable_set(obj, editable);
return EINA_TRUE;
}
static Eina_Bool
elm_prefs_entry_editable_get(Evas_Object *obj)
{
return elm_entry_editable_get(obj);
}
static Eina_Bool
elm_prefs_entry_expand_want(Evas_Object *obj EINA_UNUSED)
{
return EINA_TRUE;
}
PREFS_ITEM_WIDGET_ADD(entry,
supported_types,
elm_prefs_entry_value_set,
elm_prefs_entry_value_get,
elm_prefs_entry_value_validate,
NULL,
elm_prefs_entry_icon_set,
elm_prefs_entry_editable_set,
elm_prefs_entry_editable_get,
elm_prefs_entry_expand_want);