1 /* gcal-time-selector.c
2 *
3 * Copyright (C) 2015 Erick Pérez Castellanos <erickpc@gnome.org>
4 * 2014 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
5 *
6 * gnome-calendar is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * gnome-calendar is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define G_LOG_DOMAIN "GcalTimeSelector"
21
22 #include "gcal-time-selector.h"
23
24 #include <glib/gi18n.h>
25
26 struct _GcalTimeSelector
27 {
28 GtkBox parent;
29
30 GtkAdjustment *hour_adjustment;
31 GtkAdjustment *minute_adjustment;
32
33 GtkWidget *hour_spin;
34 GtkWidget *minute_spin;
35 GtkWidget *period_combo;
36
37 GDateTime *time;
38
39 GcalTimeFormat time_format;
40 };
41
42 enum
43 {
44 PROP_0,
45 PROP_TIME,
46 LAST_PROP
47 };
48
49 enum
50 {
51 AM,
52 PM
53 };
54
55 G_DEFINE_TYPE (GcalTimeSelector, gcal_time_selector, GTK_TYPE_BOX);
56
57 static void
update_time(GcalTimeSelector * selector)58 update_time (GcalTimeSelector *selector)
59 {
60 GDateTime *now, *new_time;
61 gint hour, minute;
62
63 /* Retrieve current time */
64 hour = (gint) gtk_adjustment_get_value (selector->hour_adjustment);
65 minute = (gint) gtk_adjustment_get_value (selector->minute_adjustment);
66
67 if (selector->time_format == GCAL_TIME_FORMAT_12H)
68 {
69 hour = hour % 12;
70
71 if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector->period_combo)) == PM)
72 {
73 g_signal_handlers_block_by_func (selector->period_combo, update_time, selector);
74
75 gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12);
76 hour += 12;
77
78 g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector);
79 }
80 }
81
82 now = g_date_time_new_now_local ();
83 new_time = g_date_time_new_local (g_date_time_get_year (now),
84 g_date_time_get_month (now),
85 g_date_time_get_day_of_month (now),
86 hour, minute, 0);
87
88 /* Set the new time */
89 gcal_time_selector_set_time (selector, new_time);
90
91 g_clear_pointer (&new_time, g_date_time_unref);
92 g_clear_pointer (&now, g_date_time_unref);
93 }
94
95 static gboolean
on_output(GtkWidget * widget,GcalTimeSelector * selector)96 on_output (GtkWidget *widget,
97 GcalTimeSelector *selector)
98 {
99 GtkAdjustment *adjustment;
100 gchar *text;
101 gint value;
102
103 adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget));
104 value = (gint) gtk_adjustment_get_value (adjustment);
105 text = g_strdup_printf ("%02d", value);
106 gtk_entry_set_text (GTK_ENTRY (widget), text);
107
108 g_free (text);
109
110 return TRUE;
111 }
112
113 static void
gcal_time_selector_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)114 gcal_time_selector_get_property (GObject *object,
115 guint prop_id,
116 GValue *value,
117 GParamSpec *pspec)
118 {
119 GcalTimeSelector *self = (GcalTimeSelector*) object;
120
121 switch (prop_id)
122 {
123 case PROP_TIME:
124 g_value_set_boxed (value, self->time);
125 break;
126
127 default:
128 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129 }
130 }
131
132 static void
gcal_time_selector_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)133 gcal_time_selector_set_property (GObject *object,
134 guint prop_id,
135 const GValue *value,
136 GParamSpec *pspec)
137 {
138 GcalTimeSelector *self = (GcalTimeSelector*) object;
139
140 switch (prop_id)
141 {
142 case PROP_TIME:
143 gcal_time_selector_set_time (self, g_value_get_boxed (value));
144 break;
145
146 default:
147 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
148 }
149 }
150
151 void
gcal_time_selector_set_time_format(GcalTimeSelector * selector,GcalTimeFormat time_format)152 gcal_time_selector_set_time_format (GcalTimeSelector *selector,
153 GcalTimeFormat time_format)
154 {
155 g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector));
156
157 selector->time_format = time_format;
158 gtk_widget_set_visible (selector->period_combo, time_format == GCAL_TIME_FORMAT_12H);
159
160 if (time_format == GCAL_TIME_FORMAT_24H)
161 {
162 gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 0.0);
163 gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 23.0);
164 }
165 else
166 {
167 gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 1.0);
168 gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 12.0);
169 }
170 }
171
172 static void
gcal_time_selector_finalize(GObject * object)173 gcal_time_selector_finalize (GObject *object)
174 {
175 GcalTimeSelector *self = GCAL_TIME_SELECTOR (object);
176
177 g_clear_pointer (&self->time, g_date_time_unref);
178 G_OBJECT_CLASS (gcal_time_selector_parent_class)->finalize (object);
179 }
180
181 static void
gcal_time_selector_dispose(GObject * object)182 gcal_time_selector_dispose (GObject *object)
183 {
184 G_OBJECT_CLASS (gcal_time_selector_parent_class)->dispose (object);
185 }
186
187 static void
gcal_time_selector_class_init(GcalTimeSelectorClass * klass)188 gcal_time_selector_class_init (GcalTimeSelectorClass *klass)
189 {
190 GObjectClass *object_class;
191
192 object_class = G_OBJECT_CLASS (klass);
193 object_class->dispose = gcal_time_selector_dispose;
194 object_class->finalize = gcal_time_selector_finalize;
195 object_class->get_property = gcal_time_selector_get_property;
196 object_class->set_property = gcal_time_selector_set_property;
197
198 /**
199 * GcalTimeSelector::time:
200 *
201 * The current time of the selector.
202 */
203 g_object_class_install_property (object_class,
204 PROP_TIME,
205 g_param_spec_boxed ("time",
206 "Time of the selector",
207 "The current time of the selector",
208 G_TYPE_DATE_TIME,
209 G_PARAM_READWRITE));
210
211 gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/calendar/ui/event-editor/gcal-time-selector.ui");
212
213 gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_adjustment);
214 gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_spin);
215 gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_adjustment);
216 gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_spin);
217 gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, period_combo);
218
219 gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), on_output);
220 gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), update_time);
221 }
222
223 static void
gcal_time_selector_init(GcalTimeSelector * self)224 gcal_time_selector_init (GcalTimeSelector *self)
225 {
226 self->time = g_date_time_new_now_local ();
227
228 gtk_widget_init_template (GTK_WIDGET (self));
229 }
230
231 /* Public API */
232 GtkWidget*
gcal_time_selector_new(void)233 gcal_time_selector_new (void)
234 {
235 return g_object_new (GCAL_TYPE_TIME_SELECTOR, NULL);
236 }
237
238 void
gcal_time_selector_set_time(GcalTimeSelector * selector,GDateTime * time)239 gcal_time_selector_set_time (GcalTimeSelector *selector,
240 GDateTime *time)
241 {
242 g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector));
243
244 if (selector->time != time)
245 {
246 gint hour, minute;
247
248 g_clear_pointer (&selector->time, g_date_time_unref);
249 selector->time = g_date_time_new_local (g_date_time_get_year (time),
250 g_date_time_get_month (time),
251 g_date_time_get_day_of_month (time),
252 g_date_time_get_hour (time),
253 g_date_time_get_minute (time),
254 0);
255
256 /* Update the spinners */
257 g_signal_handlers_block_by_func (selector->hour_adjustment, update_time, selector);
258 g_signal_handlers_block_by_func (selector->minute_adjustment, update_time, selector);
259
260 hour = g_date_time_get_hour (time);
261 minute = g_date_time_get_minute (time);
262
263 if (selector->time_format == GCAL_TIME_FORMAT_12H)
264 {
265 g_signal_handlers_block_by_func (selector->period_combo, update_time, selector);
266
267 gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12);
268 hour = hour % 12;
269 hour = (hour == 0)? 12 : hour;
270
271 g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector);
272 }
273
274 gtk_adjustment_set_value (selector->hour_adjustment, hour);
275 gtk_adjustment_set_value (selector->minute_adjustment, minute);
276
277 g_signal_handlers_unblock_by_func (selector->hour_adjustment, update_time, selector);
278 g_signal_handlers_unblock_by_func (selector->minute_adjustment, update_time, selector);
279
280 g_object_notify (G_OBJECT (selector), "time");
281 }
282 }
283
284 GDateTime*
gcal_time_selector_get_time(GcalTimeSelector * selector)285 gcal_time_selector_get_time (GcalTimeSelector *selector)
286 {
287 g_return_val_if_fail (GCAL_IS_TIME_SELECTOR (selector), NULL);
288
289 return selector->time;
290 }
291