2008-11-19 Alejandro Pinheiro <apinheiro@igalia.com>
[hildon] / src / hildon-date-selector.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2008 Nokia Corporation.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /**
22  * SECTION:hildon-date-selector
23  * @short_description: A widget to select the current date.
24  *
25  * HildonDateSelector is a date widget, equivalent to hildon-calendar, but with a multi-column
26  * approach
27  *
28  */
29
30 #define _GNU_SOURCE     /* needed for GNU nl_langinfo_l */
31 #define __USE_GNU       /* needed for locale */
32
33 #include <locale.h>
34
35 #ifdef HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
38
39 #include <string.h>
40 #include <stdlib.h>
41
42 #include <libintl.h>
43 #include <time.h>
44 #include <langinfo.h>
45
46 #include "hildon-date-selector.h"
47
48 #define HILDON_DATE_SELECTOR_GET_PRIVATE(obj)                           \
49   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorPrivate))
50
51 G_DEFINE_TYPE (HildonDateSelector, hildon_date_selector, HILDON_TYPE_TOUCH_SELECTOR)
52
53 #define INIT_YEAR 100
54 #define LAST_YEAR 50    /* since current year */
55
56 #define _(String) dgettext("hildon-libs", String)
57
58 /* #define _(String) "%A %e. %B %Y"  debug purposes */
59
60 enum
61 {
62   COLUMN_STRING,
63   COLUMN_INT,
64   N_COLUMNS
65 };
66
67 enum
68 {
69   DAY,
70   MONTH,
71   YEAR
72 };
73
74 struct _HildonDateSelectorPrivate
75 {
76   GtkTreeModel *year_model;
77   GtkTreeModel *month_model;
78   GtkTreeModel *day_model;
79
80   GSList *column_order;
81   gint day_column;
82   gint month_column;
83   gint year_column;             /* it depends on the locale */
84
85   gchar *format;                /* day/month/year format, depends on locale */
86
87   gint creation_day;
88   gint creation_month;
89   gint creation_year;           /* date at creation time */
90
91   gint current_num_days;
92 };
93
94 static void hildon_date_selector_finalize (GObject * object);
95
96 /* private functions */
97 static GtkTreeModel *_create_day_model (HildonDateSelector * selector);
98 static GtkTreeModel *_create_year_model (HildonDateSelector * selector);
99 static GtkTreeModel *_create_month_model (HildonDateSelector * selector);
100
101 static void _get_real_date (gint * year, gint * month, gint * day);
102 static void _locales_init (HildonDateSelectorPrivate * priv);
103
104 static void _manage_selector_change_cb (HildonTouchSelector * selector,
105                                         gint num_column, gpointer data);
106
107 static GtkTreeModel *_update_day_model (HildonDateSelector * selector);
108
109 static gint _month_days (gint month, gint year);
110 static void _init_column_order (HildonDateSelector * selector);
111
112 static gchar *_custom_print_func (HildonTouchSelector * selector);
113
114 /***************************************************************************/
115 /* The following date routines are taken from the lib_date package.  Keep
116  * them separate in case we want to update them if a newer lib_date comes
117  * out with fixes.  */
118
119 typedef unsigned int N_int;
120
121 typedef unsigned long N_long;
122
123 typedef signed long Z_long;
124
125 typedef enum
126 { false = FALSE, true = TRUE } boolean;
127
128 #define                                         and &&  /* logical (boolean) operators: lower case */
129
130 #define                                         or ||
131
132 static const N_int month_length[2][13] = {
133   {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
134   {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
135 };
136
137 static const N_int days_in_months[2][14] = {
138   {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
139   {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
140 };
141
142 static Z_long _calc_days (N_int year, N_int mm, N_int dd);
143
144 static N_int _day_of_week (N_int year, N_int mm, N_int dd);
145
146 static boolean _leap (N_int year);
147
148
149 static boolean
150 _leap (N_int year)
151 {
152   return ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
153 }
154
155 static N_int
156 _day_of_week (N_int year, N_int mm, N_int dd)
157 {
158   Z_long days;
159
160   days = _calc_days (year, mm, dd);
161   if (days > 0L) {
162     days--;
163     days %= 7L;
164     days++;
165   }
166   return ((N_int) days);
167 }
168
169 static Z_long
170 _year_to_days (N_int year)
171 {
172   return (year * 365L + (year / 4) - (year / 100) + (year / 400));
173 }
174
175 static Z_long
176 _calc_days (N_int year, N_int mm, N_int dd)
177 {
178   boolean lp;
179
180   if (year < 1)
181     return (0L);
182   if ((mm < 1) or (mm > 12))
183     return (0L);
184   if ((dd < 1) or (dd > month_length[(lp = _leap (year))][mm]))
185     return (0L);
186   return (_year_to_days (--year) + days_in_months[lp][mm] + dd);
187 }
188
189 static void
190 hildon_date_selector_class_init (HildonDateSelectorClass * class)
191 {
192   GObjectClass *gobject_class;
193   GtkObjectClass *object_class;
194   GtkWidgetClass *widget_class;
195   GtkContainerClass *container_class;
196
197   gobject_class = (GObjectClass *) class;
198   object_class = (GtkObjectClass *) class;
199   widget_class = (GtkWidgetClass *) class;
200   container_class = (GtkContainerClass *) class;
201
202   /* GObject */
203   gobject_class->finalize = hildon_date_selector_finalize;
204
205   /* GtkWidget */
206
207   /* GtkContainer */
208
209   /* signals */
210
211   g_type_class_add_private (object_class, sizeof (HildonDateSelectorPrivate));
212 }
213
214 static void
215 hildon_date_selector_init (HildonDateSelector * selector)
216 {
217   GSList *iter = NULL;
218   gint current_item = 0;
219   HildonTouchSelectorColumn *column = NULL;
220
221   selector->priv = HILDON_DATE_SELECTOR_GET_PRIVATE (selector);
222
223   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
224   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
225
226   hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector),
227                                         _custom_print_func);
228
229   _locales_init (selector->priv);
230
231   _init_column_order (selector);
232
233   _get_real_date (&selector->priv->creation_year,
234                   &selector->priv->creation_month, &selector->priv->creation_day);
235
236   selector->priv->year_model = _create_year_model (selector);
237   selector->priv->month_model = _create_month_model (selector);
238   selector->priv->day_model = _create_day_model (selector);
239   selector->priv->current_num_days = 31;
240
241   /* We add the columns, checking the locale order */
242   iter = selector->priv->column_order;
243   for (iter = selector->priv->column_order; iter; iter = g_slist_next (iter)) {
244     current_item = GPOINTER_TO_INT (iter->data);
245
246     switch (current_item) {
247     case DAY:
248       column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
249                                                          selector->priv->day_model, TRUE);
250       g_object_set (G_OBJECT (column), "text-column", 0, NULL);
251       break;
252     case MONTH:
253       column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
254                                                          selector->priv->month_model, TRUE);
255       g_object_set (G_OBJECT (column), "text-column", 0, NULL);
256       break;
257     case YEAR:
258       column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
259                                                          selector->priv->year_model, TRUE);
260       g_object_set (G_OBJECT (column), "text-column", 0, NULL);
261       break;
262     default:
263       g_error ("Current column order incorrect");
264       break;
265     }
266   }
267
268   g_signal_connect (G_OBJECT (selector),
269                     "changed", G_CALLBACK (_manage_selector_change_cb), NULL);
270
271   /* By default we should select the current day */
272   hildon_date_selector_select_current_date (selector, selector->priv->creation_year,
273                                             selector->priv->creation_month,
274                                             selector->priv->creation_day);
275 }
276
277 static void
278 hildon_date_selector_finalize (GObject * object)
279 {
280   HildonDateSelector *selector = NULL;
281
282   selector = HILDON_DATE_SELECTOR (object);
283
284   g_slist_free (selector->priv->column_order);
285
286   (*G_OBJECT_CLASS (hildon_date_selector_parent_class)->finalize) (object);
287 }
288
289 /* ------------------------------ PRIVATE METHODS ---------------------------- */
290 static gchar *
291 _custom_print_func (HildonTouchSelector * touch_selector)
292 {
293   HildonDateSelector *selector = NULL;
294   gchar *result = NULL;
295   guint year, month, day;
296   gint day_of_week = 0;
297   static gchar string[255];
298   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
299
300   selector = HILDON_DATE_SELECTOR (touch_selector);
301
302   hildon_date_selector_get_date (selector, &year, &month, &day);
303   day_of_week = _day_of_week (year, month + 1, day) % 7;
304
305   tm.tm_mday = day;
306   tm.tm_mon = month;
307   tm.tm_year = year - 1900;
308   tm.tm_wday = day_of_week;
309
310   strftime (string, 255, _("wdgt_va_date_long"), &tm);
311
312   result = g_strdup (string);
313
314   return result;
315 }
316
317 /* This was copied from hildon-calendar */
318 static void
319 _locales_init (HildonDateSelectorPrivate * priv)
320 {
321   /* Hildon: This is not exactly portable, see
322    * http://bugzilla.gnome.org/show_bug.cgi?id=343415
323    * The labels need to be instance variables as the startup wizard changes
324    * locale on runtime.
325    */
326   locale_t l;
327
328   l = newlocale (LC_TIME_MASK, setlocale (LC_MESSAGES, NULL), NULL);
329
330   priv->format = g_locale_to_utf8 (nl_langinfo_l (D_FMT, l),
331                                    -1, NULL, NULL, NULL);
332
333   freelocale (l);
334 }
335
336 static void
337 _init_column_order (HildonDateSelector * selector)
338 {
339   gchar *current_order[3] = { NULL, NULL, NULL };
340   gchar *day_pos = NULL;
341   gchar *month_pos = NULL;
342   gchar *year_pos = NULL;
343   gint i, c;
344   gchar *aux = NULL;
345
346   g_debug ("Current format: %s", selector->priv->format);
347
348   /* search each token on the format */
349   day_pos = g_strrstr (selector->priv->format, "%d");
350
351   month_pos = g_strrstr (selector->priv->format, "%m");
352   year_pos = g_strrstr (selector->priv->format, "%y");
353   if (year_pos == NULL) {
354     year_pos = g_strrstr (selector->priv->format, "%Y");
355   }
356
357
358   if ((day_pos == NULL) || (month_pos == NULL) || (year_pos == NULL)) {
359     g_error ("Wrong date format");      /* so default values */
360
361     selector->priv->day_column = 0;
362     selector->priv->month_column = 1;
363     selector->priv->year_column = 2;
364     selector->priv->column_order = g_slist_append (NULL, GINT_TO_POINTER (DAY));
365     selector->priv->column_order =
366       g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH));
367     selector->priv->column_order =
368       g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR));
369   }
370
371   /* sort current_order with this values (bubble sort) */
372   current_order[0] = day_pos;
373   current_order[1] = month_pos;
374   current_order[2] = year_pos;
375
376   for (c = 1; c <= 2; c++) {
377     for (i = 0; i < 3 - c; i++) {
378       if (current_order[i] > current_order[i + 1]) {
379         aux = current_order[i];
380         current_order[i] = current_order[i + 1];
381         current_order[i + 1] = aux;
382       }
383     }
384   }
385
386   /* fill the column positions */
387   selector->priv->column_order = NULL;
388   c = 0;
389   for (i = 0; i < 3; i++) {
390     if (current_order[i] == day_pos) {
391       selector->priv->column_order =
392         g_slist_append (selector->priv->column_order, GINT_TO_POINTER (DAY));
393       selector->priv->day_column = c++;
394     }
395     if (current_order[i] == month_pos) {
396       selector->priv->column_order =
397         g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH));
398       selector->priv->month_column = c++;
399     }
400     if (current_order[i] == year_pos) {
401       selector->priv->column_order =
402         g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR));
403       selector->priv->year_column = c++;
404     }
405   }
406 }
407
408
409 static GtkTreeModel *
410 _create_day_model (HildonDateSelector * selector)
411 {
412   GtkListStore *store_days = NULL;
413   gint i = 0;
414   gchar label[255];
415   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
416   GtkTreeIter iter;
417
418   store_days = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
419   for (i = 1; i < 32; i++) {
420     tm.tm_mday = i;
421     strftime (label, 255, _("wdgt_va_day_numeric"), &tm);
422
423     gtk_list_store_append (store_days, &iter);
424     gtk_list_store_set (store_days, &iter,
425                         COLUMN_STRING, label, COLUMN_INT, i, -1);
426   }
427
428   return GTK_TREE_MODEL (store_days);
429 }
430
431 static GtkTreeModel *
432 _create_year_model (HildonDateSelector * selector)
433 {
434   GtkListStore *store_years = NULL;
435   gint real_year = 0;
436   gint i = 0;
437   static gchar label[255];
438   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
439   GtkTreeIter iter;
440
441   real_year = selector->priv->creation_year;
442
443   store_years = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
444   for (i = real_year - INIT_YEAR; i < real_year + LAST_YEAR; i++) {
445     tm.tm_year = i - 1900;
446     strftime (label, 255, _("wdgt_va_year"), &tm);
447
448     gtk_list_store_append (store_years, &iter);
449     gtk_list_store_set (store_years, &iter,
450                         COLUMN_STRING, label, COLUMN_INT, i, -1);
451   }
452
453   return GTK_TREE_MODEL (store_years);
454 }
455
456 static GtkTreeModel *
457 _create_month_model (HildonDateSelector * selector)
458 {
459   GtkTreeIter iter;
460   gint i = 0;
461   GtkListStore *store_months = NULL;
462   static gchar label[255];
463   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
464
465   store_months = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
466   for (i = 0; i < 12; i++) {
467     tm.tm_mon = i;
468     strftime (label, 255, _("wdgt_va_month"), &tm);
469
470     gtk_list_store_append (store_months, &iter);
471     gtk_list_store_set (store_months, &iter, COLUMN_STRING, label,
472                         COLUMN_INT, i,
473                         -1);
474   }
475
476   return GTK_TREE_MODEL (store_months);
477 }
478
479 static GtkTreeModel *
480 _update_day_model (HildonDateSelector * selector)
481 {
482   GtkListStore *store_days = NULL;
483   GtkTreePath *path = NULL;
484   gint i = 0;
485   GtkTreeIter iter;
486   static gchar label[255];
487   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
488   guint current_day = 0;
489   guint current_year = 0;
490   guint current_month = 0;
491   guint num_days = 31;
492
493   hildon_date_selector_get_date (selector, &current_year, &current_month,
494                                  &current_day);
495
496   num_days = _month_days (current_month, current_year);
497   store_days = GTK_LIST_STORE (selector->priv->day_model);
498
499   if (num_days == selector->priv->current_num_days) {
500     return GTK_TREE_MODEL (store_days);
501   }
502
503   if (num_days > selector->priv->current_num_days) {
504     for (i = selector->priv->current_num_days + 1; i <= num_days; i++) {
505       tm.tm_mday = i;
506       strftime (label, 255, _("wdgt_va_day_numeric"), &tm);
507
508       gtk_list_store_append (store_days, &iter);
509       gtk_list_store_set (store_days, &iter,
510                           COLUMN_STRING, label, COLUMN_INT, i, -1);
511     }
512   } else {
513     path = gtk_tree_path_new_from_indices (num_days,
514                                            -1);
515     gtk_tree_model_get_iter (GTK_TREE_MODEL (store_days), &iter, path);
516     do {
517     }while (gtk_list_store_remove (store_days, &iter));
518
519     gtk_tree_path_free (path);
520   }
521
522
523   selector->priv->current_num_days = num_days;
524
525   /* now we select a day */
526   if (current_day >= num_days) {
527     current_day = num_days;
528   }
529
530   hildon_date_selector_select_day (selector, current_day);
531
532   return GTK_TREE_MODEL (store_days);
533 }
534
535
536 static void
537 _get_real_date (gint * year, gint * month, gint * day)
538 {
539   time_t secs;
540   struct tm *tm = NULL;
541
542   secs = time (NULL);
543   tm = localtime (&secs);
544
545   if (year != NULL) {
546     *year = 1900 + tm->tm_year;
547   }
548
549   if (month != NULL) {
550     *month = tm->tm_mon;
551   }
552
553   if (day != NULL) {
554     *day = tm->tm_mday;
555   }
556 }
557
558
559 static void
560 _manage_selector_change_cb (HildonTouchSelector * touch_selector,
561                             gint num_column, gpointer data)
562 {
563   HildonDateSelector *selector = NULL;
564
565   g_return_if_fail (HILDON_IS_DATE_SELECTOR (touch_selector));
566   selector = HILDON_DATE_SELECTOR (touch_selector);
567
568   if ((num_column == selector->priv->month_column) ||
569       (num_column == selector->priv->year_column)) /* it is required to check that with
570                                                     * the years too,remember: leap years
571                                                     * update_day_model will check if
572                                                     * the number of days is different
573                                                     */
574   {
575     _update_day_model (selector);
576   }
577 }
578
579 static gint
580 _month_days (gint month, gint year)
581 {
582   gint month_days[2][12] = {
583     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
584     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
585   };
586
587   g_return_val_if_fail (month >= 0 && month <= 12, -1);
588
589   return month_days[_leap (year)][month];
590 }
591
592
593 /* ------------------------------ PUBLIC METHODS ---------------------------- */
594
595 /**
596  * hildon_date_selector_new:
597  *
598  * Creates a new #HildonDateSelector
599  *
600  * Returns: a new #HildonDateSelector
601  **/
602 GtkWidget *
603 hildon_date_selector_new ()
604 {
605   return g_object_new (HILDON_TYPE_DATE_SELECTOR, NULL);
606 }
607
608
609 /**
610  * hildon_date_selector_select_current_date:
611  * @selector: the #HildonDateSelector
612  * @year:  the current year
613  * @month: the current month (0-11)
614  * @day:   the current day (1-31, 1-30, 1-29, 1-28) depends on the month
615  *
616  * Sets the current active date on the #HildonDateSelector widget
617  *
618  **/
619 gboolean
620 hildon_date_selector_select_current_date (HildonDateSelector * selector,
621                                           guint year, guint month, guint day)
622 {
623   GtkTreeIter iter;
624   gint min_year = 0;
625   gint max_year = 0;
626   gint num_days = 0;
627
628   min_year = selector->priv->creation_year - INIT_YEAR;
629   max_year = selector->priv->creation_year + LAST_YEAR;
630
631   g_return_val_if_fail (year > min_year && year < max_year, FALSE);
632   g_return_val_if_fail (month >= 0 && month < 12, FALSE);
633
634   num_days = _month_days (month, year);
635   g_return_val_if_fail (day > 0 && day <= num_days, FALSE);
636
637
638   gtk_tree_model_iter_nth_child (selector->priv->year_model, &iter, NULL,
639                                  year - selector->priv->creation_year +
640                                  INIT_YEAR);
641   hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
642                                      selector->priv->year_column, &iter,
643                                      FALSE);
644
645   gtk_tree_model_iter_nth_child (selector->priv->month_model, &iter, NULL,
646                                  month);
647   hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
648                                      selector->priv->month_column, &iter,
649                                      FALSE);
650
651   gtk_tree_model_iter_nth_child (selector->priv->day_model, &iter, NULL,
652                                  day - 1);
653   hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
654                                      selector->priv->day_column, &iter,
655                                      FALSE);
656
657   return TRUE;
658 }
659
660
661 /**
662  * hildon_date_selector_get_date:
663  * @selector: the #HildonDateSelector
664  * @year:  to set the current year
665  * @month: to set the current month (0-11)
666  * @day:   to the current day (1-31, 1-30, 1-29, 1-28) depends on the month
667  *
668  * Gets the current active date on the #HildonDateSelector widget
669  *
670  *
671  **/
672 void
673 hildon_date_selector_get_date (HildonDateSelector * selector,
674                                guint * year, guint * month, guint * day)
675 {
676   GtkTreeIter iter;
677
678   if (year != NULL) {
679     hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
680                                         selector->priv->year_column, &iter);
681     gtk_tree_model_get (selector->priv->year_model,
682                         &iter, COLUMN_INT, year, -1);
683   }
684
685   if (month != NULL) {
686     hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
687                                         selector->priv->month_column, &iter);
688     gtk_tree_model_get (selector->priv->month_model,
689                         &iter, COLUMN_INT, month, -1);
690   }
691
692
693   if (day != NULL) {
694     if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
695                                             selector->priv->day_column, &iter))
696     {
697       gtk_tree_model_get (selector->priv->day_model,
698                           &iter, COLUMN_INT, day, -1);
699     }
700 /*       *day = *day - 1;  */
701   }
702
703 }
704
705
706 /**
707  * hildon_date_selector_select_month:
708  * @selector: the #HildonDateSelector
709  * @month: the current month (0-11)
710  * @year:  the current year
711  *
712  * Modify the current month and year on the current active date
713  *
714  * Utility function, too keep this API more similar to the previously existing
715  * hildon-calendar widget.
716  *
717  *
718  **/
719 gboolean hildon_date_selector_select_month (HildonDateSelector *selector,
720                                             guint month, guint year)
721 {
722   guint day = 0;
723
724   hildon_date_selector_get_date (selector, NULL, NULL, &day);
725
726   return hildon_date_selector_select_current_date (selector, year, month, day);
727 }
728
729 /**
730  * hildon_date_selector_select_day:
731  * @selector: the #HildonDateSelector
732  * @day:   the current day (1-31, 1-30, 1-29, 1-28) depends on the month
733  *
734  * Modify the current day on the current active date
735  *
736  * Utility function, too keep this API more similar to the previously existing
737  * hildon-calendar widget.
738  *
739  *
740  **/
741 void
742 hildon_date_selector_select_day (HildonDateSelector *selector, guint day)
743 {
744   guint month = 0;
745   guint year = 0;
746
747   hildon_date_selector_get_date (selector, &year, &month, NULL);
748
749   hildon_date_selector_select_current_date (selector, year, month, day);
750 }