]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-calendar-button.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / libempathy-gtk / empathy-calendar-button.c
1 /*
2  * empathy-calendar-button.c - Source for EmpathyCalendarButton
3  * Copyright (C) 2012 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "config.h"
21 #include "empathy-calendar-button.h"
22
23 #include <glib/gi18n-lib.h>
24
25 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER_THING
26 #include "empathy-debug.h"
27
28 G_DEFINE_TYPE (EmpathyCalendarButton, empathy_calendar_button, GTK_TYPE_BOX)
29
30 /* signal enum */
31 enum {
32   DATE_CHANGED,
33   LAST_SIGNAL,
34 };
35
36 static guint signals[LAST_SIGNAL] = {0};
37
38 struct _EmpathyCalendarButtonPriv {
39   GDate *date;
40
41   GtkWidget *button_date;
42   GtkWidget *button_clear;
43   GtkWidget *dialog;
44   GtkWidget *calendar;
45 };
46
47 static void
48 empathy_calendar_button_finalize (GObject *object)
49 {
50   EmpathyCalendarButton *self = (EmpathyCalendarButton *) object;
51
52   tp_clear_pointer (&self->priv->date, g_date_free);
53
54   G_OBJECT_CLASS (empathy_calendar_button_parent_class)->finalize (object);
55 }
56
57 static void
58 update_label (EmpathyCalendarButton *self)
59 {
60   if (self->priv->date == NULL)
61     {
62       gtk_button_set_label (GTK_BUTTON (self->priv->button_date),
63           _("Select..."));
64     }
65   else
66     {
67       gchar buffer[128];
68
69       g_date_strftime (buffer, 128, "%e %b %Y", self->priv->date);
70       gtk_button_set_label (GTK_BUTTON (self->priv->button_date), buffer);
71     }
72 }
73
74 static void
75 empathy_calendar_button_constructed (GObject *object)
76 {
77   EmpathyCalendarButton *self = (EmpathyCalendarButton *) object;
78
79   G_OBJECT_CLASS (empathy_calendar_button_parent_class)->constructed (
80       object);
81
82   update_label (self);
83 }
84
85 static void
86 dialog_response (GtkDialog *dialog,
87     gint response,
88     EmpathyCalendarButton *self)
89 {
90   GDate *date;
91   guint year, month, day;
92
93   if (response != GTK_RESPONSE_OK)
94     goto out;
95
96   gtk_calendar_get_date (GTK_CALENDAR (self->priv->calendar),
97       &year, &month, &day);
98   date = g_date_new_dmy (day, month + 1, year);
99
100   empathy_calendar_button_set_date (self, date);
101
102   g_date_free (date);
103
104 out:
105   gtk_widget_hide (GTK_WIDGET (dialog));
106 }
107
108 static gboolean
109 dialog_destroy (GtkWidget *widget,
110     EmpathyCalendarButton *self)
111 {
112   self->priv->dialog = NULL;
113   self->priv->calendar = NULL;
114
115   return FALSE;
116 }
117
118 static void
119 update_calendar (EmpathyCalendarButton *self)
120 {
121   if (self->priv->calendar == NULL)
122     return;
123
124   gtk_calendar_clear_marks (GTK_CALENDAR (self->priv->calendar));
125
126   if (self->priv->date == NULL)
127     return;
128
129   gtk_calendar_select_day (GTK_CALENDAR (self->priv->calendar),
130       g_date_get_day (self->priv->date));
131   gtk_calendar_select_month (GTK_CALENDAR (self->priv->calendar),
132       g_date_get_month (self->priv->date) - 1,
133       g_date_get_year (self->priv->date));
134   gtk_calendar_mark_day (GTK_CALENDAR (self->priv->calendar),
135       g_date_get_day (self->priv->date));
136 }
137
138 static void
139 empathy_calendar_button_date_clicked (GtkButton *button,
140     EmpathyCalendarButton *self)
141 {
142   if (self->priv->dialog == NULL)
143     {
144       GtkWidget *parent, *content;
145
146       parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
147
148       self->priv->dialog = gtk_dialog_new_with_buttons (NULL,
149           GTK_WINDOW (parent), GTK_DIALOG_MODAL,
150           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
151           _("_Select"), GTK_RESPONSE_OK,
152           NULL);
153
154       gtk_window_set_transient_for (GTK_WINDOW (self->priv->dialog),
155           GTK_WINDOW (parent));
156
157       self->priv->calendar = gtk_calendar_new ();
158
159       update_calendar (self);
160
161       content = gtk_dialog_get_content_area (GTK_DIALOG (self->priv->dialog));
162
163       gtk_box_pack_start (GTK_BOX (content), self->priv->calendar, TRUE, TRUE,
164           6);
165       gtk_widget_show (self->priv->calendar);
166
167       g_signal_connect (self->priv->dialog, "response",
168           G_CALLBACK (dialog_response), self);
169       g_signal_connect (self->priv->dialog, "destroy",
170           G_CALLBACK (dialog_destroy), self);
171     }
172
173   gtk_window_present (GTK_WINDOW (self->priv->dialog));
174 }
175
176 static void
177 empathy_calendar_button_clear_clicked (GtkButton *button,
178     EmpathyCalendarButton *self)
179 {
180   empathy_calendar_button_set_date (self, NULL);
181 }
182
183 static void
184 empathy_calendar_button_init (EmpathyCalendarButton *self)
185 {
186   GtkWidget *image;
187   GtkStyleContext *context;
188
189   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
190       EMPATHY_TYPE_CALENDAR_BUTTON, EmpathyCalendarButtonPriv);
191
192   context = gtk_widget_get_style_context (GTK_WIDGET (self));
193   gtk_style_context_add_class (context, GTK_STYLE_CLASS_LINKED);
194
195   /* Date */
196   self->priv->button_date = gtk_button_new ();
197
198   g_signal_connect (self->priv->button_date, "clicked",
199       G_CALLBACK (empathy_calendar_button_date_clicked), self);
200
201   gtk_button_set_alignment (GTK_BUTTON (self->priv->button_date), 0, 0.5);
202
203   gtk_box_pack_start (GTK_BOX (self), self->priv->button_date, TRUE, TRUE, 0);
204   gtk_widget_show (self->priv->button_date);
205
206   /* Clear */
207   self->priv->button_clear = gtk_button_new ();
208
209   image = gtk_image_new_from_stock (GTK_STOCK_CLEAR,
210       GTK_ICON_SIZE_MENU);
211   gtk_button_set_image (GTK_BUTTON (self->priv->button_clear), image);
212   gtk_widget_show (image);
213
214   g_signal_connect (self->priv->button_clear, "clicked",
215       G_CALLBACK (empathy_calendar_button_clear_clicked), self);
216
217   gtk_box_pack_start (GTK_BOX (self), self->priv->button_clear,
218       FALSE, FALSE, 0);
219   gtk_widget_show (self->priv->button_clear);
220 }
221
222 static void
223 empathy_calendar_button_class_init (EmpathyCalendarButtonClass *klass)
224 {
225   GObjectClass *oclass = G_OBJECT_CLASS (klass);
226
227   g_type_class_add_private (klass, sizeof (EmpathyCalendarButtonPriv));
228
229   oclass->finalize = empathy_calendar_button_finalize;
230   oclass->constructed = empathy_calendar_button_constructed;
231
232   signals[DATE_CHANGED] = g_signal_new ("date-changed",
233       G_TYPE_FROM_CLASS (klass),
234       G_SIGNAL_RUN_LAST, 0,
235       NULL, NULL,
236       g_cclosure_marshal_generic,
237       G_TYPE_NONE, 1, G_TYPE_DATE);
238 }
239
240 GtkWidget *
241 empathy_calendar_button_new (void)
242 {
243   return g_object_new (EMPATHY_TYPE_CALENDAR_BUTTON,
244       "orientation", GTK_ORIENTATION_HORIZONTAL,
245       NULL);
246 }
247
248 GDate *
249 empathy_calendar_button_get_date (EmpathyCalendarButton *self)
250 {
251   return self->priv->date;
252 }
253
254 void
255 empathy_calendar_button_set_date (EmpathyCalendarButton *self,
256     GDate *date)
257 {
258   if (date == self->priv->date)
259     return;
260
261   tp_clear_pointer (&self->priv->date, g_date_free);
262
263   if (date != NULL)
264     {
265       /* There is no g_date_copy()... */
266       self->priv->date = g_date_new_dmy (date->day, date->month, date->year);
267     }
268
269   update_label (self);
270   update_calendar (self);
271
272   g_signal_emit (self, signals[DATE_CHANGED], 0, self->priv->date);
273 }