diff options
Diffstat (limited to 'src/idocalendarmenuitem.c')
-rw-r--r-- | src/idocalendarmenuitem.c | 255 |
1 files changed, 248 insertions, 7 deletions
diff --git a/src/idocalendarmenuitem.c b/src/idocalendarmenuitem.c index baae342..94f4f61 100644 --- a/src/idocalendarmenuitem.c +++ b/src/idocalendarmenuitem.c @@ -24,6 +24,7 @@ */ #include <gdk/gdkkeysyms.h> +#include "idoactionhelper.h" #include "idocalendarmenuitem.h" #include "config.h" @@ -324,21 +325,44 @@ calendar_day_selected_double_click_cb (GtkWidget *widget, g_signal_emit_by_name (item, "day-selected-double-click", NULL); } -/* Public API */ +/** + * ido_calendar_menu_item_new: + * + * Creates a new #IdoCalendarMenuItem + * + * Return Value: a new #IdoCalendarMenuItem. + **/ GtkWidget * ido_calendar_menu_item_new (void) { return g_object_new (IDO_TYPE_CALENDAR_MENU_ITEM, NULL); } +/** + * ido_calendar_menu_item_get_calendar: + * @menuitem: A #IdoCalendarMenuItem + * + * Returns the calendar associated with this menu item. + * + * Return Value: (transfer none): The #GtkCalendar used in this item. + */ GtkWidget * -ido_calendar_menu_item_get_calendar (IdoCalendarMenuItem *item) +ido_calendar_menu_item_get_calendar (IdoCalendarMenuItem *menuitem) { - g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM (item), NULL); + g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM (menuitem), NULL); - return item->priv->calendar; + return menuitem->priv->calendar; } +/** + * ido_calendar_menu_item_mark_day: + * @menuitem: A #IdoCalendarMenuItem + * @day: the day number to unmark between 1 and 31. + * + * Places a visual marker on a particular day. + * + * Return Value: #TRUE + */ gboolean ido_calendar_menu_item_mark_day (IdoCalendarMenuItem *menuitem, guint day) { @@ -348,6 +372,15 @@ ido_calendar_menu_item_mark_day (IdoCalendarMenuItem *menuitem, guint day) return TRUE; } +/** + * ido_calendar_menu_item_unmark_day: + * @menuitem: A #IdoCalendarMenuItem + * @day: the day number to unmark between 1 and 31. + * + * Removes the visual marker from a particular day. + * + * Return Value: #TRUE + */ gboolean ido_calendar_menu_item_unmark_day (IdoCalendarMenuItem *menuitem, guint day) { @@ -357,6 +390,12 @@ ido_calendar_menu_item_unmark_day (IdoCalendarMenuItem *menuitem, guint day) return TRUE; } +/** + * ido_calendar_menu_item_clear_marks: + * @menuitem: A #IdoCalendarMenuItem + * + * Remove all visual markers. + */ void ido_calendar_menu_item_clear_marks (IdoCalendarMenuItem *menuitem) { @@ -365,6 +404,13 @@ ido_calendar_menu_item_clear_marks (IdoCalendarMenuItem *menuitem) gtk_calendar_clear_marks(GTK_CALENDAR (menuitem->priv->calendar)); } +/** + * ido_calendar_menu_item_set_display_options: + * @menuitem: A #IdoCalendarMenuItem + * @flags: the display options to set + * + * Set the display options for the calendar. + */ void ido_calendar_menu_item_set_display_options (IdoCalendarMenuItem *menuitem, GtkCalendarDisplayOptions flags) { @@ -373,6 +419,14 @@ ido_calendar_menu_item_set_display_options (IdoCalendarMenuItem *menuitem, GtkCa gtk_calendar_set_display_options (GTK_CALENDAR (menuitem->priv->calendar), flags); } +/** + * ido_calendar_menu_item_get_display_options: + * @menuitem: A #IdoCalendarMenuItem + * + * Get the display options for the calendar. + * + * Return Value: the display options in use + */ GtkCalendarDisplayOptions ido_calendar_menu_item_get_display_options (IdoCalendarMenuItem *menuitem) { @@ -381,6 +435,15 @@ ido_calendar_menu_item_get_display_options (IdoCalendarMenuItem *menuitem) return gtk_calendar_get_display_options (GTK_CALENDAR (menuitem->priv->calendar)); } +/** + * ido_calendar_menu_item_get_date: + * @menuitem: A #IdoCalendarMenuItem + * @year: (out) (allow-none): location to store the year as a decimal number (e.g. 2011), or #NULL. + * @month: (out) (allow-none): location to store the month number (between 0 and 11), or #NULL. + * @day: (out) (allow-none): location to store the day number (between 1 and 31), or #NULL. + * + * Gets the selected date. + */ void ido_calendar_menu_item_get_date (IdoCalendarMenuItem *menuitem, guint *year, @@ -391,17 +454,195 @@ ido_calendar_menu_item_get_date (IdoCalendarMenuItem *menuitem, gtk_calendar_get_date (GTK_CALENDAR (menuitem->priv->calendar), year, month, day); } +/** + * ido_calendar_menu_item_set_date: + * @menuitem: A #IdoCalendarMenuItem + * @year: the year to show (e.g. 2011). + * @month: a month number (between 0 and 11). + * @day: The day number (between 1 and 31). + * + * Set the date shown on the calendar. + * + * Return Value: #TRUE + */ gboolean ido_calendar_menu_item_set_date (IdoCalendarMenuItem *menuitem, guint year, guint month, guint day) { - g_return_val_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem), FALSE); - gtk_calendar_select_month (GTK_CALENDAR (menuitem->priv->calendar), month, year); - gtk_calendar_select_day (GTK_CALENDAR (menuitem->priv->calendar), day); + guint old_y, old_m, old_d; + + g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM(menuitem), FALSE); + + ido_calendar_menu_item_get_date (menuitem, &old_y, &old_m, &old_d); + + if ((old_y != year) || (old_m != month)) + gtk_calendar_select_month (GTK_CALENDAR (menuitem->priv->calendar), month, year); + + if (old_d != day) + gtk_calendar_select_day (GTK_CALENDAR (menuitem->priv->calendar), day); + return TRUE; } +/*** +**** +**** +**** +***/ + +static void +activate_current_day (IdoCalendarMenuItem * ido_calendar, + const char * action_name_key) +{ + GObject * o; + const char * action_name; + GActionGroup * action_group; + + o = G_OBJECT (ido_calendar); + action_name = g_object_get_data (o, action_name_key); + action_group = g_object_get_data (o, "ido-action-group"); + + if (action_group && action_name) + { + guint y, m, d; + GDateTime * date_time; + GVariant * target; + + ido_calendar_menu_item_get_date (ido_calendar, &y, &m, &d); + m++; /* adjust month from GtkCalendar (0 based) to GDateTime (1 based) */ + date_time = g_date_time_new_local (y, m, d, 9, 0, 0); + target = g_variant_new_int64 (g_date_time_to_unix (date_time)); + + g_action_group_activate_action (action_group, action_name, target); + + g_date_time_unref (date_time); + } +} + +static void +on_day_selected (IdoCalendarMenuItem * ido_calendar) +{ + activate_current_day (ido_calendar, "ido-selection-action-name"); +} + +static void +on_day_double_clicked (IdoCalendarMenuItem * ido_calendar) +{ + activate_current_day (ido_calendar, "ido-activation-action-name"); +} + +static void +on_action_state_changed (IdoActionHelper * helper, + GVariant * state, + gpointer unused G_GNUC_UNUSED) +{ + GVariant * v; + const char * key; + IdoCalendarMenuItem * ido_calendar; + ido_calendar = IDO_CALENDAR_MENU_ITEM (ido_action_helper_get_widget (helper)); + + g_return_if_fail (ido_calendar != NULL); + g_return_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE_DICTIONARY)); + + /* an int64 representing a time_t indicating which year and month should + be visible in the calendar and which day should be given the cursor. */ + key = "calendar-day"; + if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE_INT64))) + { + int y, m, d; + time_t t; + GDateTime * date_time; + + t = g_variant_get_int64 (v); + date_time = g_date_time_new_from_unix_local (t); + g_date_time_get_ymd (date_time, &y, &m, &d); + m--; /* adjust month from GDateTime (1 based) to GtkCalendar (0 based) */ + ido_calendar_menu_item_set_date (ido_calendar, y, m, d); + + g_date_time_unref (date_time); + g_variant_unref (v); + } + /* a boolean value of whether or not to show the week numbers */ + key = "show-week-numbers"; + if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE_BOOLEAN))) + { + const GtkCalendarDisplayOptions old_flags = ido_calendar_menu_item_get_display_options (ido_calendar); + GtkCalendarDisplayOptions new_flags = old_flags; + + if (g_variant_get_boolean (v)) + new_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; + else + new_flags &= ~GTK_CALENDAR_SHOW_WEEK_NUMBERS; + + if (new_flags != old_flags) + ido_calendar_menu_item_set_display_options (ido_calendar, new_flags); + + g_variant_unref (v); + } + + /* an array of int32 day-of-months denoting days that have appointments */ + key = "appointment-days"; + ido_calendar_menu_item_clear_marks (ido_calendar); + if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE("ai")))) + { + gint32 day; + GVariantIter iter; + + g_variant_iter_init (&iter, v); + while (g_variant_iter_next (&iter, "i", &day)) + ido_calendar_menu_item_mark_day (ido_calendar, day); + + g_variant_unref (v); + } +} + +GtkMenuItem * +ido_calendar_menu_item_new_from_model (GMenuItem * menu_item, + GActionGroup * actions) +{ + GObject * o; + GtkWidget * calendar; + IdoCalendarMenuItem * ido_calendar; + gchar * selection_action_name; + gchar * activation_action_name; + + /* get the select & activate action names */ + g_menu_item_get_attribute (menu_item, "action", "s", &selection_action_name); + g_menu_item_get_attribute (menu_item, "activation-action", "s", &activation_action_name); + + /* remember the action group & action names so that we can poke them + when user selects and double-clicks */ + ido_calendar = IDO_CALENDAR_MENU_ITEM (ido_calendar_menu_item_new ()); + o = G_OBJECT (ido_calendar); + g_object_set_data_full (o, "ido-action-group", g_object_ref(actions), g_object_unref); + g_object_set_data_full (o, "ido-selection-action-name", selection_action_name, g_free); + g_object_set_data_full (o, "ido-activation-action-name", activation_action_name, g_free); + calendar = ido_calendar_menu_item_get_calendar (ido_calendar); + g_signal_connect_swapped (calendar, "day-selected", + G_CALLBACK(on_day_selected), ido_calendar); + g_signal_connect_swapped (calendar, "day-selected-double-click", + G_CALLBACK(on_day_double_clicked), ido_calendar); + + /* Use an IdoActionHelper for state updates. + Since we have two separate actions for selection & activation, + we'll do the activation & targets logic here in ido-calendar */ + if (selection_action_name != NULL) + { + IdoActionHelper * helper; + + helper = ido_action_helper_new (GTK_WIDGET(ido_calendar), + actions, + selection_action_name, + NULL); + g_signal_connect (helper, "action-state-changed", + G_CALLBACK (on_action_state_changed), NULL); + g_signal_connect_swapped (ido_calendar, "destroy", + G_CALLBACK (g_object_unref), helper); + } + + return GTK_MENU_ITEM (ido_calendar); +} |