]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-calendar-button.c
Merge branch 'gnome-3-6'
[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
22 #include <glib/gi18n-lib.h>
23
24 #include "empathy-calendar-button.h"
25
26 #include <libempathy/empathy-utils.h>
27
28 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER_THING
29 #include <libempathy/empathy-debug.h>
30
31 G_DEFINE_TYPE (EmpathyCalendarButton, empathy_calendar_button, GTK_TYPE_BOX)
32
33 /* signal enum */
34 enum {
35   DATE_CHANGED,
36   LAST_SIGNAL,
37 };
38
39 static guint signals[LAST_SIGNAL] = {0};
40
41 struct _EmpathyCalendarButtonPriv {
42   GDate *date;
43
44   GtkWidget *button_date;
45   GtkWidget *button_clear;
46   GtkWidget *dialog;
47   GtkWidget *calendar;
48 };
49
50 static void
51 empathy_calendar_button_finalize (GObject *object)
52 {
53   EmpathyCalendarButton *self = (EmpathyCalendarButton *) object;
54
55   tp_clear_pointer (&self->priv->date, g_date_free);
56
57   G_OBJECT_CLASS (empathy_calendar_button_parent_class)->finalize (object);
58 }
59
60 static void
61 update_label (EmpathyCalendarButton *self)
62 {
63   if (self->priv->date == NULL)
64     {
65       gtk_button_set_label (GTK_BUTTON (self->priv->button_date),
66           _("Select..."));
67     }
68   else
69     {
70       gchar buffer[128];
71
72       g_date_strftime (buffer, 128, "%e %b %Y", self->priv->date);
73       gtk_button_set_label (GTK_BUTTON (self->priv->button_date), buffer);
74     }
75 }
76
77 static void
78 empathy_calendar_button_constructed (GObject *object)
79 {
80   EmpathyCalendarButton *self = (EmpathyCalendarButton *) object;
81
82   G_OBJECT_CLASS (empathy_calendar_button_parent_class)->constructed (
83       object);
84
85   update_label (self);
86 }
87
88 static void
89 dialog_response (GtkDialog *dialog,
90     gint response,
91     EmpathyCalendarButton *self)
92 {
93   GDate *date;
94   guint year, month, day;
95
96   if (response != GTK_RESPONSE_OK)
97     goto out;
98
99   gtk_calendar_get_date (GTK_CALENDAR (self->priv->calendar),
100       &year, &month, &day);
101   date = g_date_new_dmy (day, month + 1, year);
102
103   empathy_calendar_button_set_date (self, date);
104
105   g_date_free (date);
106
107 out:
108   gtk_widget_hide (GTK_WIDGET (dialog));
109 }
110
111 static gboolean
112 dialog_destroy (GtkWidget *widget,
113     EmpathyCalendarButton *self)
114 {
115   self->priv->dialog = NULL;
116   self->priv->calendar = NULL;
117
118   return FALSE;
119 }
120
121 static void
122 update_calendar (EmpathyCalendarButton *self)
123 {
124   if (self->priv->calendar == NULL)
125     return;
126
127   gtk_calendar_clear_marks (GTK_CALENDAR (self->priv->calendar));
128
129   if (self->priv->date == NULL)
130     return;
131
132   gtk_calendar_select_day (GTK_CALENDAR (self->priv->calendar),
133       g_date_get_day (self->priv->date));
134   gtk_calendar_select_month (GTK_CALENDAR (self->priv->calendar),
135       g_date_get_month (self->priv->date) - 1,
136       g_date_get_year (self->priv->date));
137   gtk_calendar_mark_day (GTK_CALENDAR (self->priv->calendar),
138       g_date_get_day (self->priv->date));
139 }
140
141 static void
142 empathy_calendar_button_date_clicked (GtkButton *button,
143     EmpathyCalendarButton *self)
144 {
145   if (self->priv->dialog == NULL)
146     {
147       GtkWidget *parent, *content;
148
149       parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
150
151       self->priv->dialog = gtk_dialog_new_with_buttons (NULL,
152           GTK_WINDOW (parent), GTK_DIALOG_MODAL,
153           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
154           _("_Select"), GTK_RESPONSE_OK,
155           NULL);
156
157       gtk_window_set_transient_for (GTK_WINDOW (self->priv->dialog),
158           GTK_WINDOW (parent));
159
160       self->priv->calendar = gtk_calendar_new ();
161
162       update_calendar (self);
163
164       content = gtk_dialog_get_content_area (GTK_DIALOG (self->priv->dialog));
165
166       gtk_box_pack_start (GTK_BOX (content), self->priv->calendar, TRUE, TRUE,
167           6);
168       gtk_widget_show (self->priv->calendar);
169
170       g_signal_connect (self->priv->dialog, "response",
171           G_CALLBACK (dialog_response), self);
172       g_signal_connect (self->priv->dialog, "destroy",
173           G_CALLBACK (dialog_destroy), self);
174     }
175
176   gtk_window_present (GTK_WINDOW (self->priv->dialog));
177 }
178
179 static void
180 empathy_calendar_button_clear_clicked (GtkButton *button,
181     EmpathyCalendarButton *self)
182 {
183   empathy_calendar_button_set_date (self, NULL);
184 }
185
186 static void
187 empathy_calendar_button_init (EmpathyCalendarButton *self)
188 {
189   GtkWidget *image;
190   GtkStyleContext *context;
191
192   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
193       EMPATHY_TYPE_CALENDAR_BUTTON, EmpathyCalendarButtonPriv);
194
195   context = gtk_widget_get_style_context (GTK_WIDGET (self));
196   gtk_style_context_add_class (context, GTK_STYLE_CLASS_LINKED);
197
198   /* Date */
199   self->priv->button_date = gtk_button_new ();
200
201   g_signal_connect (self->priv->button_date, "clicked",
202       G_CALLBACK (empathy_calendar_button_date_clicked), self);
203
204   gtk_button_set_alignment (GTK_BUTTON (self->priv->button_date), 0, 0.5);
205
206   gtk_box_pack_start (GTK_BOX (self), self->priv->button_date, TRUE, TRUE, 0);
207   gtk_widget_show (self->priv->button_date);
208
209   /* Clear */
210   self->priv->button_clear = gtk_button_new ();
211
212   image = gtk_image_new_from_stock (GTK_STOCK_CLEAR,
213       GTK_ICON_SIZE_MENU);
214   gtk_button_set_image (GTK_BUTTON (self->priv->button_clear), image);
215   gtk_widget_show (image);
216
217   g_signal_connect (self->priv->button_clear, "clicked",
218       G_CALLBACK (empathy_calendar_button_clear_clicked), self);
219
220   gtk_box_pack_start (GTK_BOX (self), self->priv->button_clear,
221       FALSE, FALSE, 0);
222   gtk_widget_show (self->priv->button_clear);
223 }
224
225 static void
226 empathy_calendar_button_class_init (EmpathyCalendarButtonClass *klass)
227 {
228   GObjectClass *oclass = G_OBJECT_CLASS (klass);
229
230   g_type_class_add_private (klass, sizeof (EmpathyCalendarButtonPriv));
231
232   oclass->finalize = empathy_calendar_button_finalize;
233   oclass->constructed = empathy_calendar_button_constructed;
234
235   signals[DATE_CHANGED] = g_signal_new ("date-changed",
236       G_TYPE_FROM_CLASS (klass),
237       G_SIGNAL_RUN_LAST, 0,
238       NULL, NULL,
239       g_cclosure_marshal_generic,
240       G_TYPE_NONE, 1, G_TYPE_DATE);
241 }
242
243 GtkWidget *
244 empathy_calendar_button_new (void)
245 {
246   return g_object_new (EMPATHY_TYPE_CALENDAR_BUTTON,
247       "orientation", GTK_ORIENTATION_HORIZONTAL,
248       NULL);
249 }
250
251 GDate *
252 empathy_calendar_button_get_date (EmpathyCalendarButton *self)
253 {
254   return self->priv->date;
255 }
256
257 void
258 empathy_calendar_button_set_date (EmpathyCalendarButton *self,
259     GDate *date)
260 {
261   if (date == self->priv->date)
262     return;
263
264   tp_clear_pointer (&self->priv->date, g_date_free);
265
266   if (date != NULL)
267     {
268       /* There is no g_date_copy()... */
269       self->priv->date = g_date_new_dmy (date->day, date->month, date->year);
270     }
271
272   update_label (self);
273   update_calendar (self);
274
275   g_signal_emit (self, signals[DATE_CHANGED], 0, self->priv->date);
276 }