2 * This file is part of hildon-libs
4 * Copyright (C) 2005 Nokia Corporation.
6 * Contact: Luc Pionchon <luc.pionchon@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-weekday-picker
27 * @short_description: A widget for picking days on which a certain event
29 * @see_also: #HildonWeekdayPicker
31 * #HildonWeekdayPicker supports non-mutually exclusive selection of days of
32 * the week. Selected days of the week are shown with a pushed-in effect.
34 * #HildonWeekdayPicker is used where users are required to pick days on which
35 * a certain event should take place, for example, which days a Calendar event
36 * should be repeated on. It is used in Calendar in the Repeat dialog, in Tasks
37 * in the Repeat dialog and in the Email set-up wizard.
40 /* GDate numbers days from 1 to 7 and G_DATE_MONDAY is 1st day. However
41 according to locale settings first day is sunday. To get around this
42 problem, we addjust GDate days numbering to be same as locale
51 #include <sys/types.h>
56 #include <gtk/gtksignal.h>
57 #include <gdk/gdkkeysyms.h>
58 #include <gtk/gtktogglebutton.h>
59 #include <gtk/gtksizegroup.h>
60 #include <gtk/gtkwindow.h>
61 #include "hildon-weekday-picker.h"
62 #include "hildon-composite-widget.h"
64 #define HILDON_WEEKDAY_PICKER_GET_PRIVATE(obj) \
65 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
66 HILDON_WEEKDAY_PICKER_TYPE, HildonWeekdayPickerPrivate));
68 static GtkContainerClass *parent_class;
70 typedef struct _HildonWeekdayPickerPrivate HildonWeekdayPickerPrivate;
73 hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class);
75 hildon_weekday_picker_init(HildonWeekdayPicker * picker);
77 hildon_weekday_picker_size_allocate(GtkWidget * widget,
78 GtkAllocation * allocation);
80 hildon_weekday_picker_size_request(GtkWidget * widget,
81 GtkRequisition * requisition);
83 hildon_weekday_picker_forall(GtkContainer * container,
84 gboolean include_internals,
85 GtkCallback callback, gpointer callback_data);
87 hildon_weekday_picker_destroy(GtkObject * self);
90 button_toggle(GtkToggleButton * togglebutton, gpointer wpicker);
92 struct _HildonWeekdayPickerPrivate {
93 GtkWidget *buttons[8]; /* weekday buttons in show order */
94 GtkWidget *day_order_buttons[8]; /* weekday buttons in glib day order */
98 SELECTION_CHANGED_SIGNAL,
102 static guint signals[LAST_SIGNAL] = { 0 };
104 GType hildon_weekday_picker_get_type(void)
106 static GType picker_type = 0;
109 static const GTypeInfo picker_info = {
110 sizeof(HildonWeekdayPickerClass),
111 NULL, /* base_init */
112 NULL, /* base_finalize */
113 (GClassInitFunc) hildon_weekday_picker_class_init,
114 NULL, /* class_finalize */
115 NULL, /* class_data */
116 sizeof(HildonWeekdayPicker),
118 (GInstanceInitFunc) hildon_weekday_picker_init,
120 picker_type = g_type_register_static(GTK_TYPE_CONTAINER,
121 "HildonWeekdayPicker",
128 hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class)
130 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(picker_class);
131 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(picker_class);
132 GObjectClass *object_class = G_OBJECT_CLASS(picker_class);
134 parent_class = g_type_class_peek_parent(picker_class);
136 g_type_class_add_private(picker_class,
137 sizeof(HildonWeekdayPickerPrivate));
139 /* Override virtual methods */
140 widget_class->size_request = hildon_weekday_picker_size_request;
141 widget_class->size_allocate = hildon_weekday_picker_size_allocate;
142 widget_class->focus = hildon_composite_widget_focus;
143 container_class->forall = hildon_weekday_picker_forall;
144 GTK_OBJECT_CLASS(picker_class)->destroy =
145 hildon_weekday_picker_destroy;
147 /* Create a signal for reporting user actions */
148 signals[SELECTION_CHANGED_SIGNAL] = g_signal_new("selection_changed",
154 (HildonWeekdayPickerClass,
155 selection_changed), NULL, NULL,
156 gtk_marshal_VOID__INT,
157 G_TYPE_NONE, 1, G_TYPE_INT);
161 hildon_weekday_picker_init(HildonWeekdayPicker * picker)
163 HildonWeekdayPickerPrivate *priv;
165 /* weekday indexes to be used with nl_langinfo. These are shifted
166 * by one for glib compability */
168 -1, /* 0 = invalid date */
169 ABDAY_2, /* 1 = monday in glib */
170 ABDAY_3, /* 2 = tuesday in glib */
171 ABDAY_4, /* 3 = wednesday in glib */
172 ABDAY_5, /* 4 = thursday in glib */
173 ABDAY_6, /* 5 = friday in glib */
174 ABDAY_7, /* 6 = saturday in glib */
175 ABDAY_1 }; /* 7 = sunday in glib */
176 GtkSizeGroup *sgroup;
178 sgroup = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
180 /* Check our first weekday */
181 day = *nl_langinfo(_NL_TIME_FIRST_WEEKDAY);
183 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
185 /* Shift the days by one. This is done because GDateWeekday
186 * starts with Monday(1) and langinfo's first day is Sunday */
191 /* Initialize and pack day buttons */
192 for (i = 1; i <= 7; i++) {
194 gtk_toggle_button_new_with_label(nl_langinfo(wdays[day]));
195 priv->day_order_buttons[day] = priv->buttons[i];
201 g_signal_connect(GTK_WIDGET(priv->buttons[i]),
202 "toggled", G_CALLBACK(button_toggle), picker);
204 gtk_size_group_add_widget(sgroup, priv->buttons[i]);
206 gtk_widget_set_parent(priv->buttons[i], GTK_WIDGET(picker));
207 gtk_widget_show(priv->buttons[i]);
210 GTK_WIDGET_SET_FLAGS(picker, GTK_NO_WINDOW);
212 g_object_unref( sgroup );
216 * hildon_weekday_picker_new:
218 * Creates a new #HildonWeekdayPicker.
220 * Returns: pointer to a new #HildonWeekdayPicker widget.
222 GtkWidget *hildon_weekday_picker_new(void)
224 return g_object_new(HILDON_WEEKDAY_PICKER_TYPE, NULL);
228 hildon_weekday_picker_forall(GtkContainer * container,
229 gboolean include_internals, GtkCallback callback,
230 gpointer callback_data)
232 HildonWeekdayPicker *picker;
233 HildonWeekdayPickerPrivate *priv;
239 picker = HILDON_WEEKDAY_PICKER(container);
240 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
242 /* We only have internal children */
243 if (!include_internals)
246 /* Activate callback for each day button */
247 for (i = 1; i <= 7; ++i) {
248 (*callback) (priv->buttons[i], callback_data);
254 hildon_weekday_picker_destroy(GtkObject * self)
256 HildonWeekdayPickerPrivate *priv;
259 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(self);
261 /* Destroy internal children... */
262 for (i = 1; i <= 7; ++i) {
263 if (priv->buttons[i])
265 gtk_widget_unparent(priv->buttons[i]);
266 priv->buttons[i] = NULL;
270 /* ... and chain to parent. */
271 if (GTK_OBJECT_CLASS(parent_class)->destroy)
272 GTK_OBJECT_CLASS(parent_class)->destroy(self);
277 hildon_weekday_picker_size_request(GtkWidget * widget,
278 GtkRequisition *requisition)
280 HildonWeekdayPicker *picker;
281 HildonWeekdayPickerPrivate *priv;
285 picker = HILDON_WEEKDAY_PICKER(widget);
286 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
287 requisition->width = 0;
288 requisition->height = 0;
290 /* Request an area that is as wide as all of the buttons
291 together and tall enough to hold heightest button */
292 for (i = 1; i <= 7; ++i) {
293 gtk_widget_size_request(priv->buttons[i], &req);
294 requisition->width += req.width;
295 if (req.height > requisition->height)
296 requisition->height = req.height;
302 hildon_weekday_picker_size_allocate(GtkWidget * widget,
303 GtkAllocation * allocation)
305 HildonWeekdayPicker *picker;
306 HildonWeekdayPickerPrivate *priv;
309 GtkRequisition child_requisition;
312 GtkTextDirection direction;
315 g_assert(allocation);
317 /* Check orientation */
318 direction = gtk_widget_get_direction(widget);
320 picker = HILDON_WEEKDAY_PICKER(widget);
321 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
322 header_x = allocation->x;
323 widget->allocation = *allocation;
325 if (direction == GTK_TEXT_DIR_LTR || direction == GTK_TEXT_DIR_NONE)
330 /* Allocate day buttons side by side honouring the text direction */
331 for (i = 1; i <= 7; ++i) {
332 gtk_widget_get_child_requisition(priv->buttons[sval],
336 alloc.y = allocation->y;
337 alloc.width = child_requisition.width;
338 alloc.height = child_requisition.height;
339 header_x += alloc.width;
340 gtk_widget_size_allocate(priv->buttons[sval], &alloc);
341 if (direction == GTK_TEXT_DIR_RTL)
349 button_toggle(GtkToggleButton * button, gpointer wpicker)
351 HildonWeekdayPicker *picker;
352 HildonWeekdayPickerPrivate *priv;
358 picker = HILDON_WEEKDAY_PICKER(wpicker);
359 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
361 for (i = 1; i <= 7; ++i) {
362 if (GTK_WIDGET(button) == priv->day_order_buttons[i]) {
363 g_signal_emit (GTK_WIDGET(picker),
364 signals[SELECTION_CHANGED_SIGNAL], 0, i);
371 * hildon_weekday_picker_set_day:
372 * @picker: the #HildonWeekdayPicker widget
373 * @day: day to be set active
375 * Sets specified weekday active.
378 hildon_weekday_picker_set_day(HildonWeekdayPicker * picker,
381 HildonWeekdayPickerPrivate *priv;
383 g_return_if_fail(picker);
384 g_return_if_fail(g_date_valid_weekday(day));
386 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
388 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
389 (priv->day_order_buttons[day]), TRUE);
393 * hildon_weekday_picker_unset_day:
394 * @picker: the #HildonWeekdayPicker widget
395 * @day: day to be set inactive
397 * Sets specified weekday inactive.
400 hildon_weekday_picker_unset_day(HildonWeekdayPicker * picker,
403 HildonWeekdayPickerPrivate *priv;
405 g_return_if_fail(picker);
406 g_return_if_fail(g_date_valid_weekday(day));
408 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
410 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON
411 (priv->day_order_buttons[day]), FALSE);
415 * hildon_weekday_picker_toggle_day:
416 * @picker: the #HildonWeekdayPicker widget
417 * @day: day to be toggled
419 * Toggles current status of the specified weekday.
422 hildon_weekday_picker_toggle_day(HildonWeekdayPicker * picker,
425 HildonWeekdayPickerPrivate *priv;
427 g_return_if_fail(picker);
428 g_return_if_fail(g_date_valid_weekday(day));
430 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
432 gtk_toggle_button_set_active(
433 GTK_TOGGLE_BUTTON(priv->day_order_buttons[day]),
434 !gtk_toggle_button_get_active(
435 GTK_TOGGLE_BUTTON(priv->day_order_buttons[day])));
439 * hildon_weekday_picker_set_all:
440 * @picker: the #HildonWeekdayPicker widget
442 * Sets all weekdays active.
445 hildon_weekday_picker_set_all(HildonWeekdayPicker * picker)
447 HildonWeekdayPickerPrivate *priv;
450 g_return_if_fail(picker);
452 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
454 for (i = 1; i <= 7; i++)
455 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]),
460 * hildon_weekday_picker_unset_all:
461 * @picker: the #HildonWeekdayPicker widget
463 * Sets all weekdays inactive.
466 hildon_weekday_picker_unset_all(HildonWeekdayPicker * picker)
468 HildonWeekdayPickerPrivate *priv;
471 g_return_if_fail(picker);
473 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
475 for (i = 1; i <= 7; i++)
476 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]),
481 * hildon_weekday_picker_isset_day:
482 * @picker: the #HildonWeekdayPicker widget
483 * @day: day to be checked.
485 * Checks if the specified weekday is set active.
487 * Returns: TRUE if the day is set, FALSE if the day is not set
490 hildon_weekday_picker_isset_day(HildonWeekdayPicker * picker,
493 HildonWeekdayPickerPrivate *priv;
495 g_return_val_if_fail(picker, FALSE);
496 g_return_val_if_fail(g_date_valid_weekday(day), FALSE);
498 priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker);
500 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
501 priv->day_order_buttons[day]));