From 66a8c6b7ab153ef1b9b13ed479c2f66f4e2636c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20H=C3=BCgel?= <129184-gwastar@users.noreply.gitlab.gnome.org> Date: Sat, 4 Nov 2023 13:39:31 +0100 Subject: [PATCH] common/date-chooser: Jump to first day of month on button press Encode the day in the combined choice value and use the callbacks introduced in the previous commit to always jump to the first day of the month when the next/previous month buttons are clicked. Closes: https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1103 Part-of: --- src/gui/common/gcal-date-chooser.blp | 6 +- src/gui/common/gcal-date-chooser.c | 113 ++++++++++++++++++++++----- 2 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/gui/common/gcal-date-chooser.blp b/src/gui/common/gcal-date-chooser.blp index 9da7954d..eb36fd96 100644 --- a/src/gui/common/gcal-date-chooser.blp +++ b/src/gui/common/gcal-date-chooser.blp @@ -41,8 +41,10 @@ template $GcalDateChooser: Adw.Bin { $GcalMultiChoice combined_choice { visible: bind $get_combined_choice_visible(template.show-heading, template.split-month-year) as ; halign: fill; - min-value: 12; - max-value: 119999; + // From January 1st, 1 (32 * (1 * 12 + 0) + 0): + min-value: 384; + // …to December 31st, 9999 (32 * (9999×12+11) + 30): + max-value: 3839998; popover: popover; animate: false; value: 0; diff --git a/src/gui/common/gcal-date-chooser.c b/src/gui/common/gcal-date-chooser.c index 789d4555..d0ffc116 100644 --- a/src/gui/common/gcal-date-chooser.c +++ b/src/gui/common/gcal-date-chooser.c @@ -131,6 +131,70 @@ get_split_choice_visible (gpointer user_data, return show_heading && split_month_year; } +static void +decode_combined_choice_value (gint value, + gint *year, + gint *month, + gint *day) +{ + gint y, m, d, ym; + + d = value % 32 + 1; + ym = value / 32; + y = ym / 12; + m = ym % 12 + 1; + + g_assert (g_date_valid_dmy (d, m, y)); + + if (year) + *year = y; + if (month) + *month = m; + if (day) + *day = d; +} + +static gint +encode_combined_choice_value (gint year, + gint month, + gint day) +{ + g_assert (g_date_valid_dmy (day, month, year)); + return (year * 12 + month - 1) * 32 + day - 1; +} + +static gint +compute_prev_combined_choice_value (gint value) +{ + gint year, month; + + decode_combined_choice_value (value, &year, &month, NULL); + + if (--month < 1) + { + month = 12; + year--; + } + + return encode_combined_choice_value (year, month, 1); +} + +static gint +compute_next_combined_choice_value (gint value) +{ + gint year, month; + + decode_combined_choice_value (value, &year, &month, NULL); + + if (++month > 12) + { + month = 1; + year++; + } + + return encode_combined_choice_value (year, month, 1); +} + static gboolean leap (guint year) { @@ -342,13 +406,12 @@ format_month_year (GcalMultiChoice *choice, g_autoptr (GDateTime) now = g_date_time_new_now (g_date_time_get_timezone (self->date)); gint year, month; - year = value / 12; - month = value % 12; + decode_combined_choice_value (value, &year, &month, NULL); if (g_date_time_get_year (now) == year) - return g_strdup (gcal_get_month_name (month)); + return g_strdup (gcal_get_month_name (month - 1)); else - return g_strdup_printf ("%s %d", gcal_get_month_name (month), year); + return g_strdup_printf ("%s %d", gcal_get_month_name (month - 1), year); } static void @@ -515,11 +578,14 @@ gcal_date_chooser_set_date (GcalView *view, gcal_set_date_time (&self->date, date); + if (y1 != y2 || m1 != m2 || d1 != d2) + gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->combined_choice), + encode_combined_choice_value (y2, m2, d2)); + if (y1 != y2 || m1 != m2) { gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->year_choice), y2); gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->month_choice), m2 - 1); - gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->combined_choice), y2 * 12 + m2 - 1); calendar_compute_days (self); gcal_timeline_subscriber_range_changed (GCAL_TIMELINE_SUBSCRIBER (self)); } @@ -753,15 +819,10 @@ calendar_get_property (GObject *obj, static void multi_choice_changed (GcalDateChooser *self, gint year, - gint month) + gint month, + gint day) { g_autoptr (GDateTime) date = NULL; - gint day; - - day = g_date_time_get_day_of_month (self->date); - - /* Make sure the day is valid at that month */ - day = MIN (day, month_length[leap (year)][month]); date = g_date_time_new_local (year, month, day, 0, 0, 0); gcal_date_chooser_set_date (GCAL_VIEW (self), date); @@ -770,23 +831,28 @@ multi_choice_changed (GcalDateChooser *self, static void combined_multi_choice_changed (GcalDateChooser *self) { - gint year, month; + gint year, month, day, value; - year = gcal_multi_choice_get_value (GCAL_MULTI_CHOICE (self->combined_choice)) / 12; - month = gcal_multi_choice_get_value (GCAL_MULTI_CHOICE (self->combined_choice)) % 12 + 1; + value = gcal_multi_choice_get_value (GCAL_MULTI_CHOICE (self->combined_choice)); + decode_combined_choice_value (value, &year, &month, &day); - multi_choice_changed (self, year, month); + multi_choice_changed (self, year, month, day); } static void split_multi_choice_changed (GcalDateChooser *self) { - gint year, month; + gint year, month, day; year = gcal_multi_choice_get_value (GCAL_MULTI_CHOICE (self->year_choice)); month = gcal_multi_choice_get_value (GCAL_MULTI_CHOICE (self->month_choice)) + 1; - multi_choice_changed (self, year, month); + day = g_date_time_get_day_of_month (self->date); + + /* Make sure the day is valid at that month */ + day = MIN (day, month_length[leap (year)][month]); + + multi_choice_changed (self, year, month, day); } static gboolean @@ -1017,7 +1083,7 @@ gcal_date_chooser_init (GcalDateChooser *self) GtkDropTarget *drop_target; GtkWidget *label; gint row, col; - gint year, month; + gint year, month, day; GtkLayoutManager *layout_manager; self->show_heading = TRUE; @@ -1145,12 +1211,17 @@ gcal_date_chooser_init (GcalDateChooser *self) calendar_init_weekday_display (self); calendar_compute_days (self); - g_date_time_get_ymd (self->date, &year, &month, NULL); + g_date_time_get_ymd (self->date, &year, &month, &day); gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->year_choice), year); gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->month_choice), month - 1); - gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->combined_choice), year * 12 + month - 1); + gcal_multi_choice_set_value (GCAL_MULTI_CHOICE (self->combined_choice), + encode_combined_choice_value (year, month, day)); calendar_update_selected_day_display (self); + gcal_multi_choice_set_value_callbacks (GCAL_MULTI_CHOICE (self->combined_choice), + compute_prev_combined_choice_value, + compute_next_combined_choice_value); + drop_target = gtk_drop_target_new (G_TYPE_STRING, GDK_ACTION_COPY); gtk_drop_target_set_preload (drop_target, TRUE); g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop_target_drop_cb), NULL);