diff options
Diffstat (limited to 'calendar/gui')
-rw-r--r-- | calendar/gui/Makefile.am | 6 | ||||
-rw-r--r-- | calendar/gui/layout.c | 309 | ||||
-rw-r--r-- | calendar/gui/layout.h | 56 | ||||
-rw-r--r-- | calendar/gui/print.c | 270 |
4 files changed, 166 insertions, 475 deletions
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 93e4c928f1..3d92a30ae4 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -42,6 +42,8 @@ glade_DATA = \ glade_messages = event-editor-dialog.glade.h evolution_calendar_SOURCES = \ + print.c \ + print.h \ alarm.c \ alarm.h \ calendar-commands.c \ @@ -80,15 +82,11 @@ evolution_calendar_SOURCES = \ gnome-cal.c \ gnome-cal.h \ goto.c \ - layout.c \ - layout.h \ main.c \ mark.c \ mark.h \ popup-menu.c \ popup-menu.h \ - print.c \ - print.h \ prop.c evolution_calendar_LDADD = \ diff --git a/calendar/gui/layout.c b/calendar/gui/layout.c deleted file mode 100644 index c8dfde6bdb..0000000000 --- a/calendar/gui/layout.c +++ /dev/null @@ -1,309 +0,0 @@ -/* Evolution calendar - Event layout engine - * - * Copyright (C) 2000 Helix Code, Inc. - * - * Authors: Miguel de Icaza <miguel@helixcode.com> - * Federico Mena-Quintero <federico@helixcode.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include <stdlib.h> -#include "layout.h" - - - -/* This structure is used to pass around layout information among the internal - * layout functions. - */ -struct layout_info { - GList *events; /* List of events from client */ - int num_events; /* The number of events (length of the list) */ - LayoutQueryTimeFunc func; /* Function to convert a list item to a start/end time pair */ - int num_rows; /* Size of the time partition */ - time_t *partition; /* The time partition containing start and end time values */ - int *array; /* Working array of free and allocated time slots */ - int *allocations; /* Returned array of slot allocations */ - int *slots; /* Returned array of slots used */ - int num_slots; /* Number of slots used */ -}; - - - -/* This defines the maximum number of events to overlap per row. More than that - * number of events will not be displayed. This is not ideal, so sue me. - */ -#define MAX_EVENTS_PER_ROW 32 - - -/* Compares two time_t values, used for qsort() */ -static int -compare_time_t (const void *a, const void *b) -{ - time_t ta, tb; - - ta = *((time_t *) a); - tb = *((time_t *) b); - - if (ta < tb) - return -1; - else if (ta > tb) - return 1; - else - return 0; -} - -/* Builds a partition of the time range occupied by the events in the list. It returns an array - * with the times that define the partition and the number of items in the partition. - */ -static void -build_partition (struct layout_info *li) -{ - time_t *rows, *p, *q; - GList *list; - int i, unique_vals; - - /* This is the maximum number of rows we would need */ - - li->num_rows = li->num_events * 2; - - /* Fill the rows with the times */ - - rows = g_new (time_t, li->num_rows); - - for (list = li->events, p = rows; list; list = list->next) { - (* li->func) (list, &p[0], &p[1]); - p += 2; - } - - /* Do a sort | uniq on the array */ - - qsort (rows, li->num_rows, sizeof (time_t), compare_time_t); - - p = rows; - q = rows + 1; - unique_vals = 1; - - for (i = 1; i < li->num_rows; i++, q++) - if (*q != *p) { - unique_vals++; - p++; - *p = *q; - } - - /* Return the number of unique values in the partition and the partition array itself */ - - li->num_rows = unique_vals; - li->partition = rows; -} - -/* Returns the index of the element in the partition that corresponds to the specified time */ -static int -find_index (struct layout_info *li, time_t t) -{ - int i; - - for (i = 0; ; i++) - if (li->partition[i] == t) - return i; - - g_assert_not_reached (); -} - -#define xy(li, x, y) li->array[(y * MAX_EVENTS_PER_ROW) + (x)] - -/* Checks that all the cells in the slot array at the specified slot column are free to use by an - * event that has the specified range. - */ -static int -range_is_empty (struct layout_info *li, int slot, time_t start, time_t end) -{ - int i; - - for (i = find_index (li, start); li->partition[i] < end; i++) - if (xy (li, slot, i) != -1) - return FALSE; - - return TRUE; -} - -/* Allocates a time in the slot array for the specified event's index */ -static void -range_allocate (struct layout_info *li, int slot, time_t start, time_t end, int ev_num) -{ - int i; - - for (i = find_index (li, start); li->partition[i] < end; i++) - xy (li, slot, i) = ev_num; -} - -/* Performs the initial allocation of slots for events. Each event gets one column; they will be - * expanded in a later stage. Returns the number of columns used. - */ -static void -initial_allocate (struct layout_info *li) -{ - GList *events; - int i; - int slot; - int num_slots; - time_t start, end; - - num_slots = 0; - - for (i = 0, events = li->events; events; events = events->next, i++) { - (* li->func) (events, &start, &end); - - /* Start with no allocation, no columns */ - - li->allocations[i] = -1; - li->slots[i] = 0; - - /* Find a free column for the event */ - - for (slot = 0; slot < MAX_EVENTS_PER_ROW; slot++) - if (range_is_empty (li, slot, start, end)) { - range_allocate (li, slot, start, end, i); - - li->allocations[i] = slot; - li->slots[i] = 1; - - if ((slot + 1) > num_slots) - num_slots = slot + 1; - - break; - } - } - - li->num_slots = num_slots; -} - -/* Returns the maximum number of columns that an event can expanded by in the slot array */ -static int -columns_to_expand (struct layout_info *li, int ev_num, time_t start, time_t end) -{ - int cols; - int slot; - int i_start; - int i; - - cols = 0; - - i_start = find_index (li, start); - - for (slot = li->allocations[ev_num] + 1; slot < li->num_slots; slot++) { - for (i = i_start; li->partition[i] < end; i++) - if (xy (li, slot, i) != -1) - return cols; - - cols++; - } - - return cols; -} - -/* Expands an event by the specified number of columns */ -static void -do_expansion (struct layout_info *li, int ev_num, time_t start, time_t end, int num_cols) -{ - int i, j; - int slot; - - for (i = find_index (li, start); li->partition[i] < end; i++) { - slot = li->allocations[ev_num] + 1; - - for (j = 0; j < num_cols; j++) - xy (li, slot + j, i) = ev_num; - } -} - -/* Expands the events in the slot array to occupy as many columns as possible. This is the second - * pass of the layout algorithm. - */ -static void -expand_events (struct layout_info *li) -{ - GList *events; - time_t start, end; - int i; - int cols; - - for (i = 0, events = li->events; events; events = events->next, i++) { - (* li->func) (events, &start, &end); - - cols = columns_to_expand (li, i, start, end); - - if (cols == 0) - continue; /* We can't expand this event */ - - do_expansion (li, i, start, end, cols); - - li->slots[i] += cols; - } -} - -void -layout_events (GList *events, LayoutQueryTimeFunc func, - int *num_slots, int **allocations, int **slots) -{ - struct layout_info li; - int i; - - g_return_if_fail (num_slots != NULL); - g_return_if_fail (allocations != NULL); - g_return_if_fail (slots != NULL); - - if (!events) { - *num_slots = 0; - *allocations = NULL; - *slots = NULL; - - return; - } - - li.events = events; - li.num_events = g_list_length (events); - li.func = func; - - /* Build the partition of the time range, and then build the array of slots */ - - build_partition (&li); - - li.array = g_new (int, li.num_rows * MAX_EVENTS_PER_ROW); - for (i = 0; i < (li.num_rows * MAX_EVENTS_PER_ROW); i++) - li.array[i] = -1; /* This is our 'empty' value */ - - /* Build the arrays for allocations and columns used */ - - li.allocations = g_new (int, li.num_events); - li.slots = g_new (int, li.num_events); - - /* Perform initial allocation and then expand the events to as many - * slots as they can occupy. - */ - - initial_allocate (&li); - expand_events (&li); - - /* Clean up and return values */ - - g_free (li.partition); - g_free (li.array); - - *num_slots = li.num_slots; - *allocations = li.allocations; - *slots = li.slots; -} diff --git a/calendar/gui/layout.h b/calendar/gui/layout.h deleted file mode 100644 index ed40e40a29..0000000000 --- a/calendar/gui/layout.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Evolution calendar - Event layout engine - * - * Copyright (C) 2000 Helix Code, Inc. - * - * Authors: Miguel de Icaza <miguel@helixcode.com> - * Federico Mena-Quintero <federico@helixcode.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef LAYOUT_H -#define LAYOUT_H - -#include <glib.h> -#include <time.h> - - - -/* Functions of this type must translate the list item into two time_t values - * for the start and end of an event. - */ -typedef void (* LayoutQueryTimeFunc) (GList *event, time_t *start, time_t *end); - - -/* This is the main layout function for overlapping events. You pass in a list - * of (presumably) events and a function that should take a list element and - * return the start and end times for the event corresponding to that list - * element. - * - * It returns the number of slots ("columns") that you need to take into account - * when actually painting the events, the array of the first slot index that - * each event occupies, and the array of number of slots that each event - * occupies. You have to free both arrays. - * - * You will get somewhat better-looking results if the list of events is sorted - * by using the start time as the primary sort key and the end time as the - * secondary sort key -- so that "longer" events go first in the list. - */ -void layout_events (GList *events, LayoutQueryTimeFunc func, - int *num_slots, int **allocations, int **slots); - - - -#endif diff --git a/calendar/gui/print.c b/calendar/gui/print.c index 3b4f2c4a18..1554be0b96 100644 --- a/calendar/gui/print.c +++ b/calendar/gui/print.c @@ -35,7 +35,6 @@ #include <cal-util/timeutil.h> #include "calendar-commands.h" #include "gnome-cal.h" -#include "layout.h" #include "print.h" @@ -67,6 +66,30 @@ static const int sept_1752[42] = { #define SEPT_1752_START 2 /* Start day within month */ #define SEPT_1752_END 20 /* End day within month */ +struct pdinfo +{ + GList *slots; +}; + +struct psinfo +{ + GList *events; +}; + +struct ptinfo +{ + GList *todos; +}; + +struct einfo +{ + char *text; + time_t start; + time_t end; + int count; +}; + + /* Returns the number of leap years since year 1 up to (but not including) the specified year */ static int leap_years_up_to (int year) @@ -366,16 +389,14 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, for (x=0;x<7;x++) { day = days[y*7+x]; if (day!=0) { - GList *events; + GList *uids; sprintf(buf, "%d", day); /* this is a slow messy way to do this ... but easy ... */ - events = cal_client_get_events_in_range (gcal->client, - now, - time_day_end (now)); - font = events ? font_bold : font_normal; - cal_obj_instance_list_free (events); + uids = cal_client_get_objects_in_range (gcal->client, CALOBJ_TYPE_EVENT, now, time_day_end (now)); + font = uids ? font_bold : font_normal; + cal_obj_uid_list_free (uids); next = time_add_day(now, 1); if ((now>=greystart && now<greyend) @@ -491,26 +512,57 @@ bound_text(GnomePrintContext *pc, GnomeFont *font, char *text, double left, doub return top; } -/* Used with layout_events(), takes in a list element and returns the start and - * end times for the event corresponding to that element. +/* + * Print Day Details */ -static void -event_layout_query_func (GList *instance, time_t *start, time_t *end) +static gboolean +print_day_details_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data) { - CalObjInstance *coi = instance->data; + CalComponentText text; + GList *l, *col = NULL; + struct pdinfo *pdi = (struct pdinfo *)data; + struct einfo *ei; + + ei = g_new (struct einfo, 1); - *start = coi->start; - *end = coi->end; + cal_component_get_summary (comp, &text); + ei->text = g_strdup (text.value); + + ei->start = istart; + ei->end = iend; + ei->count = 0; + + for (l = pdi->slots; l; l = l->next) { + struct einfo *testei; + + col = (GList *)l->data; + testei = (struct einfo *)col->data; + + if (ei->start >= testei->end) { + col = g_list_prepend (col, ei); + l->data = col; + return TRUE; + } + + testei->count++; + ei->count++; + } + + col = NULL; + col = g_list_prepend (col, ei); + pdi->slots = g_list_append (pdi->slots, col); + + return TRUE; } static void print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, double left, double right, double top, double bottom) { + struct pdinfo pdi; time_t start, end; - GList *l, *events; - int num_slots, *allocations, *slots; - int i; + GList *l; + int num_slots, i; GnomeFont *font_hour, *font_minute, *font_summary; double yinc, y, yend, x, xend; double width=40, slot_width; @@ -559,48 +611,39 @@ print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, start = time_day_begin(whence); end = time_day_end(start); - events = cal_client_get_events_in_range (gcal->client, start, end); - - layout_events (events, event_layout_query_func, &num_slots, &allocations, &slots); - + cal_client_generate_instances (gcal->client, CALOBJ_TYPE_EVENT, start, end, + print_day_details_cb, &pdi); + + num_slots = g_list_length (pdi.slots); slot_width = (right-left-width)/num_slots; - for (i = 0, l = events; l != NULL; l = l->next, i++) { - CalObjInstance *coi; - iCalObject *ico; - CalClientGetStatus status; - - coi = l->data; - status = cal_client_get_object (gcal->client, coi->uid, &ico); + for (i = num_slots, l = pdi.slots; l; i--, l = l->next) { + GList *e = (GList *)l->data; + + for (; e; e = e->next) { + struct einfo *ei = (struct einfo *)e->data; + + y = top - (top - bottom) * (ei->start - start) / (end - start) - 1; + yend = top - (top - bottom) * (ei->end - start) / (end - start) + 1; + x = left + width + slot_width * (num_slots - i); + + if (num_slots > 0) + x++; + + if (i == 0) + xend = x + (num_slots - ei->count) * slot_width - 2; + else + xend = x + slot_width - 2; + + print_border (pc, x, xend, y, yend, 0.0, 0.9); + + bound_text (pc, font_summary, ei->text, x, xend, y, yend, 0); - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - /* Go on */ - break; - case CAL_CLIENT_GET_SYNTAX_ERROR: - case CAL_CLIENT_GET_NOT_FOUND: - g_message ("print_day_details(): syntax error in fetched object"); - continue; + g_free (ei); } - - y = top - (top - bottom) * (coi->start - start) / (end - start) - 1; - yend = top - (top - bottom) * (coi->end - start) / (end - start) + 1; - x = left + width + slot_width * allocations[i]; - - if (num_slots > 0) - x++; - - xend = x + slots[i] * slot_width - 2; - - print_border (pc, x, xend, y, yend, 0.0, 0.9); - - bound_text (pc, font_summary, ico->summary, x, xend, y, yend, 0); - ical_object_unref (ico); + g_list_free (e); } - - cal_obj_instance_list_free (events); - g_free (allocations); - g_free (slots); + g_list_free (pdi.slots); print_border (pc, left, right, top, bottom, 1.0, -1.0); @@ -609,20 +652,44 @@ print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, gtk_object_unref (GTK_OBJECT (font_summary)); } +/* + * Print Day Summary + */ #if 0 #define TIME_FMT "%X" #else #define TIME_FMT "%l:%M%p" #endif +static gboolean +print_day_summary_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data) +{ + CalComponentText text; + struct psinfo *psi = (struct psinfo *)data; + struct einfo *ei; + + ei = g_new (struct einfo, 1); + + cal_component_get_summary (comp, &text); + ei->text = g_strdup (text.value); + + ei->start = istart; + ei->end = iend; + ei->count = 0; + + g_list_append (psi->events, ei); + + return TRUE; +} + static void print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, double left, double right, double top, double bottom, double size, int totime, int titleformat) { + struct psinfo psi; time_t start, end; - GList *l, *events; - int i; + GList *l; GnomeFont *font_summary; double y, yend, x, xend, inc, incsmall; char buf[100]; @@ -643,8 +710,8 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, titled_box (pc, buf, font_summary, ALIGN_RIGHT | ALIGN_BORDER, &left, &right, &top, &bottom, 0.0); - events = cal_client_get_events_in_range (gcal->client, start, end); - + cal_client_generate_instances (gcal->client, CALOBJ_TYPE_EVENT, start, end, + print_day_summary_cb, &psi); inc = size*0.3; incsmall = size*0.2; @@ -661,23 +728,8 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, strftime(buf, 100, TIME_FMT, &tm); margin = gnome_font_get_width_string(font_summary, buf); - for (i=0, l = events; l != NULL; l = l->next, i++) { - CalObjInstance *coi; - iCalObject *ico; - CalClientGetStatus status; - - coi = l->data; - status = cal_client_get_object (gcal->client, coi->uid, &ico); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - /* Go on */ - break; - case CAL_CLIENT_GET_SYNTAX_ERROR: - case CAL_CLIENT_GET_NOT_FOUND: - g_message ("print_day_summary(): syntax error in fetched object"); - continue; - } + for (l = psi.events; l; l = l->next) { + struct einfo *ei = (struct einfo *)l->data; x = left + incsmall; xend = right - inc; @@ -685,7 +737,7 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, if (y - font_summary->size < bottom) break; - tm = *localtime (&coi->start); + tm = *localtime (&ei->start); strftime (buf, 100, TIME_FMT, &tm); gnome_print_moveto (pc, x + (margin - gnome_font_get_width_string (font_summary, buf)), @@ -693,7 +745,7 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, gnome_print_show (pc, buf); if (totime) { - tm = *localtime (&coi->end); + tm = *localtime (&ei->end); strftime (buf, 100, TIME_FMT, &tm); gnome_print_moveto (pc, (x + margin + inc @@ -702,23 +754,22 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, y - font_summary->size); gnome_print_show (pc, buf); - y = bound_text (pc, font_summary, ico->summary, + y = bound_text (pc, font_summary, ei->text, x + margin * 2 + inc * 2, xend, y, yend, 0); } else { /* we also indent back after each time is printed */ - y = bound_text (pc, font_summary, ico->summary, + y = bound_text (pc, font_summary, ei->text, x + margin + inc, xend, y, yend, -margin + inc); } y += font_summary->size - inc; - - ical_object_unref (ico); + + g_free (ei); } - - cal_obj_instance_list_free (events); - + g_list_free (psi.events); + gtk_object_unref (GTK_OBJECT (font_summary)); } @@ -849,17 +900,35 @@ print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence, } } +/* + * Print to do details + */ +static gboolean +print_todo_details_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data) +{ + CalComponentText text; + struct ptinfo *pti = (struct ptinfo *)data; + struct einfo *ei; + + ei = g_new0 (struct einfo, 1); + + cal_component_get_summary (comp, &text); + ei->text = g_strdup (text.value); + + g_list_append (pti->todos, ei); + + return TRUE; +} + static void print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, time_t end, double left, double right, double top, double bottom) { - GList *l, *todos; - int i; + struct ptinfo pti; + GList *l; GnomeFont *font_summary; double y, yend, x, xend; - todos = cal_client_get_uids (gcal->client, CALOBJ_TYPE_TODO); - font_summary = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, 10); gnome_print_setrgbcolor (pc, 0, 0, 0); @@ -871,21 +940,11 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, ti y = top - 3; yend = bottom - 2; - for (i = 0, l = todos; l != NULL; l = l->next, i++) { - iCalObject *ico; - CalClientGetStatus status; + cal_client_generate_instances (gcal->client, CALOBJ_TYPE_TODO, start, end, + print_todo_details_cb, &pti); - status = cal_client_get_object (gcal->client, l->data, &ico); - - switch (status) { - case CAL_CLIENT_GET_SUCCESS: - /* Go on */ - break; - case CAL_CLIENT_GET_NOT_FOUND: - case CAL_CLIENT_GET_SYNTAX_ERROR: - g_message ("print_todo_details(): syntax error in fetched object"); - continue; - } + for (l = pti.todos; l; l = l->next) { + struct einfo *ei = (struct einfo *)l->data; x = left; xend = right-2; @@ -893,17 +952,16 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, ti if (y < bottom) break; - y = bound_text (pc, font_summary, ico->summary, x + 2, xend, y, yend, 0); + y = bound_text (pc, font_summary, ei->text, x + 2, xend, y, yend, 0); y += font_summary->size; gnome_print_moveto (pc, x, y - 3); gnome_print_lineto (pc, xend, y - 3); gnome_print_stroke (pc); y -= 3; - ical_object_unref (ico); + g_free (ei); } - - cal_obj_uid_list_free (todos); + g_list_free (pti.todos); gtk_object_unref (GTK_OBJECT (font_summary)); } |