/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * gcal-time-selector.c * Copyright (C) 2015 Erick Pérez Castellanos * 2014 Georges Basile Stavracas Neto * * gnome-calendar is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * gnome-calendar is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #define G_LOG_DOMAIN "GcalTimeSelector" #include "gcal-time-selector.h" #include struct _GcalTimeSelector { GtkMenuButton parent; GtkAdjustment *hour_adjustment; GtkAdjustment *minute_adjustment; GtkWidget *time_label; GtkWidget *hour_spin; GtkWidget *minute_spin; GtkWidget *period_combo; GtkWidget *grid; GDateTime *time; gboolean format_24h; }; enum { PROP_0, PROP_TIME, LAST_PROP }; enum { AM, PM }; static void gcal_time_selector_constructed (GObject *object); G_DEFINE_TYPE (GcalTimeSelector, gcal_time_selector, GTK_TYPE_MENU_BUTTON); static void update_label (GcalTimeSelector *selector) { gchar *new_label; if (selector->format_24h) { new_label = g_date_time_format (selector->time, "%H:%M"); } else { gchar *time_str; gint hour, minute, period; hour = (gint) gtk_adjustment_get_value (selector->hour_adjustment); minute = (gint) gtk_adjustment_get_value (selector->minute_adjustment); period = gtk_combo_box_get_active (GTK_COMBO_BOX (selector->period_combo)); time_str = g_strdup_printf ("%.2d:%.2d", hour, minute); if (period == AM) new_label = g_strdup_printf (_("%s AM"), time_str); else new_label = g_strdup_printf (_("%s PM"), time_str); g_free (time_str); } gtk_label_set_label (GTK_LABEL (selector->time_label), new_label); g_clear_pointer (&new_label, g_free); } static void update_time (GcalTimeSelector *selector) { GDateTime *now, *new_time; gint hour, minute; /* Retrieve current time */ hour = (gint) gtk_adjustment_get_value (selector->hour_adjustment); minute = (gint) gtk_adjustment_get_value (selector->minute_adjustment); if (!selector->format_24h) { hour = hour % 12; if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector->period_combo)) == PM) { g_signal_handlers_block_by_func (selector->period_combo, update_time, selector); gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12); hour += 12; g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector); } } now = g_date_time_new_now_local (); new_time = g_date_time_new_local (g_date_time_get_year (now), g_date_time_get_month (now), g_date_time_get_day_of_month (now), hour, minute, 0); /* Set the new time */ gcal_time_selector_set_time (selector, new_time); g_clear_pointer (&new_time, g_date_time_unref); g_clear_pointer (&now, g_date_time_unref); } static gboolean on_output (GtkWidget *widget, GcalTimeSelector *selector) { GtkAdjustment *adjustment; gchar *text; gint value; adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget)); value = (gint) gtk_adjustment_get_value (adjustment); text = g_strdup_printf ("%02d", value); gtk_entry_set_text (GTK_ENTRY (widget), text); g_free (text); return TRUE; } static void gcal_time_selector_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GcalTimeSelector *self = (GcalTimeSelector*) object; switch (prop_id) { case PROP_TIME: g_value_set_boxed (value, self->time); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void gcal_time_selector_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GcalTimeSelector *self = (GcalTimeSelector*) object; switch (prop_id) { case PROP_TIME: gcal_time_selector_set_time (self, g_value_get_boxed (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } void gcal_time_selector_set_time_format (GcalTimeSelector *selector, gboolean format_24h) { g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector)); selector->format_24h = format_24h; gtk_widget_set_visible (selector->period_combo, !format_24h); if (format_24h) { gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 0.0); gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 23.0); } else { gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 1.0); gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 12.0); } } static void gcal_time_selector_finalize (GObject *object) { GcalTimeSelector *self = GCAL_TIME_SELECTOR (object); g_clear_pointer (&self->time, g_date_time_unref); G_OBJECT_CLASS (gcal_time_selector_parent_class)->finalize (object); } static void gcal_time_selector_dispose (GObject *object) { G_OBJECT_CLASS (gcal_time_selector_parent_class)->dispose (object); } static void gcal_time_selector_class_init (GcalTimeSelectorClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->constructed = gcal_time_selector_constructed; object_class->dispose = gcal_time_selector_dispose; object_class->finalize = gcal_time_selector_finalize; object_class->get_property = gcal_time_selector_get_property; object_class->set_property = gcal_time_selector_set_property; /** * GcalTimeSelector::time: * * The current time of the selector. */ g_object_class_install_property (object_class, PROP_TIME, g_param_spec_boxed ("time", "Time of the selector", "The current time of the selector", G_TYPE_DATE_TIME, G_PARAM_READWRITE)); gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/calendar/time-selector.ui"); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, time_label); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_adjustment); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_spin); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_adjustment); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_spin); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, period_combo); gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, grid); gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), on_output); gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), update_time); } static void gcal_time_selector_init (GcalTimeSelector *self) { self->time = g_date_time_new_now_local (); gtk_widget_init_template (GTK_WIDGET (self)); } static void gcal_time_selector_constructed (GObject *object) { GcalTimeSelector *selector = GCAL_TIME_SELECTOR (object); /* chaining up */ G_OBJECT_CLASS (gcal_time_selector_parent_class)->constructed (object); gtk_widget_set_direction (selector->grid, GTK_TEXT_DIR_LTR); } /* Public API */ GtkWidget* gcal_time_selector_new (void) { return g_object_new (GCAL_TYPE_TIME_SELECTOR, NULL); } void gcal_time_selector_set_time (GcalTimeSelector *selector, GDateTime *time) { g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector)); if (selector->time != time) { gint hour, minute; g_clear_pointer (&selector->time, g_date_time_unref); selector->time = g_date_time_new_local (g_date_time_get_year (time), g_date_time_get_month (time), g_date_time_get_day_of_month (time), g_date_time_get_hour (time), g_date_time_get_minute (time), 0); /* Update the spinners */ g_signal_handlers_block_by_func (selector->hour_adjustment, update_time, selector); g_signal_handlers_block_by_func (selector->minute_adjustment, update_time, selector); hour = g_date_time_get_hour (time); minute = g_date_time_get_minute (time); if (!selector->format_24h) { g_signal_handlers_block_by_func (selector->period_combo, update_time, selector); gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12); hour = hour % 12; hour = (hour == 0)? 12 : hour; g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector); } gtk_adjustment_set_value (selector->hour_adjustment, hour); gtk_adjustment_set_value (selector->minute_adjustment, minute); update_label (selector); g_signal_handlers_unblock_by_func (selector->hour_adjustment, update_time, selector); g_signal_handlers_unblock_by_func (selector->minute_adjustment, update_time, selector); g_object_notify (G_OBJECT (selector), "time"); } } GDateTime* gcal_time_selector_get_time (GcalTimeSelector *selector) { g_return_val_if_fail (GCAL_IS_TIME_SELECTOR (selector), NULL); return selector->time; }