/* Functions to mark calendars * * Copyright (C) 1998 Red Hat Software, Inc. * * Author: Federico Mena */ #include #include "gnome-cal.h" #include "main.h" #include "mark.h" #include "timeutil.h" /* In the month item, marks all the days that are touched by the specified time span. Assumes that * the time span is completely contained within the month. */ static void mark_event_in_month (GnomeMonthItem *mitem, time_t start, time_t end) { struct tm tm; GnomeCanvasItem *item; int day_index; tm = *localtime (&start); for (; start <= end; start += 60 * 60 * 24) { mktime (&tm); /* normalize the time */ /* Figure out the day index that corresponds to this time */ day_index = gnome_month_item_day2index (mitem, tm.tm_mday); g_assert (day_index >= 0); /* Mark the day box */ item = gnome_month_item_num2child (mitem, GNOME_MONTH_ITEM_DAY_BOX + day_index); gnome_canvas_item_set (item, "fill_color", color_spec_from_prop (COLOR_PROP_MARK_DAY_BG), NULL); /* Next day */ tm.tm_mday++; } } static void mark_current_day (GnomeMonthItem *mitem) { struct tm *tm; time_t t; int day_index; GnomeCanvasItem *item; t = time (NULL); tm = localtime (&t); if (((tm->tm_year + 1900) == mitem->year) && (tm->tm_mon == mitem->month)) { day_index = gnome_month_item_day2index (mitem, tm->tm_mday); item = gnome_month_item_num2child (mitem, GNOME_MONTH_ITEM_DAY_LABEL + day_index); gnome_canvas_item_set (item, "fill_color", color_spec_from_prop (COLOR_PROP_CURRENT_DAY_FG), "font", CURRENT_DAY_FONT, NULL); } } void mark_month_item (GnomeMonthItem *mitem, Calendar *cal) { time_t month_begin, month_end; GList *list, *l; CalendarObject *co; month_begin = time_month_begin (time_from_day (mitem->year, mitem->month, 1)); month_end = time_month_end (month_begin); list = calendar_get_events_in_range (cal, month_begin, month_end); for (l = list; l; l = l->next) { co = l->data; /* We clip the event's start and end times to the month's limits */ mark_event_in_month (mitem, MAX (co->ev_start, month_begin), MIN (co->ev_end, month_end)); } calendar_destroy_event_list (list); mark_current_day (mitem); } void unmark_month_item (GnomeMonthItem *mitem) { g_return_if_fail (mitem != NULL); g_return_if_fail (GNOME_IS_MONTH_ITEM (mitem)); /* We have to do this in several calls to gnome_canvas_item_set(), as color_spec_from_prop() * returns a pointer to a static string -- and we need several values. */ gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem), "heading_color", color_spec_from_prop (COLOR_PROP_HEADING_COLOR), NULL); gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem), "outline_color", color_spec_from_prop (COLOR_PROP_OUTLINE_COLOR), NULL); gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem), "day_box_color", color_spec_from_prop (COLOR_PROP_EMPTY_DAY_BG), NULL); gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem), "day_color", color_spec_from_prop (COLOR_PROP_DAY_FG), NULL); gnome_canvas_item_set (GNOME_CANVAS_ITEM (mitem), "day_font", NORMAL_DAY_FONT, NULL); } /* Frees the prelight information in the month item when it is destroyed */ static void free_prelight_info (GtkObject *object, gpointer data) { g_free (gtk_object_get_data (object, "prelight_info")); } /* Handles EnterNotify and LeaveNotify events from the month item's day groups, and performs * appropriate prelighting. */ static gint day_event (GnomeCanvasItem *item, GdkEvent *event, gpointer data) { GnomeCanvasItem *mitem; GnomeCanvasItem *box; int child_num, day; gulong *day_pixels; GetPrelightColorFunc func; gpointer func_data; char *spec; GdkColor color; mitem = data; child_num = gnome_month_item_child2num (GNOME_MONTH_ITEM (mitem), item); day = gnome_month_item_num2day (GNOME_MONTH_ITEM (mitem), child_num); if (day == 0) return FALSE; /* it was a day outside the month's range */ child_num -= GNOME_MONTH_ITEM_DAY_GROUP; box = gnome_month_item_num2child (GNOME_MONTH_ITEM (mitem), GNOME_MONTH_ITEM_DAY_BOX + child_num); day_pixels = gtk_object_get_data (GTK_OBJECT (mitem), "prelight_info_pixels"); func = gtk_object_get_data (GTK_OBJECT (mitem), "prelight_info_func"); func_data = gtk_object_get_data (GTK_OBJECT (mitem), "prelight_info_data"); switch (event->type) { case GDK_ENTER_NOTIFY: spec = (* func) (func_data); gnome_canvas_item_set (box, "fill_color", spec, NULL); break; case GDK_LEAVE_NOTIFY: color.pixel = day_pixels[child_num]; gnome_canvas_item_set (box, "fill_color_gdk", &color, NULL); break; default: break; } return FALSE; } void month_item_prepare_prelight (GnomeMonthItem *mitem, GetPrelightColorFunc func, gpointer func_data) { gulong *day_pixels; GnomeCanvasItem *day_group; GnomeCanvasItem *box; GtkArg arg; GdkColor *color; int i; day_pixels = gtk_object_get_data (GTK_OBJECT (mitem), "prelight_info_pixels"); /* Set up the buffer for day background colors and attach it to the month item, if necessary */ if (!day_pixels) { /* Create the buffer and attach it */ day_pixels = g_new (gulong, 42); gtk_object_set_data (GTK_OBJECT (mitem), "prelight_info_pixels", day_pixels); gtk_object_set_data (GTK_OBJECT (mitem), "prelight_info_func", func); gtk_object_set_data (GTK_OBJECT (mitem), "prelight_info_data", func_data); gtk_signal_connect (GTK_OBJECT (mitem), "destroy", (GtkSignalFunc) free_prelight_info, NULL); /* Connect the appropriate signals to perform prelighting */ for (i = 0; i < 42; i++) { day_group = gnome_month_item_num2child (GNOME_MONTH_ITEM (mitem), GNOME_MONTH_ITEM_DAY_GROUP + i); gtk_signal_connect (GTK_OBJECT (day_group), "event", (GtkSignalFunc) day_event, mitem); } } /* Fetch the background colors from the day boxes and store them in the prelight info */ for (i = 0; i < 42; i++) { box = gnome_month_item_num2child (mitem, GNOME_MONTH_ITEM_DAY_BOX + i); arg.name = "fill_color_gdk"; gtk_object_getv (GTK_OBJECT (box), 1, &arg); color = GTK_VALUE_BOXED (arg); day_pixels[i] = color->pixel; g_free (color); } } char * default_prelight_func (gpointer data) { return color_spec_from_prop (COLOR_PROP_PRELIGHT_DAY_BG); }