summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumanth Krishna Mannam <sumanth.m@samsung.com>2012-03-05 11:07:05 +0000
committerCarsten Haitzler <raster@rasterman.com>2012-03-05 11:07:05 +0000
commit3448bf2eb2d24b2e3177fe3d05ec24e17d4ddb18 (patch)
tree305da2c06586814ce88120f054946b67cfd879a6
parente6eb4e1008e29da7843aff641b38f59c37080cab (diff)
From: Sumanth Krishna Mannam <sumanth.m@samsung.com>
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 <sumanth.m@samsug.com> SVN revision: 68696
-rw-r--r--AUTHORS1
-rw-r--r--config/default/base.src2
-rw-r--r--config/illume/base.src2
-rw-r--r--configure.ac1
-rw-r--r--data/themes/default.edc1
-rw-r--r--data/themes/widgets/datetime.edc349
-rw-r--r--doc/Makefile.am3
-rw-r--r--doc/examples.dox53
-rw-r--r--doc/index.doxy4
-rw-r--r--doc/widgets/Makefile.am6
-rw-r--r--doc/widgets/widget_preview_datetime1.c16
-rw-r--r--doc/widgets/widget_preview_datetime2.c19
-rw-r--r--doc/widgets/widget_preview_datetime3.c19
-rw-r--r--src/bin/Makefile.am1
-rw-r--r--src/bin/test.c2
-rw-r--r--src/bin/test_datetime.c81
-rw-r--r--src/examples/Makefile.am3
-rw-r--r--src/lib/Elementary.h.in1
-rw-r--r--src/lib/Makefile.am2
-rw-r--r--src/lib/elm_datetime.c1039
-rw-r--r--src/lib/elm_datetime.h596
-rw-r--r--src/lib/elm_priv.h8
-rw-r--r--src/modules/Makefile.am3
-rw-r--r--src/modules/datetime_input_ctxpopup/Makefile.am33
-rw-r--r--src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c325
25 files changed, 2567 insertions, 3 deletions
diff --git a/AUTHORS b/AUTHORS
index dab520286..9bad23e48 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -53,3 +53,4 @@ Hyunsil Park <hyunsil.park@samsung.com>
53Goun Lee <gouni.lee@samsung.com> 53Goun Lee <gouni.lee@samsung.com>
54Mikael Sans <sans.mikael@gmail.com> 54Mikael Sans <sans.mikael@gmail.com>
55Doyoun Kang <doyoun.kang@samsung.com> 55Doyoun Kang <doyoun.kang@samsung.com>
56M.V.K. Sumanth <sumanth.m@samsung.com> <mvksumanth@gmail.com>
diff --git a/config/default/base.src b/config/default/base.src
index 7d5f0c6a8..59a40a247 100644
--- a/config/default/base.src
+++ b/config/default/base.src
@@ -26,7 +26,7 @@ group "Elm_Config" struct {
26 value "finger_size" int: 40; 26 value "finger_size" int: 40;
27 value "fps" double: 60.0; 27 value "fps" double: 60.0;
28 value "theme" string: "default"; 28 value "theme" string: "default";
29 value "modules" string: ""; 29 value "modules" string: "datetime_input_ctxpopup>datetime/api";
30 value "tooltip_delay" double: 1.0; 30 value "tooltip_delay" double: 1.0;
31 value "cursor_engine_only" uchar: 1; 31 value "cursor_engine_only" uchar: 1;
32 value "focus_highlight_enable" uchar: 0; 32 value "focus_highlight_enable" uchar: 0;
diff --git a/config/illume/base.src b/config/illume/base.src
index 688dfd80e..7c87276ac 100644
--- a/config/illume/base.src
+++ b/config/illume/base.src
@@ -30,7 +30,7 @@ group "Elm_Config" struct {
30 value "finger_size" int: 40; 30 value "finger_size" int: 40;
31 value "fps" double: 60.0; 31 value "fps" double: 60.0;
32 value "theme" string: "default"; 32 value "theme" string: "default";
33 value "modules" string: ""; 33 value "modules" string: "datetime_input_ctxpopup>datetime/api";
34 value "tooltip_delay" double: 1.0; 34 value "tooltip_delay" double: 1.0;
35 value "cursor_engine_only" uchar: 1; 35 value "cursor_engine_only" uchar: 1;
36 value "focus_highlight_enable" uchar: 0; 36 value "focus_highlight_enable" uchar: 0;
diff --git a/configure.ac b/configure.ac
index bcf85e2d3..0045d840b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -711,6 +711,7 @@ src/lib/Elementary.h
711src/bin/Makefile 711src/bin/Makefile
712src/modules/Makefile 712src/modules/Makefile
713src/modules/access_output/Makefile 713src/modules/access_output/Makefile
714src/modules/datetime_input_ctxpopup/Makefile
714src/modules/test_entry/Makefile 715src/modules/test_entry/Makefile
715src/modules/test_map/Makefile 716src/modules/test_map/Makefile
716src/edje_externals/Makefile 717src/edje_externals/Makefile
diff --git a/data/themes/default.edc b/data/themes/default.edc
index 555cb7b78..5111d77b9 100644
--- a/data/themes/default.edc
+++ b/data/themes/default.edc
@@ -324,6 +324,7 @@ collections {
324#include "widgets/button.edc" 324#include "widgets/button.edc"
325#include "widgets/toggle.edc" 325#include "widgets/toggle.edc"
326#include "widgets/clock.edc" 326#include "widgets/clock.edc"
327#include "widgets/datetime.edc"
327#include "widgets/menu.edc" 328#include "widgets/menu.edc"
328#include "widgets/frame.edc" 329#include "widgets/frame.edc"
329#include "widgets/tooltip.edc" 330#include "widgets/tooltip.edc"
diff --git a/data/themes/widgets/datetime.edc b/data/themes/widgets/datetime.edc
new file mode 100644
index 000000000..fe68ab344
--- /dev/null
+++ b/data/themes/widgets/datetime.edc
@@ -0,0 +1,349 @@
1///////////////////////////////////////////////////////////////////////////////
2// datetime
3///////////////////////////////////////////////////////////////////////////////
4
5#define DATETIME_FIELD(_pos) \
6 part {\
7 name: "field"#_pos; \
8 type: SWALLOW; \
9 scale: 1;\
10 clip_to: "clipper";\
11 description { state: "default" 0.0; \
12 visible: 0;\
13 min: 0 0;\
14 align: 0.0 0.5;\
15 fixed: 1 0;\
16 rel1 {\
17 relative: 1.0 0.0;\
18 to: "separator"#_pos;\
19 }\
20 rel2 {\
21 relative: 1.0 1.0;\
22 to: "separator"#_pos;\
23 }\
24 }\
25 description { state: "enable" 0.0;\
26 inherit: "default" 0.0;\
27 visible: 1;\
28 min: 25 25;\
29 }\
30 }\
31 programs{\
32 program {\
33 name: "field_"#_pos"enabled";\
34 signal: "field"#_pos",enable";\
35 source: "elm";\
36 action: STATE_SET "enable" 0.0;\
37 target: "field"#_pos;\
38 }\
39 program {\
40 name: "field_"#_pos"disabled";\
41 signal: "field"#_pos",disable";\
42 source: "elm";\
43 action: STATE_SET "default" 0.0;\
44 target: "field"#_pos;\
45 }\
46 }
47
48#define DATETIME_SEPARATOR(_pos,_after) \
49 part {\
50 name: "separator"#_pos; \
51 type: TEXT;\
52 scale: 1;\
53 description {\
54 state: "default" 0.0;\
55 visible: 0;\
56 min: 0 0;\
57 align: 0.0 0.5;\
58 fixed: 1 0;\
59 rel1 {\
60 relative: 1.0 0.0;\
61 to: "field"#_after;\
62 }\
63 rel2 {\
64 relative: 1.0 1.0;\
65 to: "field"#_after;\
66 }\
67 color: 100 100 100 255;\
68 text {\
69 font: "SLP:style=Roman";\
70 size: 13;\
71 min: 1 0;\
72 align: 0.2 0.5;\
73 }\
74 }\
75 description { state: "enable" 0.0;\
76 inherit: "default" 0.0;\
77 visible: 1;\
78 min: 13 25;\
79 }\
80 }\
81 programs {\
82 program {\
83 name: "separator"#_pos",enabled";\
84 signal: "field"#_after",enable";\
85 source: "elm";\
86 action: STATE_SET "enable" 0.0;\
87 target: "separator"#_pos;\
88 }\
89 program {\
90 name: "separator"#_pos",disabled";\
91 signal: "field"#_after",disable";\
92 source: "elm";\
93 action: STATE_SET "default" 0.0;\
94 target: "separator"#_pos;\
95 }\
96 }
97
98
99group { name: "elm/datetime/base/default";
100 parts {
101 part {
102 name: "bg";
103 type: RECT;
104 scale: 1;
105 description {
106 state: "default" 0.0;
107 color: 0 0 0 0;
108 }
109 }
110 part {
111 name: "separator0";
112 type: RECT;
113 scale: 1;
114 description {
115 state: "default" 0.0;
116 visible: 0;
117 min: 13 25;
118 align: 0.0 0.5;
119 fixed: 1 0;
120 rel2 {
121 relative: 0.0 1.0;
122 to: "bg";
123 }
124 }
125 }
126 DATETIME_FIELD(0)
127 DATETIME_SEPARATOR(1,0)
128 DATETIME_FIELD(1)
129 DATETIME_SEPARATOR(2,1)
130 DATETIME_FIELD(2)
131 DATETIME_SEPARATOR(3,2)
132 DATETIME_FIELD(3)
133 DATETIME_SEPARATOR(4,3)
134 DATETIME_FIELD(4)
135 DATETIME_SEPARATOR(5,4)
136 DATETIME_FIELD(5)
137 DATETIME_SEPARATOR(6,5)
138 part {
139 name: "clipper";
140 type: RECT;
141 description { state: "default" 0.0;
142 rel1 {
143 relative: 0.0 0.0;
144 to: "separator0";
145 }
146 rel2 {
147 relative: 1.0 1.0;
148 to: "separator6";
149 }
150 color: 255 255 255 255;
151 }
152 description { state: "enable" 0.0;
153 inherit: "default" 0.0;
154 color: 255 255 255 127;
155 }
156 }
157 part {
158 name: "disabler";
159 type: RECT;
160 description { state: "default" 0.0;
161 color: 0 0 0 0;
162 visible: 0;
163 }
164 description { state: "visible" 0.0;
165 inherit: "default" 0.0;
166 visible: 1;
167 }
168 }
169 }
170 programs {
171 program {
172 name: "disble_datetime";
173 signal: "elm,state,disabled";
174 source: "elm";
175 action: STATE_SET "visible" 0.0;
176 target: "disabler";
177 target: "clipper";
178 }
179 program {
180 name: "enable_datetime";
181 signal: "elm,state,enabled";
182 source: "elm";
183 action: STATE_SET "default" 0.0;
184 target: "disabler";
185 target: "clipper";
186 }
187 }
188}//end datetime group
189
190///////////////////////////////////////////////////////////////////////////////
191// diskselector item : datetime style
192///////////////////////////////////////////////////////////////////////////////
193group { name: "elm/diskselector/item/datetime/default";
194 data {
195 item: "len_threshold" "10";
196 item: "min_height" "-1";
197 item: "min_width" "-1";
198 }
199 parts {
200 part {
201 name: "elm.text";
202 type: TEXT;
203 mouse_events: 0;
204 scale: 1;
205 description {
206 state: "default" 0.0;
207 min: 25 25;
208 fixed: 1 1;
209 align: 0.0 0.0;
210 color: 172 172 172 255;
211 visible: 1;
212 text {
213 font: "Sans,Edje-Vera";
214 size: 13;
215 min: 1 1;
216 }
217 }
218 description {
219 state: "center_sel" 0.0;
220 inherit: "default" 0.0;
221 color: 255 255 255 255;
222 }
223 description { state: "left_side" 0.0;
224 inherit: "default" 0.0;
225 color: 152 152 152 255;
226 text.size: 10;
227 text.align: 0.2 0.5;
228 }
229 description { state: "left_side_sel" 0.0;
230 inherit: "default" 0.0;
231 color: 255 255 255 255;
232 text.size: 10;
233 text.align: 0.2 0.5;
234 }
235 description { state: "right_side" 0.0;
236 inherit: "default" 0.0;
237 color: 152 152 152 255;
238 text.size: 10;
239 text.align: 0.8 0.5;
240 }
241 description { state: "right_side_sel" 0.0;
242 inherit: "default" 0.0;
243 color: 255 255 255 255;
244 text.size: 10;
245 text.align: 0.8 0.5;
246 }
247 }
248 part {
249 name: "over1";
250 mouse_events: 1;
251 repeat_events: 1;
252 ignore_flags: ON_HOLD;
253 description {
254 state: "default" 0.0;
255 }
256 }
257 }
258 programs {
259 script {
260 public field_pos; // center = 0,left = 1, right =2.
261 public field_selected; //field is selected(1) or not(0).
262
263 public update_state() {
264 new pos, is_sel;
265 pos = get_int(field_pos)
266 is_sel = get_int(field_selected);
267
268 if (is_sel == 1)
269 {
270 if (pos == 0)
271 set_state(PART:"elm.text", "center_sel", 0.0);
272 else if (pos == 1)
273 set_state(PART:"elm.text", "left_side_sel", 0.0);
274 else if (pos == 2)
275 set_state(PART:"elm.text", "right_side_sel", 0.0);
276 }
277 else if (is_sel == 0)
278 {
279 if (pos == 0)
280 set_state(PART:"elm.text", "default", 0.0);
281 else if (pos == 1)
282 set_state(PART:"elm.text", "left_side", 0.0);
283 else if (pos == 2)
284 set_state(PART:"elm.text", "right_side", 0.0);
285 }
286 }
287 }
288 program {
289 name: "selected_text";
290 signal: "elm,state,selected";
291 source: "elm";
292 script {
293 set_int(field_selected, 1);
294 update_state();
295 }
296 }
297 program {
298 name: "default_text";
299 signal: "elm,state,default";
300 source: "elm";
301 script {
302 set_int(field_selected, 0);
303 update_state();
304 }
305 }
306 program { name: "center_text";
307 signal: "elm,state,center";
308 source: "elm";
309 script {
310 set_int(field_pos, 0);
311 update_state();
312 }
313 }
314 program { name: "center_small_text";
315 signal: "elm,state,center_small";
316 source: "elm";
317 script {
318 set_int(field_pos, 0);
319 update_state();
320 }
321 }
322 program { name: "l_side_text";
323 signal: "elm,state,left_side";
324 source: "elm";
325 script {
326 set_int(field_pos, 1);
327 update_state();
328 }
329 }
330 program { name: "r_side_text";
331 signal: "elm,state,right_side";
332 source: "elm";
333 script {
334 set_int(field_pos, 2);
335 update_state();
336 }
337 }
338 program {
339 name: "field_click";
340 signal: "mouse,clicked,1";
341 source: "over1";
342 action: SIGNAL_EMIT "elm,action,click" "";
343 }
344 }
345}
346
347///////////////////////////////////////////////////////////////////////////////
348// end of datetime style
349///////////////////////////////////////////////////////////////////////////////
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 942e09cee..bdb473186 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -33,6 +33,9 @@ WGT_PREVIEW = \
33 frame:preview-00.png:widget_preview_frame:100:50 \ 33 frame:preview-00.png:widget_preview_frame:100:50 \
34 label:preview-00.png:widget_preview_label:70:30 \ 34 label:preview-00.png:widget_preview_label:70:30 \
35 clock:preview-00.png:widget_preview_clock:200:100 \ 35 clock:preview-00.png:widget_preview_clock:200:100 \
36 datetime:preview-00.png:widget_preview_datetime1:360:60 \
37 datetime:preview-01.png:widget_preview_datetime2:200:60 \
38 datetime:preview-02.png:widget_preview_datetime3:200:60 \
36 slider:preview-00.png:widget_preview_slider:200:100 \ 39 slider:preview-00.png:widget_preview_slider:200:100 \
37 panes:preview-00.png:widget_preview_panes:200:100 \ 40 panes:preview-00.png:widget_preview_panes:200:100 \
38 toolbar:preview-00.png:widget_preview_toolbar:300:100 \ 41 toolbar:preview-00.png:widget_preview_toolbar:300:100 \
diff --git a/doc/examples.dox b/doc/examples.dox
index fda24f3ec..3b0235835 100644
--- a/doc/examples.dox
+++ b/doc/examples.dox
@@ -37,6 +37,8 @@
37 * 37 *
38 * @ref clock_example 38 * @ref clock_example
39 * 39 *
40 * @ref datetime_example
41 *
40 * @ref mapbuf_example 42 * @ref mapbuf_example
41 43
42 * @ref map_example_01 44 * @ref map_example_01
@@ -1698,6 +1700,51 @@
1698 */ 1700 */
1699 1701
1700/** 1702/**
1703 * @page datetime_example Datetime widget example
1704 *
1705 * This code places three Elementary Datetime widgets on a window, each of
1706 * them exemplifying the widget's different usage.
1707 *
1708 * The first of them is <b>"only Date display"</b>:
1709 * @dontinclude datetime_example.c
1710 * @skip only DATE
1711 * @until evas_object_show
1712 *
1713 * For <b>"only Time display"</b>, see the second datetime:
1714 * @dontinclude datetime_example.c
1715 * @skip only TIME
1716 * @until evas_object_show
1717 *
1718 * The third one will display datetime shows both <b>Date and Time</b>, corresponding format will be
1719 * taken from system @b locale. Note, besides, that the strings are different
1720 * for different language settings.
1721 *
1722 * <b>Datetime format</b> can be programmatically set by using
1723 * elm_datetime_format_set():
1724 * @dontinclude datetime_example.c
1725 * @skip DATE and TIME
1726 * @until evas_object_show
1727 * The default format of any locale consists:
1728 * - Year Field
1729 * - Month Field
1730 * - Date Field
1731 * - Hour Field(12hr/24hr format)
1732 * - Minute Field
1733 * - AM/PM (if exists).
1734 *
1735 * This is how the example program's window looks like with the datetime widget
1736 * showing only date, only time and both date & time:
1737 *
1738 * @image html screenshots/datetime_example.png
1739 * @image latex screenshots/datetime_example.eps width=\textwidth
1740 *
1741 * See the full @ref datetime_example_c "source code" for
1742 * this example.
1743 *
1744 * @example datetime_example.c
1745 */
1746
1747/**
1701 * @page mapbuf_example Mapbuf Widget Example 1748 * @page mapbuf_example Mapbuf Widget Example
1702 * 1749 *
1703 * This code places a Elementary mapbuf widget on a window, 1750 * This code places a Elementary mapbuf widget on a window,
@@ -6164,6 +6211,12 @@
6164 * @example clock_example.c 6211 * @example clock_example.c
6165 */ 6212 */
6166 6213
6214 /**
6215 * @page datetime_example_c Datetime example
6216 * @include datetime_example.c
6217 * @example datetime_example.c
6218 */
6219
6167/** 6220/**
6168 * @page flipselector_example_c Flipselector example 6221 * @page flipselector_example_c Flipselector example
6169 * @include flipselector_example.c 6222 * @include flipselector_example.c
diff --git a/doc/index.doxy b/doc/index.doxy
index e787b194b..61c42ca78 100644
--- a/doc/index.doxy
+++ b/doc/index.doxy
@@ -83,6 +83,10 @@
83 * 83 *
84 * @image html img/widget/ctxpopup/preview-00.png 84 * @image html img/widget/ctxpopup/preview-00.png
85 * @image latex img/widget/ctxpopup/preview-00.eps 85 * @image latex img/widget/ctxpopup/preview-00.eps
86 * @li @ref Datetime
87 *
88 * @image html img/widget/datetime/preview-00.png
89 * @image latex img/widget/datetime/preview-00.eps
86 * @li @ref Diskselector 90 * @li @ref Diskselector
87 * 91 *
88 * @image html img/widget/diskselector/preview-00.png 92 * @image html img/widget/diskselector/preview-00.png
diff --git a/doc/widgets/Makefile.am b/doc/widgets/Makefile.am
index 0bbb0b748..d9ec6e082 100644
--- a/doc/widgets/Makefile.am
+++ b/doc/widgets/Makefile.am
@@ -32,6 +32,9 @@ widget_preview_spinner \
32widget_preview_bubble1 \ 32widget_preview_bubble1 \
33widget_preview_bubble2 \ 33widget_preview_bubble2 \
34widget_preview_bubble3 \ 34widget_preview_bubble3 \
35widget_preview_datetime1 \
36widget_preview_datetime2 \
37widget_preview_datetime3 \
35widget_preview_fileselector_button1 \ 38widget_preview_fileselector_button1 \
36widget_preview_fileselector_button2 \ 39widget_preview_fileselector_button2 \
37widget_preview_fileselector_button3 \ 40widget_preview_fileselector_button3 \
@@ -122,6 +125,9 @@ EXTRA_DIST = \
122 widget_preview_mapbuf.c \ 125 widget_preview_mapbuf.c \
123 widget_preview_map.c \ 126 widget_preview_map.c \
124 widget_preview_ctxpopup.c \ 127 widget_preview_ctxpopup.c \
128 widget_preview_datetime1.c \
129 widget_preview_datetime2.c \
130 widget_preview_datetime3.c \
125 widget_preview_diskselector.c \ 131 widget_preview_diskselector.c \
126 widget_preview_entry1.c \ 132 widget_preview_entry1.c \
127 widget_preview_entry2.c \ 133 widget_preview_entry2.c \
diff --git a/doc/widgets/widget_preview_datetime1.c b/doc/widgets/widget_preview_datetime1.c
new file mode 100644
index 000000000..359753f07
--- /dev/null
+++ b/doc/widgets/widget_preview_datetime1.c
@@ -0,0 +1,16 @@
1#include "widget_preview_tmpl_head.c"
2
3Evas_Object *bx = elm_box_add(win);
4evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
5evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
6elm_win_resize_object_add(win, bx);
7evas_object_show(bx);
8evas_object_size_hint_min_set(bx, 360, 60);
9
10Evas_Object *datetime = elm_datetime_add(win);
11evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
12evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL);
13elm_box_pack_end(bx, datetime);
14evas_object_show(datetime);
15
16#include "widget_preview_tmpl_foot.c"
diff --git a/doc/widgets/widget_preview_datetime2.c b/doc/widgets/widget_preview_datetime2.c
new file mode 100644
index 000000000..59e9aa062
--- /dev/null
+++ b/doc/widgets/widget_preview_datetime2.c
@@ -0,0 +1,19 @@
1#include "widget_preview_tmpl_head.c"
2
3Evas_Object *bx = elm_box_add(win);
4evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
5evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
6elm_win_resize_object_add(win, bx);
7evas_object_show(bx);
8evas_object_size_hint_min_set(bx, 200, 60);
9
10Evas_Object *datetime = elm_datetime_add(win);
11evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
12evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL);
13elm_datetime_field_visible_set(datetime, ELM_DATETIME_HOUR, EINA_FALSE);
14elm_datetime_field_visible_set(datetime, ELM_DATETIME_MINUTE, EINA_FALSE);
15elm_datetime_field_visible_set(datetime, ELM_DATETIME_AMPM, EINA_FALSE);
16elm_box_pack_end(bx, datetime);
17evas_object_show(datetime);
18
19#include "widget_preview_tmpl_foot.c"
diff --git a/doc/widgets/widget_preview_datetime3.c b/doc/widgets/widget_preview_datetime3.c
new file mode 100644
index 000000000..bf51f7f4d
--- /dev/null
+++ b/doc/widgets/widget_preview_datetime3.c
@@ -0,0 +1,19 @@
1#include "widget_preview_tmpl_head.c"
2
3Evas_Object *bx = elm_box_add(win);
4evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
5evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
6elm_win_resize_object_add(win, bx);
7evas_object_show(bx);
8evas_object_size_hint_min_set(bx, 200, 60);
9
10Evas_Object *datetime = elm_datetime_add(win);
11evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
12evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, EVAS_HINT_FILL);
13elm_datetime_field_visible_set(datetime, ELM_DATETIME_YEAR, EINA_FALSE);
14elm_datetime_field_visible_set(datetime, ELM_DATETIME_MONTH, EINA_FALSE);
15elm_datetime_field_visible_set(datetime, ELM_DATETIME_DATE, EINA_FALSE);
16elm_box_pack_end(bx, datetime);
17evas_object_show(datetime);
18
19#include "widget_preview_tmpl_foot.c"
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 9718e5572..85ae36e67 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -48,6 +48,7 @@ test_colorselector.c \
48test_conform.c \ 48test_conform.c \
49test_ctxpopup.c \ 49test_ctxpopup.c \
50test_cursor.c \ 50test_cursor.c \
51test_datetime.c \
51test_diskselector.c \ 52test_diskselector.c \
52test_entry.c \ 53test_entry.c \
53test_factory.c \ 54test_factory.c \
diff --git a/src/bin/test.c b/src/bin/test.c
index 30271e796..1c965d264 100644
--- a/src/bin/test.c
+++ b/src/bin/test.c
@@ -163,6 +163,7 @@ void test_glview(void *data, Evas_Object *obj, void *event_info);
163void test_3d(void *data, Evas_Object *obj, void *event_info); 163void test_3d(void *data, Evas_Object *obj, void *event_info);
164void test_naviframe(void *data, Evas_Object *obj, void *event_info); 164void test_naviframe(void *data, Evas_Object *obj, void *event_info);
165void test_factory(void *data, Evas_Object *obj, void *event_info); 165void test_factory(void *data, Evas_Object *obj, void *event_info);
166void test_datetime(void *data, Evas_Object *obj, void *event_info);
166#ifdef HAVE_EMOTION 167#ifdef HAVE_EMOTION
167void test_video(void *data, Evas_Object *obj, void *event_info); 168void test_video(void *data, Evas_Object *obj, void *event_info);
168#endif 169#endif
@@ -508,6 +509,7 @@ add_tests:
508 ADD_TEST(NULL, "Times & Dates", "Clock", test_clock); 509 ADD_TEST(NULL, "Times & Dates", "Clock", test_clock);
509 ADD_TEST(NULL, "Times & Dates", "Clock 2", test_clock2); 510 ADD_TEST(NULL, "Times & Dates", "Clock 2", test_clock2);
510 ADD_TEST(NULL, "Times & Dates", "Clock 3", test_clock3); 511 ADD_TEST(NULL, "Times & Dates", "Clock 3", test_clock3);
512 ADD_TEST(NULL, "Times & Dates", "Datetime", test_datetime);
511 513
512 //------------------------------// 514 //------------------------------//
513 ADD_TEST(NULL, "Text", "Anchorview", test_anchorview); 515 ADD_TEST(NULL, "Text", "Anchorview", test_anchorview);
diff --git a/src/bin/test_datetime.c b/src/bin/test_datetime.c
new file mode 100644
index 000000000..d54970236
--- /dev/null
+++ b/src/bin/test_datetime.c
@@ -0,0 +1,81 @@
1#include <Elementary.h>
2#ifdef HAVE_CONFIG_H
3#include "elementary_config.h"
4#endif
5#ifndef ELM_LIB_QUICKLAUNCH
6
7/* A simple test, just displaying datetime in its default format */
8
9static void
10_changed_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
11{
12 printf("Datetime value is changed\n");
13}
14
15void
16test_datetime(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
17{
18 Evas_Object *win, *bg, *bx, *datetime;
19 time_t t;
20 struct tm time1;
21
22 win = elm_win_add(NULL, "Datetime", ELM_WIN_BASIC);
23 elm_win_title_set(win, "Datetime");
24 elm_win_autodel_set(win, 1);
25
26 bg = elm_bg_add(win);
27 elm_win_resize_object_add(win, bg);
28 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
29 evas_object_show(bg);
30
31 bx = elm_box_add(win);
32 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
33 elm_win_resize_object_add(win, bx);
34 elm_box_horizontal_set(bx, EINA_FALSE);
35 evas_object_show(bx);
36 evas_object_size_hint_min_set(bx, 360, 240);
37
38 datetime = elm_datetime_add(bx);
39 evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
40 evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5);
41 elm_datetime_field_visible_set(datetime, ELM_DATETIME_HOUR, EINA_FALSE);
42 elm_datetime_field_visible_set(datetime, ELM_DATETIME_MINUTE, EINA_FALSE);
43 elm_datetime_field_visible_set(datetime, ELM_DATETIME_AMPM, EINA_FALSE);
44 elm_box_pack_end(bx, datetime);
45 evas_object_show(datetime);
46
47 datetime = elm_datetime_add(bx);
48 evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
49 evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5);
50 elm_datetime_field_visible_set(datetime, ELM_DATETIME_YEAR, EINA_FALSE);
51 elm_datetime_field_visible_set(datetime, ELM_DATETIME_MONTH, EINA_FALSE);
52 elm_datetime_field_visible_set(datetime, ELM_DATETIME_DATE, EINA_FALSE);
53 elm_box_pack_end(bx, datetime);
54 evas_object_show(datetime);
55
56 datetime = elm_datetime_add(bx);
57 evas_object_size_hint_weight_set(datetime, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
58 evas_object_size_hint_align_set(datetime, EVAS_HINT_FILL, 0.5);
59
60 // get the current local time
61 t = time(NULL);
62 localtime_r(&t, &time1);
63 // set the max year as 2030 and the remaining fields are equal to current time values
64 time1.tm_year = 130;
65 elm_datetime_value_max_set(datetime, &time1);
66 // set the min time limit as "1980 January 10th 02:30 PM"
67 time1.tm_year = 80;
68 time1.tm_mon = 4;
69 time1.tm_mday = 10;
70 time1.tm_hour = 14;
71 time1.tm_min = 30;
72 elm_datetime_value_min_set(datetime, &time1);
73 // minutes can be input only in between 15 and 45
74 elm_datetime_field_limit_set(datetime, ELM_DATETIME_MINUTE, 15, 45);
75 evas_object_smart_callback_add(datetime, "changed", _changed_cb, datetime);
76 elm_box_pack_end(bx, datetime);
77 evas_object_show(datetime);
78
79 evas_object_show(win);
80}
81#endif
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
index 4acc8eb72..47473361f 100644
--- a/src/examples/Makefile.am
+++ b/src/examples/Makefile.am
@@ -61,6 +61,7 @@ SRCS = \
61 calendar_example_04.c \ 61 calendar_example_04.c \
62 calendar_example_05.c \ 62 calendar_example_05.c \
63 calendar_example_06.c \ 63 calendar_example_06.c \
64 datetime_example.c \
64 map_example_01.c \ 65 map_example_01.c \
65 map_example_02.c \ 66 map_example_02.c \
66 map_example_03.c \ 67 map_example_03.c \
@@ -170,6 +171,7 @@ examples_PROGRAMS += \
170 calendar_example_04 \ 171 calendar_example_04 \
171 calendar_example_05 \ 172 calendar_example_05 \
172 calendar_example_06 \ 173 calendar_example_06 \
174 datetime_example \
173 map_example_01 \ 175 map_example_01 \
174 map_example_02 \ 176 map_example_02 \
175 map_example_03 \ 177 map_example_03 \
@@ -259,6 +261,7 @@ SCREENSHOTS = \
259 calendar_example_04:calendar_example_04.png:0.0 \ 261 calendar_example_04:calendar_example_04.png:0.0 \
260 calendar_example_05:calendar_example_05.png:0.0 \ 262 calendar_example_05:calendar_example_05.png:0.0 \
261 calendar_example_06:calendar_example_06.png:0.0 \ 263 calendar_example_06:calendar_example_06.png:0.0 \
264 datetime_example:datetime_example.png:0.0 \
262 map_example_01:map_example_01.png:2 \ 265 map_example_01:map_example_01.png:2 \
263 map_example_02:map_example_02.png:2.5 \ 266 map_example_02:map_example_02.png:2.5 \
264 map_example_03:map_example_03.png:2 \ 267 map_example_03:map_example_03.png:2 \
diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in
index 3f9b9c7c7..57a9756af 100644
--- a/src/lib/Elementary.h.in
+++ b/src/lib/Elementary.h.in
@@ -189,6 +189,7 @@ EAPI extern Elm_Version *elm_version;
189#include <elm_config.h> 189#include <elm_config.h>
190#include <elm_conform.h> // XXX: comments in elm_conform.h 190#include <elm_conform.h> // XXX: comments in elm_conform.h
191#include <elm_cursor.h> // XXX: comments in elm_cursor.h. review was not finished. 191#include <elm_cursor.h> // XXX: comments in elm_cursor.h. review was not finished.
192#include <elm_datetime.h>
192#include <elm_debug.h> // OK 193#include <elm_debug.h> // OK
193#include <elm_diskselector.h> 194#include <elm_diskselector.h>
194 195
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index c7a3756f2..ac58bc02c 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -70,6 +70,7 @@ elm_colorselector.h \
70elm_config.h \ 70elm_config.h \
71elm_conform.h \ 71elm_conform.h \
72elm_cursor.h \ 72elm_cursor.h \
73elm_datetime.h \
73elm_debug.h \ 74elm_debug.h \
74elm_deprecated.h \ 75elm_deprecated.h \
75elm_deprecated_before.h \ 76elm_deprecated_before.h \
@@ -162,6 +163,7 @@ elm_cnp.c \
162elm_colorselector.c \ 163elm_colorselector.c \
163elm_config.c \ 164elm_config.c \
164elm_conform.c \ 165elm_conform.c \
166elm_datetime.c \
165elm_diskselector.c \ 167elm_diskselector.c \
166elm_entry.c \ 168elm_entry.c \
167elm_factory.c \ 169elm_factory.c \
diff --git a/src/lib/elm_datetime.c b/src/lib/elm_datetime.c
new file mode 100644
index 000000000..1edbae77f
--- /dev/null
+++ b/src/lib/elm_datetime.c
@@ -0,0 +1,1039 @@
1#include <locale.h>
2#include <langinfo.h>
3#include <Elementary.h>
4#include "elm_priv.h"
5
6typedef struct _Widget_Data Widget_Data;
7typedef struct _Datetime_Field Datetime_Field;
8typedef struct _Datetime_Mod_Api Datetime_Mod_Api;
9typedef struct _Format_Map Format_Map;
10
11#define DATETIME_TYPE_COUNT 6
12#define MAX_FORMAT_LEN 64
13#define MAX_SEPARATOR_LEN 6
14#define MAX_FIELD_FORMAT_LEN 3
15#define MIN_DAYS_IN_MONTH 28
16#define BUFFER_SIZE 1024
17
18// interface between EDC & C code. Field names & signal names.
19// values 0 to DATETIME_TYPE_COUNT are valid range, can be substituted for %d.
20#define EDC_DATETIME_ENABLE_SIG_STR "elm,state,enabled"
21#define EDC_DATETIME_DISABLE_SIG_STR "elm,state,disabled"
22#define EDC_DATETIME_FOCUSIN_SIG_STR "elm,action,focus"
23#define EDC_DATETIME_FOCUSOUT_SIG_STR "elm,action,unfocus"
24#define EDC_PART_FIELD_STR "field%d"
25#define EDC_PART_SEPARATOR_STR "separator%d"
26#define EDC_PART_FIELD_ENABLE_SIG_STR "field%d,enable"
27#define EDC_PART_FIELD_DISABLE_SIG_STR "field%d,disable"
28
29// struct tm does not define the fields in the order from year, month, date, hour, minute.
30// values are reassigned to an array for easy handling.
31#define DATETIME_TM_ARRAY(intptr, tmptr) int *intptr[] = {&(tmptr)->tm_year, \
32 &(tmptr)->tm_mon, &(tmptr)->tm_mday, &(tmptr)->tm_hour, &(tmptr)->tm_min}
33
34struct _Datetime_Field
35{
36 Evas_Object *item_obj;
37 char fmt[MAX_FIELD_FORMAT_LEN];
38 Elm_Datetime_Field_Type type;
39 const char *separator;
40 int location; // location of the field as per the current format
41 int min, max;
42 Eina_Bool fmt_exist:1; // whether field format is present or not
43 Eina_Bool visible:1; // whether field can be visible or not
44};
45
46struct _Datetime_Mod_Api
47{
48 Elm_Datetime_Module_Data *(*obj_hook) (Evas_Object *obj);
49 void (*obj_unhook) (Elm_Datetime_Module_Data *module_data);
50 Evas_Object *(*field_create) (Elm_Datetime_Module_Data *module_data,
51 Elm_Datetime_Field_Type field_type);
52 void (*field_value_display) (Elm_Datetime_Module_Data *module_data,
53 Evas_Object *obj);
54};
55
56struct _Widget_Data
57{
58 Evas_Object *base;
59 Datetime_Field field_list[DATETIME_TYPE_COUNT]; // fixed set of fields.
60 struct tm curr_time, min_limit, max_limit;
61 Elm_Datetime_Module_Data *mod_data;
62 char format[MAX_FORMAT_LEN];
63 Eina_Bool user_format:1; // whether user set format or default format.
64};
65
66struct _Format_Map
67{
68 char *fmt_char;
69 int def_min;
70 int def_max;
71};
72
73// default limits for individual fields
74static const Format_Map mapping[DATETIME_TYPE_COUNT] = {
75 [ELM_DATETIME_YEAR] = { "Yy", 0, 137 },
76 [ELM_DATETIME_MONTH] = { "mbBh", 0, 11 },
77 [ELM_DATETIME_DATE] = { "de", 1, 31 },
78 [ELM_DATETIME_HOUR] = { "IHkl", 0, 23 },
79 [ELM_DATETIME_MINUTE] = { "M", 0, 59 },
80 [ELM_DATETIME_AMPM] = { "pP", 0, 1 }
81};
82
83static const char *multifield_formats = "cxXrRTDF";
84
85static Datetime_Mod_Api *dt_mod = NULL;
86static const char *widtype = NULL;
87
88static void _del_hook(Evas_Object *obj);
89static void _disable_hook(Evas_Object *obj);
90static void _translate_hook(Evas_Object *obj);
91static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
92static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
93static void _sizing_eval(Evas_Object *obj);
94static void _theme_hook(Evas_Object *obj);
95static void _validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap);
96static void _apply_field_limits(Evas_Object *obj);
97static void _apply_range_restrictions(Evas_Object *obj, struct tm *time);
98static const char *_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type);
99static void _field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type,
100 int *range_min, int *range_max);
101static void _reload_format(Evas_Object *obj);
102static void _field_list_display(Evas_Object *obj);
103static void _field_list_arrange(Evas_Object *obj);
104static void _field_list_init(Evas_Object *obj);
105
106static const char SIG_CHANGED[] = "changed";
107static const char SIG_LANGUAGE_CHANGED[] = "language,changed";
108static const Evas_Smart_Cb_Description _signals[] = {
109 {SIG_CHANGED, ""},
110 {SIG_LANGUAGE_CHANGED, ""},
111 {NULL, NULL}
112};
113
114static Datetime_Mod_Api *
115_dt_mod_init()
116{
117 Elm_Module *mod = NULL;
118 if (!(mod = _elm_module_find_as("datetime/api"))) return NULL;
119
120 mod->api = malloc(sizeof(Datetime_Mod_Api));
121 if (!mod->api) return NULL;
122
123 ((Datetime_Mod_Api *)(mod->api))->obj_hook = _elm_module_symbol_get(mod, "obj_hook");
124 ((Datetime_Mod_Api *)(mod->api))->obj_unhook = _elm_module_symbol_get(mod, "obj_unhook");
125 ((Datetime_Mod_Api *)(mod->api))->field_create = _elm_module_symbol_get(mod, "field_create");
126 ((Datetime_Mod_Api *)(mod->api))->field_value_display = _elm_module_symbol_get(mod, "field_value_display");
127
128 return mod->api;
129}
130
131static void
132_del_hook(Evas_Object *obj)
133{
134 Widget_Data *wd;
135 Datetime_Field *tmp;
136 unsigned int idx;
137
138 wd = elm_widget_data_get(obj);
139 if (!wd) return;
140
141 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
142 {
143 tmp = wd->field_list + idx;
144 evas_object_del(tmp->item_obj);
145 eina_stringshare_del(tmp->separator);
146 }
147
148 if ((dt_mod) && (dt_mod->obj_unhook))
149 dt_mod->obj_unhook(wd->mod_data); // module - unhook
150
151 free(wd);
152}
153
154static void
155_disable_hook(Evas_Object *obj)
156{
157 Widget_Data *wd;
158
159 wd = elm_widget_data_get(obj);
160 if (!wd || !wd->base) return;
161 if (elm_widget_disabled_get(obj))
162 edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR, "elm");
163 else
164 edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm");
165}
166
167static void
168_translate_hook(Evas_Object *obj)
169{
170 Widget_Data *wd;
171 wd = elm_widget_data_get(obj);
172 if (!wd) return;
173
174 if (!wd->user_format) _reload_format(obj);
175 else _field_list_display(obj);
176 evas_object_smart_callback_call(obj, SIG_LANGUAGE_CHANGED, NULL);
177}
178
179static void
180_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
181{
182 Widget_Data *wd;
183
184 wd = elm_widget_data_get(obj);
185 if (!wd) return;
186
187 if (elm_widget_focus_get(obj))
188 edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSIN_SIG_STR, "elm");
189 else
190 edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSOUT_SIG_STR, "elm");
191}
192
193static Eina_List *
194_datetime_items_get(const Evas_Object *obj)
195{
196 Widget_Data *wd;
197 Eina_List *items;
198 Datetime_Field *field;
199 int loc, count = 0;
200 unsigned int idx;
201
202 wd = elm_widget_data_get(obj);
203 if (!wd) return NULL;
204
205 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
206 {
207 field = wd->field_list + idx;
208 if (field->fmt_exist && field->visible) count++;
209 }
210 for (loc = 0; loc < count; loc++)
211 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
212 {
213 field = wd->field_list + idx;
214 if (field->location == loc)
215 items = eina_list_append(items, field->item_obj);
216 }
217
218 return items;
219}
220
221static Eina_Bool
222_elm_datetime_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
223{
224 Widget_Data *wd;
225 const Eina_List *items;
226 void *(*list_data_get) (const Eina_List *list);
227 Eina_List *(*list_free) (Eina_List *list);
228 Eina_Bool ret;
229
230 wd = elm_widget_data_get(obj);
231 if (!wd) return EINA_FALSE;
232
233 if ((items = elm_widget_focus_custom_chain_get(obj)))
234 {
235 list_data_get = eina_list_data_get;
236 list_free = NULL;
237 }
238 else
239 {
240 items = _datetime_items_get(obj);
241 list_data_get = eina_list_data_get;
242 list_free = eina_list_free;
243 if (!items) return EINA_FALSE;
244 }
245
246 ret = elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
247 if (list_free) list_free((Eina_List *)items);
248
249 return ret;
250}
251
252static void
253_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
254{
255 Widget_Data *wd;
256
257 wd = elm_widget_data_get(obj);
258 if (!wd) return;
259
260 edje_object_mirrored_set(wd->base, rtl);
261}
262
263static void
264_sizing_eval(Evas_Object *obj)
265{
266 Widget_Data *wd;
267 Datetime_Field *field;
268 Evas_Coord minw = -1, minh = -1;
269 unsigned int idx, field_count = 0;
270
271 wd = elm_widget_data_get(obj);
272 if (!wd || !wd->base) return;
273 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
274 {
275 field = wd->field_list + idx;
276 if ((field->visible) && (field->fmt_exist)) field_count ++;
277 }
278 if (field_count)
279 elm_coords_finger_size_adjust(field_count, &minw, 1, &minh);
280 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
281 evas_object_size_hint_min_set(obj, minw, minh);
282 evas_object_size_hint_max_set(obj, -1, -1);
283}
284
285static void
286_theme_hook(Evas_Object *obj)
287{
288 Widget_Data *wd;
289 Datetime_Field *field;
290 char buf[BUFFER_SIZE];
291 unsigned int idx;
292
293 wd = elm_widget_data_get(obj);
294 if (!wd || !wd->base) return;
295
296 _elm_theme_object_set(obj, wd->base, "datetime", "base",
297 elm_widget_style_get(obj));
298 _elm_widget_mirrored_reload(obj);
299 _mirrored_set(obj, elm_widget_mirrored_get(obj));
300
301 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
302
303 if (elm_widget_disabled_get(obj))
304 edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR,"elm");
305 else
306 edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm");
307
308 if ((!dt_mod) || (!dt_mod->field_value_display)) return;
309
310 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
311 {
312 field = wd->field_list + idx;
313 if (field->fmt_exist && field->visible)
314 {
315 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR, field->location);
316 edje_object_signal_emit(wd->base, buf, "elm");
317 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, field->location);
318 edje_object_part_text_set(wd->base, buf, field->separator);
319 dt_mod->field_value_display(wd->mod_data, field->item_obj);
320 }
321 else
322 {
323 snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR, field->location);
324 edje_object_signal_emit(wd->base, buf, "elm");
325 }
326 }
327 edje_object_message_signal_process(wd->base);
328 _sizing_eval(obj);
329}
330
331static int
332_max_days_get(int year, int month)
333{
334 struct tm time1;
335 time_t t;
336 int day;
337
338 t = time(NULL);
339 localtime_r(&t, &time1);
340 time1.tm_year = year;
341 time1.tm_mon = month;
342 for(day = MIN_DAYS_IN_MONTH; day <= mapping[ELM_DATETIME_DATE].def_max; day++)
343 {
344 time1.tm_mday = day;
345 mktime(&time1);
346 if (time1.tm_mday == 1) break;
347 }
348 day --;
349 return day;
350}
351
352static Eina_Bool
353_date_cmp(struct tm *time1, struct tm *time2)
354{
355 unsigned int idx;
356 DATETIME_TM_ARRAY(timearr1, time1);
357 DATETIME_TM_ARRAY(timearr2, time2);
358
359 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
360 {
361 if (*timearr1[idx] != *timearr2[idx])
362 return EINA_FALSE;
363 }
364 return EINA_TRUE;
365}
366
367// validates curr_time/min_limt/max_limit according to the newly set value
368static void
369_validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap)
370{
371 struct tm *t1, *t2;
372 unsigned int idx;
373 if (!time1 || !time2) return;
374
375 t1 = (swap) ? time2 : time1;
376 t2 = (swap) ? time1 : time2;
377
378 DATETIME_TM_ARRAY(timearr1, time1);
379 DATETIME_TM_ARRAY(timearr2, time2);
380 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
381 {
382 if (*timearr1[idx] < *timearr2[idx])
383 {
384 memcpy(t1, t2, sizeof(struct tm));
385 break;
386 }
387 else if (*timearr1[idx] > *timearr2[idx])
388 break;
389 }
390}
391
392static void
393_apply_field_limits(Evas_Object *obj)
394{
395 Widget_Data *wd;
396 Datetime_Field *field;
397 int val;
398 unsigned int idx = 0;
399
400 wd = elm_widget_data_get(obj);
401 if (!wd) return;
402
403 DATETIME_TM_ARRAY(timearr, &wd->curr_time);
404 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
405 {
406 field = wd->field_list + idx;
407 val = *timearr[idx];
408 if (val < field->min)
409 *timearr[idx] = field->min;
410 else if (val > field->max)
411 *timearr[idx] = field->max;
412 }
413 _field_list_display(obj);
414}
415
416static void
417_apply_range_restrictions(Evas_Object *obj, struct tm *time)
418{
419 Widget_Data *wd;
420 unsigned int idx;
421 int val, min, max;
422
423 wd = elm_widget_data_get(obj);
424 if (!wd || !time) return;
425
426 DATETIME_TM_ARRAY(timearr, time);
427 for (idx = ELM_DATETIME_MONTH; idx < DATETIME_TYPE_COUNT - 1; idx++)
428 {
429 val = *timearr[idx];
430 min = mapping[idx].def_min;
431 max = mapping[idx].def_max;
432 if (idx == ELM_DATETIME_DATE)
433 max = _max_days_get(time->tm_year, time->tm_mon);
434 if (val < min)
435 *timearr[idx] = min;
436 else if (val > max)
437 *timearr[idx] = max;
438 }
439}
440
441static const char *
442_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type)
443{
444 Widget_Data *wd;
445 Datetime_Field *field;
446
447 wd = elm_widget_data_get(obj);
448 if (!wd) return NULL;
449
450 field = wd->field_list + field_type;
451 if (!field) return NULL;
452
453 return field->fmt;
454}
455
456static void
457_field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max)
458{
459 Widget_Data *wd;
460 Datetime_Field *field;
461 int min, max, max_days;
462 unsigned int idx;
463
464 wd = elm_widget_data_get(obj);
465 if (!wd) return;
466
467 field = wd->field_list + field_type;
468 if (!field) return;
469
470 min = field->min;
471 max = field->max;
472
473 DATETIME_TM_ARRAY(curr_timearr, &wd->curr_time);
474 DATETIME_TM_ARRAY(min_timearr, &wd->min_limit);
475 DATETIME_TM_ARRAY(max_timearr, &wd->max_limit);
476
477 for (idx = 0; idx < field->type; idx++)
478 if (*curr_timearr[idx] > *min_timearr[idx]) break;
479 if ((idx == field_type) && (min < *min_timearr[field_type]))
480 min = *min_timearr[field_type];
481 if (field_type == ELM_DATETIME_DATE)
482 {
483 max_days = _max_days_get(wd->curr_time.tm_year, wd->curr_time.tm_mon);
484 if (max > max_days) max = max_days;
485 }
486 for (idx = 0; idx < field->type; idx++)
487 if (*curr_timearr[idx] < *max_timearr[idx]) break;
488 if ((idx == field_type) && (max > *max_timearr[field_type]))
489 max = *max_timearr[field_type];
490
491 *range_min = min;
492 *range_max = max;
493}
494
495static void
496_field_list_display(Evas_Object *obj)
497{
498 Widget_Data *wd;
499 Datetime_Field *field;
500 unsigned int idx= 0;
501
502 wd = elm_widget_data_get(obj);
503 if (!wd) return;
504
505 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
506 {
507 field = wd->field_list + idx;
508 if (field->fmt_exist && field->visible)
509 {
510 if ((dt_mod) && (dt_mod->field_value_display))
511 dt_mod->field_value_display(wd->mod_data, field->item_obj);
512 }
513 }
514}
515
516static void
517_field_list_arrange(Evas_Object *obj)
518{
519 Widget_Data *wd;
520 Datetime_Field *field;
521 char buf[BUFFER_SIZE];
522 int idx;
523
524 wd = elm_widget_data_get(obj);
525 if (!wd) return;
526
527 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
528 {
529 field = wd->field_list + idx;
530 edje_object_part_unswallow(wd->base, field->item_obj);
531 }
532 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
533 {
534 field = wd->field_list + idx;
535 if (field->visible && field->fmt_exist)
536 {
537 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
538 edje_object_part_swallow(wd->base, buf, field->item_obj);
539 }
540 else evas_object_hide(field->item_obj);
541 }
542 _sizing_eval(obj);
543 _field_list_display(obj);
544}
545
546// returns expanded format string for corresponding multi-field format character
547static char *
548_expanded_fmt_str_get(char ch)
549{
550 char *exp_fmt = "";
551 switch (ch)
552 {
553 case 'c':
554 exp_fmt = nl_langinfo(D_T_FMT);
555 break;
556 case 'x':
557 exp_fmt = nl_langinfo(D_FMT);
558 break;
559 case 'X':
560 exp_fmt = nl_langinfo(T_FMT);
561 break;
562 case 'r':
563 exp_fmt = nl_langinfo(T_FMT_AMPM);
564 break;
565 case 'R':
566 exp_fmt = "%H:%M";
567 break;
568 case 'T':
569 exp_fmt = "%H:%M:%S";
570 break;
571 case 'D':
572 exp_fmt = "%m/%d/%y";
573 break;
574 case 'F':
575 exp_fmt = "%Y-%m-%d";
576 break;
577 default:
578 exp_fmt = "";
579 break;
580 }
581 return exp_fmt;
582}
583
584static void
585_expand_format(char * dt_fmt)
586{
587 char *ptr, *expanded_fmt, ch;
588 char buf[MAX_FORMAT_LEN] = {0,};
589 unsigned int idx = 0, len = 0;
590 Eina_Bool fmt_char = EINA_FALSE;
591
592 ptr = dt_fmt;
593 while ((ch = *ptr))
594 {
595 if ((fmt_char) && (strchr(multifield_formats, ch)))
596 {
597 // replace the multi-field format characters with corresponding expanded format
598 expanded_fmt = _expanded_fmt_str_get(ch);
599 len = strlen(expanded_fmt);
600 buf[--idx] = 0;
601 strncat(buf, expanded_fmt, len);
602 idx += len;
603 }
604 else buf[idx++] = ch;
605 if (ch == '%') fmt_char = EINA_TRUE;
606 else fmt_char = EINA_FALSE;
607 ptr++;
608 }
609 buf[idx] = 0;
610 strncpy(dt_fmt, buf, MAX_FORMAT_LEN);
611}
612
613static unsigned int
614_parse_format(Evas_Object *obj, char *fmt_ptr)
615{
616 Widget_Data *wd;
617 Datetime_Field *field = NULL;
618 unsigned int len = 0, idx, location = 0;
619 char separator[MAX_SEPARATOR_LEN];
620 char cur;
621 Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
622 sep_lookup = EINA_FALSE;
623
624 wd = elm_widget_data_get(obj);
625
626 while ((cur = *fmt_ptr))
627 {
628 if (fmt_parsing)
629 {
630 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
631 {
632 if (strchr(mapping[idx].fmt_char, cur))
633 {
634 field = wd->field_list + idx;
635 // ignore the fields already have or disabled
636 // valid formats, means already parsed & repeated, ignore.
637 if (!field->visible || field->location != -1) break;
638 field->fmt[1] = cur;
639 field->fmt_exist = EINA_TRUE;
640 field->location = location++;
641 fmt_parsing = EINA_FALSE;
642 sep_lookup = EINA_TRUE;
643 len = 0;
644 break;
645 }
646 }
647 }
648 if (cur == ' ') separator[len++] = cur;
649 else if (cur == '%') fmt_parsing = EINA_TRUE;
650 if ((cur == ' ') || (cur == '%'))
651 {
652 sep_parsing = EINA_FALSE;
653 // set the separator to previous field
654 separator[len] = 0;
655 if (field) eina_stringshare_replace(&field->separator, separator);
656 }
657 if (sep_parsing && (len < MAX_SEPARATOR_LEN-1) &&
658 (field->type != ELM_DATETIME_AMPM) &&
659 (!((field->type == ELM_DATETIME_MINUTE) && (cur ==':'))))
660 separator[len++] = cur;
661 if (sep_lookup) sep_parsing = EINA_TRUE;
662 sep_lookup = EINA_FALSE;
663 fmt_ptr++;
664 }
665 // return the number of valid fields parsed.
666 return location;
667}
668
669static void
670_reload_format(Evas_Object *obj)
671{
672 Widget_Data *wd;
673 Datetime_Field *field;
674 char buf[BUFFER_SIZE];
675 unsigned int idx, field_count;
676 char *dt_fmt;
677
678 wd = elm_widget_data_get(obj);
679 if (!wd) return;
680
681 // fetch the default format from Libc.
682 if (!wd->user_format)
683 strncpy(wd->format, nl_langinfo(D_T_FMT), MAX_FORMAT_LEN);
684
685 dt_fmt = (char *)malloc(MAX_FORMAT_LEN);
686 strncpy(dt_fmt, wd->format, MAX_FORMAT_LEN);
687
688 _expand_format(dt_fmt);
689
690 // reset all the fields to disable state
691 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
692 {
693 field = wd->field_list + idx;
694 field->fmt_exist = EINA_FALSE;
695 field->location = -1;
696 }
697
698 field_count = _parse_format(obj, dt_fmt);
699 free(dt_fmt);
700
701 // assign locations to disabled fields for uniform usage
702 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
703 {
704 field = wd->field_list + idx;
705 if (field->location == -1) field->location = field_count++;
706
707 if (field->fmt_exist && field->visible)
708 {
709 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
710 field->location);
711 edje_object_signal_emit(wd->base, buf, "elm");
712 }
713 else
714 {
715 snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR,
716 field->location);
717 edje_object_signal_emit(wd->base, buf, "elm");
718 }
719 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, (field->location + 1));
720 edje_object_part_text_set(wd->base, buf, field->separator);
721 }
722 edje_object_message_signal_process(wd->base);
723 _field_list_arrange(obj);
724}
725
726static void
727_field_list_init(Evas_Object *obj)
728{
729 Widget_Data *wd;
730 Datetime_Field *field;
731 unsigned int idx;
732 time_t t;
733
734 wd = elm_widget_data_get(obj);
735 if (!wd) return;
736
737 t = time(NULL);
738 localtime_r(&t, &wd->curr_time);
739
740 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
741 {
742 field = wd->field_list + idx;
743 field->type = ELM_DATETIME_YEAR + idx;
744 field->fmt[0] = '%';
745 field->fmt_exist = EINA_FALSE;
746 field->visible = EINA_TRUE;
747 field->min = mapping[idx].def_min;
748 field->max = mapping[idx].def_max;
749 }
750 DATETIME_TM_ARRAY(min_timearr, &wd->min_limit);
751 DATETIME_TM_ARRAY(max_timearr, &wd->max_limit);
752 for (idx = 0; idx < DATETIME_TYPE_COUNT-1; idx++)
753 {
754 *min_timearr[idx] = mapping[idx].def_min;
755 *max_timearr[idx] = mapping[idx].def_max;
756 }
757}
758
759EAPI Evas_Object *
760elm_datetime_add(Evas_Object *parent)
761{
762 Evas_Object *obj;
763 Evas *e;
764 Widget_Data *wd;
765 Datetime_Field *field;
766 int idx;
767
768 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
769
770 ELM_SET_WIDTYPE(widtype, "datetime");
771 elm_widget_type_set(obj, widtype);
772 elm_widget_sub_object_add(parent, obj);
773 elm_widget_data_set(obj, wd);
774 elm_widget_del_hook_set(obj, _del_hook);
775 elm_widget_theme_hook_set(obj, _theme_hook);
776 elm_widget_translate_hook_set(obj, _translate_hook);
777 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
778 elm_widget_disable_hook_set(obj, _disable_hook);
779 elm_widget_can_focus_set(obj, EINA_TRUE);
780 elm_widget_focus_next_hook_set(obj, _elm_datetime_focus_next_hook);
781
782 wd->base = edje_object_add(e);
783 elm_widget_resize_object_set(obj, wd->base);
784 _elm_theme_object_set(obj, wd->base, "datetime", "base", "default");
785 evas_object_smart_callbacks_descriptions_set(obj, _signals);
786
787 // module - initialise module for datetime
788 if (!dt_mod) dt_mod = _dt_mod_init();
789 if ((dt_mod) && (dt_mod->obj_hook))
790 wd->mod_data = dt_mod->obj_hook(obj);
791 // update module data
792 if (wd->mod_data)
793 {
794 wd->mod_data->base = obj;
795 wd->mod_data->field_limit_get = _field_limit_get;
796 wd->mod_data->field_format_get = _field_format_get;
797 }
798
799 _field_list_init(obj);
800 _reload_format(obj);
801
802 if ((dt_mod)&&(dt_mod->field_create))
803 {
804 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
805 {
806 field = wd->field_list + idx;
807 field->item_obj = dt_mod->field_create(wd->mod_data, idx);
808 }
809 }
810 _field_list_arrange(obj);
811 _mirrored_set(obj, elm_widget_mirrored_get(obj));
812
813 return obj;
814}
815
816EAPI const char *
817elm_datetime_format_get(const Evas_Object *obj)
818{
819 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
820 Widget_Data *wd;
821
822 wd = elm_widget_data_get(obj);
823 if (!wd) return NULL;
824
825 return wd->format;
826}
827
828EAPI void
829elm_datetime_format_set(Evas_Object *obj, const char *fmt)
830{
831 ELM_CHECK_WIDTYPE(obj, widtype);
832 Widget_Data *wd;
833
834 wd = elm_widget_data_get(obj);
835 if (!wd) return;
836
837 if (fmt)
838 {
839 strncpy(wd->format, fmt, MAX_FORMAT_LEN);
840 wd->user_format = EINA_TRUE;
841 }
842 else
843 wd->user_format = EINA_FALSE;
844
845 _reload_format(obj);
846}
847
848EAPI Eina_Bool
849elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type
850 fieldtype)
851{
852 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
853 Widget_Data *wd;
854 Datetime_Field *field;
855
856 wd = elm_widget_data_get(obj);
857 if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return EINA_FALSE;
858
859 field = wd->field_list + fieldtype;
860 return field->visible;
861}
862
863EAPI void
864elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
865 Eina_Bool visible)
866{
867 ELM_CHECK_WIDTYPE(obj, widtype);
868 Widget_Data *wd;
869 Datetime_Field *field;
870
871 wd = elm_widget_data_get(obj);
872 if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return;
873
874 field = wd->field_list + fieldtype;
875 if (field->visible == visible) return;
876
877 field->visible = visible;
878 _reload_format(obj);
879}
880
881EAPI void
882elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
883 int *min, int *max)
884{
885 ELM_CHECK_WIDTYPE(obj, widtype);
886 Widget_Data *wd;
887 Datetime_Field *field;
888
889 wd = elm_widget_data_get(obj);
890 if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return;
891
892 field = wd->field_list + fieldtype;
893 if (min) *min = field->min;
894 if (max) *max = field->max;
895}
896
897EAPI void
898elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
899 int min, int max)
900{
901 ELM_CHECK_WIDTYPE(obj, widtype);
902 Widget_Data *wd;
903 Datetime_Field *field;
904
905 wd = elm_widget_data_get(obj);
906 if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return;
907
908 if (min > max) return;
909
910 field = wd->field_list + fieldtype;
911 if ((min > mapping[fieldtype].def_min && min < mapping[fieldtype].def_max)
912 || (field->type == ELM_DATETIME_YEAR))
913 field->min = min;
914 if ((max > mapping[fieldtype].def_min && max < mapping[fieldtype].def_max)
915 || (field->type == ELM_DATETIME_YEAR))
916 field->max = max;
917
918 _apply_field_limits(obj);
919}
920
921EAPI Eina_Bool
922elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime)
923{
924 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
925 EINA_SAFETY_ON_NULL_RETURN_VAL(currtime, EINA_FALSE);
926 Widget_Data *wd;
927
928 wd = elm_widget_data_get(obj);
929 if (!wd) return EINA_FALSE;
930
931 *currtime = wd->curr_time;
932 return EINA_TRUE;
933}
934
935EAPI Eina_Bool
936elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime)
937{
938 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
939 EINA_SAFETY_ON_NULL_RETURN_VAL(newtime, EINA_FALSE);
940 Widget_Data *wd;
941 struct tm old_time;
942
943 wd = elm_widget_data_get(obj);
944 if (!wd) return EINA_FALSE;
945
946 old_time = wd->curr_time;
947 wd->curr_time = *newtime;
948 // apply default field restrictions for curr_time
949 _apply_range_restrictions(obj, &wd->curr_time);
950 // validate the curr_time according to the min_limt and max_limt
951 _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE);
952 _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE);
953 _apply_field_limits(obj);
954
955 if (!_date_cmp(&old_time, &wd->curr_time))
956 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
957
958 return EINA_TRUE;
959}
960
961EAPI Eina_Bool
962elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime)
963{
964 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
965 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
966 Widget_Data *wd;
967
968 wd = elm_widget_data_get(obj);
969 if (!wd) return EINA_FALSE;
970
971 *mintime = wd->min_limit;
972 return EINA_TRUE;
973}
974
975EAPI Eina_Bool
976elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime)
977{
978 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
979 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
980 Widget_Data *wd;
981 struct tm old_time;
982
983 wd = elm_widget_data_get(obj);
984 if (!wd) return EINA_FALSE;
985
986 wd->min_limit = *mintime;
987 old_time = wd->curr_time;
988 // apply default field restrictions for min_limit
989 _apply_range_restrictions(obj, &wd->min_limit);
990 // validate curr_time and max_limt according to the min_limit
991 _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_FALSE);
992 _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE);
993 _apply_field_limits(obj);
994
995 if (!_date_cmp(&old_time, &wd->curr_time))
996 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
997
998 return EINA_TRUE;
999}
1000
1001EAPI Eina_Bool
1002elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime)
1003{
1004 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1005 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1006 Widget_Data *wd;
1007
1008 wd = elm_widget_data_get(obj);
1009 if (!wd) return EINA_FALSE;
1010
1011 *maxtime = wd->max_limit;
1012 return EINA_TRUE;
1013}
1014
1015EAPI Eina_Bool
1016elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime)
1017{
1018 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1019 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1020 Widget_Data *wd;
1021 struct tm old_time;
1022
1023 wd = elm_widget_data_get(obj);
1024 if (!wd) return EINA_FALSE;
1025
1026 wd->max_limit = *maxtime;
1027 old_time = wd->curr_time;
1028 // apply default field restrictions for max_limit
1029 _apply_range_restrictions(obj, &wd->max_limit);
1030 // validate curr_time and min_limt according to the max_limit
1031 _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_TRUE);
1032 _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE);
1033 _apply_field_limits(obj);
1034
1035 if (!_date_cmp(&old_time, &wd->curr_time))
1036 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
1037
1038 return EINA_TRUE;
1039}
diff --git a/src/lib/elm_datetime.h b/src/lib/elm_datetime.h
new file mode 100644
index 000000000..a4cf388e8
--- /dev/null
+++ b/src/lib/elm_datetime.h
@@ -0,0 +1,596 @@
1
2 /**
3 * @defgroup Datetime Datetime
4 *
5 *
6 * @image html img/widget/datetime/preview-00.png
7 * @image latex img/widget/datetime/preview-00.eps
8 *
9 * @image html img/widget/datetime/preview-01.png
10 * @image latex img/widget/datetime/preview-01.eps
11 *
12 * @image html img/widget/datetime/preview-02.png
13 * @image latex img/widget/datetime/preview-02.eps
14 *
15 * Datetime widget is used to display and input date & time values.
16 * This widget displays date and time as per the <b>system's locale</b> settings (Date
17 * includes Day, Month & Year along with the defined separators and
18 * Time includes Hour, Minute & AM/PM fields. Separator for AM/PM field is ignored.
19 *
20 * The corresponding Month, AM/PM strings are displayed according to the
21 * system’s language settings.
22 *
23 * Datetime format is a combination of LIBC standard characters like
24 * “%%d %%b %%Y %%I : %%M %%p” which, as a whole represents both Date as well as Time
25 * format.
26 *
27 * Elm_datetime supports only the following sub set of libc date format specifiers:
28 *
29 * @b %%Y : The year as a decimal number including the century (example: 2011).
30 *
31 * @b %%y : The year as a decimal number without a century (range 00 to 99)
32 *
33 * @b %%m : The month as a decimal number (range 01 to 12).
34 *
35 * @b %%b : The abbreviated month name according to the current locale.
36 *
37 * @b %%B : The full month name according to the current locale.
38 *
39 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
40 *
41 * @b %%d : The day of the month as a decimal number (range 01 to 31).
42 *
43 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
44 * digits are preceded by a blank.
45 *
46 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
47 *
48 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
49 *
50 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
51 * digits are preceded by a blank.
52 *
53 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
54 * digits are preceded by a blank.
55 *
56 * @b %%M : The minute as a decimal number (range 00 to 59).
57 *
58 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
59 * corresponding strings for the current locale. Noon is treated as 'PM'
60 * and midnight as 'AM'
61 *
62 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
63 * the current locale.
64 *
65 * @b %%c : The preferred date and time representation for the current locale.
66 *
67 * @b %%x : The preferred date representation for the current locale without the time.
68 *
69 * @b %%X : The preferred time representation for the current locale without the date.
70 *
71 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
72 *
73 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
74 *
75 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
76 *
77 * @b %%D : The date using the format %%m/%%d/%%y.
78 *
79 * @b %%F : The date using the format %%Y-%%m-%%d.
80 *
81 * (For more reference on the available <b>LIBC date format specifiers</b>, please
82 * visit the link:
83 * http://www.gnu.org/s/hello/manual/libc.html#Formatting-Calendar-Time )
84 *
85 * Datetime widget can provide Unicode @b separators in between its fields
86 * except for AM/PM field.
87 * A separator can be any <b>Unicode character</b> other than the LIBC standard
88 * date format specifiers.( Example: In the format %%b %%d @b , %%y %%H @b : %%M
89 * comma(,) is separator for date field %%d and colon(:) is separator for
90 * hour field %%H ).
91 *
92 * The default format is a predefined one, based on the system Locale.
93 *
94 * Hour format 12hr(1-12) or 24hr(0-23) display can be selected by setting
95 * the corresponding user format.
96 *
97 * Datetime supports six fields: Year, Month, Date, Hour, Minute, AM/PM.
98 * Depending on the Datetime module that is loaded, the user can see
99 * different UI to select the individual field values.
100 *
101 * The individual fields of Datetime can be arranged in any order according to the format
102 * set by application.
103 *
104 * There is a provision to set the visibility of a particular field as TRUE/ FALSE
105 * so that <b>only time/ only date / only required fields</b> will be displayed.
106 *
107 * Each field is having a default minimum and maximum values just like the daily
108 * calendar information. These min/max values can be modified as per the application usage.
109 *
110 * User can enter the values only in between the range of maximum and minimum.
111 * Apart from these APIs, there is a provision to display only a limited set of
112 * values out of the possible values. APIs to select the individual field limits
113 * are intended for this purpose.
114 *
115 * The whole widget is left aligned and its size grows horizontally depending
116 * on the current format and each field's visible/disabled state.
117 *
118 * Datetime individual field selection is implemented in a modular style.
119 * Module can be implemented as a Ctxpopup based selection or an ISE based
120 * selection or even a spinner like selection etc.
121 *
122 * <b>Datetime Module design:</b>
123 *
124 * The following functions are expected to be implemented in a Datetime module:
125 *
126 * <b>Field creation:</b>
127 * <pre>
128 *
129 * __________ __________
130 * | |----- obj_hook() ---------------------->>>| |
131 * | |<<<----------------returns Mod_data ------| |
132 * | Datetime |_______ | |
133 * | widget | |Assign module call backs | Module |
134 * | base |<<<____| | |
135 * | | | |
136 * | |----- field_create() ------------------>>>| |
137 * |__________|<<<----------------returns field_obj -----|__________|
138 *
139 * </pre>
140 *
141 * <b>Field value setting:</b>
142 * <pre>
143 *
144 * __________ __________
145 * | | | |
146 * | Datetime |<<<----------elm_datetime_value_set()---| |
147 * | widget | | Module |
148 * | base |----display_field_value()------------>>>| |
149 * |__________| |__________|
150 *
151 * </pre>
152 *
153 * <b>del_hook:</b>
154 * <pre>
155 * __________ __________
156 * | | | |
157 * | Datetime |----obj_unhook()-------------------->>>>| |
158 * | widget | | Module |
159 * | base | <<<-----frees mod_data---------| |
160 * |__________| |__________|
161 *
162 * </pre>
163 *
164 *
165 * Any module can use the following shared functions that are implemented in elm_datetime.c :
166 *
167 * <b>field_format_get()</b> - gives the field format.
168 *
169 * <b>field_limit_get()</b> - gives the field minimum, maximum limits.
170 *
171 * To enable a module, set the ELM_MODULES environment variable as shown:
172 *
173 * <b>export ELM_MODULES="datetime_input_ctxpopup>datetime/api"</b>
174 *
175 *
176 * Datetime widgets emits the following signals:
177 *
178 * @li @b "changed" - whenever Datetime field value is changed, this signal is sent.
179 *
180 * @li @b "language,changed" - whenever system locale changes, this signal is sent.
181 *
182 * Here is an example on its usage:
183 * @li @ref datetime_example
184 *
185 */
186
187 /**
188 * @addtogroup Datetime
189 * @{
190 */
191
192 /**
193 * Identifies a Datetime field, The widget supports 6 fields : Year, month,
194 * Date, Hour, Minute, AM/PM
195 *
196 */
197 typedef enum _Elm_Datetime_Field_Type
198 {
199 ELM_DATETIME_YEAR = 0, /**< Indicates Year field */
200 ELM_DATETIME_MONTH = 1, /**< Indicates Month field */
201 ELM_DATETIME_DATE = 2, /**< Indicates Date field */
202 ELM_DATETIME_HOUR = 3, /**< Indicates Hour field */
203 ELM_DATETIME_MINUTE = 4, /**< Indicates Minute field */
204 ELM_DATETIME_AMPM = 5, /**< Indicates AM/PM field */
205 } Elm_Datetime_Field_Type;
206
207 /**
208 * @brief Adds a new datetime Widget
209 *
210 * The default datetime format and corresponding strings are based on current locale.
211 *
212 * @param parent The parent object
213 * @return The new object or NULL if it cannot be created
214 *
215 * This function inserts a new datetime widget on the canvas.
216 *
217 * @ingroup Datetime
218 */
219 EAPI Evas_Object *elm_datetime_add(Evas_Object *parent);
220
221 /**
222 * Get the datetime format. Format is a combination of allowed Libc date format
223 * specifiers like: "%b %d, %Y %I : %M %p".
224 *
225 * Maximum allowed format length is 64 chars.
226 *
227 * Format can include separators for each individual datetime field except
228 * for AM/PM field.
229 *
230 * Each separator can be a maximum of 6 UTF-8 bytes.
231 * Space is also taken as a separator but it can come only once for each field.
232 *
233 * Following are the allowed set of format specifiers for each datetime field.
234 *
235 * @b %%Y : The year as a decimal number including the century.
236 *
237 * @b %%y : The year as a decimal number without a century (range 00 to 99).
238 *
239 * @b %%m : The month as a decimal number (range 01 to 12).
240 *
241 * @b %%b : The abbreviated month name according to the current locale.
242 *
243 * @b %%B : The full month name according to the current locale.
244 *
245 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
246 *
247 * @b %%d : The day of the month as a decimal number (range 01 to 31).
248 *
249 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
250 * digits are preceded by a blank.
251 *
252 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
253 *
254 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
255 *
256 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
257 * digits are preceded by a blank.
258 *
259 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
260 * digits are preceded by a blank.
261 *
262 * @b %%M : The minute as a decimal number (range 00 to 59).
263 *
264 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
265 * corresponding strings for the current locale. Noon is treated as 'PM'
266 * and midnight as 'AM'.
267 *
268 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
269 * the current locale.
270 *
271 * @b %%c : The preferred date and time representation for the current locale.
272 *
273 * @b %%x : The preferred date representation for the current locale without the time.
274 *
275 * @b %%X : The preferred time representation for the current locale without the date.
276 *
277 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
278 *
279 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
280 *
281 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
282 *
283 * @b %%D : The date using the format %%m/%%d/%%y.
284 *
285 * @b %%F : The date using the format %%Y-%%m-%%d.
286 *
287 * These specifiers can be arranged in any order and the widget will display the
288 * fields accordingly.
289 *
290 * Default format is taken as per the system locale settings.
291 *
292 * @param obj The datetime object
293 * @return The datetime format string. Example: "%b %d, %Y %I : %M %p"
294 *
295 * @see elm_datetime_format_set()
296 * @ingroup Datetime
297 */
298 EAPI const char *elm_datetime_format_get(const Evas_Object *obj);
299
300 /**
301 * Set the datetime format. Format is a combination of allowed Libc date format
302 * specifiers like: "%b %d, %Y %I : %M %p".
303 *
304 * Maximum allowed format length is 64 chars.
305 *
306 * Format can include separators for each individual datetime field except
307 * for AM/PM field.
308 *
309 * Each separator can be a maximum of 6 UTF-8 bytes.
310 * Space is also taken as a separator but it can come only once for each field.
311 *
312 * Following are the allowed set of format specifiers for each datetime field.
313 *
314 * @b %%Y : The year as a decimal number including the century.
315 *
316 * @b %%y : The year as a decimal number without a century (range 00 to 99).
317 *
318 * @b %%m : The month as a decimal number (range 01 to 12).
319 *
320 * @b %%b : The abbreviated month name according to the current locale.
321 *
322 * @b %%B : The full month name according to the current locale.
323 *
324 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
325 *
326 * @b %%d : The day of the month as a decimal number (range 01 to 31).
327 *
328 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
329 * digits are preceded by a blank.
330 *
331 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
332 *
333 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
334 *
335 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
336 * digits are preceded by a blank.
337 *
338 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
339 * digits are preceded by a blank.
340 *
341 * @b %%M : The minute as a decimal number (range 00 to 59).
342 *
343 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
344 * corresponding strings for the current locale. Noon is treated as 'PM'
345 * and midnight as 'AM'.
346 *
347 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
348 * the current locale.
349 *
350 * @b %%c : The preferred date and time representation for the current locale.
351 *
352 * @b %%x : The preferred date representation for the current locale without the time.
353 *
354 * @b %%X : The preferred time representation for the current locale without the date.
355 *
356 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
357 *
358 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
359 *
360 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
361 *
362 * @b %%D : The date using the format %%m/%%d/%%y.
363 *
364 * @b %%F : The date using the format %%Y-%%m-%%d.
365 *
366 * These specifiers can be arranged in any order and the widget will display the
367 * fields accordingly.
368 *
369 * Default format is taken as per the system locale settings.
370 *
371 * @param obj The datetime object
372 * @param fmt The datetime format
373 *
374 * @see elm_datetime_format_get()
375 * @ingroup Datetime
376 */
377 EAPI void elm_datetime_format_set(Evas_Object *obj, const char *fmt);
378
379 /**
380 * @brief Get the upper boundary of a field.
381 *
382 * Year: years since 1900. Negative value represents year below 1900 (year
383 * value -30 represents 1870). Year default range is from 70 to 137.
384 *
385 * Month: default value range is from 0 to 11.
386 *
387 * Date: default value range is from 1 to 31 according to the month value.
388 *
389 * Hour: default value will be in terms of 24 hr format (0~23)
390 *
391 * Minute: default value range is from 0 to 59.
392 *
393 * @param obj The datetime object
394 * @param maxtime Time structure containing the maximum time value.
395 * @return int The maximum value of the field.
396 *
397 * @see elm_datetime_value_max_set()
398 * @ingroup Datetime
399 */
400 EAPI Eina_Bool elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime);
401
402 /**
403 * @brief Set the upper boundary of a field.
404 *
405 * Year: years since 1900. Negative value represents year below 1900 (year
406 * value -30 represents 1870). Year default range is from 70 to 137.
407 *
408 * Month: default value range is from 0 to 11.
409 *
410 * Date: default value range is from 1 to 31 according to the month value.
411 *
412 * Hour: default value will be in terms of 24 hr format (0~23)
413 *
414 * Minute: default value range is from 0 to 59.
415 *
416 * @param obj The datetime object
417 * @param maxtime Time structure containing the maximum time value.
418 * @return EINA_TRUE if maximum value is accepted.
419 *
420 * @see elm_datetime_value_max_get()
421 * @ingroup Datetime
422 */
423 EAPI Eina_Bool elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime);
424
425 /**
426 * @brief Get the lower boundary of a field.
427 *
428 * Year: years since 1900. Negative value represents year below 1900 (year
429 * value -30 represents 1870). Year default range is from 70 to 137.
430 *
431 * Month: default value range is from 0 to 11.
432 *
433 * Date: default value range is from 1 to 31 according to the month value.
434 *
435 * Hour: default value will be in terms of 24 hr format (0~23)
436 *
437 * Minute: default value range is from 0 to 59.
438 *
439 * @param obj The datetime object
440 * @param mintime Time structure.
441 * @return EINA_TRUE if minimum value is successfully returned.
442 *
443 * @see elm_datetime_value_min_set()
444 * @ingroup Datepicker
445 */
446 EAPI Eina_Bool elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime);
447
448 /**
449 * @brief Set the lower boundary of a field.
450 *
451 * Year: years since 1900. Negative value represents year below 1900 (year
452 * value -30 represents 1870). Year default range is from 70 to 137.
453 *
454 * Month: default value range is from 0 to 11.
455 *
456 * Date: default value range is from 1 to 31 according to the month value.
457 *
458 * Hour: default value will be in terms of 24 hr format (0~23)
459 *
460 * Minute: default value range is from 0 to 59.
461 *
462 * @param obj The datetime object.
463 * @param mintime Time structure containing the minimum time value.
464 * @return EINA_TRUE if minimum value is accepted.
465 *
466 * @see elm_datetime_value_min_get()
467 * @ingroup Datetime
468 */
469 EAPI Eina_Bool elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime);
470
471 /**
472 * @brief Get the field limits of a field.
473 *
474 * Limits can be set to individual fields, independently, except for AM/PM field.
475 * Any field can display the values only in between these Minimum and Maximum limits unless
476 * the corresponding time value is restricted from MinTime to MaxTime.
477 * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime.
478 *
479 * There is no provision to set the limits of AM/PM field.
480 *
481 * @param obj The datetime object
482 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
483 * @param min Reference to field's minimum value
484 * @param max Reference to field's maximum value
485 *
486 * @see elm_datetime_field_limit_set()
487 * @ingroup Datetime
488 */
489 EAPI void elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int *min, int *max);
490
491 /**
492 * @brief Set the field limits of a field.
493 *
494 * Limits can be set to individual fields, independently, except for AM/PM field.
495 * Any field can display the values only in between these Minimum and Maximum limits unless
496 * the corresponding time value is restricted from MinTime to MaxTime.
497 * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime.
498 *
499 * There is no provision to set the limits of AM/PM field.
500 *
501 * @param obj The datetime object
502 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
503 * @param min Reference to field's minimum value
504 * @param max Reference to field's maximum value
505 *
506 * @see elm_datetime_field_limit_set()
507 * @ingroup Datetime
508 */
509 EAPI void elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int min, int max);
510
511 /**
512 * @brief Get the current value of a field.
513 *
514 * Year: years since 1900. Negative value represents year below 1900 (year
515 * value -30 represents 1870). Year default range is from 70 to 137.
516 *
517 * Month: default value range is from 0 to 11.
518 *
519 * Date: default value range is from 1 to 31 according to the month value.
520 *
521 * Hour: default value will be in terms of 24 hr format (0~23)
522 *
523 * Minute: default value range is from 0 to 59.
524 *
525 * @param obj The datetime object.
526 * @param currtime Time structure.
527 * @return EINA_TRUE if current time is returned successfully.
528 *
529 * @see elm_datetime_field_value_set()
530 * @ingroup Datetime
531 */
532 EAPI Eina_Bool elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime);
533
534 /**
535 * @brief Set the current value of a Datetime object.
536 *
537 * Year: years since 1900. Negative value represents year below 1900 (year
538 * value -30 represents 1870). Year default range is from 70 to 137.
539 *
540 * Month: default value range is from 0 to 11.
541 *
542 * Date: default value range is from 1 to 31 according to the month value.
543 *
544 * Hour: default value will be in terms of 24 hr format (0~23)
545 *
546 * Minute: default value range is from 0 to 59.
547 *
548 *
549 * @param obj The datetime object.
550 * @param newtime Time structure filled with values to be set.
551 * @return EINA_TRUE if current time is set successfully.
552 *
553 * @see elm_datetime_value_set()
554 * @ingroup Datetime
555 */
556 EAPI Eina_Bool elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime);
557
558 /**
559 * @brief Get whether a field can be visible/not
560 *
561 * @param obj The datetime object
562 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc
563 * @return bool @c EINA_TRUE, if field can be visible. @c EINA_FALSE otherwise.
564 *
565 * @see elm_datetime_field_visible_set()
566 * @ingroup Datetime
567 */
568 EAPI Eina_Bool elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype);
569
570 /**
571 * @brief Set a field to be visible or not.
572 * Setting this API True does not ensure that the field is visible, apart from
573 * this, the field's format must be present in Datetime overall format.
574 * If a field's visibility is set to False then it won't appear even though
575 * its format is present in overall format.
576 * So if and only if this API is set true and the corresponding field's format
577 * is present in Datetime format, the field is visible.
578 *
579 * By default the field visibility is set to True.
580 *
581 * @param obj The datetime object
582 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
583 * @param visible @c EINA_TRUE field can be visible, @c EINA_FALSE otherwise.
584 *
585 * @see elm_datetime_field_visible_get()
586 * @ingroup Datetime
587 */
588 EAPI void elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, Eina_Bool visible);
589
590 /**
591 * @}
592 */
593
594#ifdef __cplusplus
595}
596#endif
diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h
index ce266f4f1..94e64aa52 100644
--- a/src/lib/elm_priv.h
+++ b/src/lib/elm_priv.h
@@ -43,6 +43,7 @@
43 43
44typedef struct _Elm_Config Elm_Config; 44typedef struct _Elm_Config Elm_Config;
45typedef struct _Elm_Module Elm_Module; 45typedef struct _Elm_Module Elm_Module;
46typedef struct _Elm_Datetime_Module_Data Elm_Datetime_Module_Data;
46 47
47struct _Elm_Theme 48struct _Elm_Theme
48{ 49{
@@ -186,6 +187,13 @@ struct _Elm_Module
186 int references; 187 int references;
187}; 188};
188 189
190struct _Elm_Datetime_Module_Data
191{
192 Evas_Object *base;
193 void (*field_limit_get)(Evas_Object *obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max);
194 const char *(*field_format_get)(Evas_Object * obj, Elm_Datetime_Field_Type field_type);
195};
196
189int _elm_ews_wm_init(void); 197int _elm_ews_wm_init(void);
190void _elm_ews_wm_shutdown(void); 198void _elm_ews_wm_shutdown(void);
191void _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme); 199void _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme);
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index 9354af629..e435e37ff 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -4,4 +4,5 @@ MAINTAINERCLEANFILES = Makefile.in
4SUBDIRS = \ 4SUBDIRS = \
5test_entry \ 5test_entry \
6test_map \ 6test_map \
7access_output 7access_output \
8datetime_input_ctxpopup
diff --git a/src/modules/datetime_input_ctxpopup/Makefile.am b/src/modules/datetime_input_ctxpopup/Makefile.am
new file mode 100644
index 000000000..73be6a774
--- /dev/null
+++ b/src/modules/datetime_input_ctxpopup/Makefile.am
@@ -0,0 +1,33 @@
1
2MAINTAINERCLEANFILES = Makefile.in
3
4AM_CPPFLAGS = \
5-DELM_INTERNAL_API_ARGESFSDFEFC=1 \
6-I. \
7-I$(top_builddir) \
8-I$(top_srcdir) \
9-I$(top_srcdir)/src/lib \
10-I$(top_builddir)/src/lib \
11-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
12-DPACKAGE_LIB_DIR=\"$(libdir)\" \
13@ELEMENTARY_CFLAGS@ \
14@ELEMENTARY_X_CFLAGS@ \
15@ELEMENTARY_FB_CFLAGS@ \
16@ELEMENTARY_WIN32_CFLAGS@ \
17@ELEMENTARY_WINCE_CFLAGS@ \
18@ELEMENTARY_EDBUS_CFLAGS@ \
19@ELEMENTARY_EFREET_CFLAGS@ \
20@ELEMENTARY_ETHUMB_CFLAGS@
21
22if ELEMENTARY_WINDOWS_BUILD
23AM_CPPFLAGS += -DELEMENTARY_BUILD
24endif
25
26pkgdir = $(libdir)/elementary/modules/datetime_input_ctxpopup/$(MODULE_ARCH)
27pkg_LTLIBRARIES = module.la
28
29module_la_SOURCES = datetime_input_ctxpopup.c
30
31module_la_LIBADD = @ELEMENTARY_LIBS@ $(top_builddir)/src/lib/libelementary.la
32module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
33module_la_LIBTOOLFLAGS = --tag=disable-static
diff --git a/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c b/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c
new file mode 100644
index 000000000..485d0f563
--- /dev/null
+++ b/src/modules/datetime_input_ctxpopup/datetime_input_ctxpopup.c
@@ -0,0 +1,325 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#ifdef HAVE_CONFIG_H
4#include "elementary_config.h"
5#endif
6
7#define DATETIME_FIELD_COUNT 6
8#define FIELD_FORMAT_LEN 3
9#define DISKSELECTOR_MIN_ITEMS 4
10#define BUFF_SIZE 1024
11
12typedef struct _Ctxpopup_Module_Data Ctxpopup_Module_Data;
13typedef struct _DiskItem_Data DiskItem_Data;
14
15struct _Ctxpopup_Module_Data
16{
17 Elm_Datetime_Module_Data mod_data;
18 Evas_Object *ctxpopup;
19};
20
21struct _DiskItem_Data
22{
23 Ctxpopup_Module_Data *ctx_mod;
24 Elm_Datetime_Field_Type sel_field_type;
25 unsigned int sel_field_value;
26};
27
28static void
29_diskselector_item_free_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
30{
31 if (data) free(data);
32}
33
34static void
35_ctxpopup_dismissed_cb(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__ )
36{
37 Evas_Object *diskselector;
38
39 diskselector = elm_object_content_unset(obj);
40 if (diskselector) evas_object_del(diskselector);
41}
42
43static void
44_datetime_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
45 void *event_info __UNUSED__)
46{
47 Ctxpopup_Module_Data *ctx_mod;
48
49 ctx_mod = (Ctxpopup_Module_Data *)data;
50 if (!ctx_mod) return;
51
52 evas_object_hide(ctx_mod->ctxpopup);
53}
54
55static void
56_ctxpopup_parent_resize_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
57 void *event_info __UNUSED__)
58{
59 Ctxpopup_Module_Data *ctx_mod;
60
61 ctx_mod = (Ctxpopup_Module_Data *)data;
62 if (!ctx_mod) return;
63 elm_ctxpopup_hover_parent_set(ctx_mod->ctxpopup, elm_widget_top_get(ctx_mod->mod_data.base));
64}
65
66static void
67_datetime_move_cb(void *data, Evas *e __UNUSED__,Evas_Object *obj __UNUSED__,
68 void *event_info __UNUSED__)
69{
70 Ctxpopup_Module_Data *ctx_mod;
71
72 ctx_mod = (Ctxpopup_Module_Data *)data;
73 if (!ctx_mod) return;
74
75 evas_object_hide(ctx_mod->ctxpopup);
76}
77
78static void
79_field_value_set(struct tm *time, Elm_Datetime_Field_Type field_type, int val)
80{
81 if (field_type >= DATETIME_FIELD_COUNT - 1) return;
82
83 int *timearr[]= { &time->tm_year, &time->tm_mon, &time->tm_mday, &time->tm_hour, &time->tm_min };
84 *timearr[field_type] = val;
85}
86
87static int
88_field_value_get(struct tm *time, Elm_Datetime_Field_Type field_type)
89{
90 if (field_type >= DATETIME_FIELD_COUNT - 1) return -1;
91
92 int *timearr[]= { &time->tm_year, &time->tm_mon, &time->tm_mday, &time->tm_hour, &time->tm_min };
93 return (*timearr[field_type]);
94}
95
96static void
97_diskselector_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
98{
99 DiskItem_Data *disk_data;
100 struct tm curr_time;
101 const char *fmt;
102
103 disk_data = (DiskItem_Data *)data;
104 if (!disk_data || !(disk_data->ctx_mod)) return;
105
106 elm_datetime_value_get(disk_data->ctx_mod->mod_data.base, &curr_time);
107 fmt = disk_data->ctx_mod->mod_data.field_format_get(disk_data->ctx_mod->mod_data.base, disk_data->sel_field_type);
108 if ((disk_data->sel_field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) ||
109 (!strncmp(fmt, "%l", FIELD_FORMAT_LEN))) && (curr_time.tm_hour >= 12))
110 disk_data->sel_field_value += 12;
111 _field_value_set(&curr_time, disk_data->sel_field_type, disk_data->sel_field_value);
112 elm_datetime_value_set(disk_data->ctx_mod->mod_data.base, &curr_time);
113 evas_object_hide(disk_data->ctx_mod->ctxpopup);
114}
115
116static void
117_ampm_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
118{
119 Ctxpopup_Module_Data *ctx_mod;
120 struct tm curr_time;
121
122 ctx_mod = (Ctxpopup_Module_Data *)data;
123 if (!ctx_mod) return;
124
125 elm_datetime_value_get(ctx_mod->mod_data.base, &curr_time);
126 if (curr_time.tm_hour >= 12) curr_time.tm_hour -= 12;
127 else curr_time.tm_hour += 12;
128 elm_datetime_value_set(ctx_mod->mod_data.base, &curr_time);
129}
130
131static void
132_field_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
133{
134 Ctxpopup_Module_Data *ctx_mod;
135 Evas_Object *diskselector;
136 Elm_Object_Item *item;
137 DiskItem_Data *disk_data;
138 Elm_Datetime_Field_Type field_type;
139 time_t t;
140 struct tm time1;
141 char buf[BUFF_SIZE], label[BUFF_SIZE];
142 const char *fmt;
143 int idx, min, max, val;
144 unsigned int display_item_num, text_len = 0;
145 Evas_Coord x = 0, y = 0, w = 0, h = 0, width;
146
147 ctx_mod = (Ctxpopup_Module_Data *)data;
148 if (!ctx_mod || !ctx_mod->ctxpopup) return;
149
150 // because of the diskselector behaviour, it is being recreated
151 diskselector = elm_diskselector_add(elm_widget_top_get(ctx_mod->mod_data.base));
152 snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj));
153 elm_object_style_set(diskselector, buf);
154 elm_object_content_set(ctx_mod->ctxpopup, diskselector);
155
156 t = time(NULL);
157 localtime_r(&t, &time1);
158
159 field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type");
160 fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type);
161 elm_datetime_value_get(ctx_mod->mod_data.base, &time1);
162 val = _field_value_get(&time1, field_type);
163 ctx_mod->mod_data.field_limit_get(ctx_mod->mod_data.base, field_type, &min, &max);
164
165 time1.tm_mday = 1; // To avoid month wrapping, set the first day of the month to start with.
166
167 if ((field_type == ELM_DATETIME_HOUR) && ((!strncmp(fmt, "%I", FIELD_FORMAT_LEN)) ||
168 (!strncmp(fmt, "%l", FIELD_FORMAT_LEN))))
169 {
170 if (max >= 12) max -= 12;
171 if (val >= 12) val -= 12;
172 if (min >= 12) min -= 12;
173 }
174 for (idx = min; idx <= max; idx++)
175 {
176 _field_value_set(&time1, field_type, idx);
177 strftime(label, BUFF_SIZE, fmt, &time1);
178 if (strlen(label) > text_len) text_len = strlen(label);
179 if (idx == val)
180 {
181 item = elm_diskselector_item_append(diskselector, label, NULL, NULL, NULL);
182 elm_diskselector_item_selected_set(item, EINA_TRUE);
183 }
184 else
185 {
186 disk_data = (DiskItem_Data *) malloc (sizeof(DiskItem_Data));
187 disk_data->ctx_mod = ctx_mod;
188 disk_data->sel_field_type = field_type;
189 disk_data->sel_field_value = idx;
190 item = elm_diskselector_item_append(diskselector, label, NULL, _diskselector_cb, disk_data);
191 elm_object_item_del_cb_set(item, _diskselector_item_free_cb);
192 }
193 }
194 elm_diskselector_side_label_length_set(diskselector, text_len);
195
196 evas_object_geometry_get(obj, &x, &y, &w, &h);
197 evas_object_geometry_get(elm_widget_top_get(ctx_mod->mod_data.base), NULL, NULL, &width, NULL);
198 evas_object_size_hint_min_set(ctx_mod->ctxpopup, width, -1);
199 display_item_num = width / (w + elm_finger_size_get());
200 // always display even number of items to avoid autoselection
201 if (display_item_num % 2) display_item_num -= 1;
202 if (display_item_num < DISKSELECTOR_MIN_ITEMS)
203 display_item_num = DISKSELECTOR_MIN_ITEMS;
204 elm_diskselector_display_item_num_set(diskselector, display_item_num);
205 elm_diskselector_round_set(diskselector, EINA_TRUE);
206
207 elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_DOWN,
208 ELM_CTXPOPUP_DIRECTION_UP, -1, -1);
209 evas_object_move(ctx_mod->ctxpopup, (x+w/2), (y+h));
210
211 // if the direction of Ctxpopup is upwards, move it to the top of datetime
212 if (elm_ctxpopup_direction_get (ctx_mod->ctxpopup) == ELM_CTXPOPUP_DIRECTION_UP)
213 {
214 elm_ctxpopup_direction_priority_set(ctx_mod->ctxpopup, ELM_CTXPOPUP_DIRECTION_UP,
215 ELM_CTXPOPUP_DIRECTION_DOWN, -1, -1);
216 evas_object_move(ctx_mod->ctxpopup, (x+w/2), y);
217 }
218 evas_object_show(ctx_mod->ctxpopup);
219}
220
221// module fucns for the specific module type
222EAPI void
223field_value_display(Elm_Datetime_Module_Data *module_data, Evas_Object *obj)
224{
225 Ctxpopup_Module_Data *ctx_mod;
226 Elm_Datetime_Field_Type field_type;
227 struct tm time;
228 char buf[BUFF_SIZE];
229 const char *fmt;
230
231 ctx_mod = (Ctxpopup_Module_Data *)module_data;
232 if (!ctx_mod || !obj) return;
233
234 elm_datetime_value_get(ctx_mod->mod_data.base, &time);
235 field_type = (Elm_Datetime_Field_Type )evas_object_data_get(obj, "_field_type");
236 fmt = ctx_mod->mod_data.field_format_get(ctx_mod->mod_data.base, field_type);
237 strftime(buf, sizeof(buf), fmt, &time);
238 elm_object_text_set(obj, buf);
239}
240
241EAPI Evas_Object *
242field_create(Elm_Datetime_Module_Data *module_data, Elm_Datetime_Field_Type field_type)
243{
244 Ctxpopup_Module_Data *ctx_mod;
245 Evas_Object *field_obj;
246
247 ctx_mod = (Ctxpopup_Module_Data *)module_data;
248 if (!ctx_mod) return NULL;
249
250 if (field_type == ELM_DATETIME_AMPM)
251 {
252 field_obj = elm_button_add(ctx_mod->mod_data.base);
253 evas_object_smart_callback_add(field_obj, "clicked", _ampm_clicked_cb, ctx_mod);
254 }
255 else
256 {
257 field_obj = elm_entry_add(ctx_mod->mod_data.base);
258 elm_entry_single_line_set(field_obj, EINA_TRUE);
259 elm_entry_editable_set(field_obj, EINA_FALSE);
260 elm_entry_input_panel_enabled_set(field_obj, EINA_FALSE);
261 elm_entry_context_menu_disabled_set(field_obj, EINA_TRUE);
262 evas_object_smart_callback_add(field_obj, "clicked", _field_clicked_cb, ctx_mod);
263 }
264 evas_object_data_set(field_obj, "_field_type", (void *)field_type);
265 return field_obj;
266}
267
268EAPI Elm_Datetime_Module_Data *
269obj_hook(Evas_Object *obj)
270{
271 Ctxpopup_Module_Data *ctx_mod;
272 char buf[BUFF_SIZE];
273
274 ctx_mod = ELM_NEW(Ctxpopup_Module_Data);
275 if (!ctx_mod) return NULL;
276
277 ctx_mod->ctxpopup = elm_ctxpopup_add(elm_widget_top_get(obj));
278 snprintf(buf, sizeof(buf), "datetime/%s", elm_object_style_get(obj));
279 elm_object_style_set(ctx_mod->ctxpopup, buf);
280 elm_ctxpopup_horizontal_set(ctx_mod->ctxpopup, EINA_TRUE);
281 evas_object_size_hint_weight_set(ctx_mod->ctxpopup, EVAS_HINT_EXPAND,
282 EVAS_HINT_EXPAND);
283 evas_object_size_hint_align_set(ctx_mod->ctxpopup, EVAS_HINT_FILL, 0.5);
284 evas_object_smart_callback_add(ctx_mod->ctxpopup, "dismissed",
285 _ctxpopup_dismissed_cb, ctx_mod);
286 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
287 _datetime_resize_cb, ctx_mod);
288 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
289 _datetime_move_cb, ctx_mod);
290 evas_object_event_callback_add(elm_widget_top_get(obj), EVAS_CALLBACK_RESIZE,
291 _ctxpopup_parent_resize_cb, ctx_mod);
292
293 return ((Elm_Datetime_Module_Data*)ctx_mod);
294}
295
296EAPI void
297obj_unhook(Elm_Datetime_Module_Data *module_data)
298{
299 Ctxpopup_Module_Data *ctx_mod;
300
301 ctx_mod = (Ctxpopup_Module_Data *)module_data;
302 if (!ctx_mod) return;
303
304 if (ctx_mod->ctxpopup)
305 evas_object_del(ctx_mod->ctxpopup);
306
307 if (ctx_mod)
308 {
309 free(ctx_mod);
310 ctx_mod = NULL;
311 }
312}
313
314// module api funcs needed
315EAPI int
316elm_modapi_init(void *m __UNUSED__)
317{
318 return 1; // succeed always
319}
320
321EAPI int
322elm_modapi_shutdown(void *m __UNUSED__)
323{
324 return 1; // succeed always
325}