aboutsummaryrefslogtreecommitdiff
path: root/hildon/hildon-weekday-picker.c
diff options
context:
space:
mode:
Diffstat (limited to 'hildon/hildon-weekday-picker.c')
-rw-r--r--hildon/hildon-weekday-picker.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/hildon/hildon-weekday-picker.c b/hildon/hildon-weekday-picker.c
new file mode 100644
index 0000000..d357c91
--- /dev/null
+++ b/hildon/hildon-weekday-picker.c
@@ -0,0 +1,565 @@
+/*
+ * This file is a part of hildon
+ *
+ * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
+ *
+ * Contact: Rodrigo Novo <rodrigo.novo@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+/**
+ * SECTION:hildon-weekday-picker
+ * @short_description: A widget for picking days on which a certain event
+ * should take place.
+ * @see_also: #HildonWeekdayPicker
+ *
+ * #HildonWeekdayPicker supports non-mutually exclusive selection of days of
+ * the week. Selected days of the week are shown with a pushed-in effect.
+ *
+ * #HildonWeekdayPicker is used where users are required to pick days on which
+ * a certain event should take place, for example, which days a Calendar event
+ * should be repeated on. It is used in Calendar in the Repeat dialog, in Tasks
+ * in the Repeat dialog and in the Email set-up wizard.
+ *
+ * <note>
+ * <para>
+ * #HildonWeekdayPicker has been deprecated since Hildon 2.2 and should not
+ * be used in newly written code. See
+ * <link linkend="hildon-migrating-date-widgets">Migrating Date Widgets</link>
+ * section to know how to migrate this deprecated widget.
+ * </para>
+ * </note>
+ *
+ * <example>
+ * <title>HildonWeekdayPicker example</title>
+ * <programlisting>
+ * gint i;
+ * HildonWeekdayPicker *picker = hildon_weekday_picker_new ();
+ * <!-- -->
+ * hildon_weekday_picker_set_day (picker, i);
+ * hildon_weekday_picker_unset_day (picker, i);
+ * hildon_weekday_picker_toggle_day (picker, i);
+ * hildon_weekday_picker_set_all (picker);
+ * <!-- -->
+ * hildon_weekday_picker_unset_all( picker );
+ * </programlisting>
+ * </example>
+ *
+ */
+
+ /* GDate numbers days from 1 to 7 and G_DATE_MONDAY is 1st day. However
+ according to locale settings first day is sunday. To get around this
+ problem, we addjust GDate days numbering to be same as locale
+ numbering */
+
+#undef HILDON_DISABLE_DEPRECATED
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <langinfo.h>
+#include <time.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "hildon-weekday-picker.h"
+#include "hildon-private.h"
+#include "hildon-weekday-picker-private.h"
+
+static GtkContainerClass* parent_class;
+
+static void
+hildon_weekday_picker_class_init (HildonWeekdayPickerClass *picker_class);
+
+static void
+hildon_weekday_picker_init (HildonWeekdayPicker *picker);
+
+static void
+hildon_weekday_picker_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gboolean
+hildon_weekday_picker_focus (GtkWidget *widget,
+ GtkDirectionType direction);
+static void
+hildon_weekday_picker_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void
+hildon_weekday_picker_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void
+hildon_weekday_picker_destroy (GtkObject *self);
+
+static void
+button_toggle (GtkToggleButton *togglebutton,
+ gpointer wpicker);
+
+enum
+{
+ SELECTION_CHANGED_SIGNAL,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 } ;
+
+/**
+ * hildon_weekday_picker_get_type:
+ *
+ * Initializes and returns the type of a hildon weekday picker.
+ *
+ * Returns: GType of #HildonWeekdayPicker
+ */
+GType G_GNUC_CONST
+hildon_weekday_picker_get_type (void)
+{
+ static GType picker_type = 0;
+
+ if (! picker_type) {
+ static const GTypeInfo picker_info = {
+ sizeof (HildonWeekdayPickerClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) hildon_weekday_picker_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (HildonWeekdayPicker),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) hildon_weekday_picker_init,
+ };
+ picker_type = g_type_register_static (GTK_TYPE_CONTAINER,
+ "HildonWeekdayPicker",
+ &picker_info, 0);
+ }
+
+ return picker_type;
+}
+
+static void
+hildon_weekday_picker_class_init (HildonWeekdayPickerClass *picker_class)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (picker_class);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (picker_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (picker_class);
+
+ parent_class = g_type_class_peek_parent (picker_class);
+
+ g_type_class_add_private (picker_class,
+ sizeof (HildonWeekdayPickerPrivate));
+
+ /* Override virtual methods */
+ widget_class->size_request = hildon_weekday_picker_size_request;
+ widget_class->size_allocate = hildon_weekday_picker_size_allocate;
+ widget_class->focus = hildon_weekday_picker_focus;
+ container_class->forall = hildon_weekday_picker_forall;
+ GTK_OBJECT_CLASS (picker_class)->destroy = hildon_weekday_picker_destroy;
+
+ /* Create a signal for reporting user actions */
+ signals [SELECTION_CHANGED_SIGNAL] = g_signal_new ("selection_changed",
+ G_OBJECT_CLASS_TYPE
+ (object_class),
+ G_SIGNAL_RUN_LAST |
+ G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (HildonWeekdayPickerClass, selection_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+hildon_weekday_picker_init (HildonWeekdayPicker *picker)
+{
+ HildonWeekdayPickerPrivate *priv;
+ gint i, day;
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ /* weekday indexes to be used with nl_langinfo. These are shifted
+ * by one for glib compability */
+ int wdays[] = {
+ -1, /* 0 = invalid date */
+ ABDAY_2, /* 1 = monday in glib */
+ ABDAY_3, /* 2 = tuesday in glib */
+ ABDAY_4, /* 3 = wednesday in glib */
+ ABDAY_5, /* 4 = thursday in glib */
+ ABDAY_6, /* 5 = friday in glib */
+ ABDAY_7, /* 6 = saturday in glib */
+ ABDAY_1 }; /* 7 = sunday in glib */
+ GtkSizeGroup *sgroup;
+
+ sgroup = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
+
+ /* Check our first weekday */
+ day = *nl_langinfo (_NL_TIME_FIRST_WEEKDAY);
+
+
+ /* Shift the days by one. This is done because GDateWeekday
+ * starts with Monday(1) and langinfo's first day is Sunday */
+ day--;
+
+ if (day < 1)
+ day = 7;
+
+ /* Initialize and pack day buttons */
+ for (i = 1; i <= 7; i++) {
+ priv->buttons [i] =
+ gtk_toggle_button_new_with_label (nl_langinfo (wdays[day]));
+ priv->day_order_buttons [day] = priv->buttons [i];
+ day++;
+
+ if (day > 7)
+ day = 1;
+
+ g_signal_connect (GTK_WIDGET (priv->buttons [i]),
+ "toggled", G_CALLBACK (button_toggle), picker);
+
+ gtk_size_group_add_widget (sgroup, priv->buttons [i]);
+
+ gtk_widget_set_parent (priv->buttons [i], GTK_WIDGET (picker));
+ gtk_widget_show (priv->buttons[i]);
+ }
+
+ GTK_WIDGET_SET_FLAGS (picker, GTK_NO_WINDOW);
+
+ g_object_unref (sgroup);
+}
+
+/**
+ * hildon_weekday_picker_new:
+ *
+ * Creates a new #HildonWeekdayPicker.
+ *
+ * Returns: pointer to a new #HildonWeekdayPicker widget.
+ */
+GtkWidget*
+hildon_weekday_picker_new (void)
+{
+ return g_object_new (HILDON_TYPE_WEEKDAY_PICKER, NULL);
+}
+
+static void
+hildon_weekday_picker_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ HildonWeekdayPicker *picker;
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+
+ g_assert (container);
+ g_assert (callback);
+
+ picker = HILDON_WEEKDAY_PICKER (container);
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ /* We only have internal children */
+ if (! include_internals)
+ return;
+
+ /* Activate callback for each day button */
+ for (i = 1; i <= 7; ++i) {
+ (*callback) (priv->buttons [i], callback_data);
+ }
+}
+
+static void
+hildon_weekday_picker_destroy (GtkObject *self)
+{
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (self);
+ g_assert (priv);
+
+ /* Destroy internal children... */
+ for (i = 1; i <= 7; ++i) {
+ if (priv->buttons [i])
+ {
+ gtk_widget_unparent (priv->buttons [i]);
+ priv->buttons [i] = NULL;
+ }
+ }
+
+ /* ... and chain to parent. */
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ GTK_OBJECT_CLASS (parent_class)->destroy (self);
+
+}
+
+static void
+hildon_weekday_picker_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ HildonWeekdayPicker *picker;
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+ GtkRequisition req;
+
+ picker = HILDON_WEEKDAY_PICKER (widget);
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ /* Request an area that is as wide as all of the buttons
+ together and tall enough to hold heightest button */
+ for (i = 1; i <= 7; ++i) {
+ gtk_widget_size_request (priv->buttons [i], &req);
+ requisition->width += req.width;
+ if (req.height > requisition->height)
+ requisition->height = req.height;
+
+ }
+}
+
+static void
+hildon_weekday_picker_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ HildonWeekdayPicker *picker;
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+ GtkAllocation alloc;
+ GtkRequisition child_requisition;
+ gint header_x;
+ guint sval;
+ GtkTextDirection direction;
+
+ g_assert (widget);
+ g_assert (allocation);
+
+ /* Check orientation */
+ direction = gtk_widget_get_direction (widget);
+
+ picker = HILDON_WEEKDAY_PICKER (widget);
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ header_x = allocation->x;
+ widget->allocation = *allocation;
+
+ if (direction == GTK_TEXT_DIR_LTR || direction == GTK_TEXT_DIR_NONE)
+ sval = 1;
+ else
+ sval = 7;
+
+ /* Allocate day buttons side by side honouring the text direction */
+ for (i = 1; i <= 7; ++i) {
+ gtk_widget_get_child_requisition (priv->buttons[sval], &child_requisition);
+
+ alloc.x = header_x;
+ alloc.y = allocation->y;
+ alloc.width = child_requisition.width;
+ alloc.height = child_requisition.height;
+ header_x += alloc.width;
+ gtk_widget_size_allocate (priv->buttons [sval], &alloc);
+ if (direction == GTK_TEXT_DIR_RTL)
+ sval--;
+ else
+ sval++;
+ }
+}
+
+static gboolean
+hildon_weekday_picker_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ gboolean retval;
+ GtkDirectionType effective_direction;
+
+ g_assert (HILDON_IS_WEEKDAY_PICKER (widget));
+
+ retval = hildon_private_composite_focus (widget, direction, &effective_direction);
+
+ if (retval == TRUE)
+ return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction);
+ else
+ return FALSE;
+}
+
+static void
+button_toggle (GtkToggleButton *button,
+ gpointer wpicker)
+{
+ HildonWeekdayPicker *picker;
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+
+ g_assert(button);
+ g_assert(wpicker);
+
+ picker = HILDON_WEEKDAY_PICKER (wpicker);
+ g_assert (picker);
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ for (i = 1; i <= 7; ++i) {
+ if (GTK_WIDGET (button) == priv->day_order_buttons [i]) {
+ g_signal_emit (GTK_WIDGET (picker),
+ signals [SELECTION_CHANGED_SIGNAL], 0, i);
+ break;
+ }
+ }
+}
+
+/**
+ * hildon_weekday_picker_set_day:
+ * @picker: the #HildonWeekdayPicker widget
+ * @day: day to be set active
+ *
+ * Sets specified weekday active.
+ */
+void
+hildon_weekday_picker_set_day (HildonWeekdayPicker *picker,
+ GDateWeekday day)
+{
+ HildonWeekdayPickerPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker));
+ g_return_if_fail (g_date_valid_weekday(day));
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+ (priv->day_order_buttons[day]), TRUE);
+}
+
+/**
+ * hildon_weekday_picker_unset_day:
+ * @picker: the #HildonWeekdayPicker widget
+ * @day: day to be set inactive
+ *
+ * Unselect specified weekday.
+ */
+void
+hildon_weekday_picker_unset_day (HildonWeekdayPicker *picker,
+ GDateWeekday day)
+{
+ HildonWeekdayPickerPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker));
+ g_return_if_fail (g_date_valid_weekday (day));
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON
+ (priv->day_order_buttons [day]), FALSE);
+}
+
+/**
+ * hildon_weekday_picker_toggle_day:
+ * @picker: the #HildonWeekdayPicker widget
+ * @day: day to be toggled
+ *
+ * Toggles current status of the specified weekday.
+ */
+void
+hildon_weekday_picker_toggle_day (HildonWeekdayPicker *picker,
+ GDateWeekday day)
+{
+ HildonWeekdayPickerPrivate *priv;
+
+ g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker));
+ g_return_if_fail (g_date_valid_weekday (day));
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ gtk_toggle_button_set_active (
+ GTK_TOGGLE_BUTTON (priv->day_order_buttons [day]),
+ ! gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON (priv->day_order_buttons[day])));
+}
+
+/**
+ * hildon_weekday_picker_set_all:
+ * @picker: the #HildonWeekdayPicker widget
+ *
+ * Sets all weekdays active.
+ */
+void
+hildon_weekday_picker_set_all (HildonWeekdayPicker *picker)
+{
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+
+ g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker));
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ for (i = 1; i <= 7; i++)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->buttons [i]), TRUE);
+}
+
+/**
+ * hildon_weekday_picker_unset_all:
+ * @picker: the #HildonWeekdayPicker widget
+ *
+ * Sets all weekdays inactive.
+ */
+void
+hildon_weekday_picker_unset_all (HildonWeekdayPicker *picker)
+{
+ HildonWeekdayPickerPrivate *priv;
+ gint i;
+
+ g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker));
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (priv);
+
+ for (i = 1; i <= 7; i++)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->buttons [i]), FALSE);
+}
+
+/**
+ * hildon_weekday_picker_isset_day:
+ * @picker: the #HildonWeekdayPicker widget
+ * @day: day to be checked.
+ *
+ * Checks if the specified weekday is set active.
+ *
+ * Returns: TRUE if the day is set, FALSE if the day is not set
+ */
+gboolean
+hildon_weekday_picker_isset_day (HildonWeekdayPicker *picker,
+ GDateWeekday day)
+{
+ HildonWeekdayPickerPrivate *priv;
+
+ g_return_val_if_fail (HILDON_IS_WEEKDAY_PICKER (picker), FALSE);
+ g_return_val_if_fail (g_date_valid_weekday (day), FALSE);
+
+ priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker);
+ g_assert (picker);
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->day_order_buttons[day]));
+}
+