Goun Lee <gouni.lee@samsung.com>
Mikael Sans <sans.mikael@gmail.com>
Doyoun Kang <doyoun.kang@samsung.com>
+M.V.K. Sumanth <sumanth.m@samsung.com> <mvksumanth@gmail.com>
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;
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;
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
#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"
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// 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
+///////////////////////////////////////////////////////////////////////////////
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 \
*
* @ref clock_example
*
+ * @ref datetime_example
+ *
* @ref mapbuf_example
* @ref map_example_01
*/
/**
+ * @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 <b>"only Date display"</b>:
+ * @dontinclude datetime_example.c
+ * @skip only DATE
+ * @until evas_object_show
+ *
+ * For <b>"only Time display"</b>, see the second datetime:
+ * @dontinclude datetime_example.c
+ * @skip only TIME
+ * @until evas_object_show
+ *
+ * The third one will display datetime shows both <b>Date and Time</b>, corresponding format will be
+ * taken from system @b locale. Note, besides, that the strings are different
+ * for different language settings.
+ *
+ * <b>Datetime format</b> 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
*
* This code places a Elementary mapbuf widget on a window,
* @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
*
* @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
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 \
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 \
--- /dev/null
+#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"
--- /dev/null
+#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"
--- /dev/null
+#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"
test_conform.c \
test_ctxpopup.c \
test_cursor.c \
+test_datetime.c \
test_diskselector.c \
test_entry.c \
test_factory.c \
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
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);
--- /dev/null
+#include <Elementary.h>
+#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
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 \
calendar_example_04 \
calendar_example_05 \
calendar_example_06 \
+ datetime_example \
map_example_01 \
map_example_02 \
map_example_03 \
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 \
#include <elm_config.h>
#include <elm_conform.h> // XXX: comments in elm_conform.h
#include <elm_cursor.h> // XXX: comments in elm_cursor.h. review was not finished.
+#include <elm_datetime.h>
#include <elm_debug.h> // OK
#include <elm_diskselector.h>
elm_config.h \
elm_conform.h \
elm_cursor.h \
+elm_datetime.h \
elm_debug.h \
elm_deprecated.h \
elm_deprecated_before.h \
elm_colorselector.c \
elm_config.c \
elm_conform.c \
+elm_datetime.c \
elm_diskselector.c \
elm_entry.c \
elm_factory.c \
--- /dev/null
+#include <locale.h>
+#include <langinfo.h>
+#include <Elementary.h>
+#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;
+}
--- /dev/null
+
+ /**
+ * @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 <b>system's locale</b> 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 <b>LIBC date format specifiers</b>, 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 <b>Unicode character</b> 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 <b>only time/ only date / only required fields</b> 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.
+ *
+ * <b>Datetime Module design:</b>
+ *
+ * The following functions are expected to be implemented in a Datetime module:
+ *
+ * <b>Field creation:</b>
+ * <pre>
+ *
+ * __________ __________
+ * | |----- obj_hook() ---------------------->>>| |
+ * | |<<<----------------returns Mod_data ------| |
+ * | Datetime |_______ | |
+ * | widget | |Assign module call backs | Module |
+ * | base |<<<____| | |
+ * | | | |
+ * | |----- field_create() ------------------>>>| |
+ * |__________|<<<----------------returns field_obj -----|__________|
+ *
+ * </pre>
+ *
+ * <b>Field value setting:</b>
+ * <pre>
+ *
+ * __________ __________
+ * | | | |
+ * | Datetime |<<<----------elm_datetime_value_set()---| |
+ * | widget | | Module |
+ * | base |----display_field_value()------------>>>| |
+ * |__________| |__________|
+ *
+ * </pre>
+ *
+ * <b>del_hook:</b>
+ * <pre>
+ * __________ __________
+ * | | | |
+ * | Datetime |----obj_unhook()-------------------->>>>| |
+ * | widget | | Module |
+ * | base | <<<-----frees mod_data---------| |
+ * |__________| |__________|
+ *
+ * </pre>
+ *
+ *
+ * Any module can use the following shared functions that are implemented in elm_datetime.c :
+ *
+ * <b>field_format_get()</b> - gives the field format.
+ *
+ * <b>field_limit_get()</b> - gives the field minimum, maximum limits.
+ *
+ * To enable a module, set the ELM_MODULES environment variable as shown:
+ *
+ * <b>export ELM_MODULES="datetime_input_ctxpopup>datetime/api"</b>
+ *
+ *
+ * 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
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
{
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);
SUBDIRS = \
test_entry \
test_map \
-access_output
+access_output \
+datetime_input_ctxpopup
--- /dev/null
+
+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
--- /dev/null
+#include <Elementary.h>
+#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
+}