From 14df28cdaebb78613411753f2445765c6e2468ec Mon Sep 17 00:00:00 2001 From: Sumanth Krishna Mannam Date: Mon, 5 Mar 2012 11:07:05 +0000 Subject: [PATCH] From: Sumanth Krishna Mannam Subject: [E-devel] [Patch] Elementary : New widget Elm_datetime patch Attached to the mail is the patch for new elementary widget elm_datetime. Refer to the below EFL post history for more details. The datetime widget provides an option to display Date & time based on current locale format and the user can edit them through dynamic Modules. Dynamic modules can be based on 1. Content Popup/diskselector based list 2. Elm_entry with ISE based input 3. Elm_Spinner based etc. Refer to the Screenshots: <1.ctxpopup_diskselector_UI> <2.entry_ise_UI> <3.spinner_selection_UI> Can someone review and push this patch to EFL repository? Change description: New widget Elm_datetime is added. Datetime widget displays the Date &Time fields and provides a customizable way to edit them. The widget is implemented in a modular fashion for date/time field inputs. Ctxpopup based input is proposed as the default selection module. Localization support based on Libc is also supported. Sign-Off By: Sumanth M.V.K SVN revision: 68696 --- legacy/elementary/AUTHORS | 1 + legacy/elementary/config/default/base.src | 2 +- legacy/elementary/config/illume/base.src | 2 +- legacy/elementary/configure.ac | 1 + legacy/elementary/data/themes/default.edc | 1 + .../data/themes/widgets/datetime.edc | 349 ++++++ legacy/elementary/doc/Makefile.am | 3 + legacy/elementary/doc/examples.dox | 53 + legacy/elementary/doc/index.doxy | 4 + legacy/elementary/doc/widgets/Makefile.am | 6 + .../doc/widgets/widget_preview_datetime1.c | 16 + .../doc/widgets/widget_preview_datetime2.c | 19 + .../doc/widgets/widget_preview_datetime3.c | 19 + legacy/elementary/src/bin/Makefile.am | 1 + legacy/elementary/src/bin/test.c | 2 + legacy/elementary/src/bin/test_datetime.c | 81 ++ legacy/elementary/src/examples/Makefile.am | 3 + legacy/elementary/src/lib/Elementary.h.in | 1 + legacy/elementary/src/lib/Makefile.am | 2 + legacy/elementary/src/lib/elm_datetime.c | 1039 +++++++++++++++++ legacy/elementary/src/lib/elm_datetime.h | 596 ++++++++++ legacy/elementary/src/lib/elm_priv.h | 8 + legacy/elementary/src/modules/Makefile.am | 3 +- .../datetime_input_ctxpopup/Makefile.am | 33 + .../datetime_input_ctxpopup.c | 325 ++++++ 25 files changed, 2567 insertions(+), 3 deletions(-) create mode 100644 legacy/elementary/data/themes/widgets/datetime.edc create mode 100644 legacy/elementary/doc/widgets/widget_preview_datetime1.c create mode 100644 legacy/elementary/doc/widgets/widget_preview_datetime2.c create mode 100644 legacy/elementary/doc/widgets/widget_preview_datetime3.c create mode 100644 legacy/elementary/src/bin/test_datetime.c create mode 100644 legacy/elementary/src/lib/elm_datetime.c create mode 100644 legacy/elementary/src/lib/elm_datetime.h create mode 100644 legacy/elementary/src/modules/datetime_input_ctxpopup/Makefile.am create mode 100644 legacy/elementary/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c diff --git a/legacy/elementary/AUTHORS b/legacy/elementary/AUTHORS index dab520286e..9bad23e484 100644 --- a/legacy/elementary/AUTHORS +++ b/legacy/elementary/AUTHORS @@ -53,3 +53,4 @@ Hyunsil Park Goun Lee Mikael Sans Doyoun Kang +M.V.K. Sumanth diff --git a/legacy/elementary/config/default/base.src b/legacy/elementary/config/default/base.src index 7d5f0c6a8d..59a40a247c 100644 --- a/legacy/elementary/config/default/base.src +++ b/legacy/elementary/config/default/base.src @@ -26,7 +26,7 @@ group "Elm_Config" struct { value "finger_size" int: 40; value "fps" double: 60.0; value "theme" string: "default"; - value "modules" string: ""; + value "modules" string: "datetime_input_ctxpopup>datetime/api"; value "tooltip_delay" double: 1.0; value "cursor_engine_only" uchar: 1; value "focus_highlight_enable" uchar: 0; diff --git a/legacy/elementary/config/illume/base.src b/legacy/elementary/config/illume/base.src index 688dfd80e4..7c87276ace 100644 --- a/legacy/elementary/config/illume/base.src +++ b/legacy/elementary/config/illume/base.src @@ -30,7 +30,7 @@ group "Elm_Config" struct { value "finger_size" int: 40; value "fps" double: 60.0; value "theme" string: "default"; - value "modules" string: ""; + value "modules" string: "datetime_input_ctxpopup>datetime/api"; value "tooltip_delay" double: 1.0; value "cursor_engine_only" uchar: 1; value "focus_highlight_enable" uchar: 0; diff --git a/legacy/elementary/configure.ac b/legacy/elementary/configure.ac index bcf85e2d36..0045d840bc 100644 --- a/legacy/elementary/configure.ac +++ b/legacy/elementary/configure.ac @@ -711,6 +711,7 @@ src/lib/Elementary.h src/bin/Makefile src/modules/Makefile src/modules/access_output/Makefile +src/modules/datetime_input_ctxpopup/Makefile src/modules/test_entry/Makefile src/modules/test_map/Makefile src/edje_externals/Makefile diff --git a/legacy/elementary/data/themes/default.edc b/legacy/elementary/data/themes/default.edc index 555cb7b789..5111d77b9d 100644 --- a/legacy/elementary/data/themes/default.edc +++ b/legacy/elementary/data/themes/default.edc @@ -324,6 +324,7 @@ collections { #include "widgets/button.edc" #include "widgets/toggle.edc" #include "widgets/clock.edc" +#include "widgets/datetime.edc" #include "widgets/menu.edc" #include "widgets/frame.edc" #include "widgets/tooltip.edc" diff --git a/legacy/elementary/data/themes/widgets/datetime.edc b/legacy/elementary/data/themes/widgets/datetime.edc new file mode 100644 index 0000000000..fe68ab3446 --- /dev/null +++ b/legacy/elementary/data/themes/widgets/datetime.edc @@ -0,0 +1,349 @@ +/////////////////////////////////////////////////////////////////////////////// +// datetime +/////////////////////////////////////////////////////////////////////////////// + +#define DATETIME_FIELD(_pos) \ + part {\ + name: "field"#_pos; \ + type: SWALLOW; \ + scale: 1;\ + clip_to: "clipper";\ + description { state: "default" 0.0; \ + visible: 0;\ + min: 0 0;\ + align: 0.0 0.5;\ + fixed: 1 0;\ + rel1 {\ + relative: 1.0 0.0;\ + to: "separator"#_pos;\ + }\ + rel2 {\ + relative: 1.0 1.0;\ + to: "separator"#_pos;\ + }\ + }\ + description { state: "enable" 0.0;\ + inherit: "default" 0.0;\ + visible: 1;\ + min: 25 25;\ + }\ + }\ + programs{\ + program {\ + name: "field_"#_pos"enabled";\ + signal: "field"#_pos",enable";\ + source: "elm";\ + action: STATE_SET "enable" 0.0;\ + target: "field"#_pos;\ + }\ + program {\ + name: "field_"#_pos"disabled";\ + signal: "field"#_pos",disable";\ + source: "elm";\ + action: STATE_SET "default" 0.0;\ + target: "field"#_pos;\ + }\ + } + +#define DATETIME_SEPARATOR(_pos,_after) \ + part {\ + name: "separator"#_pos; \ + type: TEXT;\ + scale: 1;\ + description {\ + state: "default" 0.0;\ + visible: 0;\ + min: 0 0;\ + align: 0.0 0.5;\ + fixed: 1 0;\ + rel1 {\ + relative: 1.0 0.0;\ + to: "field"#_after;\ + }\ + rel2 {\ + relative: 1.0 1.0;\ + to: "field"#_after;\ + }\ + color: 100 100 100 255;\ + text {\ + font: "SLP:style=Roman";\ + size: 13;\ + min: 1 0;\ + align: 0.2 0.5;\ + }\ + }\ + description { state: "enable" 0.0;\ + inherit: "default" 0.0;\ + visible: 1;\ + min: 13 25;\ + }\ + }\ + programs {\ + program {\ + name: "separator"#_pos",enabled";\ + signal: "field"#_after",enable";\ + source: "elm";\ + action: STATE_SET "enable" 0.0;\ + target: "separator"#_pos;\ + }\ + program {\ + name: "separator"#_pos",disabled";\ + signal: "field"#_after",disable";\ + source: "elm";\ + action: STATE_SET "default" 0.0;\ + target: "separator"#_pos;\ + }\ + } + + +group { name: "elm/datetime/base/default"; + parts { + part { + name: "bg"; + type: RECT; + scale: 1; + description { + state: "default" 0.0; + color: 0 0 0 0; + } + } + part { + name: "separator0"; + type: RECT; + scale: 1; + description { + state: "default" 0.0; + visible: 0; + min: 13 25; + align: 0.0 0.5; + fixed: 1 0; + rel2 { + relative: 0.0 1.0; + to: "bg"; + } + } + } + DATETIME_FIELD(0) + DATETIME_SEPARATOR(1,0) + DATETIME_FIELD(1) + DATETIME_SEPARATOR(2,1) + DATETIME_FIELD(2) + DATETIME_SEPARATOR(3,2) + DATETIME_FIELD(3) + DATETIME_SEPARATOR(4,3) + DATETIME_FIELD(4) + DATETIME_SEPARATOR(5,4) + DATETIME_FIELD(5) + DATETIME_SEPARATOR(6,5) + part { + name: "clipper"; + type: RECT; + description { state: "default" 0.0; + rel1 { + relative: 0.0 0.0; + to: "separator0"; + } + rel2 { + relative: 1.0 1.0; + to: "separator6"; + } + color: 255 255 255 255; + } + description { state: "enable" 0.0; + inherit: "default" 0.0; + color: 255 255 255 127; + } + } + part { + name: "disabler"; + type: RECT; + description { state: "default" 0.0; + color: 0 0 0 0; + visible: 0; + } + description { state: "visible" 0.0; + inherit: "default" 0.0; + visible: 1; + } + } + } + programs { + program { + name: "disble_datetime"; + signal: "elm,state,disabled"; + source: "elm"; + action: STATE_SET "visible" 0.0; + target: "disabler"; + target: "clipper"; + } + program { + name: "enable_datetime"; + signal: "elm,state,enabled"; + source: "elm"; + action: STATE_SET "default" 0.0; + target: "disabler"; + target: "clipper"; + } + } +}//end datetime group + +/////////////////////////////////////////////////////////////////////////////// +// diskselector item : datetime style +/////////////////////////////////////////////////////////////////////////////// +group { name: "elm/diskselector/item/datetime/default"; + data { + item: "len_threshold" "10"; + item: "min_height" "-1"; + item: "min_width" "-1"; + } + parts { + part { + name: "elm.text"; + type: TEXT; + mouse_events: 0; + scale: 1; + description { + state: "default" 0.0; + min: 25 25; + fixed: 1 1; + align: 0.0 0.0; + color: 172 172 172 255; + visible: 1; + text { + font: "Sans,Edje-Vera"; + size: 13; + min: 1 1; + } + } + description { + state: "center_sel" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + description { state: "left_side" 0.0; + inherit: "default" 0.0; + color: 152 152 152 255; + text.size: 10; + text.align: 0.2 0.5; + } + description { state: "left_side_sel" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + text.size: 10; + text.align: 0.2 0.5; + } + description { state: "right_side" 0.0; + inherit: "default" 0.0; + color: 152 152 152 255; + text.size: 10; + text.align: 0.8 0.5; + } + description { state: "right_side_sel" 0.0; + inherit: "default" 0.0; + color: 255 255 255 255; + text.size: 10; + text.align: 0.8 0.5; + } + } + part { + name: "over1"; + mouse_events: 1; + repeat_events: 1; + ignore_flags: ON_HOLD; + description { + state: "default" 0.0; + } + } + } + programs { + script { + public field_pos; // center = 0,left = 1, right =2. + public field_selected; //field is selected(1) or not(0). + + public update_state() { + new pos, is_sel; + pos = get_int(field_pos) + is_sel = get_int(field_selected); + + if (is_sel == 1) + { + if (pos == 0) + set_state(PART:"elm.text", "center_sel", 0.0); + else if (pos == 1) + set_state(PART:"elm.text", "left_side_sel", 0.0); + else if (pos == 2) + set_state(PART:"elm.text", "right_side_sel", 0.0); + } + else if (is_sel == 0) + { + if (pos == 0) + set_state(PART:"elm.text", "default", 0.0); + else if (pos == 1) + set_state(PART:"elm.text", "left_side", 0.0); + else if (pos == 2) + set_state(PART:"elm.text", "right_side", 0.0); + } + } + } + program { + name: "selected_text"; + signal: "elm,state,selected"; + source: "elm"; + script { + set_int(field_selected, 1); + update_state(); + } + } + program { + name: "default_text"; + signal: "elm,state,default"; + source: "elm"; + script { + set_int(field_selected, 0); + update_state(); + } + } + program { name: "center_text"; + signal: "elm,state,center"; + source: "elm"; + script { + set_int(field_pos, 0); + update_state(); + } + } + program { name: "center_small_text"; + signal: "elm,state,center_small"; + source: "elm"; + script { + set_int(field_pos, 0); + update_state(); + } + } + program { name: "l_side_text"; + signal: "elm,state,left_side"; + source: "elm"; + script { + set_int(field_pos, 1); + update_state(); + } + } + program { name: "r_side_text"; + signal: "elm,state,right_side"; + source: "elm"; + script { + set_int(field_pos, 2); + update_state(); + } + } + program { + name: "field_click"; + signal: "mouse,clicked,1"; + source: "over1"; + action: SIGNAL_EMIT "elm,action,click" ""; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// end of datetime style +/////////////////////////////////////////////////////////////////////////////// diff --git a/legacy/elementary/doc/Makefile.am b/legacy/elementary/doc/Makefile.am index 942e09ceee..bdb473186b 100644 --- a/legacy/elementary/doc/Makefile.am +++ b/legacy/elementary/doc/Makefile.am @@ -33,6 +33,9 @@ WGT_PREVIEW = \ frame:preview-00.png:widget_preview_frame:100:50 \ label:preview-00.png:widget_preview_label:70:30 \ clock:preview-00.png:widget_preview_clock:200:100 \ + datetime:preview-00.png:widget_preview_datetime1:360:60 \ + datetime:preview-01.png:widget_preview_datetime2:200:60 \ + datetime:preview-02.png:widget_preview_datetime3:200:60 \ slider:preview-00.png:widget_preview_slider:200:100 \ panes:preview-00.png:widget_preview_panes:200:100 \ toolbar:preview-00.png:widget_preview_toolbar:300:100 \ diff --git a/legacy/elementary/doc/examples.dox b/legacy/elementary/doc/examples.dox index fda24f3ec3..3b0235835e 100644 --- a/legacy/elementary/doc/examples.dox +++ b/legacy/elementary/doc/examples.dox @@ -37,6 +37,8 @@ * * @ref clock_example * + * @ref datetime_example + * * @ref mapbuf_example * @ref map_example_01 @@ -1697,6 +1699,51 @@ * @example clock_example.c */ +/** + * @page datetime_example Datetime widget example + * + * This code places three Elementary Datetime widgets on a window, each of + * them exemplifying the widget's different usage. + * + * The first of them is "only Date display": + * @dontinclude datetime_example.c + * @skip only DATE + * @until evas_object_show + * + * For "only Time display", see the second datetime: + * @dontinclude datetime_example.c + * @skip only TIME + * @until evas_object_show + * + * The third one will display datetime shows both Date and Time, corresponding format will be + * taken from system @b locale. Note, besides, that the strings are different + * for different language settings. + * + * Datetime format can be programmatically set by using + * elm_datetime_format_set(): + * @dontinclude datetime_example.c + * @skip DATE and TIME + * @until evas_object_show + * The default format of any locale consists: + * - Year Field + * - Month Field + * - Date Field + * - Hour Field(12hr/24hr format) + * - Minute Field + * - AM/PM (if exists). + * + * This is how the example program's window looks like with the datetime widget + * showing only date, only time and both date & time: + * + * @image html screenshots/datetime_example.png + * @image latex screenshots/datetime_example.eps width=\textwidth + * + * See the full @ref datetime_example_c "source code" for + * this example. + * + * @example datetime_example.c + */ + /** * @page mapbuf_example Mapbuf Widget Example * @@ -6164,6 +6211,12 @@ * @example clock_example.c */ + /** + * @page datetime_example_c Datetime example + * @include datetime_example.c + * @example datetime_example.c + */ + /** * @page flipselector_example_c Flipselector example * @include flipselector_example.c diff --git a/legacy/elementary/doc/index.doxy b/legacy/elementary/doc/index.doxy index e787b194b3..61c42ca78f 100644 --- a/legacy/elementary/doc/index.doxy +++ b/legacy/elementary/doc/index.doxy @@ -83,6 +83,10 @@ * * @image html img/widget/ctxpopup/preview-00.png * @image latex img/widget/ctxpopup/preview-00.eps + * @li @ref Datetime + * + * @image html img/widget/datetime/preview-00.png + * @image latex img/widget/datetime/preview-00.eps * @li @ref Diskselector * * @image html img/widget/diskselector/preview-00.png diff --git a/legacy/elementary/doc/widgets/Makefile.am b/legacy/elementary/doc/widgets/Makefile.am index 0bbb0b748d..d9ec6e0822 100644 --- a/legacy/elementary/doc/widgets/Makefile.am +++ b/legacy/elementary/doc/widgets/Makefile.am @@ -32,6 +32,9 @@ widget_preview_spinner \ widget_preview_bubble1 \ widget_preview_bubble2 \ widget_preview_bubble3 \ +widget_preview_datetime1 \ +widget_preview_datetime2 \ +widget_preview_datetime3 \ widget_preview_fileselector_button1 \ widget_preview_fileselector_button2 \ widget_preview_fileselector_button3 \ @@ -122,6 +125,9 @@ EXTRA_DIST = \ widget_preview_mapbuf.c \ widget_preview_map.c \ widget_preview_ctxpopup.c \ + widget_preview_datetime1.c \ + widget_preview_datetime2.c \ + widget_preview_datetime3.c \ widget_preview_diskselector.c \ widget_preview_entry1.c \ widget_preview_entry2.c \ diff --git a/legacy/elementary/doc/widgets/widget_preview_datetime1.c b/legacy/elementary/doc/widgets/widget_preview_datetime1.c new file mode 100644 index 0000000000..359753f07f --- /dev/null +++ b/legacy/elementary/doc/widgets/widget_preview_datetime1.c @@ -0,0 +1,16 @@ +#include "widget_preview_tmpl_head.c" + +Evas_Object *bx = elm_box_add(win); +evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +elm_win_resize_object_add(win, bx); +evas_object_show(bx); +evas_object_size_hint_min_set(bx, 360, 60); + +Evas_Object *datetime = elm_datetime_add(win); +evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL); +elm_box_pack_end(bx, datetime); +evas_object_show(datetime); + +#include "widget_preview_tmpl_foot.c" diff --git a/legacy/elementary/doc/widgets/widget_preview_datetime2.c b/legacy/elementary/doc/widgets/widget_preview_datetime2.c new file mode 100644 index 0000000000..59e9aa0627 --- /dev/null +++ b/legacy/elementary/doc/widgets/widget_preview_datetime2.c @@ -0,0 +1,19 @@ +#include "widget_preview_tmpl_head.c" + +Evas_Object *bx = elm_box_add(win); +evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +elm_win_resize_object_add(win, bx); +evas_object_show(bx); +evas_object_size_hint_min_set(bx, 200, 60); + +Evas_Object *datetime = elm_datetime_add(win); +evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_HOUR, EINA_FALSE); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_MINUTE, EINA_FALSE); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_AMPM, EINA_FALSE); +elm_box_pack_end(bx, datetime); +evas_object_show(datetime); + +#include "widget_preview_tmpl_foot.c" diff --git a/legacy/elementary/doc/widgets/widget_preview_datetime3.c b/legacy/elementary/doc/widgets/widget_preview_datetime3.c new file mode 100644 index 0000000000..bf51f7f4da --- /dev/null +++ b/legacy/elementary/doc/widgets/widget_preview_datetime3.c @@ -0,0 +1,19 @@ +#include "widget_preview_tmpl_head.c" + +Evas_Object *bx = elm_box_add(win); +evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +elm_win_resize_object_add(win, bx); +evas_object_show(bx); +evas_object_size_hint_min_set(bx, 200, 60); + +Evas_Object *datetime = elm_datetime_add(win); +evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); +evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_YEAR, EINA_FALSE); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_MONTH, EINA_FALSE); +elm_datetime_field_visible_set(datetime, ELM_DATETIME_DATE, EINA_FALSE); +elm_box_pack_end(bx, datetime); +evas_object_show(datetime); + +#include "widget_preview_tmpl_foot.c" diff --git a/legacy/elementary/src/bin/Makefile.am b/legacy/elementary/src/bin/Makefile.am index 9718e55725..85ae36e67f 100644 --- a/legacy/elementary/src/bin/Makefile.am +++ b/legacy/elementary/src/bin/Makefile.am @@ -48,6 +48,7 @@ test_colorselector.c \ test_conform.c \ test_ctxpopup.c \ test_cursor.c \ +test_datetime.c \ test_diskselector.c \ test_entry.c \ test_factory.c \ diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index 30271e7963..1c965d264d 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -163,6 +163,7 @@ void test_glview(void *data, Evas_Object *obj, void *event_info); void test_3d(void *data, Evas_Object *obj, void *event_info); void test_naviframe(void *data, Evas_Object *obj, void *event_info); void test_factory(void *data, Evas_Object *obj, void *event_info); +void test_datetime(void *data, Evas_Object *obj, void *event_info); #ifdef HAVE_EMOTION void test_video(void *data, Evas_Object *obj, void *event_info); #endif @@ -508,6 +509,7 @@ add_tests: ADD_TEST(NULL, "Times & Dates", "Clock", test_clock); ADD_TEST(NULL, "Times & Dates", "Clock 2", test_clock2); ADD_TEST(NULL, "Times & Dates", "Clock 3", test_clock3); + ADD_TEST(NULL, "Times & Dates", "Datetime", test_datetime); //------------------------------// ADD_TEST(NULL, "Text", "Anchorview", test_anchorview); diff --git a/legacy/elementary/src/bin/test_datetime.c b/legacy/elementary/src/bin/test_datetime.c new file mode 100644 index 0000000000..d54970236b --- /dev/null +++ b/legacy/elementary/src/bin/test_datetime.c @@ -0,0 +1,81 @@ +#include +#ifdef HAVE_CONFIG_H +#include "elementary_config.h" +#endif +#ifndef ELM_LIB_QUICKLAUNCH + +/* A simple test, just displaying datetime in its default format */ + +static void +_changed_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + printf("Datetime value is changed\n"); +} + +void +test_datetime(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *win, *bg, *bx, *datetime; + time_t t; + struct tm time1; + + win = elm_win_add(NULL, "Datetime", ELM_WIN_BASIC); + elm_win_title_set(win, "Datetime"); + elm_win_autodel_set(win, 1); + + bg = elm_bg_add(win); + elm_win_resize_object_add(win, bg); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(bg); + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + elm_box_horizontal_set(bx, EINA_FALSE); + evas_object_show(bx); + evas_object_size_hint_min_set(bx, 360, 240); + + datetime = elm_datetime_add(bx); + evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_HOUR, EINA_FALSE); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_MINUTE, EINA_FALSE); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_AMPM, EINA_FALSE); + elm_box_pack_end(bx, datetime); + evas_object_show(datetime); + + datetime = elm_datetime_add(bx); + evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_YEAR, EINA_FALSE); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_MONTH, EINA_FALSE); + elm_datetime_field_visible_set(datetime, ELM_DATETIME_DATE, EINA_FALSE); + elm_box_pack_end(bx, datetime); + evas_object_show(datetime); + + datetime = elm_datetime_add(bx); + evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5); + + // get the current local time + t = time(NULL); + localtime_r(&t, &time1); + // set the max year as 2030 and the remaining fields are equal to current time values + time1.tm_year = 130; + elm_datetime_value_max_set(datetime, &time1); + // set the min time limit as "1980 January 10th 02:30 PM" + time1.tm_year = 80; + time1.tm_mon = 4; + time1.tm_mday = 10; + time1.tm_hour = 14; + time1.tm_min = 30; + elm_datetime_value_min_set(datetime, &time1); + // minutes can be input only in between 15 and 45 + elm_datetime_field_limit_set(datetime, ELM_DATETIME_MINUTE, 15, 45); + evas_object_smart_callback_add(datetime, "changed", _changed_cb, datetime); + elm_box_pack_end(bx, datetime); + evas_object_show(datetime); + + evas_object_show(win); +} +#endif diff --git a/legacy/elementary/src/examples/Makefile.am b/legacy/elementary/src/examples/Makefile.am index 4acc8eb72b..47473361ff 100644 --- a/legacy/elementary/src/examples/Makefile.am +++ b/legacy/elementary/src/examples/Makefile.am @@ -61,6 +61,7 @@ SRCS = \ calendar_example_04.c \ calendar_example_05.c \ calendar_example_06.c \ + datetime_example.c \ map_example_01.c \ map_example_02.c \ map_example_03.c \ @@ -170,6 +171,7 @@ examples_PROGRAMS += \ calendar_example_04 \ calendar_example_05 \ calendar_example_06 \ + datetime_example \ map_example_01 \ map_example_02 \ map_example_03 \ @@ -259,6 +261,7 @@ SCREENSHOTS = \ calendar_example_04:calendar_example_04.png:0.0 \ calendar_example_05:calendar_example_05.png:0.0 \ calendar_example_06:calendar_example_06.png:0.0 \ + datetime_example:datetime_example.png:0.0 \ map_example_01:map_example_01.png:2 \ map_example_02:map_example_02.png:2.5 \ map_example_03:map_example_03.png:2 \ diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 3f9b9c7c70..57a9756afe 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -189,6 +189,7 @@ EAPI extern Elm_Version *elm_version; #include #include // XXX: comments in elm_conform.h #include // XXX: comments in elm_cursor.h. review was not finished. +#include #include // OK #include diff --git a/legacy/elementary/src/lib/Makefile.am b/legacy/elementary/src/lib/Makefile.am index c7a3756f28..ac58bc02ca 100644 --- a/legacy/elementary/src/lib/Makefile.am +++ b/legacy/elementary/src/lib/Makefile.am @@ -70,6 +70,7 @@ elm_colorselector.h \ elm_config.h \ elm_conform.h \ elm_cursor.h \ +elm_datetime.h \ elm_debug.h \ elm_deprecated.h \ elm_deprecated_before.h \ @@ -162,6 +163,7 @@ elm_cnp.c \ elm_colorselector.c \ elm_config.c \ elm_conform.c \ +elm_datetime.c \ elm_diskselector.c \ elm_entry.c \ elm_factory.c \ diff --git a/legacy/elementary/src/lib/elm_datetime.c b/legacy/elementary/src/lib/elm_datetime.c new file mode 100644 index 0000000000..1edbae77fe --- /dev/null +++ b/legacy/elementary/src/lib/elm_datetime.c @@ -0,0 +1,1039 @@ +#include +#include +#include +#include "elm_priv.h" + +typedef struct _Widget_Data Widget_Data; +typedef struct _Datetime_Field Datetime_Field; +typedef struct _Datetime_Mod_Api Datetime_Mod_Api; +typedef struct _Format_Map Format_Map; + +#define DATETIME_TYPE_COUNT 6 +#define MAX_FORMAT_LEN 64 +#define MAX_SEPARATOR_LEN 6 +#define MAX_FIELD_FORMAT_LEN 3 +#define MIN_DAYS_IN_MONTH 28 +#define BUFFER_SIZE 1024 + +// interface between EDC & C code. Field names & signal names. +// values 0 to DATETIME_TYPE_COUNT are valid range, can be substituted for %d. +#define EDC_DATETIME_ENABLE_SIG_STR "elm,state,enabled" +#define EDC_DATETIME_DISABLE_SIG_STR "elm,state,disabled" +#define EDC_DATETIME_FOCUSIN_SIG_STR "elm,action,focus" +#define EDC_DATETIME_FOCUSOUT_SIG_STR "elm,action,unfocus" +#define EDC_PART_FIELD_STR "field%d" +#define EDC_PART_SEPARATOR_STR "separator%d" +#define EDC_PART_FIELD_ENABLE_SIG_STR "field%d,enable" +#define EDC_PART_FIELD_DISABLE_SIG_STR "field%d,disable" + +// struct tm does not define the fields in the order from year, month, date, hour, minute. +// values are reassigned to an array for easy handling. +#define DATETIME_TM_ARRAY(intptr, tmptr) int *intptr[] = {&(tmptr)->tm_year, \ + &(tmptr)->tm_mon, &(tmptr)->tm_mday, &(tmptr)->tm_hour, &(tmptr)->tm_min} + +struct _Datetime_Field +{ + Evas_Object *item_obj; + char fmt[MAX_FIELD_FORMAT_LEN]; + Elm_Datetime_Field_Type type; + const char *separator; + int location; // location of the field as per the current format + int min, max; + Eina_Bool fmt_exist:1; // whether field format is present or not + Eina_Bool visible:1; // whether field can be visible or not +}; + +struct _Datetime_Mod_Api +{ + Elm_Datetime_Module_Data *(*obj_hook) (Evas_Object *obj); + void (*obj_unhook) (Elm_Datetime_Module_Data *module_data); + Evas_Object *(*field_create) (Elm_Datetime_Module_Data *module_data, + Elm_Datetime_Field_Type field_type); + void (*field_value_display) (Elm_Datetime_Module_Data *module_data, + Evas_Object *obj); +}; + +struct _Widget_Data +{ + Evas_Object *base; + Datetime_Field field_list[DATETIME_TYPE_COUNT]; // fixed set of fields. + struct tm curr_time, min_limit, max_limit; + Elm_Datetime_Module_Data *mod_data; + char format[MAX_FORMAT_LEN]; + Eina_Bool user_format:1; // whether user set format or default format. +}; + +struct _Format_Map +{ + char *fmt_char; + int def_min; + int def_max; +}; + +// default limits for individual fields +static const Format_Map mapping[DATETIME_TYPE_COUNT] = { + [ELM_DATETIME_YEAR] = { "Yy", 0, 137 }, + [ELM_DATETIME_MONTH] = { "mbBh", 0, 11 }, + [ELM_DATETIME_DATE] = { "de", 1, 31 }, + [ELM_DATETIME_HOUR] = { "IHkl", 0, 23 }, + [ELM_DATETIME_MINUTE] = { "M", 0, 59 }, + [ELM_DATETIME_AMPM] = { "pP", 0, 1 } +}; + +static const char *multifield_formats = "cxXrRTDF"; + +static Datetime_Mod_Api *dt_mod = NULL; +static const char *widtype = NULL; + +static void _del_hook(Evas_Object *obj); +static void _disable_hook(Evas_Object *obj); +static void _translate_hook(Evas_Object *obj); +static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj); +static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl); +static void _sizing_eval(Evas_Object *obj); +static void _theme_hook(Evas_Object *obj); +static void _validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap); +static void _apply_field_limits(Evas_Object *obj); +static void _apply_range_restrictions(Evas_Object *obj, struct tm *time); +static const char *_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type); +static void _field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type, + int *range_min, int *range_max); +static void _reload_format(Evas_Object *obj); +static void _field_list_display(Evas_Object *obj); +static void _field_list_arrange(Evas_Object *obj); +static void _field_list_init(Evas_Object *obj); + +static const char SIG_CHANGED[] = "changed"; +static const char SIG_LANGUAGE_CHANGED[] = "language,changed"; +static const Evas_Smart_Cb_Description _signals[] = { + {SIG_CHANGED, ""}, + {SIG_LANGUAGE_CHANGED, ""}, + {NULL, NULL} +}; + +static Datetime_Mod_Api * +_dt_mod_init() +{ + Elm_Module *mod = NULL; + if (!(mod = _elm_module_find_as("datetime/api"))) return NULL; + + mod->api = malloc(sizeof(Datetime_Mod_Api)); + if (!mod->api) return NULL; + + ((Datetime_Mod_Api *)(mod->api))->obj_hook = _elm_module_symbol_get(mod, "obj_hook"); + ((Datetime_Mod_Api *)(mod->api))->obj_unhook = _elm_module_symbol_get(mod, "obj_unhook"); + ((Datetime_Mod_Api *)(mod->api))->field_create = _elm_module_symbol_get(mod, "field_create"); + ((Datetime_Mod_Api *)(mod->api))->field_value_display = _elm_module_symbol_get(mod, "field_value_display"); + + return mod->api; +} + +static void +_del_hook(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *tmp; + unsigned int idx; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + tmp = wd->field_list + idx; + evas_object_del(tmp->item_obj); + eina_stringshare_del(tmp->separator); + } + + if ((dt_mod) && (dt_mod->obj_unhook)) + dt_mod->obj_unhook(wd->mod_data); // module - unhook + + free(wd); +} + +static void +_disable_hook(Evas_Object *obj) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd || !wd->base) return; + if (elm_widget_disabled_get(obj)) + edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR, "elm"); + else + edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm"); +} + +static void +_translate_hook(Evas_Object *obj) +{ + Widget_Data *wd; + wd = elm_widget_data_get(obj); + if (!wd) return; + + if (!wd->user_format) _reload_format(obj); + else _field_list_display(obj); + evas_object_smart_callback_call(obj, SIG_LANGUAGE_CHANGED, NULL); +} + +static void +_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + if (elm_widget_focus_get(obj)) + edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSIN_SIG_STR, "elm"); + else + edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSOUT_SIG_STR, "elm"); +} + +static Eina_List * +_datetime_items_get(const Evas_Object *obj) +{ + Widget_Data *wd; + Eina_List *items; + Datetime_Field *field; + int loc, count = 0; + unsigned int idx; + + wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->fmt_exist && field->visible) count++; + } + for (loc = 0; loc < count; loc++) + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->location == loc) + items = eina_list_append(items, field->item_obj); + } + + return items; +} + +static Eina_Bool +_elm_datetime_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) +{ + Widget_Data *wd; + const Eina_List *items; + void *(*list_data_get) (const Eina_List *list); + Eina_List *(*list_free) (Eina_List *list); + Eina_Bool ret; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + if ((items = elm_widget_focus_custom_chain_get(obj))) + { + list_data_get = eina_list_data_get; + list_free = NULL; + } + else + { + items = _datetime_items_get(obj); + list_data_get = eina_list_data_get; + list_free = eina_list_free; + if (!items) return EINA_FALSE; + } + + ret = elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next); + if (list_free) list_free((Eina_List *)items); + + return ret; +} + +static void +_mirrored_set(Evas_Object *obj, Eina_Bool rtl) +{ + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + edje_object_mirrored_set(wd->base, rtl); +} + +static void +_sizing_eval(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + Evas_Coord minw = -1, minh = -1; + unsigned int idx, field_count = 0; + + wd = elm_widget_data_get(obj); + if (!wd || !wd->base) return; + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if ((field->visible) && (field->fmt_exist)) field_count ++; + } + if (field_count) + elm_coords_finger_size_adjust(field_count, &minw, 1, &minh); + edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh); + evas_object_size_hint_min_set(obj, minw, minh); + evas_object_size_hint_max_set(obj, -1, -1); +} + +static void +_theme_hook(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + char buf[BUFFER_SIZE]; + unsigned int idx; + + wd = elm_widget_data_get(obj); + if (!wd || !wd->base) return; + + _elm_theme_object_set(obj, wd->base, "datetime", "base", + elm_widget_style_get(obj)); + _elm_widget_mirrored_reload(obj); + _mirrored_set(obj, elm_widget_mirrored_get(obj)); + + edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale); + + if (elm_widget_disabled_get(obj)) + edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR,"elm"); + else + edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm"); + + if ((!dt_mod) || (!dt_mod->field_value_display)) return; + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->fmt_exist && field->visible) + { + snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR, field->location); + edje_object_signal_emit(wd->base, buf, "elm"); + snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, field->location); + edje_object_part_text_set(wd->base, buf, field->separator); + dt_mod->field_value_display(wd->mod_data, field->item_obj); + } + else + { + snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR, field->location); + edje_object_signal_emit(wd->base, buf, "elm"); + } + } + edje_object_message_signal_process(wd->base); + _sizing_eval(obj); +} + +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 = MIN_DAYS_IN_MONTH; day <= mapping[ELM_DATETIME_DATE].def_max; day++) + { + time1.tm_mday = day; + mktime(&time1); + if (time1.tm_mday == 1) break; + } + day --; + return day; +} + +static Eina_Bool +_date_cmp(struct tm *time1, struct tm *time2) +{ + unsigned int idx; + DATETIME_TM_ARRAY(timearr1, time1); + DATETIME_TM_ARRAY(timearr2, time2); + + for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++) + { + if (*timearr1[idx] != *timearr2[idx]) + return EINA_FALSE; + } + return EINA_TRUE; +} + +// validates curr_time/min_limt/max_limit according to the newly set value +static void +_validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap) +{ + struct tm *t1, *t2; + unsigned int idx; + if (!time1 || !time2) return; + + t1 = (swap) ? time2 : time1; + t2 = (swap) ? time1 : time2; + + DATETIME_TM_ARRAY(timearr1, time1); + DATETIME_TM_ARRAY(timearr2, time2); + for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++) + { + if (*timearr1[idx] < *timearr2[idx]) + { + memcpy(t1, t2, sizeof(struct tm)); + break; + } + else if (*timearr1[idx] > *timearr2[idx]) + break; + } +} + +static void +_apply_field_limits(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + int val; + unsigned int idx = 0; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + DATETIME_TM_ARRAY(timearr, &wd->curr_time); + for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++) + { + field = wd->field_list + idx; + val = *timearr[idx]; + if (val < field->min) + *timearr[idx] = field->min; + else if (val > field->max) + *timearr[idx] = field->max; + } + _field_list_display(obj); +} + +static void +_apply_range_restrictions(Evas_Object *obj, struct tm *time) +{ + Widget_Data *wd; + unsigned int idx; + int val, min, max; + + wd = elm_widget_data_get(obj); + if (!wd || !time) return; + + DATETIME_TM_ARRAY(timearr, time); + for (idx = ELM_DATETIME_MONTH; idx < DATETIME_TYPE_COUNT - 1; idx++) + { + val = *timearr[idx]; + min = mapping[idx].def_min; + max = mapping[idx].def_max; + if (idx == ELM_DATETIME_DATE) + max = _max_days_get(time->tm_year, time->tm_mon); + if (val < min) + *timearr[idx] = min; + else if (val > max) + *timearr[idx] = max; + } +} + +static const char * +_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type) +{ + Widget_Data *wd; + Datetime_Field *field; + + wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + field = wd->field_list + field_type; + if (!field) return NULL; + + return field->fmt; +} + +static void +_field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max) +{ + Widget_Data *wd; + Datetime_Field *field; + int min, max, max_days; + unsigned int idx; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + field = wd->field_list + field_type; + if (!field) return; + + min = field->min; + max = field->max; + + DATETIME_TM_ARRAY(curr_timearr, &wd->curr_time); + DATETIME_TM_ARRAY(min_timearr, &wd->min_limit); + DATETIME_TM_ARRAY(max_timearr, &wd->max_limit); + + for (idx = 0; idx < field->type; idx++) + if (*curr_timearr[idx] > *min_timearr[idx]) break; + if ((idx == field_type) && (min < *min_timearr[field_type])) + min = *min_timearr[field_type]; + if (field_type == ELM_DATETIME_DATE) + { + max_days = _max_days_get(wd->curr_time.tm_year, wd->curr_time.tm_mon); + if (max > max_days) max = max_days; + } + for (idx = 0; idx < field->type; idx++) + if (*curr_timearr[idx] < *max_timearr[idx]) break; + if ((idx == field_type) && (max > *max_timearr[field_type])) + max = *max_timearr[field_type]; + + *range_min = min; + *range_max = max; +} + +static void +_field_list_display(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + unsigned int idx= 0; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->fmt_exist && field->visible) + { + if ((dt_mod) && (dt_mod->field_value_display)) + dt_mod->field_value_display(wd->mod_data, field->item_obj); + } + } +} + +static void +_field_list_arrange(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + char buf[BUFFER_SIZE]; + int idx; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + edje_object_part_unswallow(wd->base, field->item_obj); + } + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->visible && field->fmt_exist) + { + snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location); + edje_object_part_swallow(wd->base, buf, field->item_obj); + } + else evas_object_hide(field->item_obj); + } + _sizing_eval(obj); + _field_list_display(obj); +} + +// returns expanded format string for corresponding multi-field format character +static char * +_expanded_fmt_str_get(char ch) +{ + char *exp_fmt = ""; + switch (ch) + { + case 'c': + exp_fmt = nl_langinfo(D_T_FMT); + break; + case 'x': + exp_fmt = nl_langinfo(D_FMT); + break; + case 'X': + exp_fmt = nl_langinfo(T_FMT); + break; + case 'r': + exp_fmt = nl_langinfo(T_FMT_AMPM); + 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; + char buf[MAX_FORMAT_LEN] = {0,}; + unsigned int idx = 0, len = 0; + Eina_Bool fmt_char = 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); + 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); +} + +static unsigned int +_parse_format(Evas_Object *obj, char *fmt_ptr) +{ + Widget_Data *wd; + Datetime_Field *field = NULL; + unsigned int len = 0, idx, location = 0; + char separator[MAX_SEPARATOR_LEN]; + char cur; + Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE, + sep_lookup = EINA_FALSE; + + wd = elm_widget_data_get(obj); + + while ((cur = *fmt_ptr)) + { + if (fmt_parsing) + { + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + if (strchr(mapping[idx].fmt_char, cur)) + { + field = wd->field_list + idx; + // ignore the fields already have or disabled + // valid formats, means already parsed & repeated, ignore. + if (!field->visible || field->location != -1) break; + field->fmt[1] = cur; + field->fmt_exist = EINA_TRUE; + field->location = location++; + fmt_parsing = EINA_FALSE; + sep_lookup = EINA_TRUE; + len = 0; + break; + } + } + } + if (cur == ' ') separator[len++] = cur; + else if (cur == '%') fmt_parsing = EINA_TRUE; + if ((cur == ' ') || (cur == '%')) + { + sep_parsing = EINA_FALSE; + // set the separator to previous field + separator[len] = 0; + if (field) eina_stringshare_replace(&field->separator, separator); + } + if (sep_parsing && (len < MAX_SEPARATOR_LEN-1) && + (field->type != ELM_DATETIME_AMPM) && + (!((field->type == ELM_DATETIME_MINUTE) && (cur ==':')))) + separator[len++] = cur; + if (sep_lookup) sep_parsing = EINA_TRUE; + sep_lookup = EINA_FALSE; + fmt_ptr++; + } + // return the number of valid fields parsed. + return location; +} + +static void +_reload_format(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + char buf[BUFFER_SIZE]; + unsigned int idx, field_count; + char *dt_fmt; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + // fetch the default format from Libc. + if (!wd->user_format) + strncpy(wd->format, nl_langinfo(D_T_FMT), MAX_FORMAT_LEN); + + dt_fmt = (char *)malloc(MAX_FORMAT_LEN); + strncpy(dt_fmt, wd->format, MAX_FORMAT_LEN); + + _expand_format(dt_fmt); + + // reset all the fields to disable state + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + field->fmt_exist = EINA_FALSE; + field->location = -1; + } + + field_count = _parse_format(obj, dt_fmt); + free(dt_fmt); + + // assign locations to disabled fields for uniform usage + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + if (field->location == -1) field->location = field_count++; + + if (field->fmt_exist && field->visible) + { + snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR, + field->location); + edje_object_signal_emit(wd->base, buf, "elm"); + } + else + { + snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR, + field->location); + edje_object_signal_emit(wd->base, buf, "elm"); + } + snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, (field->location + 1)); + edje_object_part_text_set(wd->base, buf, field->separator); + } + edje_object_message_signal_process(wd->base); + _field_list_arrange(obj); +} + +static void +_field_list_init(Evas_Object *obj) +{ + Widget_Data *wd; + Datetime_Field *field; + unsigned int idx; + time_t t; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + t = time(NULL); + localtime_r(&t, &wd->curr_time); + + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + field->type = ELM_DATETIME_YEAR + idx; + field->fmt[0] = '%'; + field->fmt_exist = EINA_FALSE; + field->visible = EINA_TRUE; + field->min = mapping[idx].def_min; + field->max = mapping[idx].def_max; + } + DATETIME_TM_ARRAY(min_timearr, &wd->min_limit); + DATETIME_TM_ARRAY(max_timearr, &wd->max_limit); + for (idx = 0; idx < DATETIME_TYPE_COUNT-1; idx++) + { + *min_timearr[idx] = mapping[idx].def_min; + *max_timearr[idx] = mapping[idx].def_max; + } +} + +EAPI Evas_Object * +elm_datetime_add(Evas_Object *parent) +{ + Evas_Object *obj; + Evas *e; + Widget_Data *wd; + Datetime_Field *field; + int idx; + + ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); + + ELM_SET_WIDTYPE(widtype, "datetime"); + elm_widget_type_set(obj, widtype); + elm_widget_sub_object_add(parent, obj); + elm_widget_data_set(obj, wd); + elm_widget_del_hook_set(obj, _del_hook); + elm_widget_theme_hook_set(obj, _theme_hook); + elm_widget_translate_hook_set(obj, _translate_hook); + elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); + elm_widget_disable_hook_set(obj, _disable_hook); + elm_widget_can_focus_set(obj, EINA_TRUE); + elm_widget_focus_next_hook_set(obj, _elm_datetime_focus_next_hook); + + wd->base = edje_object_add(e); + elm_widget_resize_object_set(obj, wd->base); + _elm_theme_object_set(obj, wd->base, "datetime", "base", "default"); + evas_object_smart_callbacks_descriptions_set(obj, _signals); + + // module - initialise module for datetime + if (!dt_mod) dt_mod = _dt_mod_init(); + if ((dt_mod) && (dt_mod->obj_hook)) + wd->mod_data = dt_mod->obj_hook(obj); + // update module data + if (wd->mod_data) + { + wd->mod_data->base = obj; + wd->mod_data->field_limit_get = _field_limit_get; + wd->mod_data->field_format_get = _field_format_get; + } + + _field_list_init(obj); + _reload_format(obj); + + if ((dt_mod)&&(dt_mod->field_create)) + { + for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++) + { + field = wd->field_list + idx; + field->item_obj = dt_mod->field_create(wd->mod_data, idx); + } + } + _field_list_arrange(obj); + _mirrored_set(obj, elm_widget_mirrored_get(obj)); + + return obj; +} + +EAPI const char * +elm_datetime_format_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + return wd->format; +} + +EAPI void +elm_datetime_format_set(Evas_Object *obj, const char *fmt) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return; + + if (fmt) + { + strncpy(wd->format, fmt, MAX_FORMAT_LEN); + wd->user_format = EINA_TRUE; + } + else + wd->user_format = EINA_FALSE; + + _reload_format(obj); +} + +EAPI Eina_Bool +elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type + fieldtype) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + Widget_Data *wd; + Datetime_Field *field; + + wd = elm_widget_data_get(obj); + if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return EINA_FALSE; + + field = wd->field_list + fieldtype; + return field->visible; +} + +EAPI void +elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, + Eina_Bool visible) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + Datetime_Field *field; + + wd = elm_widget_data_get(obj); + if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return; + + field = wd->field_list + fieldtype; + if (field->visible == visible) return; + + field->visible = visible; + _reload_format(obj); +} + +EAPI void +elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, + int *min, int *max) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + Datetime_Field *field; + + wd = elm_widget_data_get(obj); + if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return; + + field = wd->field_list + fieldtype; + if (min) *min = field->min; + if (max) *max = field->max; +} + +EAPI void +elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, + int min, int max) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + Datetime_Field *field; + + wd = elm_widget_data_get(obj); + if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return; + + if (min > max) return; + + field = wd->field_list + fieldtype; + if ((min > mapping[fieldtype].def_min && min < mapping[fieldtype].def_max) + || (field->type == ELM_DATETIME_YEAR)) + field->min = min; + if ((max > mapping[fieldtype].def_min && max < mapping[fieldtype].def_max) + || (field->type == ELM_DATETIME_YEAR)) + field->max = max; + + _apply_field_limits(obj); +} + +EAPI Eina_Bool +elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(currtime, EINA_FALSE); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + *currtime = wd->curr_time; + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(newtime, EINA_FALSE); + Widget_Data *wd; + struct tm old_time; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + old_time = wd->curr_time; + wd->curr_time = *newtime; + // apply default field restrictions for curr_time + _apply_range_restrictions(obj, &wd->curr_time); + // validate the curr_time according to the min_limt and max_limt + _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE); + _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE); + _apply_field_limits(obj); + + if (!_date_cmp(&old_time, &wd->curr_time)) + evas_object_smart_callback_call(obj, SIG_CHANGED, NULL); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + *mintime = wd->min_limit; + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE); + Widget_Data *wd; + struct tm old_time; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + wd->min_limit = *mintime; + old_time = wd->curr_time; + // apply default field restrictions for min_limit + _apply_range_restrictions(obj, &wd->min_limit); + // validate curr_time and max_limt according to the min_limit + _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_FALSE); + _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE); + _apply_field_limits(obj); + + if (!_date_cmp(&old_time, &wd->curr_time)) + evas_object_smart_callback_call(obj, SIG_CHANGED, NULL); + + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + *maxtime = wd->max_limit; + return EINA_TRUE; +} + +EAPI Eina_Bool +elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE); + Widget_Data *wd; + struct tm old_time; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + wd->max_limit = *maxtime; + old_time = wd->curr_time; + // apply default field restrictions for max_limit + _apply_range_restrictions(obj, &wd->max_limit); + // validate curr_time and min_limt according to the max_limit + _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_TRUE); + _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE); + _apply_field_limits(obj); + + if (!_date_cmp(&old_time, &wd->curr_time)) + evas_object_smart_callback_call(obj, SIG_CHANGED, NULL); + + return EINA_TRUE; +} diff --git a/legacy/elementary/src/lib/elm_datetime.h b/legacy/elementary/src/lib/elm_datetime.h new file mode 100644 index 0000000000..a4cf388e87 --- /dev/null +++ b/legacy/elementary/src/lib/elm_datetime.h @@ -0,0 +1,596 @@ + + /** + * @defgroup Datetime Datetime + * + * + * @image html img/widget/datetime/preview-00.png + * @image latex img/widget/datetime/preview-00.eps + * + * @image html img/widget/datetime/preview-01.png + * @image latex img/widget/datetime/preview-01.eps + * + * @image html img/widget/datetime/preview-02.png + * @image latex img/widget/datetime/preview-02.eps + * + * Datetime widget is used to display and input date & time values. + * This widget displays date and time as per the system's locale settings (Date + * includes Day, Month & Year along with the defined separators and + * Time includes Hour, Minute & AM/PM fields. Separator for AM/PM field is ignored. + * + * The corresponding Month, AM/PM strings are displayed according to the + * system’s language settings. + * + * Datetime format is a combination of LIBC standard characters like + * “%%d %%b %%Y %%I : %%M %%p” which, as a whole represents both Date as well as Time + * format. + * + * Elm_datetime supports only the following sub set of libc date format specifiers: + * + * @b %%Y : The year as a decimal number including the century (example: 2011). + * + * @b %%y : The year as a decimal number without a century (range 00 to 99) + * + * @b %%m : The month as a decimal number (range 01 to 12). + * + * @b %%b : The abbreviated month name according to the current locale. + * + * @b %%B : The full month name according to the current locale. + * + * @b %%h : The abbreviated month name according to the current locale(same as %%b). + * + * @b %%d : The day of the month as a decimal number (range 01 to 31). + * + * @b %%e : The day of the month as a decimal number (range 1 to 31). single + * digits are preceded by a blank. + * + * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12). + * + * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23). + * + * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single + * digits are preceded by a blank. + * + * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single + * digits are preceded by a blank. + * + * @b %%M : The minute as a decimal number (range 00 to 59). + * + * @b %%p : Either 'AM' or 'PM' according to the given time value, or the + * corresponding strings for the current locale. Noon is treated as 'PM' + * and midnight as 'AM' + * + * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for + * the current locale. + * + * @b %%c : The preferred date and time representation for the current locale. + * + * @b %%x : The preferred date representation for the current locale without the time. + * + * @b %%X : The preferred time representation for the current locale without the date. + * + * @b %%r : The complete calendar time using the AM/PM format of the current locale. + * + * @b %%R : The hour and minute in decimal numbers using the format %H:%M. + * + * @b %%T : The time of day in decimal numbers using the format %H:%M:%S. + * + * @b %%D : The date using the format %%m/%%d/%%y. + * + * @b %%F : The date using the format %%Y-%%m-%%d. + * + * (For more reference on the available LIBC date format specifiers, please + * visit the link: + * http://www.gnu.org/s/hello/manual/libc.html#Formatting-Calendar-Time ) + * + * Datetime widget can provide Unicode @b separators in between its fields + * except for AM/PM field. + * A separator can be any Unicode character other than the LIBC standard + * date format specifiers.( Example: In the format %%b %%d @b , %%y %%H @b : %%M + * comma(,) is separator for date field %%d and colon(:) is separator for + * hour field %%H ). + * + * The default format is a predefined one, based on the system Locale. + * + * Hour format 12hr(1-12) or 24hr(0-23) display can be selected by setting + * the corresponding user format. + * + * Datetime supports six fields: Year, Month, Date, Hour, Minute, AM/PM. + * Depending on the Datetime module that is loaded, the user can see + * different UI to select the individual field values. + * + * The individual fields of Datetime can be arranged in any order according to the format + * set by application. + * + * There is a provision to set the visibility of a particular field as TRUE/ FALSE + * so that only time/ only date / only required fields will be displayed. + * + * Each field is having a default minimum and maximum values just like the daily + * calendar information. These min/max values can be modified as per the application usage. + * + * User can enter the values only in between the range of maximum and minimum. + * Apart from these APIs, there is a provision to display only a limited set of + * values out of the possible values. APIs to select the individual field limits + * are intended for this purpose. + * + * The whole widget is left aligned and its size grows horizontally depending + * on the current format and each field's visible/disabled state. + * + * Datetime individual field selection is implemented in a modular style. + * Module can be implemented as a Ctxpopup based selection or an ISE based + * selection or even a spinner like selection etc. + * + * Datetime Module design: + * + * The following functions are expected to be implemented in a Datetime module: + * + * Field creation: + *
+    *
+    *  __________                                            __________
+    * |          |----- obj_hook() ---------------------->>>|          |
+    * |          |<<<----------------returns Mod_data ------|          |
+    * | Datetime |_______                                   |          |
+    * |  widget  |       |Assign module call backs          |  Module  |
+    * |   base   |<<<____|                                  |          |
+    * |          |                                          |          |
+    * |          |----- field_create() ------------------>>>|          |
+    * |__________|<<<----------------returns field_obj -----|__________|
+    *
+    * 
+ * + * Field value setting: + *
+    *
+    *  __________                                          __________
+    * |          |                                        |          |
+    * | Datetime |<<<----------elm_datetime_value_set()---|          |
+    * |  widget  |                                        |  Module  |
+    * |   base   |----display_field_value()------------>>>|          |
+    * |__________|                                        |__________|
+    *
+    * 
+ * + * del_hook: + *
+    *  __________                                          __________
+    * |          |                                        |          |
+    * | Datetime |----obj_unhook()-------------------->>>>|          |
+    * |  widget  |                                        |  Module  |
+    * |   base   |         <<<-----frees mod_data---------|          |
+    * |__________|                                        |__________|
+    *
+    * 
+ * + * + * Any module can use the following shared functions that are implemented in elm_datetime.c : + * + * field_format_get() - gives the field format. + * + * field_limit_get() - gives the field minimum, maximum limits. + * + * To enable a module, set the ELM_MODULES environment variable as shown: + * + * export ELM_MODULES="datetime_input_ctxpopup>datetime/api" + * + * + * Datetime widgets emits the following signals: + * + * @li @b "changed" - whenever Datetime field value is changed, this signal is sent. + * + * @li @b "language,changed" - whenever system locale changes, this signal is sent. + * + * Here is an example on its usage: + * @li @ref datetime_example + * + */ + + /** + * @addtogroup Datetime + * @{ + */ + + /** + * Identifies a Datetime field, The widget supports 6 fields : Year, month, + * Date, Hour, Minute, AM/PM + * + */ + typedef enum _Elm_Datetime_Field_Type + { + ELM_DATETIME_YEAR = 0, /**< Indicates Year field */ + ELM_DATETIME_MONTH = 1, /**< Indicates Month field */ + ELM_DATETIME_DATE = 2, /**< Indicates Date field */ + ELM_DATETIME_HOUR = 3, /**< Indicates Hour field */ + ELM_DATETIME_MINUTE = 4, /**< Indicates Minute field */ + ELM_DATETIME_AMPM = 5, /**< Indicates AM/PM field */ + } Elm_Datetime_Field_Type; + + /** + * @brief Adds a new datetime Widget + * + * The default datetime format and corresponding strings are based on current locale. + * + * @param parent The parent object + * @return The new object or NULL if it cannot be created + * + * This function inserts a new datetime widget on the canvas. + * + * @ingroup Datetime + */ + EAPI Evas_Object *elm_datetime_add(Evas_Object *parent); + + /** + * Get the datetime format. Format is a combination of allowed Libc date format + * specifiers like: "%b %d, %Y %I : %M %p". + * + * Maximum allowed format length is 64 chars. + * + * Format can include separators for each individual datetime field except + * for AM/PM field. + * + * Each separator can be a maximum of 6 UTF-8 bytes. + * Space is also taken as a separator but it can come only once for each field. + * + * Following are the allowed set of format specifiers for each datetime field. + * + * @b %%Y : The year as a decimal number including the century. + * + * @b %%y : The year as a decimal number without a century (range 00 to 99). + * + * @b %%m : The month as a decimal number (range 01 to 12). + * + * @b %%b : The abbreviated month name according to the current locale. + * + * @b %%B : The full month name according to the current locale. + * + * @b %%h : The abbreviated month name according to the current locale(same as %%b). + * + * @b %%d : The day of the month as a decimal number (range 01 to 31). + * + * @b %%e : The day of the month as a decimal number (range 1 to 31). single + * digits are preceded by a blank. + * + * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12). + * + * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23). + * + * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single + * digits are preceded by a blank. + * + * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single + * digits are preceded by a blank. + * + * @b %%M : The minute as a decimal number (range 00 to 59). + * + * @b %%p : Either 'AM' or 'PM' according to the given time value, or the + * corresponding strings for the current locale. Noon is treated as 'PM' + * and midnight as 'AM'. + * + * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for + * the current locale. + * + * @b %%c : The preferred date and time representation for the current locale. + * + * @b %%x : The preferred date representation for the current locale without the time. + * + * @b %%X : The preferred time representation for the current locale without the date. + * + * @b %%r : The complete calendar time using the AM/PM format of the current locale. + * + * @b %%R : The hour and minute in decimal numbers using the format %H:%M. + * + * @b %%T : The time of day in decimal numbers using the format %H:%M:%S. + * + * @b %%D : The date using the format %%m/%%d/%%y. + * + * @b %%F : The date using the format %%Y-%%m-%%d. + * + * These specifiers can be arranged in any order and the widget will display the + * fields accordingly. + * + * Default format is taken as per the system locale settings. + * + * @param obj The datetime object + * @return The datetime format string. Example: "%b %d, %Y %I : %M %p" + * + * @see elm_datetime_format_set() + * @ingroup Datetime + */ + EAPI const char *elm_datetime_format_get(const Evas_Object *obj); + + /** + * Set the datetime format. Format is a combination of allowed Libc date format + * specifiers like: "%b %d, %Y %I : %M %p". + * + * Maximum allowed format length is 64 chars. + * + * Format can include separators for each individual datetime field except + * for AM/PM field. + * + * Each separator can be a maximum of 6 UTF-8 bytes. + * Space is also taken as a separator but it can come only once for each field. + * + * Following are the allowed set of format specifiers for each datetime field. + * + * @b %%Y : The year as a decimal number including the century. + * + * @b %%y : The year as a decimal number without a century (range 00 to 99). + * + * @b %%m : The month as a decimal number (range 01 to 12). + * + * @b %%b : The abbreviated month name according to the current locale. + * + * @b %%B : The full month name according to the current locale. + * + * @b %%h : The abbreviated month name according to the current locale(same as %%b). + * + * @b %%d : The day of the month as a decimal number (range 01 to 31). + * + * @b %%e : The day of the month as a decimal number (range 1 to 31). single + * digits are preceded by a blank. + * + * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12). + * + * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23). + * + * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single + * digits are preceded by a blank. + * + * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single + * digits are preceded by a blank. + * + * @b %%M : The minute as a decimal number (range 00 to 59). + * + * @b %%p : Either 'AM' or 'PM' according to the given time value, or the + * corresponding strings for the current locale. Noon is treated as 'PM' + * and midnight as 'AM'. + * + * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for + * the current locale. + * + * @b %%c : The preferred date and time representation for the current locale. + * + * @b %%x : The preferred date representation for the current locale without the time. + * + * @b %%X : The preferred time representation for the current locale without the date. + * + * @b %%r : The complete calendar time using the AM/PM format of the current locale. + * + * @b %%R : The hour and minute in decimal numbers using the format %H:%M. + * + * @b %%T : The time of day in decimal numbers using the format %H:%M:%S. + * + * @b %%D : The date using the format %%m/%%d/%%y. + * + * @b %%F : The date using the format %%Y-%%m-%%d. + * + * These specifiers can be arranged in any order and the widget will display the + * fields accordingly. + * + * Default format is taken as per the system locale settings. + * + * @param obj The datetime object + * @param fmt The datetime format + * + * @see elm_datetime_format_get() + * @ingroup Datetime + */ + EAPI void elm_datetime_format_set(Evas_Object *obj, const char *fmt); + + /** + * @brief Get the upper boundary of a field. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * @param obj The datetime object + * @param maxtime Time structure containing the maximum time value. + * @return int The maximum value of the field. + * + * @see elm_datetime_value_max_set() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime); + + /** + * @brief Set the upper boundary of a field. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * @param obj The datetime object + * @param maxtime Time structure containing the maximum time value. + * @return EINA_TRUE if maximum value is accepted. + * + * @see elm_datetime_value_max_get() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime); + + /** + * @brief Get the lower boundary of a field. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * @param obj The datetime object + * @param mintime Time structure. + * @return EINA_TRUE if minimum value is successfully returned. + * + * @see elm_datetime_value_min_set() + * @ingroup Datepicker + */ + EAPI Eina_Bool elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime); + + /** + * @brief Set the lower boundary of a field. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * @param obj The datetime object. + * @param mintime Time structure containing the minimum time value. + * @return EINA_TRUE if minimum value is accepted. + * + * @see elm_datetime_value_min_get() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime); + + /** + * @brief Get the field limits of a field. + * + * Limits can be set to individual fields, independently, except for AM/PM field. + * Any field can display the values only in between these Minimum and Maximum limits unless + * the corresponding time value is restricted from MinTime to MaxTime. + * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime. + * + * There is no provision to set the limits of AM/PM field. + * + * @param obj The datetime object + * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc. + * @param min Reference to field's minimum value + * @param max Reference to field's maximum value + * + * @see elm_datetime_field_limit_set() + * @ingroup Datetime + */ + EAPI void elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int *min, int *max); + + /** + * @brief Set the field limits of a field. + * + * Limits can be set to individual fields, independently, except for AM/PM field. + * Any field can display the values only in between these Minimum and Maximum limits unless + * the corresponding time value is restricted from MinTime to MaxTime. + * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime. + * + * There is no provision to set the limits of AM/PM field. + * + * @param obj The datetime object + * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc. + * @param min Reference to field's minimum value + * @param max Reference to field's maximum value + * + * @see elm_datetime_field_limit_set() + * @ingroup Datetime + */ + EAPI void elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int min, int max); + + /** + * @brief Get the current value of a field. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * @param obj The datetime object. + * @param currtime Time structure. + * @return EINA_TRUE if current time is returned successfully. + * + * @see elm_datetime_field_value_set() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime); + + /** + * @brief Set the current value of a Datetime object. + * + * Year: years since 1900. Negative value represents year below 1900 (year + * value -30 represents 1870). Year default range is from 70 to 137. + * + * Month: default value range is from 0 to 11. + * + * Date: default value range is from 1 to 31 according to the month value. + * + * Hour: default value will be in terms of 24 hr format (0~23) + * + * Minute: default value range is from 0 to 59. + * + * + * @param obj The datetime object. + * @param newtime Time structure filled with values to be set. + * @return EINA_TRUE if current time is set successfully. + * + * @see elm_datetime_value_set() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime); + + /** + * @brief Get whether a field can be visible/not + * + * @param obj The datetime object + * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc + * @return bool @c EINA_TRUE, if field can be visible. @c EINA_FALSE otherwise. + * + * @see elm_datetime_field_visible_set() + * @ingroup Datetime + */ + EAPI Eina_Bool elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype); + + /** + * @brief Set a field to be visible or not. + * Setting this API True does not ensure that the field is visible, apart from + * this, the field's format must be present in Datetime overall format. + * If a field's visibility is set to False then it won't appear even though + * its format is present in overall format. + * So if and only if this API is set true and the corresponding field's format + * is present in Datetime format, the field is visible. + * + * By default the field visibility is set to True. + * + * @param obj The datetime object + * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc. + * @param visible @c EINA_TRUE field can be visible, @c EINA_FALSE otherwise. + * + * @see elm_datetime_field_visible_get() + * @ingroup Datetime + */ + EAPI void elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, Eina_Bool visible); + + /** + * @} + */ + +#ifdef __cplusplus +} +#endif diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index ce266f4f11..94e64aa52c 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -43,6 +43,7 @@ typedef struct _Elm_Config Elm_Config; typedef struct _Elm_Module Elm_Module; +typedef struct _Elm_Datetime_Module_Data Elm_Datetime_Module_Data; struct _Elm_Theme { @@ -186,6 +187,13 @@ struct _Elm_Module int references; }; +struct _Elm_Datetime_Module_Data +{ + Evas_Object *base; + void (*field_limit_get)(Evas_Object *obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max); + const char *(*field_format_get)(Evas_Object * obj, Elm_Datetime_Field_Type field_type); +}; + int _elm_ews_wm_init(void); void _elm_ews_wm_shutdown(void); void _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme); diff --git a/legacy/elementary/src/modules/Makefile.am b/legacy/elementary/src/modules/Makefile.am index 9354af6293..e435e37ff7 100644 --- a/legacy/elementary/src/modules/Makefile.am +++ b/legacy/elementary/src/modules/Makefile.am @@ -4,4 +4,5 @@ MAINTAINERCLEANFILES = Makefile.in SUBDIRS = \ test_entry \ test_map \ -access_output +access_output \ +datetime_input_ctxpopup diff --git a/legacy/elementary/src/modules/datetime_input_ctxpopup/Makefile.am b/legacy/elementary/src/modules/datetime_input_ctxpopup/Makefile.am new file mode 100644 index 0000000000..73be6a7744 --- /dev/null +++ b/legacy/elementary/src/modules/datetime_input_ctxpopup/Makefile.am @@ -0,0 +1,33 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-DELM_INTERNAL_API_ARGESFSDFEFC=1 \ +-I. \ +-I$(top_builddir) \ +-I$(top_srcdir) \ +-I$(top_srcdir)/src/lib \ +-I$(top_builddir)/src/lib \ +-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ +-DPACKAGE_LIB_DIR=\"$(libdir)\" \ +@ELEMENTARY_CFLAGS@ \ +@ELEMENTARY_X_CFLAGS@ \ +@ELEMENTARY_FB_CFLAGS@ \ +@ELEMENTARY_WIN32_CFLAGS@ \ +@ELEMENTARY_WINCE_CFLAGS@ \ +@ELEMENTARY_EDBUS_CFLAGS@ \ +@ELEMENTARY_EFREET_CFLAGS@ \ +@ELEMENTARY_ETHUMB_CFLAGS@ + +if ELEMENTARY_WINDOWS_BUILD +AM_CPPFLAGS += -DELEMENTARY_BUILD +endif + +pkgdir = $(libdir)/elementary/modules/datetime_input_ctxpopup/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = datetime_input_ctxpopup.c + +module_la_LIBADD = @ELEMENTARY_LIBS@ $(top_builddir)/src/lib/libelementary.la +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/legacy/elementary/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c b/legacy/elementary/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c new file mode 100644 index 0000000000..485d0f5638 --- /dev/null +++ b/legacy/elementary/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c @@ -0,0 +1,325 @@ +#include +#include "elm_priv.h" +#ifdef HAVE_CONFIG_H +#include "elementary_config.h" +#endif + +#define DATETIME_FIELD_COUNT 6 +#define FIELD_FORMAT_LEN 3 +#define DISKSELECTOR_MIN_ITEMS 4 +#define BUFF_SIZE 1024 + +typedef struct _Ctxpopup_Module_Data Ctxpopup_Module_Data; +typedef struct _DiskItem_Data DiskItem_Data; + +struct _Ctxpopup_Module_Data +{ + Elm_Datetime_Module_Data mod_data; + Evas_Object *ctxpopup; +}; + +struct _DiskItem_Data +{ + Ctxpopup_Module_Data *ctx_mod; + Elm_Datetime_Field_Type sel_field_type; + unsigned int sel_field_value; +}; + +static void +_diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + if (data) free(data); +} + +static void +_ctxpopup_dismissed_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__ ) +{ + Evas_Object *diskselector; + + diskselector = elm_object_content_unset(obj); + if (diskselector) evas_object_del(diskselector); +} + +static void +_datetime_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Ctxpopup_Module_Data *ctx_mod; + + ctx_mod = (Ctxpopup_Module_Data *)data; + if (!ctx_mod) return; + + evas_object_hide(ctx_mod->ctxpopup); +} + +static void +_ctxpopup_parent_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Ctxpopup_Module_Data *ctx_mod; + + ctx_mod = (Ctxpopup_Module_Data *)data; + if (!ctx_mod) return; + elm_ctxpopup_hover_parent_set(ctx_mod->ctxpopup, elm_widget_top_get(ctx_mod->mod_data.base)); +} + +static void +_datetime_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Ctxpopup_Module_Data *ctx_mod; + + ctx_mod = (Ctxpopup_Module_Data *)data; + if (!ctx_mod) return; + + evas_object_hide(ctx_mod->ctxpopup); +} + +static void +_field_value_set(struct tm *time, Elm_Datetime_Field_Type field_type, int val) +{ + if (field_type >= DATETIME_FIELD_COUNT - 1) return; + + int *timearr[]= { &time->tm_year, &time->tm_mon, &time->tm_mday, &time->tm_hour, &time->tm_min }; + *timearr[field_type] = val; +} + +static int +_field_value_get(struct tm *time, Elm_Datetime_Field_Type field_type) +{ + if (field_type >= DATETIME_FIELD_COUNT - 1) return -1; + + int *timearr[]= { &time->tm_year, &time->tm_mon, &time->tm_mday, &time->tm_hour, &time->tm_min }; + return (*timearr[field_type]); +} + +static void +_diskselector_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + DiskItem_Data *disk_data; + struct tm curr_time; + const char *fmt; + + disk_data = (DiskItem_Data *)data; + if (!disk_data || !(disk_data->ctx_mod)) return; + + elm_datetime_value_get(disk_data->ctx_mod->mod_data.base, &curr_time); + fmt = disk_data->ctx_mod->mod_data.field_format_get(disk_data->ctx_mod->mod_data.base, disk_data->sel_field_type); + if ((disk_data->sel_field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) || + (!strncmp(fmt, "%l", FIELD_FORMAT_LEN))) && (curr_time.tm_hour >= 12)) + disk_data->sel_field_value += 12; + _field_value_set(&curr_time, disk_data->sel_field_type, disk_data->sel_field_value); + elm_datetime_value_set(disk_data->ctx_mod->mod_data.base, &curr_time); + evas_object_hide(disk_data->ctx_mod->ctxpopup); +} + +static void +_ampm_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ctxpopup_Module_Data *ctx_mod; + struct tm curr_time; + + ctx_mod = (Ctxpopup_Module_Data *)data; + if (!ctx_mod) return; + + elm_datetime_value_get(ctx_mod->mod_data.base, &curr_time); + if (curr_time.tm_hour >= 12) curr_time.tm_hour -= 12; + else curr_time.tm_hour += 12; + elm_datetime_value_set(ctx_mod->mod_data.base, &curr_time); +} + +static void +_field_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + Ctxpopup_Module_Data *ctx_mod; + Evas_Object *diskselector; + Elm_Object_Item *item; + DiskItem_Data *disk_data; + Elm_Datetime_Field_Type field_type; + time_t t; + struct tm time1; + char buf[BUFF_SIZE], label[BUFF_SIZE]; + const char *fmt; + int idx, min, max, val; + unsigned int display_item_num, text_len = 0; + Evas_Coord x = 0, y = 0, w = 0, h = 0, width; + + ctx_mod = (Ctxpopup_Module_Data *)data; + if (!ctx_mod || !ctx_mod->ctxpopup) return; + + // because of the diskselector behaviour, it is being recreated + diskselector = elm_diskselector_add(elm_widget_top_get(ctx_mod->mod_data.base)); + snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj)); + elm_object_style_set(diskselector, buf); + elm_object_content_set(ctx_mod->ctxpopup, diskselector); + + t = time(NULL); + localtime_r(&t, &time1); + + field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type"); + fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type); + elm_datetime_value_get(ctx_mod->mod_data.base, &time1); + val = _field_value_get(&time1, field_type); + ctx_mod->mod_data.field_limit_get(ctx_mod->mod_data.base, field_type, &min, &max); + + time1.tm_mday = 1; // To avoid month wrapping, set the first day of the month to start with. + + if ((field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) || + (!strncmp(fmt, "%l", FIELD_FORMAT_LEN)))) + { + if (max >= 12) max -= 12; + if (val >= 12) val -= 12; + if (min >= 12) min -= 12; + } + for (idx = min; idx <= max; idx++) + { + _field_value_set(&time1, field_type, idx); + strftime(label, BUFF_SIZE, fmt, &time1); + if (strlen(label) > text_len) text_len = strlen(label); + if (idx == val) + { + item = elm_diskselector_item_append(diskselector, label, NULL, NULL, NULL); + elm_diskselector_item_selected_set(item, EINA_TRUE); + } + else + { + disk_data = (DiskItem_Data *) malloc (sizeof(DiskItem_Data)); + disk_data->ctx_mod = ctx_mod; + disk_data->sel_field_type = field_type; + disk_data->sel_field_value = idx; + item = elm_diskselector_item_append(diskselector, label, NULL, _diskselector_cb, disk_data); + elm_object_item_del_cb_set(item, _diskselector_item_free_cb); + } + } + elm_diskselector_side_label_length_set(diskselector, text_len); + + evas_object_geometry_get(obj, &x, &y, &w, &h); + evas_object_geometry_get(elm_widget_top_get(ctx_mod->mod_data.base), NULL, NULL, &width, NULL); + evas_object_size_hint_min_set(ctx_mod->ctxpopup, width, -1); + display_item_num = width / (w + elm_finger_size_get()); + // always display even number of items to avoid autoselection + if (display_item_num % 2) display_item_num -= 1; + if (display_item_num < DISKSELECTOR_MIN_ITEMS) + display_item_num = DISKSELECTOR_MIN_ITEMS; + elm_diskselector_display_item_num_set(diskselector, display_item_num); + elm_diskselector_round_set(diskselector, EINA_TRUE); + + elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_DOWN, + ELM_CTXPOPUP_DIRECTION_UP, -1, -1); + evas_object_move(ctx_mod->ctxpopup, (x+w/2), (y+h)); + + // if the direction of Ctxpopup is upwards, move it to the top of datetime + if (elm_ctxpopup_direction_get (ctx_mod->ctxpopup) == ELM_CTXPOPUP_DIRECTION_UP) + { + elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_UP, + ELM_CTXPOPUP_DIRECTION_DOWN, -1, -1); + evas_object_move(ctx_mod->ctxpopup, (x+w/2), y); + } + evas_object_show(ctx_mod->ctxpopup); +} + +// module fucns for the specific module type +EAPI void +field_value_display(Elm_Datetime_Module_Data *module_data, Evas_Object *obj) +{ + Ctxpopup_Module_Data *ctx_mod; + Elm_Datetime_Field_Type field_type; + struct tm time; + char buf[BUFF_SIZE]; + const char *fmt; + + ctx_mod = (Ctxpopup_Module_Data *)module_data; + if (!ctx_mod || !obj) return; + + elm_datetime_value_get(ctx_mod->mod_data.base, &time); + field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type"); + fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type); + strftime(buf, sizeof(buf), fmt, &time); + elm_object_text_set(obj, buf); +} + +EAPI Evas_Object * +field_create(Elm_Datetime_Module_Data *module_data, Elm_Datetime_Field_Type field_type) +{ + Ctxpopup_Module_Data *ctx_mod; + Evas_Object *field_obj; + + ctx_mod = (Ctxpopup_Module_Data *)module_data; + if (!ctx_mod) return NULL; + + if (field_type == ELM_DATETIME_AMPM) + { + field_obj = elm_button_add(ctx_mod->mod_data.base); + evas_object_smart_callback_add(field_obj, "clicked", _ampm_clicked_cb, ctx_mod); + } + else + { + field_obj = elm_entry_add(ctx_mod->mod_data.base); + elm_entry_single_line_set(field_obj, EINA_TRUE); + elm_entry_editable_set(field_obj, EINA_FALSE); + elm_entry_input_panel_enabled_set(field_obj, EINA_FALSE); + elm_entry_context_menu_disabled_set(field_obj, EINA_TRUE); + evas_object_smart_callback_add(field_obj, "clicked", _field_clicked_cb, ctx_mod); + } + evas_object_data_set(field_obj, "_field_type", (void *)field_type); + return field_obj; +} + +EAPI Elm_Datetime_Module_Data * +obj_hook(Evas_Object *obj) +{ + Ctxpopup_Module_Data *ctx_mod; + char buf[BUFF_SIZE]; + + ctx_mod = ELM_NEW(Ctxpopup_Module_Data); + if (!ctx_mod) return NULL; + + ctx_mod->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj)); + snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj)); + elm_object_style_set(ctx_mod->ctxpopup, buf); + elm_ctxpopup_horizontal_set(ctx_mod->ctxpopup, EINA_TRUE); + evas_object_size_hint_weight_set(ctx_mod->ctxpopup, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(ctx_mod->ctxpopup, EVAS_HINT_FILL, 0.5); + evas_object_smart_callback_add(ctx_mod->ctxpopup, "dismissed", + _ctxpopup_dismissed_cb, ctx_mod); + evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, + _datetime_resize_cb, ctx_mod); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, + _datetime_move_cb, ctx_mod); + evas_object_event_callback_add(elm_widget_top_get(obj), EVAS_CALLBACK_RESIZE, + _ctxpopup_parent_resize_cb, ctx_mod); + + return ((Elm_Datetime_Module_Data*)ctx_mod); +} + +EAPI void +obj_unhook(Elm_Datetime_Module_Data *module_data) +{ + Ctxpopup_Module_Data *ctx_mod; + + ctx_mod = (Ctxpopup_Module_Data *)module_data; + if (!ctx_mod) return; + + if (ctx_mod->ctxpopup) + evas_object_del(ctx_mod->ctxpopup); + + if (ctx_mod) + { + free(ctx_mod); + ctx_mod = NULL; + } +} + +// module api funcs needed +EAPI int +elm_modapi_init(void *m __UNUSED__) +{ + return 1; // succeed always +} + +EAPI int +elm_modapi_shutdown(void *m __UNUSED__) +{ + return 1; // succeed always +}