Intrudoce Efl Ui Date, Time interface and picker.

Summary: Create datepicker, timepicker with one manager class(efl_datetime).

Test Plan: datepicker, timepicker sample.

Reviewers: herb, Jaehyun_Cho, woohyun, SanghyeonLee

Reviewed By: Jaehyun_Cho

Subscribers: cedric

Differential Revision: https://phab.enlightenment.org/D5871
This commit is contained in:
Woochan Lee 2018-04-25 16:43:53 +09:00 committed by Jaehyun Cho
parent 3d6c72438d
commit ef2e6afd1f
24 changed files with 1905 additions and 9 deletions

View File

@ -1035,6 +1035,8 @@ elementary/themes/edc/efl/scroller.edc \
elementary/themes/edc/efl/slider.edc \
elementary/themes/edc/efl/spin.edc \
elementary/themes/edc/efl/spin_button.edc \
elementary/themes/edc/efl/datepicker.edc \
elementary/themes/edc/efl/timepicker.edc \
elementary/themes/edc/efl/text.edc \
elementary/themes/edc/efl/textpath.edc \
elementary/themes/edc/efl/tooltip.edc \

View File

@ -208,6 +208,14 @@ color_classes {
color: 0 0 0 0;
desc: "Background of a datetime widget";
}
color_class { name: "datepicker_bg";
color: 0 0 0 0;
desc: "Background of a datepicker widget";
}
color_class { name: "timepicker_bg";
color: 0 0 0 0;
desc: "Background of a timepicker widget";
}
color_class { name: "datetime_separator_text";
color: FN_COL_DEFAULT;
desc: "Text in a datetime separator area";

View File

@ -190,6 +190,8 @@ collections {
#include "edc/efl/border.edc"
#include "edc/efl/spin.edc"
#include "edc/efl/spin_button.edc"
#include "edc/efl/datepicker.edc"
#include "edc/efl/timepicker.edc"
// XXX: min size calc problems - too wide! ... err ok on my 32bit box... eh?
#include "edc/efl/cursor.edc"
#include "edc/efl/pointer.edc"

View File

@ -0,0 +1,345 @@
group { "efl/datepicker";
parts {
spacer { "base";
scale;
desc { "default";
min: 150 170;
}
}
rect { "base_bg";
scale;
desc { "default";
rel.to: "base";
color_class: "datepicker_bg";
}
}
spacer { "padding_bg_top";
scale;
desc { "default";
min: 0 10;
max: -1 10;
fixed: 0 1;
rel1 {
relative: 0.0 0.0;
to: "base_bg";
}
rel2 {
relative: 1.0 0.0;
to: "base_bg";
}
align: 0.5 0.0;
}
}
spacer { "padding_bg_bottom";
scale;
desc { "default";
min: 0 10;
max: -1 10;
fixed: 0 1;
rel1 {
relative: 0.0 1.0;
to: "base_bg";
}
rel2 {
relative: 1.0 1.0;
to: "base_bg";
}
align: 0.5 1.0;
}
}
spacer { "bg";
scale;
desc { "default";
min: 150 150;
max: 150 150;
rel1 {
relative: 0.0 1.0;
to: "padding_bg_top";
}
rel2 {
relative: 1.0 0.0;
to: "padding_bg_bottom";
}
}
}
spacer { "padding_left";
scale;
desc { "default";
min: 5 0;
max: 5 -1;
fixed: 1 0;
rel1 {
relative: 0.0 0.0;
to: "bg";
}
rel2 {
relative: 0.0 1.0;
to: "bg";
}
align: 0.0 0.0;
}
}
spacer { "padding_right";
scale;
desc { "default";
min: 5 0;
max: 5 -1;
fixed: 1 0;
rel2.to: "bg";
rel1 {
relative: 1.0 0.0;
to: "bg";
}
rel2 {
relative: 1.0 1.0;
to: "bg";
}
align: 1.0 1.0;
}
}
swallow { "field0";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
rel1 {
relative: 1.0 0.0;
to: "padding_left";
}
rel2.to: "padding_left";
align: 0.0 0.5;
}
}
spacer { "padding_center1";
scale;
desc { "default";
fixed: 1 0;
min: 10 0;
max: 10 -1;
rel1 {
relative: 1.0 0.0;
to: "field0";
}
rel2.to: "field0";
align: 0.0 0.5;
}
}
swallow { "field1";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
rel1 {
relative: 1.0 0.0;
to: "padding_center1";
}
rel2 {
relative: 0.0 1.0;
to_x: "padding_center2";
to_y: "padding_center1";
}
}
}
spacer { "padding_center2";
scale;
desc { "default";
fixed: 1 0;
min: 10 0;
max: 10 -1;
rel1.to: "field2";
rel2 {
relative: 0.0 1.0;
to: "field2";
}
align: 1.0 0.5;
}
}
swallow { "field2";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
rel1.to: "padding_right";
rel2 {
relative: 0.0 1.0;
to: "padding_right";
}
align: 1.0 0.5;
}
}
rect { "access";
repeat;
desc { "default";
fixed: 1 1;
rel1.to: "bg";
rel2.to: "bg";
color: 0 0 0 0;
}
}
}
}
group { "efl/datepicker/spin_button";
parts {
rect { "clip";
desc { "default";
rel.to: "elm.swallow.text_button";
}
}
spacer { "base";
scale;
desc { "default";
min: 40 150;
}
}
rect { "bg";
scale;
desc { "default";
color_class: "spinner_bg";
}
}
rect { "access";
repeat;
desc { "default";
fixed: 1 1;
color: 0 0 0 0;
rel1.to: "base";
rel2.to: "base";
hid;
}
desc { "active";
inherit: "default";
vis;
}
}
swallow { "elm.swallow.inc_button";
scale;
desc { "default";
align: 0.5 0.0;
min: 40 40;
max: 40 40;
fixed: 1 1;
}
}
swallow { "elm.swallow.dec_button";
scale;
desc { "default";
align: 0.5 1.0;
min: 40 40;
max: 40 40;
fixed: 1 1;
}
}
swallow { "elm.swallow.entry";
clip: "clip";
desc { "default";
fixed: 1 1;
rel1.to: "elm.swallow.text_button";
rel2.to: "elm.swallow.text_button";
hid;
}
desc { "active";
inherit: "default";
vis;
}
}
swallow { "elm.swallow.text_button";
scale;
desc { "default";
rel.to_x: "base";
rel1 {
to_y: "elm.swallow.inc_button";
relative: 0.0 1.0;
}
rel2 {
to_y: "elm.swallow.dec_button";
relative: 1.0 0.0;
}
min: 0 70;
max: -1 70;
fixed: 0 1;
}
desc { "inactive";
inherit: "default";
hid;
}
}
rect { "disabler";
norepeat;
nomouse;
desc { "default";
color: 0 0 0 0;
hid;
}
desc { "disabled";
inherit: "default";
vis;
}
}
}
programs {
program { "entry_active";
signal: "elm,state,entry,active";
source: "elm";
action: STATE_SET "active";
target: "elm.swallow.entry";
}
program { "entry_inactive";
signal: "elm,state,entry,inactive";
source: "elm";
action: STATE_SET "default";
target: "elm.swallow.entry";
}
program { "text_button_active";
signal: "elm,state,button,active";
source: "elm";
action: STATE_SET "default";
target: "elm.swallow.text_button";
}
program { "text_button_inactive";
signal: "elm,state,button,inactive";
source: "elm";
action: STATE_SET "inactive";
target: "elm.swallow.text_button";
}
program { "access_activate";
signal: "elm,state,access,active";
source: "elm";
action: STATE_SET "active";
target: "access";
}
program { "access_inactivate";
signal: "elm,state,access,inactive";
source: "elm";
action: STATE_SET "default";
target: "access";
}
program { "disable";
signal: "elm,state,disabled";
source: "elm";
action: STATE_SET "disabled";
target: "disabler";
}
program { "enable";
signal: "elm,state,enabled";
source: "elm";
action: STATE_SET "default";
target: "disabler";
}
}
}
group { "efl/datepicker/spin_button/text_button";
inherit: "efl/spin_button/text_button";
}
group { "efl/datepicker/spin_button/inc_button";
inherit: "elm/button/base/spinner/increase/vertical";
}
group { "efl/datepicker/spin_button/dec_button";
inherit: "elm/button/base/spinner/decrease/vertical";
}

View File

@ -356,6 +356,10 @@ group { name: "efl/spin_button/inc_button";
}
}
group { "efl/spin_button/entry";
inherit: "efl/text";
}
group { name: "efl/spin_button/dec_button";
inherit: "efl/spin_button/inc_button";
images.image: "sym_left_light_normal.png" COMP;

View File

@ -0,0 +1,409 @@
group { "efl/timepicker";
nomouse;
parts {
spacer { "base";
scale;
desc { "default";
min: 150 170;
}
desc { "24layout";
min: 110 170;
}
}
rect { "base_bg";
scale;
desc { "default";
rel.to: "base";
color_class: "timepicker_bg";
}
}
spacer { "padding_bg_top";
scale;
desc { "default";
min: 0 10;
max: -1 10;
fixed: 0 1;
rel1 {
relative: 0.0 0.0;
to: "base_bg";
}
rel2 {
relative: 1.0 0.0;
to: "base_bg";
}
align: 0.5 0.0;
}
}
spacer { "padding_bg_bottom";
scale;
desc { "default";
min: 0 10;
max: -1 10;
fixed: 0 1;
rel1 {
relative: 0.0 1.0;
to: "base_bg";
}
rel2 {
relative: 1.0 1.0;
to: "base_bg";
}
align: 0.5 1.0;
}
}
spacer { "bg";
scale;
desc { "default";
min: 150 150;
max: 150 150;
rel1 {
relative: 0.0 1.0;
to: "padding_bg_top";
}
rel2 {
relative: 1.0 0.0;
to: "padding_bg_bottom";
}
}
desc { "24layout";
inherit: "default";
min: 110 150;
max: 110 150;
}
}
spacer { "padding_left";
scale;
desc { "default";
min: 0 0;
max: 0 -1;
fixed: 1 0;
rel1 {
relative: 0.0 0.0;
to: "bg";
}
rel2 {
relative: 0.0 1.0;
to: "bg";
}
align: 0.0 0.0;
}
}
spacer { "padding_right";
scale;
desc { "default";
min: 0 0;
max: 0 -1;
fixed: 1 0;
rel1 {
relative: 1.0 0.0;
to: "bg";
}
rel2 {
relative: 1.0 1.0;
to: "bg";
}
align: 1.0 1.0;
}
}
swallow { "field0";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
rel1 {
relative: 1.0 0.0;
to: "padding_left";
}
rel2.to: "padding_left";
align: 0.0 0.5;
}
}
spacer{ "padding_center1";
scale;
desc { "default";
fixed: 1 0;
min: 3 0;
max: 3 -1;
rel1 {
relative: 1.0 0.0;
to: "field0";
}
rel2.to: "field0";
align: 0.0 0.5;
}
desc { "invisible";
inherit: default 0.0;
min: 15 0;
max: 15 -1;
}
}
spacer { "bg_text";
scale;
desc { "default";
rel1 {
relative: 1.0 0.0;
to: "padding_center1";
}
rel2.to: "padding_center1";
align: 0.0 0.5;
min: 9 0;
max: 9 -1;
fixed: 1 0;
}
desc { "invisible";
inherit: default 0.0;
min: 0 0;
max: 0 0;
}
}
text { "hour_minute_colon";
scale;
desc { "default";
rel1.to: "bg_text";
rel2.to: "bg_text";
color: 255 255 255 255;
fixed: 1 1;
text {
min: 1 0;
font: "Sans";
size: "15";
//text: ":";
align: 0.5 0.44;
}
vis;
}
desc { "invisible";
inherit: default 0.0;
hid;
}
}
spacer { "padding_center2";
scale;
desc { "default";
fixed: 1 0;
min: 3 0;
max: 3 -1;
rel1 {
relative: 1.0 0.0;
to: "bg_text";
}
rel2.to: "bg_text";
align: 0.0 0.5;
}
desc { "invisible";
inherit: default 0.0;
min: 0 0;
max: 0 0;
}
}
swallow { "field1";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
rel1 {
relative: 1.0 0.0;
to: "padding_center2";
}
rel2.to: "padding_center2";
align: 0.0 0.5;
}
}
spacer { "padding_center3";
scale;
desc { "default";
fixed: 1 0;
min: 3 0;
max: 3 -1;
rel1 {
relative: 1.0 0.0;
to: "field1";
}
rel2.to: "field1";
align: 0.0 0.5;
}
desc { "invisible";
inherit: default 0.0;
min: 15 0;
max: 15 -1;
}
}
spacer { "bg_text2";
scale;
desc { "default";
rel1 {
relative: 1.0 0.0;
to: "padding_center3";
}
rel2.to: "padding_center3";
align: 0.0 0.5;
min: 9 0;
max: 9 -1;
fixed: 1 0;
}
desc { "invisible";
inherit: default 0.0;
min: 0 0;
max: 0 0;
}
}
text { "hour_minute_colon2";
scale;
desc { "default";
rel1.to: "bg_text2";
rel2.to: "bg_text2";
color: 255 255 255 255;
fixed: 1 1;
text {
min: 1 0;
font: "Sans";
size: "15";
//text: ":";
align: 0.5 0.44;
}
vis;
}
desc { "invisible";
inherit: default 0.0;
hid;
}
}
spacer { "padding_center4";
scale;
desc { "default";
fixed: 1 0;
min: 3 0;
max: 3 -1;
rel1 {
relative: 1.0 0.0;
to: "bg_text2";
}
rel2.to: "bg_text2";
align: 0.0 0.5;
}
desc { "invisible";
inherit: default 0.0;
min: 0 0;
max: 0 0;
}
}
swallow { "field2";
mouse;
scale;
desc { "default";
fixed: 1 0;
min: 40 0;
max: 40 -1;
rel1 {
relative: 1.0 0.0;
to: "padding_center4";
}
rel2.to: "padding_center4";
align: 0.0 0.5;
}
desc { "24layout";
hid;
min: 0 0;
max: 0 -1;
}
}
rect { "access";
repeat;
desc { "default";
fixed: 1 1;
rel1.to: "bg";
rel2.to: "bg";
color: 0 0 0 0;
}
}
}
programs {
program { "visible_ampm";
signal: "elm,state,ampm,visible";
source: "elm";
script {
set_state(PART:"base", "default", 0.0);
set_state(PART:"bg", "default", 0.0);
set_state(PART:"field2", "default", 0.0);
}
}
program { "invisible_ampm";
signal: "elm,state,ampm,invisible";
source: "elm";
script {
set_state(PART:"base", "24layout", 0.0);
set_state(PART:"bg", "24layout", 0.0);
set_state(PART:"field2", "24layout", 0.0);
}
}
program { "visible_colon_field0";
signal: "elm,state,colon,visible,field0";
source: "elm";
action: STATE_SET "default";
target: "padding_center1";
target: "hour_minute_colon";
target: "bg_text";
target: "padding_center2";
}
program { "invisible_colon_field0";
signal: "elm,state,colon,invisible,field0";
source: "elm";
action: STATE_SET "invisible";
target: "padding_center1";
target: "hour_minute_colon";
target: "bg_text";
target: "padding_center2";
}
program { "visible_colon_field1";
signal: "elm,state,colon,visible,field1";
source: "elm";
action: STATE_SET "default";
target: "padding_center3";
target: "hour_minute_colon2";
target: "bg_text2";
target: "padding_center4";
}
program { "invisible_colon_field1";
signal: "elm,state,colon,invisible,field1";
source: "elm";
action: STATE_SET "invisible";
target: "padding_center3";
target: "hour_minute_colon2";
target: "bg_text2";
target: "padding_center4";
}
}
}
group { "efl/timepicker/spin_button";
inherit: "efl/datepicker/spin_button";
}
group { "efl/timepicker/spin_button/text_button";
inherit: "efl/spin_button/text_button";
}
group { "efl/timepicker/spin_button/inc_button";
inherit: "elm/button/base/spinner/increase/vertical";
}
group { "efl/timepicker/spin_button/dec_button";
inherit: "elm/button/base/spinner/decrease/vertical";
}
group { "efl/timepicker/button";
inherit: "efl/button";
parts {
image { "base";
desc { "default";
min: 40 40;
max: 40 40;
}
desc { "pressed";
min: 40 40;
max: 40 40;
}
}
}
}

View File

@ -854,8 +854,6 @@ group { name: "elm/entry/base-single/default";
group { name: "elm/entry/base-single/spinner/default";
alias: "elm/entry/base-single/spinner/vertical";
alias: "elm/entry/base-single/spin_button/default";
alias: "elm/entry/base-single/spin_button/vertical";
inherit: "elm/entry/base-single/default";
styles {
style { name: "entry_single_spinner_style";

View File

@ -27,6 +27,8 @@ elm_public_eolian_files = \
lib/elementary/efl_ui_slider_interval.eo \
lib/elementary/efl_ui_spin.eo \
lib/elementary/efl_ui_spin_button.eo \
lib/elementary/efl_ui_datepicker.eo \
lib/elementary/efl_ui_timepicker.eo \
lib/elementary/efl_ui_video.eo \
lib/elementary/efl_ui_win.eo \
lib/elementary/efl_ui_win_inlined.eo \
@ -145,6 +147,7 @@ elm_private_eolian_files = \
tests/elementary/focus_test.eo \
tests/elementary/focus_test_sub_main.eo \
lib/elementary/efl_selection_manager.eo \
lib/elementary/efl_datetime_manager.eo \
$(NULL)
# Legacy classes - not part of public EO API
@ -382,6 +385,8 @@ includesunstable_HEADERS = \
lib/elementary/elm_widget_spinner.h \
lib/elementary/efl_ui_spin_private.h \
lib/elementary/efl_ui_spin_button_private.h \
lib/elementary/efl_ui_datepicker_private.h \
lib/elementary/efl_ui_timepicker_private.h \
lib/elementary/elm_widget_table.h \
lib/elementary/elm_widget_thumb.h \
lib/elementary/elm_widget_toolbar.h \
@ -742,6 +747,8 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_ui_slider_interval.c \
lib/elementary/efl_ui_spin.c \
lib/elementary/efl_ui_spin_button.c \
lib/elementary/efl_ui_datepicker.c \
lib/elementary/efl_ui_timepicker.c \
lib/elementary/elm_slideshow.c \
lib/elementary/elm_spinner.c \
lib/elementary/elm_store.c \
@ -812,6 +819,7 @@ lib_elementary_libelementary_la_SOURCES = \
lib/elementary/efl_selection_manager.c \
lib/elementary/efl_selection_manager_private.h \
lib/elementary/efl_selection.c \
lib/elementary/efl_datetime_manager.c \
lib/elementary/efl_ui_dnd.c \
static_libs/buildsystem/buildsystem.h \
static_libs/buildsystem/buildsystem_autotools.c \
@ -1000,6 +1008,8 @@ bin/elementary/test_ui_slider.c \
bin/elementary/test_ui_slider_interval.c \
bin/elementary/test_ui_spin.c \
bin/elementary/test_ui_spin_button.c \
bin/elementary/test_ui_datepicker.c \
bin/elementary/test_ui_timepicker.c \
bin/elementary/test_slideshow.c \
bin/elementary/test_spinner.c \
bin/elementary/test_store.c \

View File

@ -133,6 +133,8 @@ test_slideshow.c \
test_spinner.c \
test_ui_spinner.c \
test_ui_buttonspin.c \
test_ui_datepicker.c \
test_ui_timepicker.c \
test_store.c \
test_sys_notify.c \
test_systray.c \

View File

@ -183,6 +183,8 @@ void test_efl_ui_scroller2(void *data, Evas_Object *obj, void *event_info);
void test_spinner(void *data, Evas_Object *obj, void *event_info);
void test_ui_spin(void *data, Evas_Object *obj, void *event_info);
void test_ui_spin_button(void *data, Evas_Object *obj, void *event_info);
void test_ui_datepicker(void *data, Evas_Object *obj, void *event_info);
void test_ui_timepicker(void *data, Evas_Object *obj, void *event_info);
void test_index(void *data, Evas_Object *obj, void *event_info);
void test_index2(void *data, Evas_Object *obj, void *event_info);
void test_index3(void *data, Evas_Object *obj, void *event_info);
@ -1084,6 +1086,8 @@ add_tests:
ADD_TEST(NULL, "Times & Dates", "Datetime", test_datetime);
ADD_TEST_EO(NULL, "Times & Dates", "Efl.Ui.Calendar", test_efl_ui_calendar);
ADD_TEST_EO(NULL, "Times & Dates", "Efl.Ui.Clock", test_ui_clock);
ADD_TEST_EO(NULL, "Times & Dates", "Efl.Ui.Datepicker", test_ui_datepicker);
ADD_TEST_EO(NULL, "Times & Dates", "Efl.Ui.Timepicker", test_ui_timepicker);
//------------------------------//
ADD_TEST(NULL, "Text", "Label", test_label);

View File

@ -0,0 +1,37 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
static void
_date_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
int year, month, day;
efl_ui_datepicker_date_get(ev->object, &year, &month, &day);
printf("Current date is %d %d %d\n", year, month, day);
}
void
test_ui_datepicker(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Eo *win, *bx;
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
efl_text_set(efl_added, "Efl.Ui.Datepicker"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_content_set(win, efl_added),
efl_ui_direction_set(efl_added, EFL_UI_DIR_DOWN));
efl_add(EFL_UI_DATEPICKER_CLASS, bx,
efl_ui_datepicker_date_set(efl_added, 1987, 9, 17),
efl_ui_datepicker_max_set(efl_added, 1990, 9, 17),
efl_ui_datepicker_min_set(efl_added, 1980, 9, 17),
efl_event_callback_add(efl_added, EFL_UI_DATEPICKER_EVENT_CHANGED,_date_changed_cb, NULL),
efl_pack(bx, efl_added));
efl_gfx_entity_size_set(win, EINA_SIZE2D(150, 170));
}

View File

@ -0,0 +1,36 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
static void
_time_changed_cb(void *data EINA_UNUSED, const Efl_Event *ev)
{
int hour, min;
efl_ui_timepicker_time_get(ev->object, &hour, &min);
printf("Current time is %d %d\n", hour, min);
}
void
test_ui_timepicker(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Eo *win, *bx;
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get(),
efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
efl_text_set(efl_added, "Efl.Ui.Timepicker"),
efl_ui_win_autodel_set(efl_added, EINA_TRUE));
bx = efl_add(EFL_UI_BOX_CLASS, win,
efl_content_set(win, efl_added),
efl_ui_direction_set(efl_added, EFL_UI_DIR_DOWN));
efl_add(EFL_UI_TIMEPICKER_CLASS, bx,
efl_ui_timepicker_time_set(efl_added, 11, 35),
efl_event_callback_add(efl_added, EFL_UI_TIMEPICKER_EVENT_CHANGED,_time_changed_cb, NULL),
efl_pack(bx, efl_added));
efl_gfx_entity_size_set(win, EINA_SIZE2D(150, 170));
}

View File

@ -319,6 +319,8 @@ typedef Eo Efl_Ui_Focus_Manager;
# include <efl_ui_clock.eo.h>
# include <efl_ui_spin.eo.h>
# include <efl_ui_spin_button.eo.h>
# include <efl_ui_datepicker.eo.h>
# include <efl_ui_timepicker.eo.h>
# include <efl_ui_image_factory.eo.h>
# include <efl_ui_slider_interval.eo.h>
# include <efl_ui_layout_factory.eo.h>

View File

@ -0,0 +1,193 @@
#include <config.h>
#include "Efl.h"
#ifdef HAVE_LANGINFO_H
# include <langinfo.h>
#endif
#include <Elementary.h>
#include "elm_priv.h"
#define MY_CLASS EFL_DATETIME_MANAGER_CLASS
#define MAX_FORMAT_LEN 32
static const char *multifield_formats = "cxXrRTDF";
typedef struct
{
Efl_Time time;
char format[MAX_FORMAT_LEN];
} Efl_Datetime_Manager_Data;
Eina_Bool init = EINA_FALSE;
static void
_time_init(Efl_Time *curr_time)
{
time_t t;
t = time(NULL);
localtime_r(&t, curr_time);
init = EINA_TRUE;
}
static char *
_expanded_fmt_str_get(char ch)
{
char *exp_fmt = "";
switch (ch)
{
case 'c':
#if defined(HAVE_LANGINFO_H) || defined (_WIN32)
exp_fmt = nl_langinfo(D_T_FMT);
#else
exp_fmt = "";
#endif
break;
case 'x':
#if defined(HAVE_LANGINFO_H) || defined (_WIN32)
exp_fmt = nl_langinfo(D_FMT);
#else
exp_fmt = "";
#endif
break;
case 'X':
#if defined(HAVE_LANGINFO_H) || defined (_WIN32)
exp_fmt = nl_langinfo(T_FMT);
#else
exp_fmt = "";
#endif
break;
case 'r':
#if defined(HAVE_LANGINFO_H) || defined (_WIN32)
exp_fmt = nl_langinfo(T_FMT_AMPM);
#else
exp_fmt = "";
#endif
break;
case 'R':
exp_fmt = "%H:%M";
break;
case 'T':
exp_fmt = "%H:%M:%S";
break;
case 'D':
exp_fmt = "%m/%d/%y";
break;
case 'F':
exp_fmt = "%Y-%m-%d";
break;
default:
exp_fmt = "";
break;
}
return exp_fmt;
}
static void
_expand_format(char *dt_fmt)
{
char *ptr, *expanded_fmt, ch;
unsigned int idx, len = 0;
char buf[MAX_FORMAT_LEN] = {0, };
Eina_Bool fmt_char, fmt_expanded;
do {
idx = 0;
fmt_char = EINA_FALSE;
fmt_expanded = EINA_FALSE;
ptr = dt_fmt;
while ((ch = *ptr))
{
if ((fmt_char) && (strchr(multifield_formats, ch)))
{
/* replace the multi-field format characters with
* corresponding expanded format */
expanded_fmt = _expanded_fmt_str_get(ch);
len = strlen(expanded_fmt);
if (len > 0) fmt_expanded = EINA_TRUE;
buf[--idx] = 0;
strncat(buf, expanded_fmt, len);
idx += len;
}
else buf[idx++] = ch;
if (ch == '%') fmt_char = EINA_TRUE;
else fmt_char = EINA_FALSE;
ptr++;
}
buf[idx] = 0;
strncpy(dt_fmt, buf, MAX_FORMAT_LEN);
} while (fmt_expanded);
}
EOLIAN static Eo*
_efl_datetime_manager_efl_object_constructor(Eo *obj, Efl_Datetime_Manager_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_datetime_manager_efl_object_destructor(Eo *obj, Efl_Datetime_Manager_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_datetime_manager_value_set(Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd, Efl_Time newtime)
{
pd->time = newtime;
}
EOLIAN static Efl_Time
_efl_datetime_manager_value_get(const Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd)
{
if (!init) _time_init(&pd->time);
return pd->time;
}
EOLIAN static void
_efl_datetime_manager_format_set(Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd EINA_UNUSED, const char *fmt EINA_UNUSED)
{
//Is this needed?
}
EOLIAN static const char *
_efl_datetime_manager_format_get(const Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd)
{
#if defined(HAVE_LANGINFO_H) || defined (_WIN32)
strncpy(pd->format, nl_langinfo(D_T_FMT), MAX_FORMAT_LEN);
#else
strncpy(pd->format, "", MAX_FORMAT_LEN);
#endif
pd->format[MAX_FORMAT_LEN - 1] = '\0';
_expand_format(pd->format);
return pd->format;
}
EOLIAN static const char *
_efl_datetime_manager_string_get(const Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd EINA_UNUSED, const char *fmt EINA_UNUSED)
{
//TODO: strftime on upsteam, icu module connect here on tizen.
return NULL;
}
#include "efl_datetime_manager.eo.c"

View File

@ -0,0 +1,50 @@
import efl_types;
class Efl.Datetime.Manager (Efl.Object)
{
[[Efl datetime manager class for Datepicker and Timepicker]]
methods {
@property value {
[[The value of a date, time for Datepicker or Timepicker.
The value for Datepicker contains year, month, and day. (tm_year, tm_mon, and tm_mday in Efl_Time)
The value for Timepicker contains hour, and min. (tm_hour, and tm_min in Efl_Time)
]]
set {
}
get {
}
values {
newtime: Efl.Time; [[Time structure containing date or time value.]]
}
}
@property format {
[[The format of date or time.
Default format is taken as per the system locale settings.
]]
set {
}
get {
}
values {
fmt: string; [[The format string]]
}
}
@property string {
get {
[[Get the string that matches with the format.]]
}
keys {
fmt: string; [[The format string]]
}
values {
string: string; [[The string that matches with the format]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
}

View File

@ -0,0 +1,349 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#include "efl_ui_datepicker_private.h"
#define MY_CLASS EFL_UI_DATEPICKER_CLASS
#define MY_CLASS_NAME "Efl.Ui.Datepicker"
#define FMT_LEN_MAX 32
#define DATE_GET() \
do { \
Efl_Time t = efl_datetime_manager_value_get(pd->dt_manager); \
pd->cur_date[DATEPICKER_YEAR] = t.tm_year + 1900; \
pd->cur_date[DATEPICKER_MONTH] = t.tm_mon + 1; \
pd->cur_date[DATEPICKER_DAY] = t.tm_mday; \
} while (0)
#define DATE_SET() \
do { \
Efl_Time t; \
t.tm_year = pd->cur_date[DATEPICKER_YEAR] - 1900; \
t.tm_mon = pd->cur_date[DATEPICKER_MONTH] - 1; \
t.tm_mday = pd->cur_date[DATEPICKER_DAY]; \
efl_datetime_manager_value_set(pd->dt_manager, t); \
} while (0)
static const char *fmt_char[] = {"Yy", "mbBh", "de"};
static Eina_Bool
_validate_params(int year, int month, int day)
{
if (year < 1900 || year > 2037 || month < 1 || month > 12 || day < 0 || day > 31)
return EINA_FALSE;
else return EINA_TRUE;
}
static Eina_Bool
_date_cmp(int time1[], int time2[])
{
unsigned int idx;
for (idx = 0; idx < EFL_UI_DATEPICKER_TYPE_COUNT; idx++)
{
if (time1[idx] != time2[idx])
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
_validate_date_limits(int time1[], int time2[], Eina_Bool swap)
{
unsigned int idx;
int *t1, *t2;
t1 = (swap) ? time2 : time1;
t2 = (swap) ? time1 : time2;
for (idx = 0; idx < EFL_UI_DATEPICKER_TYPE_COUNT; idx++)
{
if (time1[idx] < time2[idx])
{
memcpy(t1, t2, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT));
return EINA_TRUE;
}
else if (time1[idx] > time2[idx])
return EINA_FALSE;
}
return EINA_FALSE;
}
static int
_max_days_get(int year, int month)
{
struct tm time1;
time_t t;
int day;
t = time(NULL);
localtime_r(&t, &time1);
time1.tm_year = year;
time1.tm_mon = month;
for (day = 28; day <= 31;
day++)
{
time1.tm_mday = day;
mktime(&time1);
/* To restrict month wrapping because of summer time in some locales,
* ignore day light saving mode in mktime(). */
time1.tm_isdst = -1;
if (time1.tm_mday == 1) break;
}
day--;
return day;
}
static void
_field_value_update(Eo *obj)
{
Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS);
efl_ui_range_value_set(pd->year, pd->cur_date[DATEPICKER_YEAR]);
efl_ui_range_value_set(pd->month, pd->cur_date[DATEPICKER_MONTH]);
efl_ui_range_value_set(pd->day, pd->cur_date[DATEPICKER_DAY]);
DATE_SET();
}
static void
_field_changed_cb(void *data, const Efl_Event *ev)
{
int max_day;
Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(data, MY_CLASS);
if (ev->object == pd->year)
pd->cur_date[DATEPICKER_YEAR] = efl_ui_range_value_get(pd->year);
else if (ev->object == pd->month)
pd->cur_date[DATEPICKER_MONTH] = efl_ui_range_value_get(pd->month);
else
pd->cur_date[DATEPICKER_DAY] = efl_ui_range_value_get(pd->day);
if (!(ev->object == pd->day))
{
max_day = _max_days_get((pd->cur_date[DATEPICKER_YEAR] - 1900), (pd->cur_date[DATEPICKER_MONTH] - 1));
efl_ui_range_min_max_set(pd->day, 1, max_day);
}
if (_validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE) ||
_validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE))
{
_field_value_update(data);
return;
}
DATE_SET();
efl_event_callback_call(data, EFL_UI_DATEPICKER_EVENT_CHANGED, NULL);
}
static void
_fields_init(Eo *obj)
{
const char *fmt;
char ch;
int i;
int field = 0;
char buf[FMT_LEN_MAX];
Efl_Ui_Datepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS);
//Field create.
pd->year = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj,
efl_ui_range_min_max_set(efl_added, 1970, 2037),
efl_ui_spin_button_circulate_set(efl_added, EINA_TRUE),
efl_ui_spin_button_editable_set(efl_added, EINA_TRUE),
efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "spin_button"));
pd->month = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj,
efl_ui_range_min_max_set(efl_added, 1, 12),
efl_ui_spin_button_circulate_set(efl_added, EINA_TRUE),
efl_ui_spin_button_editable_set(efl_added, EINA_TRUE),
efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "spin_button"));
pd->day = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj,
efl_ui_range_min_max_set(efl_added, 1, 31),
efl_ui_spin_button_circulate_set(efl_added, EINA_TRUE),
efl_ui_spin_button_editable_set(efl_added, EINA_TRUE),
efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "spin_button"));
DATE_GET();
//Using system config?
pd->min_date[DATEPICKER_YEAR] = 1970;
pd->min_date[DATEPICKER_MONTH] = 1;
pd->min_date[DATEPICKER_DAY] = 1;
pd->max_date[DATEPICKER_YEAR] = 2037;
pd->max_date[DATEPICKER_MONTH] = 12;
pd->max_date[DATEPICKER_DAY] = 31;
_field_value_update(obj);
fmt = efl_datetime_manager_format_get(pd->dt_manager);
if (!fmt)
{
ERR("Failed to get current format.");
//Gives default format when the gets format failed.
fmt = "%Y %b %d";
}
//Sort fields by format.
while((ch = *fmt))
{
//TODO: ignore extensions and separators.
for (i = 0; i < EFL_UI_DATEPICKER_TYPE_COUNT; i++)
{
if (strchr(fmt_char[i], ch))
{
snprintf(buf, sizeof(buf), "field%d", field++);
if (i == DATEPICKER_YEAR)
efl_content_set(efl_part(obj, buf), pd->year);
else if (i == DATEPICKER_MONTH)
efl_content_set(efl_part(obj, buf), pd->month);
else
efl_content_set(efl_part(obj, buf), pd->day);
break;
}
}
fmt++;
}
}
EOLIAN static void
_efl_ui_datepicker_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Datepicker_Data *_pd EINA_UNUSED)
{
Evas_Coord minw = -1, minh = -1;
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
elm_coords_finger_size_adjust(1, &minw, 1, &minh);
edje_object_size_min_restricted_calc
(wd->resize_obj, &minw, &minh, minw, minh);
elm_coords_finger_size_adjust(1, &minw, 1, &minh);
evas_object_size_hint_min_set(obj, minw, minh);
evas_object_size_hint_max_set(obj, -1, -1);
}
EOLIAN static Eo *
_efl_ui_datepicker_efl_object_constructor(Eo *obj, Efl_Ui_Datepicker_Data *pd)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "datepicker");
obj = efl_constructor(efl_super(obj, MY_CLASS));
if (!elm_widget_theme_object_set(obj, wd->resize_obj,
elm_widget_theme_klass_get(obj),
elm_widget_theme_element_get(obj),
elm_widget_theme_style_get(obj)))
CRI("Failed to set layout!");
pd->dt_manager = efl_add(EFL_DATETIME_MANAGER_CLASS, obj);
_fields_init(obj);
elm_widget_sub_object_parent_add(obj);
elm_widget_can_focus_set(obj, EINA_TRUE);
return obj;
}
EOLIAN static void
_efl_ui_datepicker_efl_object_destructor(Eo *obj, Efl_Ui_Datepicker_Data *pd)
{
efl_del(pd->dt_manager);
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_ui_datepicker_min_set(Eo *obj, Efl_Ui_Datepicker_Data *pd EINA_UNUSED, int year, int month, int day)
{
int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day};
if (!_validate_params(year, month, day)) return;
if (_date_cmp(pd->min_date, new_time)) return;
memcpy(pd->min_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT));
_validate_date_limits(pd->max_date, pd->min_date, EINA_FALSE);
_validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE);
DATE_SET();
_field_value_update(obj);
}
EOLIAN static void
_efl_ui_datepicker_min_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day)
{
*year = pd->min_date[DATEPICKER_YEAR];
*month = pd->min_date[DATEPICKER_MONTH];
*day = pd->min_date[DATEPICKER_DAY];
}
EOLIAN static void
_efl_ui_datepicker_max_set(Eo *obj, Efl_Ui_Datepicker_Data *pd EINA_UNUSED, int year, int month, int day)
{
int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day};
if (!_validate_params(year, month, day)) return;
if (_date_cmp(pd->max_date, new_time)) return;
memcpy(pd->max_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT));
_validate_date_limits(pd->max_date, pd->min_date, EINA_TRUE);
_validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE);
DATE_SET();
_field_value_update(obj);
}
EOLIAN static void
_efl_ui_datepicker_max_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day)
{
*year = pd->max_date[DATEPICKER_YEAR];
*month = pd->max_date[DATEPICKER_MONTH];
*day = pd->max_date[DATEPICKER_DAY];
}
EOLIAN static void
_efl_ui_datepicker_date_set(Eo *obj, Efl_Ui_Datepicker_Data *pd, int year, int month, int day)
{
int new_time[EFL_UI_DATEPICKER_TYPE_COUNT] = {year, month, day};
if (!_validate_params(year, month, day)) return;
if (_date_cmp(pd->cur_date, new_time)) return;
memcpy(pd->cur_date, new_time, (sizeof(int) * EFL_UI_DATEPICKER_TYPE_COUNT));
_validate_date_limits(pd->cur_date, pd->min_date, EINA_FALSE);
_validate_date_limits(pd->max_date, pd->cur_date, EINA_TRUE);
DATE_SET();
_field_value_update(obj);
}
EOLIAN static void
_efl_ui_datepicker_date_get(const Eo *obj EINA_UNUSED, Efl_Ui_Datepicker_Data *pd, int *year, int *month, int *day)
{
*year = pd->cur_date[DATEPICKER_YEAR];
*month = pd->cur_date[DATEPICKER_MONTH];
*day = pd->cur_date[DATEPICKER_DAY];
}
#define EFL_UI_DATEPICKER_EXTRA_OPS \
ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_datepicker), \
#include "efl_ui_datepicker.eo.c"

View File

@ -0,0 +1,75 @@
class Efl.Ui.Datepicker (Efl.Ui.Layout.Object)
{
[[Datepicker widget
This is a widget which allows the user to pick a date using internal spinner.
User can use the internal spinner to select year, month, day or user can input
value using internal entry.
]]
methods {
@property min {
[[The lower boundary of date.
$year: Year. The year range is from 1900 to 2137.
$month: Month. The month range is from 1 to 12.
$day: Day. The day range is from 1 to 31 according to $month.
]]
set {
}
get{
}
values {
year: int; [[The year value.]]
month: int; [[The month value from 1 to 12.]]
day: int; [[The day value from 1 to 31.]]
}
}
@property max {
[[The upper boundary of date.
$year: Year. The year range is from 1900 to 2137.
$month: Month. The month range is from 1 to 12.
$day: Day. The day range is from 1 to 31 according to $month.
]]
set {
}
get {
}
values {
year: int; [[The year value.]]
month: int; [[The month value from 1 to 12.]]
day: int; [[The day value from 1 to 31.]]
}
}
@property date {
[[The current value of date.
$year: Year. The year range is from 1900 to 2137.
$month: Month. The month range is from 0 to 11.
$day: Day. The day range is from 1 to 31 according to $month.
]]
set {
}
get{
}
values {
year: int; [[The year value.]]
month: int; [[The month value from 1 to 12.]]
day: int; [[The day value from 1 to 31.]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
events {
changed; [[Called when date value is changed]]
}
}

View File

@ -0,0 +1,22 @@
#ifndef EFL_UI_DATEPICKER_PRIVATE_H
#define EFL_UI_DATEPICKER_PRIVATE_H
#define EFL_UI_DATEPICKER_TYPE_COUNT 3
typedef enum _Efl_Ui_Datepicker_Field_Type
{
DATEPICKER_YEAR,
DATEPICKER_MONTH,
DATEPICKER_DAY
} Efl_Ui_Datepicker_Field_Type;
typedef struct _Efl_Ui_Datepicker_Data Efl_Ui_Datepicker_Data;
struct _Efl_Ui_Datepicker_Data
{
Eo *dt_manager, *year, *month, *day;
int cur_date[EFL_UI_DATEPICKER_TYPE_COUNT],
min_date[EFL_UI_DATEPICKER_TYPE_COUNT],
max_date[EFL_UI_DATEPICKER_TYPE_COUNT];
};
#endif

View File

@ -20,6 +20,7 @@
#define EFL_UI_SPIN_BUTTON_DELAY_CHANGE_TIME 0.2
static const char PART_NAME_ENTRY[] = "entry";
static const char PART_NAME_DEC_BUTTON[] = "dec_button";
static const char PART_NAME_TEXT_BUTTON[] = "text_button";
static const char PART_NAME_INC_BUTTON[] = "inc_button";
@ -723,13 +724,7 @@ _efl_ui_spin_button_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Spin_Button_Data *
if (!int_ret) return EFL_UI_THEME_APPLY_FAILED;
if (sd->ent)
{
//elm_widget_element_update(obj, sd->ent, PART_NAME_TEXT);
Eina_Strbuf *buf = eina_strbuf_new();
eina_strbuf_append_printf(buf, "spin_button/%s", elm_widget_style_get(obj));
elm_widget_style_set(sd->ent, eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
}
elm_widget_element_update(obj, sd->ent, PART_NAME_ENTRY);
if (sd->inc_button)
elm_widget_element_update(obj, sd->inc_button, PART_NAME_INC_BUTTON);

View File

@ -0,0 +1,285 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#include "elm_priv.h"
#include "efl_ui_timepicker_private.h"
#define MY_CLASS EFL_UI_TIMEPICKER_CLASS
#define MY_CLASS_NAME "Efl.Ui.Timepicker"
#define FMT_LEN_MAX 32
#define TIME_GET() \
do { \
Efl_Time t = efl_datetime_manager_value_get(pd->dt_manager); \
pd->cur_time[TIMEPICKER_HOUR] = t.tm_hour; \
pd->cur_time[TIMEPICKER_MIN] = t.tm_min; \
} while (0)
#define TIME_SET() \
do { \
Efl_Time t; \
t.tm_hour = pd->cur_time[TIMEPICKER_HOUR]; \
t.tm_min = pd->cur_time[TIMEPICKER_MIN]; \
efl_datetime_manager_value_set(pd->dt_manager, t); \
} while (0)
static const char *fmt_char[] = {"IHkl", "M", "Aa"};
static Eina_Bool
_validate_params(int hour, int min)
{
if (hour < 0 || hour > 23 || min < 0 || min > 59)
return EINA_FALSE;
else return EINA_TRUE;
}
static Eina_Bool
_time_cmp(int time1[], int time2[])
{
unsigned int idx;
for (idx = 0; idx < EFL_UI_TIMEPICKER_TYPE_COUNT -1; idx++)
{
if (time1[idx] != time2[idx])
return EINA_FALSE;
}
return EINA_TRUE;
}
static void
_field_value_update(Eo *obj)
{
Efl_Ui_Timepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS);
if (!pd->is_24hour)
{
if (pd->cur_time[TIMEPICKER_HOUR] >= 12)
{
//TODO: gets text from strftime.
efl_text_set(pd->ampm, "PM");
efl_ui_range_value_set(pd->hour, pd->cur_time[TIMEPICKER_HOUR] - 12);
}
else
{
efl_text_set(pd->ampm, "AM");
efl_ui_range_value_set(pd->hour, pd->cur_time[TIMEPICKER_HOUR] + 12);
}
}
efl_ui_range_value_set(pd->min, pd->cur_time[TIMEPICKER_MIN]);
TIME_SET();
}
static void
_field_changed_cb(void *data, const Efl_Event *ev)
{
Efl_Ui_Timepicker_Data *pd = efl_data_scope_get(data, MY_CLASS);
//TODO: hour value increase when min reached max.
if (ev->object == pd->hour)
{
pd->cur_time[TIMEPICKER_HOUR] = efl_ui_range_value_get(pd->hour);
if (!pd->is_24hour && !strcmp(efl_text_get(pd->ampm), "PM"))
pd->cur_time[TIMEPICKER_HOUR] += 12;
}
else if (ev->object == pd->min)
pd->cur_time[TIMEPICKER_MIN] = efl_ui_range_value_get(pd->min);
else
{
if (!strcmp(efl_text_get(pd->ampm), "PM"))
{
efl_text_set(pd->ampm, "AM");
pd->cur_time[TIMEPICKER_HOUR] -= 12;
}
else
{
efl_text_set(pd->ampm, "PM");
pd->cur_time[TIMEPICKER_HOUR] += 12;
}
}
TIME_SET();
efl_event_callback_call(data, EFL_UI_TIMEPICKER_EVENT_CHANGED, NULL);
}
static void
_fields_init(Eo *obj)
{
const char *fmt;
char ch;
int i;
int field = 0;
char buf[FMT_LEN_MAX];
Efl_Ui_Timepicker_Data *pd = efl_data_scope_get(obj, MY_CLASS);
//Field create.
pd->hour = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj,
efl_ui_range_min_max_set(efl_added, 1, 12),
efl_ui_spin_button_circulate_set(efl_added, EINA_TRUE),
efl_ui_spin_button_editable_set(efl_added, EINA_TRUE),
efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "spin_button"));
pd->min = efl_add(EFL_UI_SPIN_BUTTON_CLASS, obj,
efl_ui_range_min_max_set(efl_added, 0, 59),
efl_ui_spin_button_circulate_set(efl_added, EINA_TRUE),
efl_ui_spin_button_editable_set(efl_added, EINA_TRUE),
efl_event_callback_add(efl_added, EFL_UI_SPIN_EVENT_CHANGED,_field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "spin_button"));
pd->ampm = efl_add(EFL_UI_BUTTON_CLASS, obj,
efl_event_callback_add(efl_added, EFL_UI_EVENT_CLICKED, _field_changed_cb, obj),
elm_widget_element_update(obj, efl_added, "button"));
pd->dt_manager = efl_add(EFL_DATETIME_MANAGER_CLASS, obj);
TIME_GET();
pd->is_24hour = EINA_FALSE;
_field_value_update(obj);
fmt = efl_datetime_manager_format_get(pd->dt_manager);
if (!fmt)
{
ERR("Failed to get current format.");
//Gives default format when the gets format failed.
fmt = "%H:%M %a";
}
//Sort fields by format.
while((ch = *fmt))
{
//TODO: ignore extensions and separators.
for (i = 0; i < EFL_UI_TIMEPICKER_TYPE_COUNT; i++)
{
if (strchr(fmt_char[i], ch))
{
snprintf(buf, sizeof(buf), "field%d", field);
if (i == TIMEPICKER_HOUR)
efl_content_set(efl_part(obj, buf), pd->hour);
else if (i == TIMEPICKER_MIN)
efl_content_set(efl_part(obj, buf), pd->min);
else
{
//TODO: monitoring locale change and update field location.
if (field == 0)
{
elm_object_signal_emit(obj, "elm,state,colon,visible,field1", "elm");
elm_object_signal_emit(obj, "elm,state,colon,invisible,field0", "elm");
}
else
{
elm_object_signal_emit(obj, "elm,state,colon,visible,field0", "elm");
elm_object_signal_emit(obj, "elm,state,colon,invisible,field1", "elm");
}
elm_layout_signal_emit(obj, "elm,state,ampm,visible", "elm");
edje_object_message_signal_process(elm_layout_edje_get(obj));
efl_content_set(efl_part(obj, buf), pd->ampm);
}
field++;
break;
}
}
fmt++;
}
}
EOLIAN static void
_efl_ui_timepicker_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Timepicker_Data *_pd EINA_UNUSED)
{
Evas_Coord minw = -1, minh = -1;
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
elm_coords_finger_size_adjust(1, &minw, 1, &minh);
edje_object_size_min_restricted_calc
(wd->resize_obj, &minw, &minh, minw, minh);
elm_coords_finger_size_adjust(1, &minw, 1, &minh);
evas_object_size_hint_min_set(obj, minw, minh);
evas_object_size_hint_max_set(obj, -1, -1);
}
EOLIAN static Eo *
_efl_ui_timepicker_efl_object_constructor(Eo *obj, Efl_Ui_Timepicker_Data *pd EINA_UNUSED)
{
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
if (!elm_widget_theme_klass_get(obj))
elm_widget_theme_klass_set(obj, "timepicker");
obj = efl_constructor(efl_super(obj, MY_CLASS));
if (!elm_widget_theme_object_set(obj, wd->resize_obj,
elm_widget_theme_klass_get(obj),
elm_widget_theme_element_get(obj),
elm_widget_theme_style_get(obj)))
CRI("Failed to set layout!");
_fields_init(obj);
elm_widget_sub_object_parent_add(obj);
elm_widget_can_focus_set(obj, EINA_TRUE);
return obj;
}
EOLIAN static void
_efl_ui_timepicker_efl_object_destructor(Eo *obj, Efl_Ui_Timepicker_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_ui_timepicker_time_set(Eo *obj, Efl_Ui_Timepicker_Data *pd, int hour, int min)
{
int new_time[EFL_UI_TIMEPICKER_TYPE_COUNT - 1] = {hour, min};
if (!_validate_params(hour, min)) return;
if (_time_cmp(pd->cur_time, new_time)) return;
memcpy(pd->cur_time, new_time, (sizeof(int) * (EFL_UI_TIMEPICKER_TYPE_COUNT -1)));
TIME_SET();
_field_value_update(obj);
}
EOLIAN static void
_efl_ui_timepicker_time_get(const Eo *obj EINA_UNUSED, Efl_Ui_Timepicker_Data *pd, int *hour, int *min)
{
*hour = pd->cur_time[TIMEPICKER_HOUR];
*min = pd->cur_time[TIMEPICKER_MIN];
}
EOLIAN static void
_efl_ui_timepicker_ampm_set(Eo *obj, Efl_Ui_Timepicker_Data *pd, Eina_Bool is_24hour)
{
if (pd->is_24hour == is_24hour) return;
pd->is_24hour = is_24hour;
if (pd->is_24hour == EINA_TRUE)
elm_layout_signal_emit(obj, "elm,state,ampm,invisible", "elm");
else
elm_layout_signal_emit(obj, "elm,state,ampm,visible", "elm");
_field_value_update(obj);
}
EOLIAN static Eina_Bool
_efl_ui_timepicker_ampm_get(const Eo *obj EINA_UNUSED, Efl_Ui_Timepicker_Data *pd)
{
return pd->is_24hour;
}
#define EFL_UI_TIMEPICKER_EXTRA_OPS \
ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_timepicker), \
#include "efl_ui_timepicker.eo.c"

View File

@ -0,0 +1,44 @@
class Efl.Ui.Timepicker (Efl.Ui.Layout.Object)
{
[[Timepicker widget
This is a widget which allows the user to pick a time using internal spinner.
User can use the internal spinner to select hour, minute, AM/PM or user can input
value using internal entry.
]]
methods {
@property time {
[[The current value of time
$hour: Hour. The hour value is in terms of 24 hour format from 0 to 23.
$min: Minute. The minute range is from 0 to 59.
]]
set {
}
get{
}
values {
hour: int; [[The hour value from 0 to 23.]]
min: int; [[The minute value from 0 to 59.]]
}
}
@property ampm {
[[Control if the Timepicker displays 24 hour time or 12 hour time including AM/PM button.]]
set {
}
get {
}
values {
is_24hour: bool; [[$true to display the 24 hour time, $false to display 12 hour time including AM/PM button.]]
}
}
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;
}
events {
changed; [[Called when date is changed]]
}
}

View File

@ -0,0 +1,21 @@
#ifndef EFL_UI_TIMEPICKER_PRIVATE_H
#define EFL_UI_TIMEPICKER_PRIVATE_H
#define EFL_UI_TIMEPICKER_TYPE_COUNT 3
typedef enum _Efl_Ui_Timepicker_Field_Type
{
TIMEPICKER_HOUR,
TIMEPICKER_MIN,
TIMEPICKER_AMPM
} Efl_Ui_Timepicker_Field_Type;
typedef struct _Efl_Ui_Timepicker_Data Efl_Ui_Timepicker_Data;
struct _Efl_Ui_Timepicker_Data
{
Eo *dt_manager, *hour, *min, *ampm;
int cur_time[EFL_UI_TIMEPICKER_TYPE_COUNT];
Eina_Bool is_24hour;
};
#endif

View File

@ -112,6 +112,8 @@ static const Elm_Color_Class _elm_color_classes[] = {
{"calendar_day_highlighted", "Highlighted Day Effect"},
{"calendar_day_checked", "Checked Day Effect"},
{"datetime_bg", "Datetime Background"},
{"datepicker_bg", "Datepicker Background"},
{"timepicker_bg", "Timepicker Background"},
{"datetime_separator_text", "Datetime Separator Text"},
{"datetime_separator_text_disabled", "Datetime Separator Disabled Text"},
{"hoversel_item_active", "Hoversel Item Text"},

View File

@ -67,6 +67,7 @@
# include "efl_ui_focus_parent_provider_standard.eo.h"
# include "elm_widget_item_static_focus.eo.h"
#include "efl_selection_manager.eo.h"
# include "efl_datetime_manager.eo.h"
# ifdef HAVE_LANGINFO_H
# include <langinfo.h>