summaryrefslogtreecommitdiff
path: root/gtk/gtkcalendar.c
diff options
context:
space:
mode:
authorTimm Bäder <mail@baedert.org>2020-02-05 09:22:21 +0100
committerMatthias Clasen <mclasen@redhat.com>2020-02-07 13:16:32 -0500
commit093eac944184a66fd84812b7897a907c7ee843b4 (patch)
tree993cf8d1c6f52d1e4d9b6e53ce2ddace926391b1 /gtk/gtkcalendar.c
parent93c6f2256fdd81d581bec68a6f7be8a1aacf161d (diff)
downloadgtk+-093eac944184a66fd84812b7897a907c7ee843b4.tar.gz
calendar: Keep a GDateTime around
Instead of a year/month/day triple.
Diffstat (limited to 'gtk/gtkcalendar.c')
-rw-r--r--gtk/gtkcalendar.c532
1 files changed, 170 insertions, 362 deletions
diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c
index c3580b262e..8b79fb4362 100644
--- a/gtk/gtkcalendar.c
+++ b/gtk/gtkcalendar.c
@@ -216,9 +216,7 @@ struct _GtkCalendarPrivate
GtkWidget *week_number_labels[6];
GtkWidget *day_number_labels[6][7];
- gint month;
- gint year;
- gint selected_day;
+ GDateTime *date;
gint day_month[6][7];
gint day[6][7];
@@ -295,8 +293,6 @@ static void calendar_invalidate_day (GtkCalendar *widget,
static void calendar_invalidate_day_num (GtkCalendar *widget,
gint day);
-static void calendar_compute_days (GtkCalendar *calendar);
-
static gboolean gtk_calendar_scroll_controller_scroll (GtkEventControllerScroll *scroll,
gdouble dx,
gdouble dy,
@@ -318,6 +314,7 @@ gtk_calendar_dispose (GObject *object)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (GTK_CALENDAR (object));
+ g_clear_pointer (&priv->date, g_date_time_unref);
g_clear_pointer (&priv->header_box, gtk_widget_unparent);
g_clear_pointer (&priv->grid, gtk_widget_unparent);
@@ -530,138 +527,6 @@ gtk_calendar_class_init (GtkCalendarClass *class)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("calendar"));
}
-static void set_month (GtkCalendar *calendar,
- int new_month);
-static void
-set_year (GtkCalendar *calendar,
- int new_year)
-{
- GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- char buffer[255];
- char *str;
- time_t tmp_time;
- struct tm *tm;
-
- priv->year = new_year;
-
- tmp_time = 1; /* Jan 1 1970, 00:00:01 UTC */
- tm = gmtime (&tmp_time);
- tm->tm_year = priv->year - 1900;
-
- /* Translators: This dictates how the year is displayed in
- * gtkcalendar widget. See strftime() manual for the format.
- * Use only ASCII in the translation.
- *
- * Also look for the msgid "2000".
- * Translate that entry to a year with the widest output of this
- * msgid.
- *
- * "%Y" is appropriate for most locales.
- */
- strftime (buffer, sizeof (buffer), C_("calendar year format", "%Y"), tm);
- str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
- gtk_label_set_label (GTK_LABEL (priv->year_label), str);
- g_free (str);
-
- /* Update month */
- set_month (calendar, priv->month);
-}
-
-static void
-set_month (GtkCalendar *calendar,
- int new_month)
-{
- GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- int i;
- int x, y;
-
- g_return_if_fail (new_month >= 0);
- g_return_if_fail (new_month < 12);
-
- priv->month = new_month;
- calendar_compute_days (calendar);
- gtk_stack_set_visible_child_name (GTK_STACK (priv->month_name_stack),
- default_monthname[priv->month]);
-
- /* Update week number labels */
- for (i = 0; i < 6; i ++)
- {
- int year, month, week;
- char buffer[255];
-
- year = priv->year;
- month = priv->month + priv->day_month[i][6] - MONTH_CURRENT;
-
- if (month < 0)
- {
- month += 12;
- year -= 1;
- }
- else if (month > 11)
- {
- month -= 12;
- year += 1;
- }
-
- month += 1;
-
- week = week_of_year (year, month, priv->day[i][6]);
-
- /* Translators: this defines whether the week numbers should use
- * localized digits or the ones used in English (0123...).
- *
- * Translate to "%Id" if you want to use localized digits, or
- * translate to "%d" otherwise.
- *
- * Note that translating this doesn't guarantee that you get localized
- * digits. That needs support from your system and locale definition
- * too.
- */
- g_snprintf (buffer, sizeof (buffer), C_("calendar:week:digits", "%d"), week);
-
- gtk_label_set_label (GTK_LABEL (priv->week_number_labels[i]), buffer);
- }
-
- /* Update day labels */
- for (y = 0; y < 6; y ++)
- for (x = 0; x < 7; x ++)
- {
- const int day = priv->day[y][x];
- GtkWidget *label = priv->day_number_labels[y][x];
- char buffer[255];
-
- /* Translators: this defines whether the day numbers should use
- * localized digits or the ones used in English (0123...).
- *
- * Translate to "%Id" if you want to use localized digits, or
- * translate to "%d" otherwise.
- *
- * Note that translating this doesn't guarantee that you get localized
- * digits. That needs support from your system and locale definition
- * too.
- */
- g_snprintf (buffer, sizeof (buffer), C_("calendar:day:digits", "%d"), day);
-
- gtk_label_set_label (GTK_LABEL (label), buffer);
-
- if (priv->day_month[y][x] == MONTH_PREV ||
- priv->day_month[y][x] == MONTH_NEXT)
- gtk_widget_add_style_class (label, "other-month");
- else
- gtk_widget_remove_style_class (label, "other-month");
-
- if (priv->marked_date[day-1])
- gtk_widget_set_state_flags (label, GTK_STATE_FLAG_CHECKED, FALSE);
- else
- gtk_widget_unset_state_flags (label, GTK_STATE_FLAG_CHECKED);
-
- if (priv->selected_day == day &&
- priv->day_month[y][x] == MONTH_CURRENT)
- gtk_widget_set_state_flags (label, GTK_STATE_FLAG_SELECTED, FALSE);
- else
- gtk_widget_unset_state_flags (label, GTK_STATE_FLAG_SELECTED);
- }
-}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
@@ -673,8 +538,6 @@ gtk_calendar_init (GtkCalendar *calendar)
GtkWidget *widget = GTK_WIDGET (calendar);
GtkEventController *controller;
GtkGesture *gesture;
- time_t secs;
- struct tm *tm;
gint i;
#ifdef G_OS_WIN32
wchar_t wbuffer[100];
@@ -862,14 +725,9 @@ gtk_calendar_init (GtkCalendar *calendar)
gtk_widget_set_vexpand (priv->grid, TRUE);
gtk_widget_set_parent (priv->grid, GTK_WIDGET (calendar));
- /* Set defaults */
- secs = time (NULL);
- tm = localtime (&secs);
-
for (i=0;i<31;i++)
priv->marked_date[i] = FALSE;
priv->num_marked_dates = 0;
- priv->selected_day = tm->tm_mday;
priv->show_heading = TRUE;
priv->show_day_names = TRUE;
@@ -954,20 +812,20 @@ gtk_calendar_init (GtkCalendar *calendar)
#endif
#endif
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (calendar))),
+ GTK_ORIENTATION_VERTICAL);
+
+ /* Select current day */
+ priv->date = g_date_time_new_from_unix_local (0);
now = g_date_time_new_now_local ();
- set_year (calendar, g_date_time_get_year (now));
- set_month (calendar, g_date_time_get_month (now) - 1);
+ gtk_calendar_select_day (calendar, now);
+ g_date_time_unref (now);
/* We just initialized the year label, now add some space to it so
* changing the year does not increase the calendar width */
gtk_widget_measure (priv->year_label, GTK_ORIENTATION_HORIZONTAL, -1,
&min_year_width, NULL, NULL, NULL);
gtk_widget_set_size_request (priv->year_label, min_year_width + 10, -1);
-
- gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (calendar))),
- GTK_ORIENTATION_VERTICAL);
-
- g_date_time_unref (now);
}
#pragma GCC diagnostic pop
@@ -979,134 +837,65 @@ calendar_queue_refresh (GtkCalendar *calendar)
}
static void
-calendar_set_month_next (GtkCalendar *calendar)
+calendar_set_month_prev (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- gint month_len;
+ GDateTime *new_date;
- if (priv->month == 11)
- {
- set_month (calendar, 0);
- set_year (calendar, priv->year + 1);
- }
- else
- set_month (calendar, priv->month + 1);
+ new_date = g_date_time_add_months (priv->date, -1);
- calendar_compute_days (calendar);
- g_signal_emit (calendar,
- gtk_calendar_signals[NEXT_MONTH_SIGNAL],
- 0);
- g_signal_emit (calendar,
- gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
- 0);
+ gtk_calendar_select_day (calendar, new_date);
+ g_date_time_unref (new_date);
+}
- month_len = month_length[leap (priv->year)][priv->month + 1];
+static void
+calendar_set_month_next (GtkCalendar *calendar)
+{
+ GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
+ GDateTime *new_date;
- if (month_len < priv->selected_day)
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, month_len,
- 0, 0, 0);
- priv->selected_day = 0;
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
- else
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, priv->selected_day,
- 0, 0, 0);
+ new_date = g_date_time_add_months (priv->date, 1);
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
+ gtk_calendar_select_day (calendar, new_date);
+ g_date_time_unref (new_date);
}
static void
calendar_set_year_prev (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- gint month_len;
-
- set_year (calendar, priv->year - 1);
-
- calendar_compute_days (calendar);
- g_signal_emit (calendar,
- gtk_calendar_signals[PREV_YEAR_SIGNAL],
- 0);
- g_signal_emit (calendar,
- gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
- 0);
+ GDateTime *new_date;
- month_len = month_length[leap (priv->year)][priv->month + 1];
+ new_date = g_date_time_add_years (priv->date, -1);
- if (month_len < priv->selected_day)
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, month_len,
- 0, 0, 0);
- priv->selected_day = 0;
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
- else
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, priv->selected_day,
- 0, 0, 0);
-
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
+ gtk_calendar_select_day (calendar, new_date);
+ g_date_time_unref (new_date);
}
static void
calendar_set_year_next (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- gint month_len;
-
- set_year (calendar, priv->year + 1);
-
- calendar_compute_days (calendar);
- g_signal_emit (calendar,
- gtk_calendar_signals[NEXT_YEAR_SIGNAL],
- 0);
- g_signal_emit (calendar,
- gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
- 0);
+ GDateTime *new_date;
- month_len = month_length[leap (priv->year)][priv->month + 1];
+ new_date = g_date_time_add_years (priv->date, 1);
- if (month_len < priv->selected_day)
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, month_len,
- 0, 0, 0);
- priv->selected_day = 0;
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
- else
- {
- GDateTime *new_date = g_date_time_new_local (priv->year, priv->month + 1, priv->selected_day,
- 0, 0, 0);
-
- gtk_calendar_select_day (calendar, new_date);
- g_date_time_unref (new_date);
- }
+ gtk_calendar_select_day (calendar, new_date);
+ g_date_time_unref (new_date);
}
static void
calendar_compute_days (GtkCalendar *calendar)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- gint month;
- gint year;
- gint ndays_in_month;
- gint ndays_in_prev_month;
- gint first_day;
- gint row;
- gint col;
- gint day;
-
- year = priv->year;
- month = priv->month + 1;
+ const int month = g_date_time_get_month (priv->date);
+ const int year = g_date_time_get_year (priv->date);
+ int ndays_in_month;
+ int ndays_in_prev_month;
+ int first_day;
+ int row;
+ int col;
+ int day;
ndays_in_month = month_length[leap (year)][month];
@@ -1180,7 +969,9 @@ calendar_select_and_focus_day (GtkCalendar *calendar,
}
}
- new_date = g_date_time_new_local (priv->year, priv->month + 1, day,
+ new_date = g_date_time_new_local (g_date_time_get_year (priv->date),
+ g_date_time_get_month (priv->date),
+ day,
0, 0, 0);
gtk_calendar_select_day (calendar, new_date);
@@ -1188,61 +979,6 @@ calendar_select_and_focus_day (GtkCalendar *calendar,
}
static void
-calendar_set_month_prev (GtkCalendar *calendar)
-{
- GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (calendar);
- gint month_len;
-
- if (priv->month == 0)
- {
- set_month (calendar, 11);
- set_year (calendar, priv->year - 1);
- }
- else
- set_month (calendar, priv->month - 1);
-
- month_len = month_length[leap (priv->year)][priv->month + 1];
-
- calendar_compute_days (calendar);
-
- g_signal_emit (calendar,
- gtk_calendar_signals[PREV_MONTH_SIGNAL],
- 0);
- g_signal_emit (calendar,
- gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
- 0);
-
- if (month_len < priv->selected_day)
- {
- GDateTime *new_date;
- priv->selected_day = 0;
-
- new_date = g_date_time_new_local (priv->year, priv->month + 1, month_len,
- 0, 0, 0);
-
- gtk_calendar_select_day (calendar, new_date);
-
- g_date_time_unref (new_date);
- }
- else
- {
- GDateTime *new_date;
-
- if (priv->selected_day < 0)
- priv->selected_day = priv->selected_day + 1 + month_length[leap (priv->year)][priv->month + 1];
-
- new_date = g_date_time_new_local (priv->year, priv->month + 1, priv->selected_day,
- 0, 0, 0);
-
- gtk_calendar_select_day (calendar, new_date);
-
- g_date_time_unref (new_date);
- }
-
- calendar_queue_refresh (calendar);
-}
-
-static void
gtk_calendar_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -1279,13 +1015,13 @@ gtk_calendar_get_property (GObject *object,
switch (prop_id)
{
case PROP_YEAR:
- g_value_set_int (value, priv->year);
+ g_value_set_int (value, g_date_time_get_year (priv->date));
break;
case PROP_MONTH:
- g_value_set_int (value, priv->month);
+ g_value_set_int (value, g_date_time_get_month (priv->date));
break;
case PROP_DAY:
- g_value_set_int (value, priv->selected_day);
+ g_value_set_int (value, g_date_time_get_day_of_month (priv->date));
break;
case PROP_SHOW_HEADING:
g_value_set_boolean (value, gtk_calendar_get_show_heading (calendar));
@@ -1421,7 +1157,9 @@ get_calendar_content (GtkCalendar *calendar)
GValue value = G_VALUE_INIT;
GdkContentProvider *content;
- date = g_date_new_dmy (priv->selected_day, priv->month + 1, priv->year);
+ date = g_date_new_dmy (g_date_time_get_day_of_month (priv->date),
+ g_date_time_get_month (priv->date),
+ g_date_time_get_year (priv->date));
g_date_strftime (str, 127, "%x", date);
g_free (date);
@@ -1829,79 +1567,150 @@ gtk_calendar_new (void)
}
/**
- * gtk_calendar_select_month:
- * @calendar: a #GtkCalendar
- * @date: (transfer none): a #GDateTime to use as reference
+ * gtk_calendar_select_day:
+ * @calendar: a #GtkCalendar.
+ * @date: (transfer none): a #GDateTime representing the day to select
*
- * Shifts the calendar to the month showing @date.
- * The exact day of @date will *NOT* be selected, only the month.
- * If you want to select @date's day, use gtk_calendar_select_day()
+ * Will switch to @date's year and month and select its day.
**/
void
-gtk_calendar_select_month (GtkCalendar *self,
- GDateTime *date)
+gtk_calendar_select_day (GtkCalendar *self,
+ GDateTime *date)
{
GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (self);
- int month, year;
+ int new_day, new_month, new_year;
+ gboolean day_changed, month_changed, year_changed;
+ char buffer[255];
+ char *str;
+ time_t tmp_time;
+ struct tm *tm;
+ int i;
+ int x, y;
g_return_if_fail (GTK_IS_CALENDAR (self));
g_return_if_fail (date != NULL);
- year = g_date_time_get_year (date);
- month = g_date_time_get_month (date);
+ day_changed = g_date_time_get_day_of_month (priv->date) != g_date_time_get_day_of_month (date);
+ month_changed = g_date_time_get_month (priv->date) != g_date_time_get_month (date);
+ year_changed = g_date_time_get_year (priv->date) != g_date_time_get_year (date);
- g_object_freeze_notify (G_OBJECT (self));
+ if (!day_changed && !month_changed && !year_changed)
+ return;
- if (priv->month != month)
- {
- set_month (self, month);
- g_object_notify (G_OBJECT (self), "month");
- }
- if (priv->year != year)
- {
- set_year (self, year);
- g_object_notify (G_OBJECT (self), "year");
- }
+ new_year = g_date_time_get_year (date);
+ new_month = g_date_time_get_month (date);
+ new_day = g_date_time_get_day_of_month (date);
- g_object_thaw_notify (G_OBJECT (self));
+ g_date_time_unref (priv->date);
+ priv->date = g_date_time_ref (date);
- g_signal_emit (self, gtk_calendar_signals[MONTH_CHANGED_SIGNAL], 0);
-}
+ tmp_time = 1; /* Jan 1 1970, 00:00:01 UTC */
+ tm = gmtime (&tmp_time);
+ tm->tm_year = new_year - 1900;
-/**
- * gtk_calendar_select_day:
- * @calendar: a #GtkCalendar.
- * @date: (transfer none): a #GDateTime representing the day to select
- *
- * Will switch to @date's year and month and select its day.
- **/
-void
-gtk_calendar_select_day (GtkCalendar *self,
- GDateTime *date)
-{
- GtkCalendarPrivate *priv = gtk_calendar_get_instance_private (self);
- int day, month, year;
+ /* Translators: This dictates how the year is displayed in
+ * gtkcalendar widget. See strftime() manual for the format.
+ * Use only ASCII in the translation.
+ *
+ * "%Y" is appropriate for most locales.
+ */
+ strftime (buffer, sizeof (buffer), C_("calendar year format", "%Y"), tm);
+ str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
+ gtk_label_set_label (GTK_LABEL (priv->year_label), str);
+ g_free (str);
- g_return_if_fail (GTK_IS_CALENDAR (self));
- g_return_if_fail (date != NULL);
+ /* Update month */
+
+ calendar_compute_days (self);
+ gtk_stack_set_visible_child_name (GTK_STACK (priv->month_name_stack),
+ default_monthname[new_month - 1]);
+
+ /* Update day labels */
+ for (y = 0; y < 6; y ++)
+ for (x = 0; x < 7; x ++)
+ {
+ const int day = priv->day[y][x];
+ GtkWidget *label = priv->day_number_labels[y][x];
+ /* Translators: this defines whether the day numbers should use
+ * localized digits or the ones used in English (0123...).
+ *
+ * Translate to "%Id" if you want to use localized digits, or
+ * translate to "%d" otherwise.
+ *
+ * Note that translating this doesn't guarantee that you get localized
+ * digits. That needs support from your system and locale definition
+ * too.
+ */
+ g_snprintf (buffer, sizeof (buffer), C_("calendar:day:digits", "%d"), day);
- year = g_date_time_get_year (date);
- month = g_date_time_get_month (date);
- day = g_date_time_get_day_of_month (date);
+ gtk_label_set_label (GTK_LABEL (label), buffer);
- if (priv->selected_day != day)
+ if (priv->day_month[y][x] == MONTH_PREV ||
+ priv->day_month[y][x] == MONTH_NEXT)
+ gtk_widget_add_style_class (label, "other-month");
+ else
+ gtk_widget_remove_style_class (label, "other-month");
+
+ if (priv->marked_date[day-1])
+ gtk_widget_set_state_flags (label, GTK_STATE_FLAG_CHECKED, FALSE);
+ else
+ gtk_widget_unset_state_flags (label, GTK_STATE_FLAG_CHECKED);
+
+ if (new_day == day &&
+ priv->day_month[y][x] == MONTH_CURRENT)
+ gtk_widget_set_state_flags (label, GTK_STATE_FLAG_SELECTED, FALSE);
+ else
+ gtk_widget_unset_state_flags (label, GTK_STATE_FLAG_SELECTED);
+ }
+
+ /* Update week number labels.
+ * We simply get the week number of priv->date and add the others.
+ * simple. */
+ for (i = 0; i < 6; i ++)
{
- priv->selected_day = day;
+ int year = new_year;
+ int month, week;
- g_object_freeze_notify (G_OBJECT (self));
- set_year (self, year);
- set_month (self, month - 1);
+ month = new_month + priv->day_month[i][6] - MONTH_CURRENT;
- g_object_notify (G_OBJECT (self), "day");
- g_object_thaw_notify (G_OBJECT (self));
+ if (month < 1)
+ {
+ month += 12;
+ year -= 1;
+ }
+ else if (month > 12)
+ {
+ month -= 12;
+ year += 1;
+ }
+ week = week_of_year (year, month, priv->day[i][6]);
+
+ /* Translators: this defines whether the week numbers should use
+ * localized digits or the ones used in English (0123...).
+ *
+ * Translate to "%Id" if you want to use localized digits, or
+ * translate to "%d" otherwise.
+ * Note that translating this doesn't guarantee that you get localized
+ * digits. That needs support from your system and locale definition
+ * too. */
+ g_snprintf (buffer, sizeof (buffer), C_("calendar:week:digits", "%d"), week);
+
+ gtk_label_set_label (GTK_LABEL (priv->week_number_labels[i]), buffer);
+ }
+
+ if (day_changed)
+ {
+ g_object_notify (G_OBJECT (self), "day");
g_signal_emit (self, gtk_calendar_signals[DAY_SELECTED_SIGNAL], 0);
}
+
+ if (month_changed)
+ g_object_notify (G_OBJECT (self), "month");
+
+ if (year_changed)
+ g_object_notify (G_OBJECT (self), "year");
+
}
/**
@@ -2010,8 +1819,7 @@ gtk_calendar_get_date (GtkCalendar *self)
g_return_val_if_fail (GTK_IS_CALENDAR (self), NULL);
- return g_date_time_new_local (priv->year, priv->month + 1, priv->selected_day,
- 0, 0, 0);
+ return g_date_time_ref (priv->date);
}
/**