/* -*- 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 . */ #include "gcal-time-selector.h" #include struct _GcalTimeSelectorPrivate { GtkWidget *time_label; GtkWidget *hour_spin; GtkWidget *minute_spin; GtkWidget *period_combo; GtkWidget *grid; gboolean format_24h; }; enum { MODIFIED, NUM_SIGNALS }; enum { AM, PM }; static guint signals[NUM_SIGNALS] = { 0, }; static void format_date_label (GcalTimeSelector *selector); static gboolean on_output (GtkSpinButton *button, gpointer user_data); static void period_changed (GtkComboBox *combo, gpointer user_data); static void time_changed (GtkAdjustment *adjustment, gpointer user_data); static void gcal_time_selector_constructed (GObject *object); G_DEFINE_TYPE_WITH_PRIVATE (GcalTimeSelector, gcal_time_selector, GTK_TYPE_MENU_BUTTON); static void format_date_label (GcalTimeSelector *selector) { GcalTimeSelectorPrivate *priv; GtkAdjustment *hour_adj; GtkAdjustment *minute_adj; gchar *new_time; gint hour, minute; priv = gcal_time_selector_get_instance_private (selector); hour_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->hour_spin)); minute_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->minute_spin)); /* get current time */ hour = (gint) gtk_adjustment_get_value (hour_adj); minute = (gint) gtk_adjustment_get_value (minute_adj); /* format time according to the system 12h/24h setting */ if (priv->format_24h) { new_time = g_strdup_printf ("%.2d:%.2d", hour, minute); } else { gint period; period = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->period_combo)); /* FIXME: we shouldn't expose print formatting code to translators */ if (period == AM) new_time = g_strdup_printf (_("%.2d:%.2d AM"), hour, minute); else new_time = g_strdup_printf (_("%.2d:%.2d PM"), hour, minute); } gtk_label_set_label (GTK_LABEL (priv->time_label), new_time); g_free (new_time); } static gboolean on_output (GtkSpinButton *button, gpointer user_data) { gchar *text; gint value; value = (gint) gtk_adjustment_get_value (gtk_spin_button_get_adjustment (button)); text = g_strdup_printf ("%02d", value); gtk_entry_set_text (GTK_ENTRY (button), text); g_free (text); return TRUE; } static void period_changed (GtkComboBox *combo, gpointer user_data) { format_date_label (GCAL_TIME_SELECTOR (user_data)); g_signal_emit (user_data, signals[MODIFIED], 0); } void gcal_time_selector_set_time_format (GcalTimeSelector *selector, gboolean format_24h) { GcalTimeSelectorPrivate *priv; priv = gcal_time_selector_get_instance_private (selector); priv->format_24h = format_24h; gtk_widget_set_visible (priv->period_combo, !format_24h); if (format_24h) gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->hour_spin)), 23.0); else gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->hour_spin)), 11.0); } static void time_changed (GtkAdjustment *adjustment, gpointer user_data) { format_date_label (GCAL_TIME_SELECTOR (user_data)); g_signal_emit (user_data, signals[MODIFIED], 0); } 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; signals[MODIFIED] = g_signal_new ("modified", GCAL_TYPE_TIME_SELECTOR, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcalTimeSelectorClass, modified), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/calendar/time-selector.ui"); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GcalTimeSelector, time_label); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_spin); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_spin); gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GcalTimeSelector, period_combo); gtk_widget_class_bind_template_child_private (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), period_changed); gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), time_changed); } static void gcal_time_selector_init (GcalTimeSelector *self) { gtk_widget_init_template (GTK_WIDGET (self)); } static void gcal_time_selector_constructed (GObject *object) { GcalTimeSelectorPrivate *priv; priv = gcal_time_selector_get_instance_private (GCAL_TIME_SELECTOR (object)); /* chaining up */ G_OBJECT_CLASS (gcal_time_selector_parent_class)->constructed (object); gtk_widget_set_direction (priv->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, gint hours, gint minutes) { GcalTimeSelectorPrivate *priv; GtkAdjustment *hour_adj; GtkAdjustment *minute_adj; g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector)); priv = gcal_time_selector_get_instance_private (selector); hour_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->hour_spin)); minute_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->minute_spin)); g_warn_if_fail (hours < 24); g_warn_if_fail (minutes < 60); /* setup spin buttons according to the format */ if (priv->format_24h) { gtk_adjustment_set_value (hour_adj, hours < 24 ? hours : 0); } else { gint period; period = hours < 12? AM : PM; hours = hours % 12; gtk_combo_box_set_active (GTK_COMBO_BOX (priv->period_combo), period); gtk_adjustment_set_value (hour_adj, hours); } gtk_adjustment_set_value (minute_adj, minutes < 60 ? minutes : 0); /* format time label accordingly */ format_date_label (selector); } void gcal_time_selector_get_time (GcalTimeSelector *selector, gint *hours, gint *minutes) { GcalTimeSelectorPrivate *priv; GtkAdjustment *hour_adj; GtkAdjustment *minute_adj; g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector)); priv = gcal_time_selector_get_instance_private (selector); hour_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->hour_spin)); minute_adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->minute_spin)); /* 24h, the easy one*/ if (priv->format_24h) { *hours = (gint) gtk_adjustment_get_value (hour_adj); } /* 12h format must calculate the time * according to the AM/PM combo box */ else { gint am_pm; am_pm = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->period_combo)); *hours = (gint) gtk_adjustment_get_value (hour_adj) + 12 * am_pm; } /* minute field isn't dependant on 12h/24h format */ *minutes = (gint) gtk_adjustment_get_value (minute_adj); }