aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamon Chaplin <damon@ximian.com>2001-05-29 10:18:00 +0800
committerDamon Chaplin <damon@src.gnome.org>2001-05-29 10:18:00 +0800
commitff523035dd2592f6ff25955e7f1e379f24640347 (patch)
tree586ea9b1c89726cace082c42865d82d61db5eb19
parentaaa9b9bb2ab4ff9fba2a6b9cc68fbc7fdfaa71bc (diff)
downloadgsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar.gz
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar.bz2
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar.lz
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar.xz
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.tar.zst
gsoc2013-evolution-ff523035dd2592f6ff25955e7f1e379f24640347.zip
new files to contain layout code split off from EDayView an EWeekView, so
2001-05-28 Damon Chaplin <damon@ximian.com> * gui/e-week-view-layout.[hc]: * gui/e-day-view-layout.[hc]: new files to contain layout code split off from EDayView an EWeekView, so we can use it for printing. * gui/print.c: rewritten to use the same layout code as the EDayView and EWeekView widgets. * gui/gnome-cal.c (gnome_calendar_get_task_pad_cal_client): added function so we can get the CalClient used for the TaskPad for printing. * gui/Makefile.am (evolution_calendar_SOURCES): added e-day-view-layout.[hc] amd e-week-view-layout.[hc]. * cal-util/timeutil.c (time_week_begin): (time_week_end): added week_start_day argument. * cal-util/cal-recur.c: added comments describing problems in it. svn path=/trunk/; revision=10037
-rw-r--r--calendar/ChangeLog20
-rw-r--r--calendar/cal-util/cal-recur.c18
-rw-r--r--calendar/cal-util/timeutil.c26
-rw-r--r--calendar/cal-util/timeutil.h41
-rw-r--r--calendar/gui/Makefile.am4
-rw-r--r--calendar/gui/e-day-view-layout.c349
-rw-r--r--calendar/gui/e-day-view-layout.h57
-rw-r--r--calendar/gui/e-day-view-main-item.c5
-rw-r--r--calendar/gui/e-day-view.c369
-rw-r--r--calendar/gui/e-day-view.h7
-rw-r--r--calendar/gui/e-week-view-layout.c426
-rw-r--r--calendar/gui/e-week-view-layout.h70
-rw-r--r--calendar/gui/e-week-view.c373
-rw-r--r--calendar/gui/e-week-view.h9
-rw-r--r--calendar/gui/gnome-cal.c22
-rw-r--r--calendar/gui/gnome-cal.h1
-rw-r--r--calendar/gui/print.c1897
17 files changed, 2526 insertions, 1168 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 0fcee177e8..de14638714 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,23 @@
+2001-05-28 Damon Chaplin <damon@ximian.com>
+
+ * gui/e-week-view-layout.[hc]:
+ * gui/e-day-view-layout.[hc]: new files to contain layout code split
+ off from EDayView an EWeekView, so we can use it for printing.
+
+ * gui/print.c: rewritten to use the same layout code as the EDayView
+ and EWeekView widgets.
+
+ * gui/gnome-cal.c (gnome_calendar_get_task_pad_cal_client): added
+ function so we can get the CalClient used for the TaskPad for printing.
+
+ * gui/Makefile.am (evolution_calendar_SOURCES): added
+ e-day-view-layout.[hc] amd e-week-view-layout.[hc].
+
+ * cal-util/timeutil.c (time_week_begin):
+ (time_week_end): added week_start_day argument.
+
+ * cal-util/cal-recur.c: added comments describing problems in it.
+
2001-05-27 Rodrigo Moya <rodrigo@ximian.com>
* gui/component-factory.c (remove_folder): implemented the
diff --git a/calendar/cal-util/cal-recur.c b/calendar/cal-util/cal-recur.c
index 0b4f114484..8ac6f771d9 100644
--- a/calendar/cal-util/cal-recur.c
+++ b/calendar/cal-util/cal-recur.c
@@ -84,6 +84,24 @@
* the BYSETPOS property is used to select which of the occurrences are
* finally output. If BYSETPOS is not specified then all the occurrences are
* output.
+ *
+ *
+ * FIXME: I think there are a few errors in this code:
+ *
+ * 1) I'm not sure it should be generating events in parallel like it says
+ * above. That needs to be checked.
+ *
+ * 2) I didn't think about timezone changes when implementing this. I just
+ * assumed all the occurrences of the event would be in local time.
+ * But when clocks go back or forwards due to daylight-saving time, some
+ * special handling may be needed, especially for the shorter frequencies.
+ * e.g. for a MINUTELY frequency it should probably iterate over all the
+ * minutes before and after clocks go back (i.e. some may be the same local
+ * time but have different UTC offsets). For longer frequencies, if an
+ * occurrence lands on the overlapping or non-existant time when clocks
+ * go back/forward, then it may need to choose which of the times to use
+ * or move the time forward or something. I'm not sure this is clear in the
+ * spec.
*/
/* Define this for some debugging output. */
diff --git a/calendar/cal-util/timeutil.c b/calendar/cal-util/timeutil.c
index 764ec5d078..7bb4c904ec 100644
--- a/calendar/cal-util/timeutil.c
+++ b/calendar/cal-util/timeutil.c
@@ -319,35 +319,45 @@ time_month_end (time_t t)
return mktime (&tm);
}
+/* Returns the start of the week. week_start_day should use the same values
+ as mktime(), i.e. 0 (Sun) to 6 (Sat). */
time_t
-time_week_begin (time_t t)
+time_week_begin (time_t t, int week_start_day)
{
struct tm tm;
-
- /* FIXME: make it take week_starts_on_monday into account */
+ int offset;
tm = *localtime (&t);
+
+ /* Calculate the current offset from the week start day. */
+ offset = (tm.tm_wday + 7 - week_start_day) % 7;
+
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mday -= tm.tm_wday;
+ tm.tm_mday -= offset;
tm.tm_isdst = -1;
return mktime (&tm);
}
+/* Returns the end of the week. week_start_day should use the same values
+ as mktime(), i.e. 0 (Sun) to 6 (Sat). */
time_t
-time_week_end (time_t t)
+time_week_end (time_t t, int week_start_day)
{
struct tm tm;
-
- /* FIXME: make it take week_starts_on_monday into account */
+ int offset;
tm = *localtime (&t);
+
+ /* Calculate the current offset from the week start day. */
+ offset = (tm.tm_wday + 7 - week_start_day) % 7;
+
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
- tm.tm_mday += 7 - tm.tm_wday;
+ tm.tm_mday += 7 - offset;
tm.tm_isdst = -1;
return mktime (&tm);
diff --git a/calendar/cal-util/timeutil.h b/calendar/cal-util/timeutil.h
index 04f1ca4867..3907a11b8c 100644
--- a/calendar/cal-util/timeutil.h
+++ b/calendar/cal-util/timeutil.h
@@ -26,41 +26,36 @@ time_t time_add_month (time_t time, int months);
time_t time_add_year (time_t time, int years);
-/* Returns the number of days in the specified month. Years are full years (starting from year 1).
- * Months are in [0, 11].
- */
+/* Returns the number of days in the specified month. Years are full years
+ (starting from year 1). Months are in [0, 11]. */
int time_days_in_month (int year, int month);
-/* Converts the specified date to a time_t at the start of the specified day. Years are full years
- * (starting from year 1). Months are in [0, 11]. Days are 1-based.
- */
+/* Converts the specified date to a time_t at the start of the specified day.
+ Years are full years (starting from year 1). Months are in [0, 11].
+ Days are 1-based. */
time_t time_from_day (int year, int month, int day);
-/* For the functions below, time ranges are considered to contain the start time, but not the end
- * time.
- */
+/* For the functions below, time ranges are considered to contain the start
+ time, but not the end time. */
-/* These two functions take a time value and return the beginning or end of the corresponding year,
- * respectively.
- */
+/* These two functions take a time value and return the beginning or end of
+ the corresponding year, respectively. */
time_t time_year_begin (time_t t);
time_t time_year_end (time_t t);
-/* These two functions take a time value and return the beginning or end of the corresponding month,
- * respectively.
- */
+/* These two functions take a time value and return the beginning or end of
+ the corresponding month, respectively. */
time_t time_month_begin (time_t t);
time_t time_month_end (time_t t);
-/* These functions take a time value and return the beginning or end of the corresponding week,
- * respectively. This takes into account the global week_starts_on_monday flag.
- */
-time_t time_week_begin (time_t t);
-time_t time_week_end (time_t t);
+/* These functions take a time value and return the beginning or end of the
+ corresponding week, respectively. week_start_day should use the same values
+ as mktime(), i.e. 0 (Sun) to 6 (Sat). */
+time_t time_week_begin (time_t t, int week_start_day);
+time_t time_week_end (time_t t, int week_start_day);
-/* These two functions take a time value and return the beginning or end of the corresponding day,
- * respectively.
- */
+/* These two functions take a time value and return the beginning or end of
+ the corresponding day, respectively. */
time_t time_day_begin (time_t t);
time_t time_day_end (time_t t);
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 29bb739a56..2910efc322 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -65,6 +65,8 @@ evolution_calendar_SOURCES = \
component-factory.h \
e-calendar-table.h \
e-calendar-table.c \
+ e-day-view-layout.c \
+ e-day-view-layout.h \
e-day-view-main-item.c \
e-day-view-main-item.h \
e-day-view-time-item.c \
@@ -79,6 +81,8 @@ evolution_calendar_SOURCES = \
e-meeting-edit.c \
e-week-view-event-item.c \
e-week-view-event-item.h \
+ e-week-view-layout.c \
+ e-week-view-layout.h \
e-week-view-main-item.c \
e-week-view-main-item.h \
e-week-view-titles-item.c \
diff --git a/calendar/gui/e-day-view-layout.c b/calendar/gui/e-day-view-layout.c
new file mode 100644
index 0000000000..00a448d7ec
--- /dev/null
+++ b/calendar/gui/e-day-view-layout.c
@@ -0,0 +1,349 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@ximian.com>
+ *
+ * Copyright 2001, Ximian, Inc.
+ *
+ * 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
+ */
+
+/*
+ * Lays out events for the Day & Work-Week views of the calendar. It is also
+ * used for printing.
+ */
+
+#include <config.h>
+
+#include "e-day-view-layout.h"
+
+static void e_day_view_layout_long_event (EDayViewEvent *event,
+ guint8 *grid,
+ gint days_shown,
+ time_t *day_starts,
+ gint *rows_in_top_display);
+
+static void e_day_view_layout_day_event (EDayViewEvent *event,
+ guint8 *grid,
+ guint16 *group_starts,
+ gint8 *cols_per_row,
+ gint rows,
+ gint mins_per_row);
+static void e_day_view_expand_day_event (EDayViewEvent *event,
+ guint8 *grid,
+ gint8 *cols_per_row,
+ gint mins_per_row);
+static void e_day_view_recalc_cols_per_row (gint rows,
+ gint8 *cols_per_row,
+ guint16 *group_starts);
+
+
+void
+e_day_view_layout_long_events (GArray *events,
+ gint days_shown,
+ time_t *day_starts,
+ gint *rows_in_top_display)
+{
+ EDayViewEvent *event;
+ gint event_num;
+ guint8 *grid;
+
+ /* This is a temporary 2-d grid which is used to place events.
+ Each element is 0 if the position is empty, or 1 if occupied.
+ We allocate the maximum size possible here, assuming that each
+ event will need its own row. */
+ grid = g_new0 (guint8, events->len * E_DAY_VIEW_MAX_DAYS);
+
+ /* Reset the number of rows in the top display to 0. It will be
+ updated as events are layed out below. */
+ *rows_in_top_display = 0;
+
+ /* Iterate over the events, finding which days they cover, and putting
+ them in the first free row available. */
+ for (event_num = 0; event_num < events->len; event_num++) {
+ event = &g_array_index (events, EDayViewEvent, event_num);
+ e_day_view_layout_long_event (event, grid,
+ days_shown, day_starts,
+ rows_in_top_display);
+ }
+
+ /* Free the grid. */
+ g_free (grid);
+}
+
+
+static void
+e_day_view_layout_long_event (EDayViewEvent *event,
+ guint8 *grid,
+ gint days_shown,
+ time_t *day_starts,
+ gint *rows_in_top_display)
+{
+ gint start_day, end_day, free_row, day, row;
+
+ event->num_columns = 0;
+
+ if (!e_day_view_find_long_event_days (event,
+ days_shown, day_starts,
+ &start_day, &end_day))
+ return;
+
+ /* Try each row until we find a free one. */
+ row = 0;
+ do {
+ free_row = row;
+ for (day = start_day; day <= end_day; day++) {
+ if (grid[row * E_DAY_VIEW_MAX_DAYS + day]) {
+ free_row = -1;
+ break;
+ }
+ }
+ row++;
+ } while (free_row == -1);
+
+ event->start_row_or_col = free_row;
+ event->num_columns = 1;
+
+ /* Mark the cells as full. */
+ for (day = start_day; day <= end_day; day++) {
+ grid[free_row * E_DAY_VIEW_MAX_DAYS + day] = 1;
+ }
+
+ /* Update the number of rows in the top canvas if necessary. */
+ *rows_in_top_display = MAX (*rows_in_top_display, free_row + 1);
+}
+
+
+void
+e_day_view_layout_day_events (GArray *events,
+ gint rows,
+ gint mins_per_row,
+ gint8 *cols_per_row)
+{
+ EDayViewEvent *event;
+ gint row, event_num;
+ guint8 *grid;
+
+ /* This is a temporary array which keeps track of rows which are
+ connected. When an appointment spans multiple rows then the number
+ of columns in each of these rows must be the same (i.e. the maximum
+ of all of them). Each element in the array corresponds to one row
+ and contains the index of the first row in the group of connected
+ rows. */
+ guint16 group_starts[12 * 24];
+
+ /* Reset the cols_per_row array, and initialize the connected rows so
+ that all rows are not connected - each row is the start of a new
+ group. */
+ for (row = 0; row < rows; row++) {
+ cols_per_row[row] = 0;
+ group_starts[row] = row;
+ }
+
+ /* This is a temporary 2-d grid which is used to place events.
+ Each element is 0 if the position is empty, or 1 if occupied. */
+ grid = g_new0 (guint8, rows * E_DAY_VIEW_MAX_COLUMNS);
+
+
+ /* Iterate over the events, finding which rows they cover, and putting
+ them in the first free column available. Increment the number of
+ events in each of the rows it covers, and make sure they are all
+ in one group. */
+ for (event_num = 0; event_num < events->len; event_num++) {
+ event = &g_array_index (events, EDayViewEvent, event_num);
+
+ e_day_view_layout_day_event (event, grid, group_starts,
+ cols_per_row, rows, mins_per_row);
+ }
+
+ /* Recalculate the number of columns needed in each row. */
+ e_day_view_recalc_cols_per_row (rows, cols_per_row, group_starts);
+
+ /* Iterate over the events again, trying to expand events horizontally
+ if there is enough space. */
+ for (event_num = 0; event_num < events->len; event_num++) {
+ event = &g_array_index (events, EDayViewEvent, event_num);
+ e_day_view_expand_day_event (event, grid, cols_per_row,
+ mins_per_row);
+ }
+
+ /* Free the grid. */
+ g_free (grid);
+}
+
+
+/* Finds the first free position to place the event in.
+ Increments the number of events in each of the rows it covers, and makes
+ sure they are all in one group. */
+static void
+e_day_view_layout_day_event (EDayViewEvent *event,
+ guint8 *grid,
+ guint16 *group_starts,
+ gint8 *cols_per_row,
+ gint rows,
+ gint mins_per_row)
+{
+ gint start_row, end_row, free_col, col, row, group_start;
+
+ start_row = event->start_minute / mins_per_row;
+ end_row = (event->end_minute - 1) / mins_per_row;
+
+ event->num_columns = 0;
+
+ /* If the event can't currently be seen, just return. */
+ if (start_row >= rows || end_row < 0)
+ return;
+
+ /* Make sure we don't go outside the visible times. */
+ start_row = CLAMP (start_row, 0, rows - 1);
+ end_row = CLAMP (end_row, 0, rows - 1);
+
+ /* Try each column until we find a free one. */
+ for (col = 0; col < E_DAY_VIEW_MAX_COLUMNS; col++) {
+ free_col = col;
+ for (row = start_row; row <= end_row; row++) {
+ if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) {
+ free_col = -1;
+ break;
+ }
+ }
+
+ if (free_col != -1)
+ break;
+ }
+
+ /* If we can't find space for the event, just return. */
+ if (free_col == -1)
+ return;
+
+ /* The event is assigned 1 col initially, but may be expanded later. */
+ event->start_row_or_col = free_col;
+ event->num_columns = 1;
+
+ /* Determine the start index of the group. */
+ group_start = group_starts[start_row];
+
+ /* Increment number of events in each of the rows the event covers.
+ We use the cols_per_row array for this. It will be sorted out after
+ all the events have been layed out. Also make sure all the rows that
+ the event covers are in one group. */
+ for (row = start_row; row <= end_row; row++) {
+ grid[row * E_DAY_VIEW_MAX_COLUMNS + free_col] = 1;
+ cols_per_row[row]++;
+ group_starts[row] = group_start;
+ }
+
+ /* If any following rows should be in the same group, add them. */
+ for (row = end_row + 1; row < rows; row++) {
+ if (group_starts[row] > end_row)
+ break;
+ group_starts[row] = group_start;
+ }
+}
+
+
+/* For each group of rows, find the max number of events in all the
+ rows, and set the number of cols in each of the rows to that. */
+static void
+e_day_view_recalc_cols_per_row (gint rows,
+ gint8 *cols_per_row,
+ guint16 *group_starts)
+{
+ gint start_row = 0, row, next_start_row, max_events;
+
+ while (start_row < rows) {
+ max_events = 0;
+ for (row = start_row; row < rows && group_starts[row] == start_row; row++)
+ max_events = MAX (max_events, cols_per_row[row]);
+
+ next_start_row = row;
+
+ for (row = start_row; row < next_start_row; row++)
+ cols_per_row[row] = max_events;
+
+ start_row = next_start_row;
+ }
+}
+
+
+/* Expands the event horizontally to fill any free space. */
+static void
+e_day_view_expand_day_event (EDayViewEvent *event,
+ guint8 *grid,
+ gint8 *cols_per_row,
+ gint mins_per_row)
+{
+ gint start_row, end_row, col, row;
+ gboolean clashed;
+
+ start_row = event->start_minute / mins_per_row;
+ end_row = (event->end_minute - 1) / mins_per_row;
+
+ /* Try each column until we find a free one. */
+ clashed = FALSE;
+ for (col = event->start_row_or_col + 1; col < cols_per_row[start_row]; col++) {
+ for (row = start_row; row <= end_row; row++) {
+ if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) {
+ clashed = TRUE;
+ break;
+ }
+ }
+
+ if (clashed)
+ break;
+
+ event->num_columns++;
+ }
+}
+
+
+/* Find the start and end days for the event. */
+gboolean
+e_day_view_find_long_event_days (EDayViewEvent *event,
+ gint days_shown,
+ time_t *day_starts,
+ gint *start_day_return,
+ gint *end_day_return)
+{
+ gint day, start_day, end_day;
+
+ start_day = -1;
+ end_day = -1;
+
+ for (day = 0; day < days_shown; day++) {
+ if (start_day == -1
+ && event->start < day_starts[day + 1])
+ start_day = day;
+ if (event->end > day_starts[day])
+ end_day = day;
+ }
+
+ /* Sanity check. */
+ if (start_day < 0 || start_day >= days_shown
+ || end_day < 0 || end_day >= days_shown
+ || end_day < start_day) {
+ g_warning ("Invalid date range for event");
+ return FALSE;
+ }
+
+ *start_day_return = start_day;
+ *end_day_return = end_day;
+
+ return TRUE;
+}
+
+
diff --git a/calendar/gui/e-day-view-layout.h b/calendar/gui/e-day-view-layout.h
new file mode 100644
index 0000000000..353d024e3c
--- /dev/null
+++ b/calendar/gui/e-day-view-layout.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@ximian.com>
+ *
+ * Copyright 2001, Ximian, Inc.
+ *
+ * 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 _E_DAY_VIEW_LAYOUT_H_
+#define _E_DAY_VIEW_LAYOUT_H_
+
+#include "e-day-view.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* I've split these functions away from EDayView so we can use them for
+ printing. */
+
+void e_day_view_layout_long_events (GArray *events,
+ gint days_shown,
+ time_t *day_starts,
+ gint *rows_in_top_display);
+
+
+void e_day_view_layout_day_events (GArray *events,
+ gint rows,
+ gint mins_per_row,
+ gint8 *cols_per_row);
+
+gboolean e_day_view_find_long_event_days (EDayViewEvent *event,
+ gint days_shown,
+ time_t *day_starts,
+ gint *start_day,
+ gint *end_day);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_DAY_VIEW_LAYOUT_H_ */
diff --git a/calendar/gui/e-day-view-main-item.c b/calendar/gui/e-day-view-main-item.c
index 3cab1f1a05..fd202bdfbe 100644
--- a/calendar/gui/e-day-view-main-item.c
+++ b/calendar/gui/e-day-view-main-item.c
@@ -29,6 +29,7 @@
*/
#include <config.h>
+#include "e-day-view-layout.h"
#include "e-day-view-main-item.h"
static void e_day_view_main_item_class_init (EDayViewMainItemClass *class);
@@ -390,7 +391,9 @@ e_day_view_main_item_draw_long_events_in_vbars (EDayViewMainItem *dvmitem,
event = &g_array_index (day_view->long_events, EDayViewEvent,
event_num);
- if (!e_day_view_find_long_event_days (day_view, event,
+ if (!e_day_view_find_long_event_days (event,
+ day_view->days_shown,
+ day_view->day_starts,
&start_day, &end_day))
continue;
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index eac99a18aa..b08ed848d8 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -53,6 +53,7 @@
#include "e-meeting-edit.h"
#include "e-day-view-time-item.h"
#include "e-day-view-top-item.h"
+#include "e-day-view-layout.h"
#include "e-day-view-main-item.h"
/* Images */
@@ -266,27 +267,9 @@ static void e_day_view_update_event_label (EDayView *day_view,
static void e_day_view_update_long_event_label (EDayView *day_view,
gint event_num);
-static void e_day_view_layout_long_events (EDayView *day_view);
-static void e_day_view_layout_long_event (EDayView *day_view,
- EDayViewEvent *event,
- guint8 *grid);
static void e_day_view_reshape_long_events (EDayView *day_view);
static void e_day_view_reshape_long_event (EDayView *day_view,
gint event_num);
-static void e_day_view_layout_day_events (EDayView *day_view,
- gint day);
-static void e_day_view_layout_day_event (EDayView *day_view,
- gint day,
- EDayViewEvent *event,
- guint8 *grid,
- guint16 *group_starts);
-static void e_day_view_expand_day_event (EDayView *day_view,
- gint day,
- EDayViewEvent *event,
- guint8 *grid);
-static void e_day_view_recalc_cols_per_row (EDayView *day_view,
- gint day,
- guint16 *group_starts);
static void e_day_view_reshape_day_events (EDayView *day_view,
gint day);
static void e_day_view_reshape_day_event (EDayView *day_view,
@@ -297,8 +280,6 @@ static void e_day_view_reshape_resize_long_event_rect_item (EDayView *day_view);
static void e_day_view_reshape_resize_rect_item (EDayView *day_view);
static void e_day_view_ensure_events_sorted (EDayView *day_view);
-static gint e_day_view_event_sort_func (const void *arg1,
- const void *arg2);
static void e_day_view_start_editing_event (EDayView *day_view,
gint day,
@@ -2909,7 +2890,9 @@ e_day_view_on_long_event_click (EDayView *day_view,
if (!(cal_component_has_recurrences (event->comp))
&& (pos == E_DAY_VIEW_POS_LEFT_EDGE
|| pos == E_DAY_VIEW_POS_RIGHT_EDGE)) {
- if (!e_day_view_find_long_event_days (day_view, event,
+ if (!e_day_view_find_long_event_days (event,
+ day_view->days_shown,
+ day_view->day_starts,
&start_day, &end_day))
return;
@@ -4163,7 +4146,7 @@ e_day_view_add_event (CalComponent *comp,
void
e_day_view_check_layout (EDayView *day_view)
{
- gint day;
+ gint day, rows_in_top_display, top_canvas_height, top_rows;
/* Don't bother if we aren't visible. */
if (!GTK_WIDGET_VISIBLE (day_view))
@@ -4174,7 +4157,10 @@ e_day_view_check_layout (EDayView *day_view)
for (day = 0; day < day_view->days_shown; day++) {
if (day_view->need_layout[day])
- e_day_view_layout_day_events (day_view, day);
+ e_day_view_layout_day_events (day_view->events[day],
+ day_view->rows,
+ day_view->mins_per_row,
+ day_view->cols_per_row[day]);
if (day_view->need_layout[day]
|| day_view->need_reshape[day]) {
@@ -4188,8 +4174,25 @@ e_day_view_check_layout (EDayView *day_view)
day_view->need_reshape[day] = FALSE;
}
- if (day_view->long_events_need_layout)
- e_day_view_layout_long_events (day_view);
+ if (day_view->long_events_need_layout) {
+ e_day_view_layout_long_events (day_view->long_events,
+ day_view->days_shown,
+ day_view->day_starts,
+ &rows_in_top_display);
+
+ /* Set the height of the top canvas based on the row height
+ and the number of rows needed (min 1 + 1 for the dates + 1
+ space for DnD).*/
+ if (day_view->rows_in_top_display != rows_in_top_display) {
+ day_view->rows_in_top_display = rows_in_top_display;
+ top_rows = MAX (1, rows_in_top_display);
+ top_canvas_height = (top_rows + 2)
+ * day_view->top_row_height;
+ gtk_widget_set_usize (day_view->top_canvas, -1,
+ top_canvas_height);
+ }
+ }
+
if (day_view->long_events_need_layout
|| day_view->long_events_need_reshape)
@@ -4201,88 +4204,6 @@ e_day_view_check_layout (EDayView *day_view)
static void
-e_day_view_layout_long_events (EDayView *day_view)
-{
- EDayViewEvent *event;
- gint event_num, old_rows_in_top_display, top_canvas_height, top_rows;
- guint8 *grid;
-
- /* This is a temporary 2-d grid which is used to place events.
- Each element is 0 if the position is empty, or 1 if occupied.
- We allocate the maximum size possible here, assuming that each
- event will need its own row. */
- grid = g_new0 (guint8,
- day_view->long_events->len * E_DAY_VIEW_MAX_DAYS);
-
- /* Reset the number of rows in the top display to 0. It will be
- updated as events are layed out below. */
- old_rows_in_top_display = day_view->rows_in_top_display;
- day_view->rows_in_top_display = 0;
-
- /* Iterate over the events, finding which days they cover, and putting
- them in the first free row available. */
- for (event_num = 0; event_num < day_view->long_events->len;
- event_num++) {
- event = &g_array_index (day_view->long_events,
- EDayViewEvent, event_num);
- e_day_view_layout_long_event (day_view, event, grid);
- }
-
- /* Free the grid. */
- g_free (grid);
-
- /* Set the height of the top canvas based on the row height and the
- number of rows needed (min 1 + 1 for the dates + 1 space for DnD).*/
- if (day_view->rows_in_top_display != old_rows_in_top_display) {
- top_rows = MAX (1, day_view->rows_in_top_display);
- top_canvas_height = (top_rows + 2) * day_view->top_row_height;
- gtk_widget_set_usize (day_view->top_canvas, -1,
- top_canvas_height);
- }
-}
-
-
-static void
-e_day_view_layout_long_event (EDayView *day_view,
- EDayViewEvent *event,
- guint8 *grid)
-{
- gint start_day, end_day, free_row, day, row;
-
- event->num_columns = 0;
-
- if (!e_day_view_find_long_event_days (day_view, event,
- &start_day, &end_day))
- return;
-
- /* Try each row until we find a free one. */
- row = 0;
- do {
- free_row = row;
- for (day = start_day; day <= end_day; day++) {
- if (grid[row * E_DAY_VIEW_MAX_DAYS + day]) {
- free_row = -1;
- break;
- }
- }
- row++;
- } while (free_row == -1);
-
- event->start_row_or_col = free_row;
- event->num_columns = 1;
-
- /* Mark the cells as full. */
- for (day = start_day; day <= end_day; day++) {
- grid[free_row * E_DAY_VIEW_MAX_DAYS + day] = 1;
- }
-
- /* Update the number of rows in the top canvas if necessary. */
- day_view->rows_in_top_display = MAX (day_view->rows_in_top_display,
- free_row + 1);
-}
-
-
-static void
e_day_view_reshape_long_events (EDayView *day_view)
{
EDayViewEvent *event;
@@ -4438,225 +4359,6 @@ e_day_view_reshape_long_event (EDayView *day_view,
}
-/* Find the start and end days for the event. */
-gboolean
-e_day_view_find_long_event_days (EDayView *day_view,
- EDayViewEvent *event,
- gint *start_day_return,
- gint *end_day_return)
-{
- gint day, start_day, end_day;
-
- start_day = -1;
- end_day = -1;
-
- for (day = 0; day < day_view->days_shown; day++) {
- if (start_day == -1
- && event->start < day_view->day_starts[day + 1])
- start_day = day;
- if (event->end > day_view->day_starts[day])
- end_day = day;
- }
-
- /* Sanity check. */
- if (start_day < 0 || start_day >= day_view->days_shown
- || end_day < 0 || end_day >= day_view->days_shown
- || end_day < start_day) {
- g_warning ("Invalid date range for event");
- return FALSE;
- }
-
- *start_day_return = start_day;
- *end_day_return = end_day;
-
- return TRUE;
-}
-
-
-static void
-e_day_view_layout_day_events (EDayView *day_view,
- gint day)
-{
- EDayViewEvent *event;
- gint row, event_num;
- guint8 *grid;
-
- /* This is a temporary array which keeps track of rows which are
- connected. When an appointment spans multiple rows then the number
- of columns in each of these rows must be the same (i.e. the maximum
- of all of them). Each element in the array corresponds to one row
- and contains the index of the first row in the group of connected
- rows. */
- guint16 group_starts[12 * 24];
-
- /* Reset the cols_per_row array, and initialize the connected rows so
- that all rows are not connected - each row is the start of a new
- group. */
- for (row = 0; row < day_view->rows; row++) {
- day_view->cols_per_row[day][row] = 0;
- group_starts[row] = row;
- }
-
- /* This is a temporary 2-d grid which is used to place events.
- Each element is 0 if the position is empty, or 1 if occupied. */
- grid = g_new0 (guint8, day_view->rows * E_DAY_VIEW_MAX_COLUMNS);
-
-
- /* Iterate over the events, finding which rows they cover, and putting
- them in the first free column available. Increment the number of
- events in each of the rows it covers, and make sure they are all
- in one group. */
- for (event_num = 0; event_num < day_view->events[day]->len;
- event_num++) {
- event = &g_array_index (day_view->events[day], EDayViewEvent,
- event_num);
-
- e_day_view_layout_day_event (day_view, day, event,
- grid, group_starts);
- }
-
- /* Recalculate the number of columns needed in each row. */
- e_day_view_recalc_cols_per_row (day_view, day, group_starts);
-
- /* Iterate over the events again, trying to expand events horizontally
- if there is enough space. */
- for (event_num = 0; event_num < day_view->events[day]->len;
- event_num++) {
- event = &g_array_index (day_view->events[day], EDayViewEvent,
- event_num);
- e_day_view_expand_day_event (day_view, day, event, grid);
- }
-
- /* Free the grid. */
- g_free (grid);
-}
-
-
-/* Finds the first free position to place the event in.
- Increments the number of events in each of the rows it covers, and makes
- sure they are all in one group. */
-static void
-e_day_view_layout_day_event (EDayView *day_view,
- gint day,
- EDayViewEvent *event,
- guint8 *grid,
- guint16 *group_starts)
-{
- gint start_row, end_row, free_col, col, row, group_start;
-
- start_row = event->start_minute / day_view->mins_per_row;
- end_row = (event->end_minute - 1) / day_view->mins_per_row;
-
- event->num_columns = 0;
-
- /* If the event can't currently be seen, just return. */
- if (start_row >= day_view->rows || end_row < 0)
- return;
-
- /* Make sure we don't go outside the visible times. */
- start_row = CLAMP (start_row, 0, day_view->rows - 1);
- end_row = CLAMP (end_row, 0, day_view->rows - 1);
-
- /* Try each column until we find a free one. */
- for (col = 0; col < E_DAY_VIEW_MAX_COLUMNS; col++) {
- free_col = col;
- for (row = start_row; row <= end_row; row++) {
- if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) {
- free_col = -1;
- break;
- }
- }
-
- if (free_col != -1)
- break;
- }
-
- /* If we can't find space for the event, just return. */
- if (free_col == -1)
- return;
-
- /* The event is assigned 1 col initially, but may be expanded later. */
- event->start_row_or_col = free_col;
- event->num_columns = 1;
-
- /* Determine the start index of the group. */
- group_start = group_starts[start_row];
-
- /* Increment number of events in each of the rows the event covers.
- We use the cols_per_row array for this. It will be sorted out after
- all the events have been layed out. Also make sure all the rows that
- the event covers are in one group. */
- for (row = start_row; row <= end_row; row++) {
- grid[row * E_DAY_VIEW_MAX_COLUMNS + free_col] = 1;
- day_view->cols_per_row[day][row]++;
- group_starts[row] = group_start;
- }
-
- /* If any following rows should be in the same group, add them. */
- for (row = end_row + 1; row < day_view->rows; row++) {
- if (group_starts[row] > end_row)
- break;
- group_starts[row] = group_start;
- }
-}
-
-
-/* For each group of rows, find the max number of events in all the
- rows, and set the number of cols in each of the rows to that. */
-static void
-e_day_view_recalc_cols_per_row (EDayView *day_view,
- gint day,
- guint16 *group_starts)
-{
- gint start_row = 0, row, next_start_row, max_events;
-
- while (start_row < day_view->rows) {
-
- max_events = 0;
- for (row = start_row; row < day_view->rows && group_starts[row] == start_row; row++)
- max_events = MAX (max_events, day_view->cols_per_row[day][row]);
-
- next_start_row = row;
-
- for (row = start_row; row < next_start_row; row++)
- day_view->cols_per_row[day][row] = max_events;
-
- start_row = next_start_row;
- }
-}
-
-
-/* Expands the event horizontally to fill any free space. */
-static void
-e_day_view_expand_day_event (EDayView *day_view,
- gint day,
- EDayViewEvent *event,
- guint8 *grid)
-{
- gint start_row, end_row, col, row;
- gboolean clashed;
-
- start_row = event->start_minute / day_view->mins_per_row;
- end_row = (event->end_minute - 1) / day_view->mins_per_row;
-
- /* Try each column until we find a free one. */
- clashed = FALSE;
- for (col = event->start_row_or_col + 1; col < day_view->cols_per_row[day][start_row]; col++) {
- for (row = start_row; row <= end_row; row++) {
- if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) {
- clashed = TRUE;
- break;
- }
- }
-
- if (clashed)
- break;
-
- event->num_columns++;
- }
-}
-
-
/* This creates or updates the sizes of the canvas items for one day of the
main canvas. */
static void
@@ -4837,7 +4539,7 @@ e_day_view_ensure_events_sorted (EDayView *day_view)
}
-static gint
+gint
e_day_view_event_sort_func (const void *arg1,
const void *arg2)
{
@@ -5774,7 +5476,9 @@ e_day_view_get_long_event_position (EDayView *day_view,
if (event->num_columns == 0)
return FALSE;
- if (!e_day_view_find_long_event_days (day_view, event,
+ if (!e_day_view_find_long_event_days (event,
+ day_view->days_shown,
+ day_view->day_starts,
start_day, end_day))
return FALSE;
@@ -6037,7 +5741,9 @@ e_day_view_update_top_canvas_drag (EDayView *day_view,
day_view->drag_event_num);
row = event->start_row_or_col + 1;
- if (!e_day_view_find_long_event_days (day_view, event,
+ if (!e_day_view_find_long_event_days (event,
+ day_view->days_shown,
+ day_view->day_starts,
&start_day, &end_day))
return;
@@ -6450,8 +6156,9 @@ e_day_view_on_top_canvas_drag_data_received (GtkWidget *widget,
day -= day_view->drag_event_offset;
day = MAX (day, 0);
- e_day_view_find_long_event_days (day_view,
- event,
+ e_day_view_find_long_event_days (event,
+ day_view->days_shown,
+ day_view->day_starts,
&start_day,
&end_day);
num_days = end_day - start_day + 1;
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index 18f8187951..9eb247a59f 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -582,10 +582,6 @@ gboolean e_day_view_get_long_event_position (EDayView *day_view,
gint *item_y,
gint *item_w,
gint *item_h);
-gboolean e_day_view_find_long_event_days (EDayView *day_view,
- EDayViewEvent *event,
- gint *start_day,
- gint *end_day);
void e_day_view_start_selection (EDayView *day_view,
gint day,
@@ -608,6 +604,9 @@ void e_day_view_convert_time_to_display (EDayView *day_view,
gint e_day_view_get_time_string_width (EDayView *day_view);
+gint e_day_view_event_sort_func (const void *arg1,
+ const void *arg2);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/calendar/gui/e-week-view-layout.c b/calendar/gui/e-week-view-layout.c
new file mode 100644
index 0000000000..21552e5f17
--- /dev/null
+++ b/calendar/gui/e-week-view-layout.c
@@ -0,0 +1,426 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@ximian.com>
+ *
+ * Copyright 2001, Ximian, Inc.
+ *
+ * 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
+ */
+
+/*
+ * Lays out events for the Week & Month views of the calendar. It is also
+ * used for printing.
+ */
+
+#include <config.h>
+
+#include "e-week-view-layout.h"
+
+
+static void e_week_view_layout_event (EWeekViewEvent *event,
+ guint8 *grid,
+ GArray *spans,
+ GArray *old_spans,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gboolean compress_weekend,
+ gint start_weekday,
+ time_t *day_starts,
+ gint *rows_per_day);
+static gint e_week_view_find_day (time_t time_to_find,
+ gboolean include_midnight_in_prev_day,
+ gint days_shown,
+ time_t *day_starts);
+static gint e_week_view_find_span_end (gboolean multi_week_view,
+ gboolean compress_weekend,
+ gint display_start_day,
+ gint day);
+
+
+GArray*
+e_week_view_layout_events (GArray *events,
+ GArray *old_spans,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gboolean compress_weekend,
+ gint start_weekday,
+ time_t *day_starts,
+ gint *rows_per_day)
+{
+ EWeekViewEvent *event;
+ EWeekViewEventSpan *span;
+ gint num_days, day, event_num, span_num;
+ guint8 *grid;
+ GArray *spans;
+
+ /* This is a temporary 2-d grid which is used to place events.
+ Each element is 0 if the position is empty, or 1 if occupied.
+ We allocate the maximum size possible here, assuming that each
+ event will need its own row. */
+ grid = g_new0 (guint8, E_WEEK_VIEW_MAX_ROWS_PER_CELL * 7
+ * E_WEEK_VIEW_MAX_WEEKS);
+
+ /* We create a new array of spans, which will replace the old one. */
+ spans = g_array_new (FALSE, FALSE, sizeof (EWeekViewEventSpan));
+
+ /* Clear the number of rows used per day. */
+ num_days = multi_week_view ? weeks_shown * 7 : 7;
+ for (day = 0; day <= num_days; day++) {
+ rows_per_day[day] = 0;
+ }
+
+ /* Iterate over the events, finding which weeks they cover, and putting
+ them in the first free row available. */
+ for (event_num = 0; event_num < events->len; event_num++) {
+ event = &g_array_index (events, EWeekViewEvent, event_num);
+ e_week_view_layout_event (event, grid, spans, old_spans,
+ multi_week_view,
+ weeks_shown, compress_weekend,
+ start_weekday, day_starts,
+ rows_per_day);
+ }
+
+ /* Free the grid. */
+ g_free (grid);
+
+ /* Destroy the old spans array, destroying any unused canvas items. */
+ if (old_spans) {
+ for (span_num = 0; span_num < old_spans->len; span_num++) {
+ span = &g_array_index (old_spans, EWeekViewEventSpan,
+ span_num);
+ if (span->background_item)
+ gtk_object_destroy (GTK_OBJECT (span->background_item));
+ if (span->text_item)
+ gtk_object_destroy (GTK_OBJECT (span->text_item));
+ }
+ g_array_free (old_spans, TRUE);
+ }
+
+ return spans;
+}
+
+
+static void
+e_week_view_layout_event (EWeekViewEvent *event,
+ guint8 *grid,
+ GArray *spans,
+ GArray *old_spans,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gboolean compress_weekend,
+ gint start_weekday,
+ time_t *day_starts,
+ gint *rows_per_day)
+{
+ gint start_day, end_day, span_start_day, span_end_day, rows_per_cell;
+ gint free_row, row, day, span_num, spans_index, num_spans, days_shown;
+ EWeekViewEventSpan span, *old_span;
+
+ days_shown = multi_week_view ? weeks_shown * 7 - 1 : 7 - 1;
+ start_day = e_week_view_find_day (event->start, FALSE, days_shown,
+ day_starts);
+ end_day = e_week_view_find_day (event->end, TRUE, days_shown,
+ day_starts);
+ start_day = CLAMP (start_day, 0, days_shown - 1);
+ end_day = CLAMP (end_day, 0, days_shown - 1);
+
+#if 0
+ g_print ("In e_week_view_layout_event Start:%i End: %i\n",
+ start_day, end_day);
+#endif
+
+ /* Iterate through each of the spans of the event, where each span
+ is a sequence of 1 or more days displayed next to each other. */
+ span_start_day = start_day;
+ rows_per_cell = E_WEEK_VIEW_MAX_ROWS_PER_CELL;
+ span_num = 0;
+ spans_index = spans->len;
+ num_spans = 0;
+ while (span_start_day <= end_day) {
+ span_end_day = e_week_view_find_span_end (multi_week_view,
+ compress_weekend,
+ start_weekday,
+ span_start_day);
+ span_end_day = MIN (span_end_day, end_day);
+#if 0
+ g_print (" Span start:%i end:%i\n", span_start_day,
+ span_end_day);
+#endif
+ /* Try each row until we find a free one or we fall off the
+ bottom of the available rows. */
+ row = 0;
+ free_row = -1;
+ while (free_row == -1 && row < rows_per_cell) {
+ free_row = row;
+ for (day = span_start_day; day <= span_end_day;
+ day++) {
+ if (grid[day * rows_per_cell + row]) {
+ free_row = -1;
+ break;
+ }
+ }
+ row++;
+ };
+
+ if (free_row != -1) {
+ /* Mark the cells as full. */
+ for (day = span_start_day; day <= span_end_day;
+ day++) {
+ grid[day * rows_per_cell + free_row] = 1;
+ rows_per_day[day] = MAX (rows_per_day[day],
+ free_row + 1);
+ }
+#if 0
+ g_print (" Span start:%i end:%i row:%i\n",
+ span_start_day, span_end_day, free_row);
+#endif
+ /* Add the span to the array, and try to reuse any
+ canvas items from the old spans. */
+ span.start_day = span_start_day;
+ span.num_days = span_end_day - span_start_day + 1;
+ span.row = free_row;
+ span.background_item = NULL;
+ span.text_item = NULL;
+ if (event->num_spans > span_num) {
+ old_span = &g_array_index (old_spans, EWeekViewEventSpan, event->spans_index + span_num);
+ span.background_item = old_span->background_item;
+ span.text_item = old_span->text_item;
+ old_span->background_item = NULL;
+ old_span->text_item = NULL;
+ }
+
+ g_array_append_val (spans, span);
+ num_spans++;
+ }
+
+ span_start_day = span_end_day + 1;
+ span_num++;
+ }
+
+ /* Set the event's spans. */
+ event->spans_index = spans_index;
+ event->num_spans = num_spans;
+}
+
+
+/* Finds the day containing the given time.
+ If include_midnight_in_prev_day is TRUE then if the time exactly
+ matches the start of a day the previous day is returned. This is useful
+ when calculating the end day of an event. */
+static gint
+e_week_view_find_day (time_t time_to_find,
+ gboolean include_midnight_in_prev_day,
+ gint days_shown,
+ time_t *day_starts)
+{
+ gint day;
+
+ if (time_to_find < day_starts[0])
+ return -1;
+ if (time_to_find > day_starts[days_shown])
+ return days_shown;
+
+ for (day = 1; day <= days_shown; day++) {
+ if (time_to_find <= day_starts[day]) {
+ if (time_to_find == day_starts[day]
+ && !include_midnight_in_prev_day)
+ return day;
+ return day - 1;
+ }
+ }
+
+ g_assert_not_reached ();
+ return days_shown;
+}
+
+
+/* This returns the last possible day in the same span as the given day.
+ A span is all the days which are displayed next to each other from left to
+ right. In the week view all spans are only 1 day, since Tuesday is below
+ Monday rather than beside it etc. In the month view, if the weekends are not
+ compressed then each week is a span, otherwise we have to break a span up
+ on Saturday, use a separate span for Sunday, and start again on Monday. */
+static gint
+e_week_view_find_span_end (gboolean multi_week_view,
+ gboolean compress_weekend,
+ gint display_start_day,
+ gint day)
+{
+ gint week, col, sat_col, end_col;
+
+ if (multi_week_view) {
+ week = day / 7;
+ col = day % 7;
+
+ /* We default to the last column in the row. */
+ end_col = 6;
+
+ /* If the weekend is compressed we must end any spans on
+ Saturday and Sunday. */
+ if (compress_weekend) {
+ sat_col = (5 + 7 - display_start_day) % 7;
+ if (col <= sat_col)
+ end_col = sat_col;
+ else if (col == sat_col + 1)
+ end_col = sat_col + 1;
+ }
+
+ return week * 7 + end_col;
+ } else {
+ return day;
+ }
+}
+
+
+void
+e_week_view_layout_get_day_position (gint day,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gint display_start_day,
+ gboolean compress_weekend,
+ gint *day_x,
+ gint *day_y,
+ gint *rows)
+{
+ gint week, day_of_week, row, col, weekend_col, box, weekend_box;
+
+ *day_x = *day_y = *rows = 0;
+ g_return_if_fail (day >= 0);
+
+ if (multi_week_view) {
+ g_return_if_fail (day < weeks_shown * 7);
+
+ week = day / 7;
+ col = day % 7;
+ day_of_week = (display_start_day + day) % 7;
+ if (compress_weekend && day_of_week >= 5) {
+ /* In the compressed view Saturday is above Sunday and
+ both have just one row as opposed to 2 for all the
+ other days. */
+ if (day_of_week == 5) {
+ *day_y = week * 2;
+ *rows = 1;
+ } else {
+ *day_y = week * 2 + 1;
+ *rows = 1;
+ col--;
+ }
+ /* Both Saturday and Sunday are in the same column. */
+ *day_x = col;
+ } else {
+ /* If the weekend is compressed and the day is after
+ the weekend we have to move back a column. */
+ if (compress_weekend) {
+ /* Calculate where the weekend column is.
+ Note that 5 is Saturday. */
+ weekend_col = (5 + 7 - display_start_day) % 7;
+ if (col > weekend_col)
+ col--;
+ }
+
+ *day_y = week * 2;
+ *rows = 2;
+ *day_x = col;
+ }
+ } else {
+ g_return_if_fail (day < 7);
+
+ /* Calculate which box to place the day in, from 0-5.
+ Note that in the week view the weekends are always
+ compressed and share a box. */
+ box = day;
+ day_of_week = (display_start_day + day) % 7;
+ weekend_box = (5 + 7 - display_start_day) % 7;
+ if (box > weekend_box)
+ box--;
+
+ if (box < 3)
+ *day_x = 0;
+ else
+ *day_x = 1;
+
+ row = (box % 3) * 2;
+ if (day_of_week < 5) {
+ *day_y = row;
+ *rows = 2;
+ } else if (day_of_week == 5) {
+ /* Saturday. */
+ *day_y = row;
+ *rows = 1;
+
+ } else {
+ /* Sunday. */
+ *day_y = row + 1;
+ *rows = 1;
+ }
+ }
+}
+
+
+/* Returns TRUE if the event span is visible or FALSE if it isn't.
+ It also returns the number of days of the span that are visible.
+ Usually this can easily be determined by the start & end days and row of
+ the span, which are set in e_week_view_layout_event(). Though we need a
+ special case for the weekends when they are compressed, since the span may
+ not fit. */
+gboolean
+e_week_view_layout_get_span_position (EWeekViewEvent *event,
+ EWeekViewEventSpan *span,
+ gint rows_per_cell,
+ gint rows_per_compressed_cell,
+ gint display_start_day,
+ gboolean multi_week_view,
+ gboolean compress_weekend,
+ gint *span_num_days)
+{
+ gint end_day_of_week;
+
+ if (span->row >= rows_per_cell)
+ return FALSE;
+
+ end_day_of_week = (display_start_day + span->start_day
+ + span->num_days - 1) % 7;
+ *span_num_days = span->num_days;
+ /* Check if the row will not be visible in compressed cells. */
+ if (span->row >= rows_per_compressed_cell) {
+ if (multi_week_view) {
+ if (compress_weekend) {
+ /* If it ends on a Saturday and is 1 day long
+ we skip it, else we shorten it. If it ends
+ on a Sunday it must be 1 day long and we
+ skip it. */
+ if (end_day_of_week == 5) { /* Sat */
+ if (*span_num_days == 1) {
+ return FALSE;
+ } else {
+ (*span_num_days)--;
+ }
+ } else if (end_day_of_week == 6) { /* Sun */
+ return FALSE;
+ }
+ }
+ } else {
+ /* All spans are 1 day long in the week view, so we
+ just skip it. */
+ if (end_day_of_week > 4)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/calendar/gui/e-week-view-layout.h b/calendar/gui/e-week-view-layout.h
new file mode 100644
index 0000000000..e4d679e793
--- /dev/null
+++ b/calendar/gui/e-week-view-layout.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@ximian.com>
+ *
+ * Copyright 2001, Ximian, Inc.
+ *
+ * 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 _E_WEEK_VIEW_LAYOUT_H_
+#define _E_WEEK_VIEW_LAYOUT_H_
+
+#include "e-week-view.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* I've split these functions away from EWeekView so we can use them for
+ printing. */
+
+GArray* e_week_view_layout_events (GArray *events,
+ GArray *old_spans,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gboolean compress_weekend,
+ gint start_weekday,
+ time_t *day_starts,
+ gint *rows_per_day);
+
+/* Returns which 'cell' in the table the day appears in. Note that most days
+ have a height of 2 rows, but Sat/Sun are sometimes compressed so they have
+ a height of only 1 row. */
+void e_week_view_layout_get_day_position(gint day,
+ gboolean multi_week_view,
+ gint weeks_shown,
+ gint display_start_day,
+ gboolean compress_weekend,
+ gint *cell_x,
+ gint *cell_y,
+ gint *rows);
+
+gboolean e_week_view_layout_get_span_position (EWeekViewEvent *event,
+ EWeekViewEventSpan *span,
+ gint rows_per_cell,
+ gint rows_per_compressed_cell,
+ gint display_start_day,
+ gboolean multi_week_view,
+ gboolean compress_weekend,
+ gint *span_num_days);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_WEEK_VIEW_LAYOUT_H_ */
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 447fce8b77..adadd5d42a 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -50,6 +50,7 @@
#include "goto.h"
#include "e-meeting-edit.h"
#include "e-week-view-event-item.h"
+#include "e-week-view-layout.h"
#include "e-week-view-main-item.h"
#include "e-week-view-titles-item.h"
@@ -63,11 +64,6 @@
#define E_WEEK_VIEW_SMALL_FONT_FALLBACK \
"-adobe-helvetica-medium-r-normal-*-*-80-*-*-p-*-iso8859-*"
-/* We use a 7-bit field to store row numbers in EWeekViewEventSpan, so the
- maximum number or rows we can allow is 127. It is very unlikely to be
- reached anyway. */
-#define E_WEEK_VIEW_MAX_ROWS_PER_CELL 127
-
#define E_WEEK_VIEW_JUMP_BUTTON_WIDTH 16
#define E_WEEK_VIEW_JUMP_BUTTON_HEIGHT 8
@@ -115,23 +111,11 @@ static gboolean e_week_view_add_event (CalComponent *comp,
time_t end,
gpointer data);
static void e_week_view_check_layout (EWeekView *week_view);
-static void e_week_view_layout_events (EWeekView *week_view);
-static void e_week_view_layout_event (EWeekView *week_view,
- EWeekViewEvent *event,
- guint8 *grid,
- GArray *spans);
static void e_week_view_ensure_events_sorted (EWeekView *week_view);
-static gint e_week_view_event_sort_func (const void *arg1,
- const void *arg2);
static void e_week_view_reshape_events (EWeekView *week_view);
static void e_week_view_reshape_event_span (EWeekView *week_view,
gint event_num,
gint span_num);
-static gint e_week_view_find_day (EWeekView *week_view,
- time_t time_to_find,
- gboolean include_midnight_in_prev_day);
-static gint e_week_view_find_span_end (EWeekView *week_view,
- gint day);
static void e_week_view_recalc_day_starts (EWeekView *week_view,
time_t lower);
static void e_week_view_on_adjustment_changed (GtkAdjustment *adjustment,
@@ -1751,85 +1735,22 @@ e_week_view_get_day_position (EWeekView *week_view,
gint *day_w,
gint *day_h)
{
- gint week, day_of_week, row, col, weekend_col, box, weekend_box;
-
- *day_x = *day_y = *day_w = *day_h = 0;
- g_return_if_fail (day >= 0);
-
- if (week_view->multi_week_view) {
- g_return_if_fail (day < week_view->weeks_shown * 7);
-
- week = day / 7;
- col = day % 7;
- day_of_week = (week_view->display_start_day + day) % 7;
- if (week_view->compress_weekend && day_of_week >= 5) {
- /* In the compressed view Saturday is above Sunday and
- both have just one row as opposed to 2 for all the
- other days. */
- if (day_of_week == 5) {
- *day_y = week_view->row_offsets[week * 2];
- *day_h = week_view->row_heights[week * 2];
- } else {
- *day_y = week_view->row_offsets[week * 2 + 1];
- *day_h = week_view->row_heights[week * 2 + 1];
- col--;
- }
- /* Both Saturday and Sunday are in the same column. */
- *day_x = week_view->col_offsets[col];
- *day_w = week_view->col_widths[col];
- } else {
- /* If the weekend is compressed and the day is after
- the weekend we have to move back a column. */
- if (week_view->compress_weekend) {
- /* Calculate where the weekend column is.
- Note that 5 is Saturday. */
- weekend_col = (5 + 7 - week_view->display_start_day) % 7;
- if (col > weekend_col)
- col--;
- }
+ gint cell_x, cell_y, cell_h;
- *day_y = week_view->row_offsets[week * 2];
- *day_h = week_view->row_heights[week * 2]
- + week_view->row_heights[week * 2 + 1];
- *day_x = week_view->col_offsets[col];
- *day_w = week_view->col_widths[col];
- }
- } else {
- g_return_if_fail (day < 7);
-
- /* Calculate which box to place the day in, from 0-5.
- Note that in the week view the weekends are always
- compressed and share a box. */
- box = day;
- day_of_week = (week_view->display_start_day + day) % 7;
- weekend_box = (5 + 7 - week_view->display_start_day) % 7;
- if (box > weekend_box)
- box--;
-
- if (box < 3) {
- *day_x = week_view->col_offsets[0];
- *day_w = week_view->col_widths[0];
- } else {
- *day_x = week_view->col_offsets[1];
- *day_w = week_view->col_widths[1];
- }
+ e_week_view_layout_get_day_position (day,
+ week_view->multi_week_view,
+ week_view->weeks_shown,
+ week_view->display_start_day,
+ week_view->compress_weekend,
+ &cell_x, &cell_y, &cell_h);
- row = (box % 3) * 2;
- if (day_of_week < 5) {
- *day_y = week_view->row_offsets[row];
- *day_h = week_view->row_heights[row]
- + week_view->row_heights[row + 1];
- } else if (day_of_week == 5) {
- /* Saturday. */
- *day_y = week_view->row_offsets[row];
- *day_h = week_view->row_heights[row];
+ *day_x = week_view->col_offsets[cell_x];
+ *day_y = week_view->row_offsets[cell_y];
- } else {
- /* Sunday. */
- *day_y = week_view->row_offsets[row + 1];
- *day_h = week_view->row_heights[row + 1];
- }
- }
+ *day_w = week_view->col_widths[cell_x];
+ *day_h = week_view->row_heights[cell_y];
+ if (cell_h == 2)
+ *day_h += week_view->row_heights[cell_y + 1];
}
@@ -1851,7 +1772,7 @@ e_week_view_get_span_position (EWeekView *week_view,
{
EWeekViewEvent *event;
EWeekViewEventSpan *span;
- gint end_day_of_week, num_days;
+ gint num_days;
gint start_x, start_y, start_w, start_h;
gint end_x, end_y, end_w, end_h;
@@ -1865,35 +1786,14 @@ e_week_view_get_span_position (EWeekView *week_view,
span = &g_array_index (week_view->spans, EWeekViewEventSpan,
event->spans_index + span_num);
- if (span->row >= week_view->rows_per_cell)
+ if (!e_week_view_layout_get_span_position (event, span,
+ week_view->rows_per_cell,
+ week_view->rows_per_compressed_cell,
+ week_view->display_start_day,
+ week_view->multi_week_view,
+ week_view->compress_weekend,
+ &num_days)) {
return FALSE;
-
- end_day_of_week = (week_view->display_start_day + span->start_day + span->num_days - 1) % 7;
- num_days = span->num_days;
- /* Check if the row will not be visible in compressed cells. */
- if (span->row >= week_view->rows_per_compressed_cell) {
- if (week_view->multi_week_view) {
- if (week_view->compress_weekend) {
- /* If it ends on a Saturday and is 1 day long
- we skip it, else we shorten it. If it ends
- on a Sunday it must be 1 day long and we
- skip it. */
- if (end_day_of_week == 5) { /* Sat */
- if (num_days == 1) {
- return FALSE;
- } else {
- num_days--;
- }
- } else if (end_day_of_week == 6) { /* Sun */
- return FALSE;
- }
- }
- } else {
- /* All spans are 1 day long in the week view, so we
- just skip it. */
- if (end_day_of_week > 4)
- return FALSE;
- }
}
e_week_view_get_day_position (week_view, span->start_day,
@@ -2235,7 +2135,14 @@ e_week_view_check_layout (EWeekView *week_view)
e_week_view_ensure_events_sorted (week_view);
if (week_view->events_need_layout)
- e_week_view_layout_events (week_view);
+ week_view->spans = e_week_view_layout_events
+ (week_view->events, week_view->spans,
+ week_view->multi_week_view,
+ week_view->weeks_shown,
+ week_view->compress_weekend,
+ week_view->display_start_day,
+ week_view->day_starts,
+ week_view->rows_per_day);
if (week_view->events_need_layout || week_view->events_need_reshape)
e_week_view_reshape_events (week_view);
@@ -2246,154 +2153,6 @@ e_week_view_check_layout (EWeekView *week_view)
static void
-e_week_view_layout_events (EWeekView *week_view)
-{
- EWeekViewEvent *event;
- EWeekViewEventSpan *span;
- gint num_days, day, event_num, span_num;
- guint8 *grid;
- GArray *spans, *old_spans;
-
- /* This is a temporary 2-d grid which is used to place events.
- Each element is 0 if the position is empty, or 1 if occupied.
- We allocate the maximum size possible here, assuming that each
- event will need its own row. */
- grid = g_new0 (guint8, E_WEEK_VIEW_MAX_ROWS_PER_CELL * 7
- * E_WEEK_VIEW_MAX_WEEKS);
-
- /* We create a new array of spans, which will replace the old one. */
- spans = g_array_new (FALSE, FALSE, sizeof (EWeekViewEventSpan));
-
- /* Clear the number of rows used per day. */
- num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7;
- for (day = 0; day <= num_days; day++) {
- week_view->rows_per_day[day] = 0;
- }
-
- /* Iterate over the events, finding which weeks they cover, and putting
- them in the first free row available. */
- for (event_num = 0; event_num < week_view->events->len; event_num++) {
- event = &g_array_index (week_view->events, EWeekViewEvent,
- event_num);
- e_week_view_layout_event (week_view, event, grid, spans);
- }
-
- /* Free the grid. */
- g_free (grid);
-
- /* Replace the spans array. */
- old_spans = week_view->spans;
- week_view->spans = spans;
-
- /* Destroy the old spans array, destroying any unused canvas items. */
- if (old_spans) {
- for (span_num = 0; span_num < old_spans->len; span_num++) {
- span = &g_array_index (old_spans, EWeekViewEventSpan,
- span_num);
- if (span->background_item)
- gtk_object_destroy (GTK_OBJECT (span->background_item));
- if (span->text_item)
- gtk_object_destroy (GTK_OBJECT (span->text_item));
- }
- g_array_free (old_spans, TRUE);
- }
-}
-
-
-static void
-e_week_view_layout_event (EWeekView *week_view,
- EWeekViewEvent *event,
- guint8 *grid,
- GArray *spans)
-{
- gint start_day, end_day, span_start_day, span_end_day, rows_per_cell;
- gint free_row, row, day, span_num, spans_index, num_spans, max_day;
- EWeekViewEventSpan span, *old_span;
-
- start_day = e_week_view_find_day (week_view, event->start, FALSE);
- end_day = e_week_view_find_day (week_view, event->end, TRUE);
- max_day = week_view->multi_week_view ? week_view->weeks_shown * 7 - 1
- : 7 - 1;
- start_day = CLAMP (start_day, 0, max_day);
- end_day = CLAMP (end_day, 0, max_day);
-
-#if 0
- g_print ("In e_week_view_layout_event Start:%i End: %i\n",
- start_day, end_day);
-#endif
-
- /* Iterate through each of the spans of the event, where each span
- is a sequence of 1 or more days displayed next to each other. */
- span_start_day = start_day;
- rows_per_cell = E_WEEK_VIEW_MAX_ROWS_PER_CELL;
- span_num = 0;
- spans_index = spans->len;
- num_spans = 0;
- while (span_start_day <= end_day) {
- span_end_day = e_week_view_find_span_end (week_view,
- span_start_day);
- span_end_day = MIN (span_end_day, end_day);
-#if 0
- g_print (" Span start:%i end:%i\n", span_start_day,
- span_end_day);
-#endif
- /* Try each row until we find a free one or we fall off the
- bottom of the available rows. */
- row = 0;
- free_row = -1;
- while (free_row == -1 && row < rows_per_cell) {
- free_row = row;
- for (day = span_start_day; day <= span_end_day;
- day++) {
- if (grid[day * rows_per_cell + row]) {
- free_row = -1;
- break;
- }
- }
- row++;
- };
-
- if (free_row != -1) {
- /* Mark the cells as full. */
- for (day = span_start_day; day <= span_end_day;
- day++) {
- grid[day * rows_per_cell + free_row] = 1;
- week_view->rows_per_day[day] = MAX (week_view->rows_per_day[day], free_row + 1);
- }
-#if 0
- g_print (" Span start:%i end:%i row:%i\n",
- span_start_day, span_end_day, free_row);
-#endif
- /* Add the span to the array, and try to reuse any
- canvas items from the old spans. */
- span.start_day = span_start_day;
- span.num_days = span_end_day - span_start_day + 1;
- span.row = free_row;
- span.background_item = NULL;
- span.text_item = NULL;
- if (event->num_spans > span_num) {
- old_span = &g_array_index (week_view->spans, EWeekViewEventSpan, event->spans_index + span_num);
- span.background_item = old_span->background_item;
- span.text_item = old_span->text_item;
- old_span->background_item = NULL;
- old_span->text_item = NULL;
- }
-
- g_array_append_val (spans, span);
- num_spans++;
- }
-
- span_start_day = span_end_day + 1;
- span_num++;
- }
-
- /* Set the event's spans. */
- event->spans_index = spans_index;
- event->num_spans = num_spans;
-}
-
-
-static void
e_week_view_ensure_events_sorted (EWeekView *week_view)
{
if (!week_view->events_sorted) {
@@ -2406,7 +2165,7 @@ e_week_view_ensure_events_sorted (EWeekView *week_view)
}
-static gint
+gint
e_week_view_event_sort_func (const void *arg1,
const void *arg2)
{
@@ -2708,76 +2467,6 @@ e_week_view_reshape_event_span (EWeekView *week_view,
}
-/* Finds the day containing the given time.
- If include_midnight_in_prev_day is TRUE then if the time exactly
- matches the start of a day the previous day is returned. This is useful
- when calculating the end day of an event. */
-static gint
-e_week_view_find_day (EWeekView *week_view,
- time_t time_to_find,
- gboolean include_midnight_in_prev_day)
-{
- gint num_days, day;
- time_t *day_starts;
-
- num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7;
- day_starts = week_view->day_starts;
-
- if (time_to_find < day_starts[0])
- return -1;
- if (time_to_find > day_starts[num_days])
- return num_days;
-
- for (day = 1; day <= num_days; day++) {
- if (time_to_find <= day_starts[day]) {
- if (time_to_find == day_starts[day]
- && !include_midnight_in_prev_day)
- return day;
- return day - 1;
- }
- }
-
- g_assert_not_reached ();
- return num_days;
-}
-
-
-/* This returns the last possible day in the same span as the given day.
- A span is all the days which are displayed next to each other from left to
- right. In the week view all spans are only 1 day, since Tuesday is below
- Monday rather than beside it etc. In the month view, if the weekends are not
- compressed then each week is a span, otherwise we have to break a span up
- on Saturday, use a separate span for Sunday, and start again on Monday. */
-static gint
-e_week_view_find_span_end (EWeekView *week_view,
- gint day)
-{
- gint week, col, sat_col, end_col;
-
- if (week_view->multi_week_view) {
- week = day / 7;
- col = day % 7;
-
- /* We default to the last column in the row. */
- end_col = 6;
-
- /* If the weekend is compressed we must end any spans on
- Saturday and Sunday. */
- if (week_view->compress_weekend) {
- sat_col = (5 + 7 - week_view->display_start_day) % 7;
- if (col <= sat_col)
- end_col = sat_col;
- else if (col == sat_col + 1)
- end_col = sat_col + 1;
- }
-
- return week * 7 + end_col;
- } else {
- return day;
- }
-}
-
-
static void
e_week_view_on_adjustment_changed (GtkAdjustment *adjustment,
EWeekView *week_view)
diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h
index 6717da9ea3..7fde751b3f 100644
--- a/calendar/gui/e-week-view.h
+++ b/calendar/gui/e-week-view.h
@@ -89,6 +89,11 @@ extern "C" {
/* The padding below the date string in the Month view. */
#define E_WEEK_VIEW_DATE_B_PAD 1
+/* We use a 7-bit field to store row numbers in EWeekViewEventSpan, so the
+ maximum number or rows we can allow is 127. It is very unlikely to be
+ reached anyway. */
+#define E_WEEK_VIEW_MAX_ROWS_PER_CELL 127
+
/* These index our colors array. */
typedef enum
{
@@ -445,6 +450,10 @@ void e_week_view_convert_time_to_display (EWeekView *week_view,
gint *suffix_width);
gint e_week_view_get_time_string_width (EWeekView *week_view);
+gint e_week_view_event_sort_func (const void *arg1,
+ const void *arg2);
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index eda8617b0b..96f88d79a7 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -1031,6 +1031,28 @@ gnome_calendar_get_cal_client (GnomeCalendar *gcal)
return priv->client;
}
+/**
+ * gnome_calendar_get_task_pad_cal_client:
+ * @gcal: A calendar view.
+ *
+ * Queries the calendar client interface object that a calendar view is using
+ * for the Task Pad.
+ *
+ * Return value: A calendar client interface object.
+ **/
+CalClient *
+gnome_calendar_get_task_pad_cal_client (GnomeCalendar *gcal)
+{
+ GnomeCalendarPrivate *priv;
+
+ g_return_val_if_fail (gcal != NULL, NULL);
+ g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), NULL);
+
+ priv = gcal->priv;
+
+ return priv->task_pad_client;
+}
+
gboolean
gnome_calendar_open (GnomeCalendar *gcal, const char *str_uri)
{
diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h
index 0192efabe4..b9b5cd42a3 100644
--- a/calendar/gui/gnome-cal.h
+++ b/calendar/gui/gnome-cal.h
@@ -65,6 +65,7 @@ GtkWidget *gnome_calendar_construct (GnomeCalendar *gcal);
GtkWidget *gnome_calendar_new (void);
CalClient *gnome_calendar_get_cal_client (GnomeCalendar *gcal);
+CalClient *gnome_calendar_get_task_pad_cal_client(GnomeCalendar *gcal);
gboolean gnome_calendar_open (GnomeCalendar *gcal, const char *str_uri);
/*
diff --git a/calendar/gui/print.c b/calendar/gui/print.c
index f89b1dae52..f6f798b88b 100644
--- a/calendar/gui/print.c
+++ b/calendar/gui/print.c
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
/* Evolution calendar - Print support
*
* Copyright (C) 2000 Helix Code, Inc.
@@ -38,14 +40,59 @@
#include <libgnomeprint/gnome-print-preview.h>
#include <libgnomeprint/gnome-printer-dialog.h>
#include <e-util/e-dialog-widgets.h>
+#include <e-util/e-time-utils.h>
#include <gal/widgets/e-unicode.h>
#include <cal-util/timeutil.h>
#include "calendar-commands.h"
+#include "calendar-config.h"
+#include "e-day-view.h"
+#include "e-day-view-layout.h"
+#include "e-week-view.h"
+#include "e-week-view-layout.h"
#include "gnome-cal.h"
#include "print.h"
+/*
+ * Note that most dimensions are in points (1/72 of an inch) since that is
+ * what gnome-print uses.
+ */
+
+/* The font size to use for normal text. */
+#define DAY_NORMAL_FONT_SIZE 12
+#define WEEK_NORMAL_FONT_SIZE 12
+#define MONTH_NORMAL_FONT_SIZE 8
+
+/* The height of the header bar across the top of the Day, Week & Month views,
+ which contains the dates shown and the 2 small calendar months. */
+#define HEADER_HEIGHT 80
+
+/* The width of the small calendar months, the space from the right edge of
+ the header rectangle, and the space between the months. */
+#define SMALL_MONTH_WIDTH 80
+#define SMALL_MONTH_PAD 4
+#define SMALL_MONTH_SPACING 12
+
+/* The minimum number of rows we leave space for for the long events in the
+ day view. */
+#define DAY_VIEW_MIN_ROWS_IN_TOP_DISPLAY 2
+
+/* The row height for long events in the day view. */
+#define DAY_VIEW_ROW_HEIGHT 20
+
+/* The minutes per row in the day view printout. */
+#define DAY_VIEW_MINS_PER_ROW 30
+
+#define DAY_VIEW_ROWS ((60 / DAY_VIEW_MINS_PER_ROW) * 24)
+
+/* The width of the column with all the times in it. */
+#define DAY_VIEW_TIME_COLUMN_WIDTH 36
+
+/* The space on the right of each event. */
+#define DAY_VIEW_EVENT_X_PAD 8
+
+
/* copied from gnome-month-item.c this should be shared?? */
/* Number of days in a month, for normal and leap years */
@@ -73,19 +120,42 @@ static const int sept_1752[42] = {
#define SEPT_1752_START 2 /* Start day within month */
#define SEPT_1752_END 20 /* End day within month */
-/* FIXME: This needs to be able to render using all the options from the new
- * calendar configuration stuff.
- */
-#define WEEK_STARTS_ON_MONDAY FALSE
struct pdinfo
{
- GList *slots;
+ gint days_shown;
+ time_t day_starts[E_DAY_VIEW_MAX_DAYS + 1];
+
+ GArray *long_events;
+ GArray *events[E_DAY_VIEW_MAX_DAYS];
+
+ gint start_hour;
+ gint end_hour;
+ gint start_minute_offset;
+ gint end_minute_offset;
+ gint rows;
+ gint mins_per_row;
+ gint8 cols_per_row[DAY_VIEW_ROWS];
+ gboolean use_24_hour_format;
};
struct psinfo
{
- GList *events;
+ gint days_shown;
+ time_t day_starts[E_WEEK_VIEW_MAX_WEEKS * 7 + 1];
+
+ GArray *events;
+
+ int rows_per_cell;
+ int rows_per_compressed_cell;
+ int display_start_weekday;
+ gboolean multi_week_view;
+ int weeks_shown;
+ int month;
+ gboolean compress_weekend;
+ gboolean use_24_hour_format;
+ double row_height;
+ double header_row_height;
};
struct ptinfo
@@ -159,10 +229,10 @@ day_in_week (int day, int month, int year)
* returned in the start and end arguments.
*/
static void
-build_month (int month, int year, int start_on_monday, int *days, int *start, int *end)
+build_month (int month, int year, int *days, int *start, int *end)
{
int i;
- int d_month, d_week;
+ int d_month, d_week, week_start_day;
/* Note that months are zero-based, so September is month 8 */
@@ -182,10 +252,15 @@ build_month (int month, int year, int start_on_monday, int *days, int *start, in
days[i] = 0;
d_month = days_in_month[is_leap_year (year)][month];
+ /* Get the start weekday in the month, 0=Sun to 6=Sat. */
d_week = day_in_week (1, month, year);
- if (start_on_monday)
- d_week = (d_week + 6) % 7;
+ /* Get the configuration setting specifying which weekday we put on
+ the left column, 0=Sun to 6=Sat. */
+ week_start_day = calendar_config_get_week_start_day ();
+
+ /* Figure out which square we want to put the 1 in. */
+ d_week = (d_week + 7 - week_start_day) % 7;
for (i = 0; i < d_month; i++)
days[d_week + i] = i + 1;
@@ -201,70 +276,135 @@ build_month (int month, int year, int start_on_monday, int *days, int *start, in
enum align_box {
ALIGN_LEFT=1,
ALIGN_RIGHT,
- ALIGN_CENTRE,
+ ALIGN_CENTER,
ALIGN_BORDER= 1<<8
};
-/* width = width of border, -'ve is no border
- fillcolour = shade of fill, -'ve is no fill */
+
+/* Prints a rectangle, with or without a border, filled or outline, and
+ possibly with triangular arrows at one or both horizontal edges.
+ width = width of border, -ve means no border.
+ fillcolor = shade of fill, -ve means no fill.
+ left_triangle_width, right_triangle_width = width from edge of rectangle to
+ point of triangle, or -ve for no triangle. */
static void
-print_border(GnomePrintContext *pc, double l, double r, double t, double b, double width, double fillcolour)
+print_border_with_triangles (GnomePrintContext *pc,
+ double l, double r, double t, double b,
+ double width, double fillcolor,
+ double left_triangle_width,
+ double right_triangle_width)
{
- int i;
gnome_print_gsave (pc);
- if (fillcolour<0.0)
- i=1;
- else
- i=0;
- for (;i<2;i++) {
- gnome_print_moveto(pc, l, t);
- gnome_print_lineto(pc, l, b);
- gnome_print_lineto(pc, r, b);
- gnome_print_lineto(pc, r, t);
- gnome_print_lineto(pc, l, t);
- if (i==0) {
- gnome_print_setrgbcolor(pc, fillcolour, fillcolour, fillcolour);
- gnome_print_fill(pc);
- if (width<0.0)
- i=2;
- } else {
- gnome_print_setrgbcolor(pc, 0, 0, 0);
- gnome_print_setlinewidth(pc, width);
- gnome_print_stroke(pc);
- }
+
+ /* Fill in the interior of the rectangle, if desired. */
+ if (fillcolor >= 0.0) {
+ gnome_print_moveto (pc, l, t);
+ if (left_triangle_width > 0.0)
+ gnome_print_lineto (pc, l - left_triangle_width,
+ (t + b) / 2);
+ gnome_print_lineto (pc, l, b);
+ gnome_print_lineto (pc, r, b);
+ if (right_triangle_width > 0.0)
+ gnome_print_lineto (pc, r + right_triangle_width,
+ (t + b) / 2);
+ gnome_print_lineto (pc, r, t);
+ gnome_print_closepath (pc);
+ gnome_print_setrgbcolor (pc, fillcolor, fillcolor,
+ fillcolor);
+ gnome_print_fill (pc);
+ }
+
+ /* Draw the outline, if desired. */
+ if (width >= 0.0) {
+ gnome_print_moveto (pc, l, t);
+ if (left_triangle_width > 0.0)
+ gnome_print_lineto (pc, l - left_triangle_width,
+ (t + b) / 2);
+ gnome_print_lineto (pc, l, b);
+ gnome_print_lineto (pc, r, b);
+ if (right_triangle_width > 0.0)
+ gnome_print_lineto (pc, r + right_triangle_width,
+ (t + b) / 2);
+ gnome_print_lineto (pc, r, t);
+ gnome_print_closepath (pc);
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ gnome_print_setlinewidth (pc, width);
+ gnome_print_stroke (pc);
}
+
gnome_print_grestore (pc);
}
-/* outputs 1 line of aligned text in a box */
+
+/* Prints a rectangle, with or without a border, and filled or outline.
+ width = width of border, -ve means no border.
+ fillcolor = shade of fill, -ve means no fill. */
+static void
+print_border (GnomePrintContext *pc,
+ double l, double r, double t, double b,
+ double width, double fillcolor)
+{
+ print_border_with_triangles (pc, l, r, t, b, width, fillcolor,
+ -1.0, -1.0);
+}
+
+
+/* Prints 1 line of aligned text in a box. It is centered vertically, and
+ the horizontal alignment can be either ALIGN_LEFT, ALIGN_RIGHT, or
+ ALIGN_CENTER. */
static void
-print_text(GnomePrintContext *pc, GnomeFont *font, const char *text, enum align_box align, double l, double r, double t, double b)
+print_text(GnomePrintContext *pc, GnomeFont *font, const char *text,
+ enum align_box align, double l, double r, double t, double b)
{
- double w, x;
+ double w, x, y;
+
gnome_print_gsave (pc);
- w = gnome_font_get_width_string(font, text);
- switch (align&3) {
- default:
+
+ w = gnome_font_get_width_string (font, text);
+
+ switch (align & 3) {
case ALIGN_LEFT:
+ default:
x = l;
break;
case ALIGN_RIGHT:
- x = l+(r-l)-w-2;
+ x = r - w;
break;
- case ALIGN_CENTRE:
- x = l+((r-l)-w)/2;
+ case ALIGN_CENTER:
+ x = l + ((r - l) - w) / 2;
break;
}
- gnome_print_moveto(pc, x, t - gnome_font_get_size (font));
- gnome_print_setfont(pc, font);
- gnome_print_setrgbcolor (pc, 0,0,0);
- gnome_print_show(pc, text);
+
+ /* Make sure we don't go off the left edge. */
+ x = MAX (l, x);
+
+ /* Calculate the top of where the text should be. */
+ y = (t + b + gnome_font_get_size (font)) / 2;
+
+ /* Now calculate the baseline. */
+ y -= gnome_font_get_ascender (font) + 1;
+
+ /* Set a clipping rectangle. */
+ gnome_print_moveto (pc, l, t);
+ gnome_print_lineto (pc, r, t);
+ gnome_print_lineto (pc, r, b);
+ gnome_print_lineto (pc, l, b);
+ gnome_print_closepath (pc);
+ gnome_print_clip (pc);
+
+ gnome_print_newpath (pc);
+ gnome_print_moveto (pc, x, y);
+ gnome_print_setfont (pc, font);
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ gnome_print_show (pc, text);
+
gnome_print_grestore (pc);
}
/* gets/frees the font for you, as a bold font */
static void
-print_text_size(GnomePrintContext *pc, double size, const char *text, enum align_box align, double l, double r, double t, double b)
+print_text_size(GnomePrintContext *pc, double size, const char *text,
+ enum align_box align, double l, double r, double t, double b)
{
GnomeFont *font;
@@ -274,19 +414,27 @@ print_text_size(GnomePrintContext *pc, double size, const char *text, enum align
}
static void
-titled_box(GnomePrintContext *pc, const char *text, GnomeFont *font, enum align_box align, double *l, double *r, double *t, double *b, double linewidth)
+titled_box (GnomePrintContext *pc, const char *text, GnomeFont *font,
+ enum align_box align, double *l, double *r, double *t, double *b,
+ double linewidth)
{
- if (align&ALIGN_BORDER) {
- gnome_print_gsave(pc);
- print_border(pc, *l, *r, *t, *t-gnome_font_get_size(font)-gnome_font_get_size(font)*0.4, linewidth, 0.9);
- print_border(pc, *l, *r, *t-gnome_font_get_size(font)-gnome_font_get_size(font)*0.4, *b, linewidth, -1.0);
- gnome_print_grestore(pc);
- *l+=2;
- *r-=2;
- *b+=2;
+ double size;
+
+ size = gnome_font_get_size (font);
+
+ if (align & ALIGN_BORDER) {
+ print_border (pc, *l, *r, *t, *t - size * 1.4,
+ linewidth, 0.9);
+ print_border (pc, *l, *r, *t - size * 1.4, *b,
+ linewidth, -1.0);
+
+ *l += 2;
+ *r -= 2;
+ *b += 2;
}
- print_text(pc, font, text, align, *l, *r, *t, *b);
- *t-=gnome_font_get_size(font)*1.4;
+
+ print_text (pc, font, text, align, *l, *r, *t, *t - size * 1.4);
+ *t -= size * 1.4;
}
enum datefmt {
@@ -346,67 +494,110 @@ format_date(time_t time, int flags, char *buffer, int bufflen)
print out the month small, embolden any days with events.
*/
static void
-print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal,
- time_t month, double left, double right, double top, double bottom,
- int titleflags, time_t greystart, time_t greyend, int bordertitle)
+print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal, time_t month,
+ double left, double right, double top, double bottom,
+ int titleflags, time_t greystart, time_t greyend,
+ int bordertitle)
{
CalClient *client;
GnomeFont *font, *font_bold, *font_normal;
time_t now, next;
int x, y;
int days[42];
- int day;
+ int day, weekday, week_start_day;
char buf[100];
struct tm tm;
- double xpad, ypad, size;
- char *daynames[] = { _("Su"), _("Mo"), _("Tu"), _("We"), _("Th"), _("Fr"), _("Sa") };
+ double font_size, max_font_size;
+ double header_size, col_width, row_height, text_xpad, w;
+ double cell_top, cell_bottom, cell_left, cell_right, text_right;
+ char *daynames[] = { N_("Su"), N_("Mo"), N_("Tu"), N_("We"),
+ N_("Th"), N_("Fr"), N_("Sa") };
+
+ /* Print the title, e.g. 'June 2001', in the top 16% of the area. */
+ format_date (month, titleflags, buf, 100);
+ header_size = (top - bottom) * 0.16;
+ font = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, FALSE,
+ header_size * 0.8);
+ if (bordertitle) {
+ print_border (pc, left, right, top, top - header_size,
+ 1.0, 0.9);
+ }
+ print_text (pc, font, buf, ALIGN_CENTER, left, right,
+ top - header_size * 0.1, top - header_size);
+ gtk_object_unref (GTK_OBJECT (font));
+
+ top -= header_size;
client = gnome_calendar_get_cal_client (gcal);
- xpad = (right-left)/7;
- ypad = (top-bottom)/8.3;
- if (xpad>ypad)
- size=ypad;
- else
- size=xpad;
+ col_width = (right - left) / 7;
- size = (xpad+ypad)/3.0;
+ /* The top row with the day abbreviations gets an extra bit of
+ vertical space around it. */
+ row_height = (top - bottom) / 7.4;
+
+ /* First we need to calculate a reasonable font size. We start with a
+ rough guess of just under the height of each row. */
+ font_size = row_height * 0.9;
+
+ /* Check that it isn't going to be too wide. The characters are about
+ twice as high as they are wide, but we need to fit two characters
+ into each cell, so we don't want to go over col_width. */
+ max_font_size = col_width * 0.65;
+
+ font_size = MIN (font_size, max_font_size);
- tm = *localtime (&month);
/* get month days */
- build_month(tm.tm_mon, tm.tm_year+1900, WEEK_STARTS_ON_MONDAY, days, 0, 0);
-
- /* build day-busy bits */
- now = time_month_begin(month);
-
- /* get title */
- format_date(month, titleflags, buf, 100);
- font = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 1, size*1.2); /* title font */
- if (bordertitle)
- print_border(pc,
- left, left+7*xpad, top, top-gnome_font_get_size(font)*1.3,
- 1.0, 0.9);
- print_text(pc, font, buf, ALIGN_CENTRE,
- left, left+7*xpad, top, top - gnome_font_get_size (font));
- gtk_object_unref (GTK_OBJECT (font));
+ tm = *localtime (&month);
+ build_month (tm.tm_mon, tm.tm_year + 1900, days, 0, 0);
+
+ font_normal = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0,
+ font_size);
+ font_bold = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0,
+ font_size);
- font_normal = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, size);
- font_bold = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0, size);
+ /* Get a reasonable estimate of the largest number we will need,
+ and use it to calculate the offset from the right edge of the
+ cell that we should put the numbers. */
+ w = gnome_font_get_width_string (font_bold, "23");
+ text_xpad = (col_width - w) / 2;
- gnome_print_setrgbcolor (pc, 0,0,0);
- for (x=0;x<7;x++) {
- print_text(pc, font_bold, daynames[(WEEK_STARTS_ON_MONDAY?x+1:x)%7], ALIGN_CENTRE,
- left+x*xpad, left+(x+1)*xpad, bottom+7*ypad, bottom+7*ypad-gnome_font_get_size(font_bold));
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+
+ /* Print the abbreviated day names across the top in bold. */
+ week_start_day = calendar_config_get_week_start_day ();
+ weekday = week_start_day;
+ for (x = 0; x < 7; x++) {
+ print_text (pc, font_bold, _(daynames[weekday]), ALIGN_CENTER,
+ left + x * col_width, left + (x + 1) * col_width,
+ top, top - row_height * 1.4);
+ weekday = (weekday + 1) % 7;
}
- for (y=0;y<6;y++) {
- for (x=0;x<7;x++) {
- day = days[y*7+x];
- if (day!=0) {
+ top -= row_height * 1.4;
+
+ now = time_month_begin (month);
+ for (y = 0; y < 6; y++) {
+
+ cell_top = top - y * row_height;
+ cell_bottom = cell_top - row_height;
+
+ for (x = 0; x < 7; x++) {
+
+ cell_left = left + x * col_width;
+ /* We add a 0.05 to make sure the cells meet up with
+ each other. Otherwise you sometimes get lines
+ between them which looks bad. Maybe I'm not using
+ coords in the way gnome-print expects. */
+ cell_right = cell_left + col_width + 0.05;
+ text_right = cell_right - text_xpad;
+
+ day = days[y * 7 + x];
+ if (day != 0) {
GList *uids;
- sprintf(buf, "%d", day);
+ sprintf (buf, "%d", day);
/* this is a slow messy way to do this ... but easy ... */
uids = cal_client_get_objects_in_range (client,
@@ -415,18 +606,18 @@ print_month_small (GnomePrintContext *pc, GnomeCalendar *gcal,
font = uids ? font_bold : font_normal;
cal_obj_uid_list_free (uids);
- next = time_add_day(now, 1);
- if ((now>=greystart && now<greyend)
- || (greystart>=now && greystart<next)) {
- print_border(pc,
- left+x*xpad+xpad*0.1,
- left+(x+1)*xpad+xpad*0.1,
- bottom+(5-y)*ypad+gnome_font_get_size(font)-ypad*0.15,
- bottom+(5-y)*ypad-ypad*0.15,
- -1.0, 0.75);
+ next = time_add_day (now, 1);
+ if ((now >= greystart && now < greyend)
+ || (greystart >= now && greystart < next)) {
+ print_border (pc,
+ cell_left, cell_right,
+ cell_top, cell_bottom,
+ -1.0, 0.75);
}
- print_text(pc, font, buf, ALIGN_RIGHT,
- left+x*xpad, left+(x+1)*xpad, bottom+(5-y)*ypad+gnome_font_get_size(font), bottom+(5-y)*ypad);
+ print_text (pc, font, buf, ALIGN_RIGHT,
+ cell_left, text_right,
+ cell_top, cell_bottom);
+
now = next;
}
}
@@ -530,151 +721,464 @@ bound_text(GnomePrintContext *pc, GnomeFont *font, const char *text,
return top;
}
-/*
- * Print Day Details
- */
-static gboolean
-print_day_details_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data)
+
+/* Draw the borders, lines, and times down the left of the day view. */
+static void
+print_day_background (GnomePrintContext *pc, GnomeCalendar *gcal,
+ time_t whence, struct pdinfo *pdi,
+ double left, double right, double top, double bottom)
{
- CalComponentText text;
- GList *l, *col = NULL;
- struct pdinfo *pdi = (struct pdinfo *)data;
- struct einfo *ei;
+ GnomeFont *font_hour, *font_minute;
+ double yinc, y;
+ double width = DAY_VIEW_TIME_COLUMN_WIDTH;
+ double font_size, max_font_size, hour_font_size, minute_font_size;
+ char buf[20], *minute;
+ gboolean use_24_hour;
+ int i, hour, row;
+
+ /* Fill the time column in light-gray. */
+ print_border (pc, left, left + width, top, bottom, -1.0, 0.9);
+
+ /* Draw the border around the entire view. */
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ print_border (pc, left, right, top, bottom, 1.0, -1.0);
- ei = g_new (struct einfo, 1);
+ /* Draw the vertical line on the right of the time column. */
+ gnome_print_setlinewidth (pc, 0.0);
+ gnome_print_moveto (pc, left + width, bottom);
+ gnome_print_lineto (pc, left + width, top);
+ gnome_print_stroke (pc);
- cal_component_get_summary (comp, &text);
- ei->text = g_strdup (text.value);
+ /* Calculate the row height. */
+ yinc = (top - bottom) / (pdi->end_hour - pdi->start_hour);
+
+ /* Get the 2 fonts we need. */
+ font_size = yinc * 0.6;
+ max_font_size = width * 0.5;
+ font_size = MIN (font_size, max_font_size);
+ font_hour = gnome_font_new_closest ("Times", GNOME_FONT_BOLD,
+ 0, font_size);
+ hour_font_size = gnome_font_get_size (font_hour);
+
+ font_size = yinc * 0.33;
+ max_font_size = width * 0.25;
+ font_size = MIN (font_size, max_font_size);
+ font_minute = gnome_font_new_closest ("Times", GNOME_FONT_BOOK,
+ 0, font_size);
+ minute_font_size = gnome_font_get_size (font_minute);
+
+ use_24_hour = calendar_config_get_24_hour_format ();
+
+ row = 0;
+ for (i = pdi->start_hour; i < pdi->end_hour; i++) {
+ y = top - yinc * (row + 1);
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
- ei->start = istart;
- ei->end = iend;
- ei->count = 0;
+ if (use_24_hour) {
+ hour = i;
+ minute = "00";
+ } else {
+ if (i < 12)
+ minute = _("am");
+ else
+ minute = _("pm");
+
+ hour = i % 12;
+ if (hour == 0)
+ hour = 12;
+ }
- for (l = pdi->slots; l; l = l->next) {
- struct einfo *testei;
+ /* the hour label/minute */
+ sprintf (buf, "%d", hour);
+ print_text (pc, font_hour, buf, ALIGN_RIGHT,
+ left, left + width * 0.58,
+ y + yinc - 4, y + yinc - 4 - hour_font_size);
+ print_text (pc, font_minute, minute, ALIGN_RIGHT,
+ left, left + width - 3,
+ y + yinc - 3, y + yinc - 3 - minute_font_size);
+
+ /* Draw the horizontal line between hours, across the entire
+ width of the day view. */
+ gnome_print_moveto (pc, left, y);
+ gnome_print_lineto (pc, right, y);
+ gnome_print_stroke (pc);
+
+ /* Draw the horizontal line for the 1/2-hours, across the
+ entire width except for part of the time column. */
+ gnome_print_moveto (pc, left + width * 0.6, y + yinc / 2);
+ gnome_print_lineto (pc, right, y + yinc / 2);
+ gnome_print_stroke (pc);
- col = (GList *)l->data;
- testei = (struct einfo *)col->data;
+ row++;
+ }
- if (ei->start >= testei->end) {
- col = g_list_prepend (col, ei);
- l->data = col;
- return TRUE;
- }
+ gtk_object_unref (GTK_OBJECT (font_hour));
+ gtk_object_unref (GTK_OBJECT (font_minute));
+}
- testei->count++;
- ei->count++;
+
+/* This adds one event to the view, adding it to the appropriate array. */
+static gint
+print_day_add_event (CalComponent *comp,
+ time_t start,
+ time_t end,
+ gint days_shown,
+ time_t *day_starts,
+ GArray *long_events,
+ GArray **events)
+
+{
+ EDayViewEvent event;
+ gint day, offset;
+ struct tm start_tm, end_tm;
+
+#if 0
+ g_print ("Day view lower: %s", ctime (&day_starts[0]));
+ g_print ("Day view upper: %s", ctime (&day_starts[days_shown]));
+ g_print ("Event start: %s", ctime (&start));
+ g_print ("Event end : %s\n", ctime (&end));
+#endif
+
+ /* Check that the event times are valid. */
+ g_return_val_if_fail (start <= end, -1);
+ g_return_val_if_fail (start < day_starts[days_shown], -1);
+ g_return_val_if_fail (end > day_starts[0], -1);
+
+ start_tm = *(localtime (&start));
+ end_tm = *(localtime (&end));
+
+ event.comp = comp;
+ gtk_object_ref (GTK_OBJECT (comp));
+ event.start = start;
+ event.end = end;
+ event.canvas_item = NULL;
+
+ /* Calculate the start & end minute, relative to the top of the
+ display. */
+ /*offset = day_view->first_hour_shown * 60
+ + day_view->first_minute_shown;*/
+ offset = 0;
+ event.start_minute = start_tm.tm_hour * 60 + start_tm.tm_min - offset;
+ event.end_minute = end_tm.tm_hour * 60 + end_tm.tm_min - offset;
+
+ event.start_row_or_col = -1;
+ event.num_columns = -1;
+
+ /* Find out which array to add the event to. */
+ for (day = 0; day < days_shown; day++) {
+ if (start >= day_starts[day] && end <= day_starts[day + 1]) {
+
+ /* Special case for when the appointment ends at
+ midnight, i.e. the start of the next day. */
+ if (end == day_starts[day + 1]) {
+
+ /* If the event last the entire day, then we
+ skip it here so it gets added to the top
+ canvas. */
+ if (start == day_starts[day])
+ break;
+
+ event.end_minute = 24 * 60;
+ }
+
+ g_array_append_val (events[day], event);
+ return day;
+ }
}
- col = NULL;
- col = g_list_prepend (col, ei);
- pdi->slots = g_list_append (pdi->slots, col);
+ /* The event wasn't within one day so it must be a long event,
+ i.e. shown in the top canvas. */
+ g_array_append_val (long_events, event);
+ return E_DAY_VIEW_LONG_EVENT;
+}
+
+
+static gboolean
+print_day_details_cb (CalComponent *comp, time_t istart, time_t iend,
+ gpointer data)
+{
+ struct pdinfo *pdi = (struct pdinfo *)data;
+
+ print_day_add_event (comp, istart, iend,
+ pdi->days_shown, pdi->day_starts,
+ pdi->long_events, pdi->events);
return TRUE;
}
+
static void
-print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
- double left, double right, double top, double bottom)
+free_event_array (GArray *array)
{
- CalClient *client;
- struct pdinfo pdi;
- time_t start, end;
- GList *l;
- int num_slots, i;
- GnomeFont *font_hour, *font_minute, *font_summary;
- double yinc, y, yend, x, xend;
- double width=40, slot_width;
- char buf[20];
+ EDayViewEvent *event;
+ gint event_num;
+
+ for (event_num = 0; event_num < array->len; event_num++) {
+ event = &g_array_index (array, EDayViewEvent, event_num);
+ if (event->canvas_item)
+ gtk_object_destroy (GTK_OBJECT (event->canvas_item));
+ gtk_object_unref (GTK_OBJECT (event->comp));
+ }
- client = gnome_calendar_get_cal_client (gcal);
+ g_array_set_size (array, 0);
+}
- yinc = (top-bottom)/24;
- /* fill static detail */
- font_hour = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0, yinc/2);
- font_minute = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0, yinc/3);
- font_summary = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, yinc/3);
+static void
+print_day_long_event (GnomePrintContext *pc, GnomeFont *font,
+ double left, double right, double top, double bottom,
+ double row_height, EDayViewEvent *event,
+ struct pdinfo *pdi)
+{
+ CalComponentText summary;
+ double x1, x2, y1, y2;
+ double left_triangle_width = -1.0, right_triangle_width = -1.0;
+ char *text;
+ char buffer[32];
+ struct tm date_tm;
+
+ /* If the event starts before the first day being printed, draw a
+ triangle. (Note that I am assuming we are just showing 1 day at
+ the moment.) */
+ if (event->start < pdi->day_starts[0])
+ left_triangle_width = 4;
+
+ /* If the event ends after the last day being printed, draw a
+ triangle. */
+ if (event->end > pdi->day_starts[1])
+ right_triangle_width = 4;
+
+ x1 = left + 10;
+ x2 = right - 10;
+ y1 = top - event->start_row_or_col * row_height - 4;
+ y2 = y1 - row_height + 4;
+ print_border_with_triangles (pc, x1, x2, y1, y2, 0.0, 0.95,
+ left_triangle_width,
+ right_triangle_width);
+
+ /* If the event starts after the first day being printed, we need to
+ print the start time. */
+ if (event->start > pdi->day_starts[0]) {
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->start_minute / 60;
+ date_tm.tm_min = event->start_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
+
+ e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
+ buffer, sizeof (buffer));
+
+ x1 += 4;
+ print_text (pc, font, buffer, ALIGN_LEFT, x1, x2, y1, y2);
+ x1 += gnome_font_get_width_string (font, buffer);
+ }
- gnome_print_setrgbcolor (pc, 0, 0, 0);
+ /* If the event ends before the end of the last day being printed,
+ we need to print the end time. */
+ if (event->end < pdi->day_starts[1]) {
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->end_minute / 60;
+ date_tm.tm_min = event->end_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
+
+ e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
+ buffer, sizeof (buffer));
+
+ x2 -= 4;
+ print_text (pc, font, buffer, ALIGN_RIGHT, x1, x2, y1, y2);
+ x2 -= gnome_font_get_width_string (font, buffer);
+ }
- /* internal lines */
- gnome_print_setlinewidth(pc, 0.0);
- gnome_print_moveto(pc, left+width, bottom);
- gnome_print_lineto(pc, left+width, top);
- gnome_print_stroke (pc);
+ /* Print the text. */
+ cal_component_get_summary (event->comp, &summary);
+ text = summary.value ? (char*) summary.value : "";
- for (i=0;i<24;i++) {
- y = top - yinc*(i+1);
- print_border(pc, left+1, left+width-1, y, y+yinc-1, -1.0, 0.9);
- gnome_print_setrgbcolor (pc, 0, 0, 0);
+ x1 += 4;
+ x2 -= 4;
+ print_text (pc, font, text, ALIGN_CENTER, x1, x2, y1, y2);
+}
- /* the hour label/minute */
- sprintf(buf, "%d", i);
- print_text(pc, font_hour, buf, ALIGN_RIGHT, left, left+width/2, y+yinc, y);
- switch(i) {
- case 12: sprintf(buf, _("pm")); break;
- case 0: sprintf(buf, _("am")); break;
- default: sprintf(buf, "00"); break;
- }
- print_text(pc, font_minute, buf, ALIGN_LEFT, left+width/2, left+width/2, y+yinc, y);
- /* internal lines */
- gnome_print_moveto(pc, left+width, y);
- gnome_print_lineto(pc, right, y);
- gnome_print_stroke (pc);
- gnome_print_moveto(pc, left+width/2, y+yinc/2);
- gnome_print_lineto(pc, right, y+yinc/2);
- gnome_print_stroke (pc);
+static void
+print_day_event (GnomePrintContext *pc, GnomeFont *font,
+ double left, double right, double top, double bottom,
+ EDayViewEvent *event, struct pdinfo *pdi)
+{
+ CalComponentText summary;
+ double x1, x2, y1, y2, col_width, row_height;
+ int start_offset, end_offset, start_row, end_row;
+ char *text, start_buffer[32], end_buffer[32];
+ gboolean display_times = FALSE, free_text = FALSE;
+ struct tm date_tm;
+
+ if ((event->start_minute >= pdi->end_minute_offset)
+ || (event->end_minute <= pdi->start_minute_offset))
+ return;
- }
+ start_offset = event->start_minute - pdi->start_minute_offset;
+ end_offset = event->end_minute - pdi->start_minute_offset;
- start = time_day_begin(whence);
- end = time_day_end(start);
+ start_row = start_offset / pdi->mins_per_row;
+ start_row = MAX (0, start_row);
+ end_row = (end_offset - 1) / pdi->mins_per_row;
+ end_row = MIN (pdi->rows - 1, end_row);
+ col_width = (right - left) / pdi->cols_per_row[event->start_minute / pdi->mins_per_row];
- pdi.slots = NULL;
+ if (start_offset != start_row * pdi->mins_per_row
+ || end_offset != (end_row + 1) * pdi->mins_per_row)
+ display_times = TRUE;
- cal_client_generate_instances (client, CALOBJ_TYPE_EVENT, start, end,
- print_day_details_cb, &pdi);
+ x1 = left + event->start_row_or_col * col_width;
+ x2 = x1 + event->num_columns * col_width - DAY_VIEW_EVENT_X_PAD;
+
+ row_height = (top - bottom) / pdi->rows;
+ y1 = top - start_row * row_height;
+ y2 = top - (end_row + 1) * row_height;
- num_slots = g_list_length (pdi.slots);
- slot_width = (right-left-width)/num_slots;
+#if 0
+ g_print ("Event: %g,%g %g,%g\n row_height: %g start_row: %i top: %g rows: %i\n",
+ x1, y1, x2, y2, row_height, start_row, top, pdi->rows);
+#endif
- for (i = num_slots, l = pdi.slots; l; i--, l = l->next) {
- GList *e = (GList *)l->data;
+ print_border (pc, x1, x2, y1, y2, 1.0, 0.95);
- for (; e; e = e->next) {
- struct einfo *ei = (struct einfo *)e->data;
+ cal_component_get_summary (event->comp, &summary);
+ text = summary.value ? (char*) summary.value : "";
- 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 (display_times) {
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->start_minute / 60;
+ date_tm.tm_min = event->start_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
- if (i == 0)
- xend = x + (num_slots - ei->count) * slot_width - 2;
- else
- xend = x + slot_width - 2;
+ e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
+ start_buffer, sizeof (start_buffer));
- print_border (pc, x, xend, y, yend, 0.0, 0.9);
+ date_tm.tm_hour = event->end_minute / 60;
+ date_tm.tm_min = event->end_minute % 60;
- bound_text (pc, font_summary, ei->text, x, xend, y, yend, 0);
+ e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
+ end_buffer, sizeof (end_buffer));
- g_free (ei);
- }
- g_list_free (e);
+ text = g_strdup_printf ("%s - %s %s ", start_buffer,
+ end_buffer, text);
+
+ free_text = TRUE;
}
- g_list_free (pdi.slots);
- print_border (pc, left, right, top, bottom, 1.0, -1.0);
+ bound_text (pc, font, text, x1 + 2, x2 - 2, y1, y2, 0);
- gtk_object_unref (GTK_OBJECT (font_hour));
- gtk_object_unref (GTK_OBJECT (font_minute));
- gtk_object_unref (GTK_OBJECT (font_summary));
+ if (free_text)
+ g_free (text);
}
+
+static void
+print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
+ double left, double right, double top, double bottom)
+{
+ CalClient *client;
+ EDayViewEvent *event;
+ GnomeFont *font;
+ time_t start, end;
+ struct pdinfo pdi;
+ gint rows_in_top_display, i;
+ double font_size, max_font_size;
+
+ start = time_day_begin (whence);
+ end = time_day_end (start);
+
+ pdi.days_shown = 1;
+ pdi.day_starts[0] = start;
+ pdi.day_starts[1] = end;
+ pdi.long_events = g_array_new (FALSE, FALSE, sizeof (EDayViewEvent));
+ pdi.events[0] = g_array_new (FALSE, FALSE, sizeof (EDayViewEvent));
+ pdi.start_hour = calendar_config_get_day_start_hour ();
+ pdi.end_hour = calendar_config_get_day_end_hour ();
+ if (calendar_config_get_day_end_minute () != 0)
+ pdi.end_hour++;
+ pdi.rows = (pdi.end_hour - pdi.start_hour) * 2;
+ pdi.mins_per_row = 30;
+ pdi.start_minute_offset = pdi.start_hour * 60;
+ pdi.end_minute_offset = pdi.end_hour * 60;
+ pdi.use_24_hour_format = calendar_config_get_24_hour_format ();
+
+ /* Get the events from the server. */
+ client = gnome_calendar_get_cal_client (gcal);
+ cal_client_generate_instances (client, CALOBJ_TYPE_EVENT, start, end,
+ print_day_details_cb, &pdi);
+ qsort (pdi.long_events->data, pdi.long_events->len,
+ sizeof (EDayViewEvent), e_day_view_event_sort_func);
+ qsort (pdi.events[0]->data, pdi.events[0]->len,
+ sizeof (EDayViewEvent), e_day_view_event_sort_func);
+
+ /* Lay them out the long events, across the top of the page. */
+ e_day_view_layout_long_events (pdi.long_events, pdi.days_shown,
+ pdi.day_starts, &rows_in_top_display);
+
+ /* Print the long events. */
+ font = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, 12);
+ for (i = 0; i < pdi.long_events->len; i++) {
+ event = &g_array_index (pdi.long_events, EDayViewEvent, i);
+ print_day_long_event (pc, font, left, right, top, bottom,
+ DAY_VIEW_ROW_HEIGHT, event, &pdi);
+ }
+ gtk_object_unref (GTK_OBJECT (font));
+
+ /* We always leave space for DAY_VIEW_MIN_ROWS_IN_TOP_DISPLAY in the
+ top display, but we may have more rows than that, in which case
+ the main display area will be compressed. */
+ rows_in_top_display = MAX (rows_in_top_display,
+ DAY_VIEW_MIN_ROWS_IN_TOP_DISPLAY);
+
+ /* Draw the border around the long events. */
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ print_border (pc, left, right,
+ top, top - rows_in_top_display * DAY_VIEW_ROW_HEIGHT - 4,
+ 1.0, -1.0);
+
+ /* Adjust the area containing the main display. */
+ top -= rows_in_top_display * DAY_VIEW_ROW_HEIGHT + 4;
+
+ /* Draw the borders, lines, and times down the left. */
+ print_day_background (pc, gcal, whence, &pdi,
+ left, right, top, bottom);
+
+ /* Now adjust to get rid of the time column. */
+ left += DAY_VIEW_TIME_COLUMN_WIDTH;
+
+ /* Lay out the short events, within the day. */
+ e_day_view_layout_day_events (pdi.events[0], DAY_VIEW_ROWS,
+ DAY_VIEW_MINS_PER_ROW, pdi.cols_per_row);
+
+ /* Print the short events. */
+ max_font_size = ((top - bottom) / pdi.rows) - 4;
+ font_size = MIN (DAY_NORMAL_FONT_SIZE, max_font_size);
+ font = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, font_size);
+ for (i = 0; i < pdi.events[0]->len; i++) {
+ event = &g_array_index (pdi.events[0], EDayViewEvent, i);
+ print_day_event (pc, font, left, right, top, bottom,
+ event, &pdi);
+ }
+ gtk_object_unref (GTK_OBJECT (font));
+
+ /* Free everything. */
+ free_event_array (pdi.long_events);
+ g_array_free (pdi.long_events, TRUE);
+ free_event_array (pdi.events[0]);
+ g_array_free (pdi.events[0], TRUE);
+}
+
+
/*
* Print Day Summary
*/
@@ -684,6 +1188,7 @@ print_day_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
#define TIME_FMT "%l:%M%p"
#endif
+#if 0
static gboolean
print_day_summary_cb (CalComponent *comp, time_t istart, time_t iend, gpointer data)
{
@@ -800,79 +1305,447 @@ print_day_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
gtk_object_unref (GTK_OBJECT (font_summary));
}
+#endif
+
+/* This adds one event to the view, adding it to the appropriate array. */
+static gboolean
+print_week_summary_cb (CalComponent *comp,
+ time_t start,
+ time_t end,
+ gpointer data)
+
+{
+ EWeekViewEvent event;
+ struct tm start_tm, end_tm;
+
+ struct psinfo *psi = (struct psinfo *)data;
+
+ /* Check that the event times are valid. */
+
+#if 0
+ g_print ("View start:%li end:%li Event start:%li end:%li\n",
+ psi->day_starts[0], psi->day_starts[psi->days_shown],
+ start, end);
+#endif
+
+ g_return_val_if_fail (start <= end, TRUE);
+ g_return_val_if_fail (start < psi->day_starts[psi->days_shown], TRUE);
+ g_return_val_if_fail (end > psi->day_starts[0], TRUE);
+
+ start_tm = *(localtime (&start));
+ end_tm = *(localtime (&end));
+
+ event.comp = comp;
+ gtk_object_ref (GTK_OBJECT (event.comp));
+ event.start = start;
+ event.end = end;
+ event.spans_index = 0;
+ event.num_spans = 0;
+
+ event.start_minute = start_tm.tm_hour * 60 + start_tm.tm_min;
+ event.end_minute = end_tm.tm_hour * 60 + end_tm.tm_min;
+ if (event.end_minute == 0 && start != end)
+ event.end_minute = 24 * 60;
+
+ g_array_append_val (psi->events, event);
+
+ return TRUE;
+}
+
+
+/* Returns TRUE if the event is a one-day event (i.e. not a long event). */
+static gboolean
+print_is_one_day_week_event (EWeekViewEvent *event,
+ EWeekViewEventSpan *span,
+ time_t *day_starts)
+{
+ if (event->start == day_starts[span->start_day]
+ && event->end == day_starts[span->start_day + 1])
+ return FALSE;
+
+ if (span->num_days == 1
+ && event->start >= day_starts[span->start_day]
+ && event->end <= day_starts[span->start_day + 1])
+ return TRUE;
+
+ return FALSE;
+}
+
static void
-print_week_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
- double left, double right, double top, double bottom)
+print_week_long_event (GnomePrintContext *pc, GnomeFont *font,
+ struct psinfo *psi,
+ double x1, double x2, double y1, double y2,
+ EWeekViewEvent *event, EWeekViewEventSpan *span,
+ char *text)
{
- double y, l, r, t, b;
- time_t now;
- int i;
+ double left_triangle_width = -1.0, right_triangle_width = -1.0;
+ struct tm date_tm;
+ char buffer[32];
+
+ /* If the event starts before the first day of the span, draw a
+ triangle to indicate it continues. */
+ if (event->start < psi->day_starts[span->start_day])
+ left_triangle_width = 4;
+
+ /* If the event ends after the last day of the span, draw a
+ triangle. */
+ if (event->end > psi->day_starts[span->start_day + span->num_days])
+ right_triangle_width = 4;
+
+ print_border_with_triangles (pc, x1, x2, y1, y2, 0.5, 0.9,
+ left_triangle_width,
+ right_triangle_width);
+
+ /* If the event starts after the first day being printed, we need to
+ print the start time. */
+ if (event->start > psi->day_starts[span->start_day]) {
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->start_minute / 60;
+ date_tm.tm_min = event->start_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
+
+ e_time_format_time (&date_tm, psi->use_24_hour_format, FALSE,
+ buffer, sizeof (buffer));
+
+ x1 += 4;
+ print_text (pc, font, buffer, ALIGN_LEFT, x1, x2, y1, y2);
+ x1 += gnome_font_get_width_string (font, buffer);
+ }
- l = left;
- r = (right-left)/2+left;
- t = top;
- y = (top-bottom)/3;
- b = top-y;
- now = time_week_begin(whence); /* returns sunday, we need monday */
- now = time_add_day(now, 1);
- for (i = 0; i < 7; i++) {
- print_day_summary (pc, gcal, now, l, r, t, b,
- 10, TRUE, DATE_DAY | DATE_DAYNAME | DATE_MONTH);
- now = time_add_day (now, 1);
- switch (i) {
- case 5:
- y /= 2.0;
- b += y;
- case 0:
- case 1:
- case 3:
- case 4:
- t -= y;
- b -= y;
- break;
- case 2:
- l = r;
- r = right;
- t = top;
- b = t-y;
- break;
- case 6:
- break;
+ /* If the event ends before the end of the last day being printed,
+ we need to print the end time. */
+ if (event->end < psi->day_starts[span->start_day + span->num_days]) {
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->end_minute / 60;
+ date_tm.tm_min = event->end_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
+
+ e_time_format_time (&date_tm, psi->use_24_hour_format, FALSE,
+ buffer, sizeof (buffer));
+
+ x2 -= 4;
+ print_text (pc, font, buffer, ALIGN_RIGHT, x1, x2, y1, y2);
+ x2 -= gnome_font_get_width_string (font, buffer);
+ }
+
+ x1 += 4;
+ x2 -= 4;
+ print_text (pc, font, text, ALIGN_CENTER, x1, x2, y1, y2);
+}
+
+
+static void
+print_week_day_event (GnomePrintContext *pc, GnomeFont *font,
+ struct psinfo *psi,
+ double x1, double x2, double y1, double y2,
+ EWeekViewEvent *event, EWeekViewEventSpan *span,
+ char *text)
+{
+ struct tm date_tm;
+ char buffer[32];
+
+ date_tm.tm_year = 2001;
+ date_tm.tm_mon = 0;
+ date_tm.tm_mday = 1;
+ date_tm.tm_hour = event->start_minute / 60;
+ date_tm.tm_min = event->start_minute % 60;
+ date_tm.tm_sec = 0;
+ date_tm.tm_isdst = -1;
+
+ e_time_format_time (&date_tm, psi->use_24_hour_format, FALSE,
+ buffer, sizeof (buffer));
+
+ print_text (pc, font, buffer, ALIGN_LEFT, x1, x2, y1, y2);
+ x1 += gnome_font_get_width_string (font, buffer);
+
+ x1 += 4;
+ print_text (pc, font, text, ALIGN_LEFT, x1, x2, y1, y2);
+}
+
+
+static void
+print_week_event (GnomePrintContext *pc, GnomeFont *font,
+ struct psinfo *psi,
+ double left, double top,
+ double cell_width, double cell_height,
+ EWeekViewEvent *event, GArray *spans)
+{
+ EWeekViewEventSpan *span;
+ gint span_num;
+ CalComponentText summary;
+ char *text;
+ int num_days, start_x, start_y, start_h, end_x, end_y, end_h;
+ double x1, x2, y1, y2;
+
+ cal_component_get_summary (event->comp, &summary);
+ text = summary.value ? (char*) summary.value : "";
+
+ for (span_num = 0; span_num < event->num_spans; span_num++) {
+ span = &g_array_index (spans, EWeekViewEventSpan,
+ event->spans_index + span_num);
+
+ if (e_week_view_layout_get_span_position
+ (event, span,
+ psi->rows_per_cell,
+ psi->rows_per_compressed_cell,
+ psi->display_start_weekday,
+ psi->multi_week_view,
+ psi->compress_weekend,
+ &num_days)) {
+
+ e_week_view_layout_get_day_position
+ (span->start_day,
+ psi->multi_week_view,
+ psi->weeks_shown,
+ psi->display_start_weekday,
+ psi->compress_weekend,
+ &start_x, &start_y, &start_h);
+
+ if (num_days == 1) {
+ end_x = start_x;
+ end_y = start_y;
+ end_h = start_h;
+ } else {
+ e_week_view_layout_get_day_position
+ (span->start_day + num_days - 1,
+ psi->multi_week_view,
+ psi->weeks_shown,
+ psi->display_start_weekday,
+ psi->compress_weekend,
+ &end_x, &end_y, &end_h);
+ }
+
+ x1 = left + start_x * cell_width + 6;
+ x2 = left + (end_x + 1) * cell_width - 6;
+ y1 = top - start_y * cell_height
+ - psi->header_row_height
+ - span->row * psi->row_height;
+ y2 = y1 - psi->row_height * 0.9;
+
+ if (print_is_one_day_week_event (event, span,
+ psi->day_starts)) {
+ print_week_day_event (pc, font, psi,
+ x1, x2, y1, y2,
+ event, span, text);
+ } else {
+ print_week_long_event (pc, font, psi,
+ x1, x2, y1, y2,
+ event, span, text);
+ }
}
}
}
+
+static void
+print_week_view_background (GnomePrintContext *pc, GnomeFont *font,
+ struct psinfo *psi,
+ double left, double top,
+ double cell_width, double cell_height)
+{
+ int day, day_x, day_y, day_h;
+ double x1, x2, y1, y2, font_size, fillcolor;
+ struct tm tm;
+ char *format_string, buffer[128];
+
+ font_size = gnome_font_get_size (font);
+
+ for (day = 0; day < psi->days_shown; day++) {
+ e_week_view_layout_get_day_position
+ (day, psi->multi_week_view, psi->weeks_shown,
+ psi->display_start_weekday, psi->compress_weekend,
+ &day_x, &day_y, &day_h);
+
+ x1 = left + day_x * cell_width;
+ x2 = left + (day_x + 1) * cell_width;
+ y1 = top - day_y * cell_height;
+ y2 = y1 - day_h * cell_height;
+
+ tm = *localtime (&psi->day_starts[day]);
+
+ /* In the month view we draw a grey background for the end
+ of the previous month and the start of the following. */
+ fillcolor = -1.0;
+ if (psi->multi_week_view && (tm.tm_mon != psi->month))
+ fillcolor = 0.9;
+
+ print_border (pc, x1, x2, y1, y2, 1.0, fillcolor);
+
+ if (psi->multi_week_view) {
+ if (tm.tm_mday == 1)
+ format_string = _("%d %B");
+ else
+ format_string = "%d";
+ } else {
+ gnome_print_moveto (pc, x1 + 0.1 * cell_width,
+ y1 - psi->header_row_height + 3);
+ gnome_print_lineto (pc, x2,
+ y1 - psi->header_row_height + 3);
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ gnome_print_setlinewidth (pc, 0.0);
+ gnome_print_stroke (pc);
+
+ /* strftime format %A = full weekday name, %d = day of
+ month, %B = full month name. You can change the
+ order but don't change the specifiers or add
+ anything. */
+ format_string = _("%A %d %B");
+
+ }
+
+ strftime (buffer, sizeof (buffer), format_string, &tm);
+ print_text (pc, font, buffer, ALIGN_RIGHT,
+ x1, x2 - 4, y1 - 2, y1 - 2 - font_size);
+ }
+}
+
+
+
+static void
+print_week_summary (GnomePrintContext *pc, GnomeCalendar *gcal,
+ time_t whence, gboolean multi_week_view, int weeks_shown,
+ int month, double font_size,
+ double left, double right, double top, double bottom)
+{
+ CalClient *client;
+ EWeekViewEvent *event;
+ struct psinfo psi;
+ time_t day_start;
+ gint rows_per_day[E_WEEK_VIEW_MAX_WEEKS * 7], day, event_num;
+ GArray *spans;
+ GnomeFont *font;
+ double cell_width, cell_height;
+
+ psi.days_shown = weeks_shown * 7;
+ psi.events = g_array_new (FALSE, FALSE, sizeof (EWeekViewEvent));
+ psi.multi_week_view = multi_week_view;
+ psi.weeks_shown = weeks_shown;
+ psi.month = month;
+
+ /* Get a few config settings. */
+ psi.compress_weekend = calendar_config_get_compress_weekend ();
+ psi.use_24_hour_format = calendar_config_get_24_hour_format ();
+
+ /* We convert this from (0 = Sun, 6 = Sat) to (0 = Mon, 6 = Sun). */
+ psi.display_start_weekday = calendar_config_get_week_start_day ();
+ psi.display_start_weekday = (psi.display_start_weekday + 6) % 7;
+
+ /* If weekends are compressed then we can't start on a Sunday. */
+ if (psi.compress_weekend && psi.display_start_weekday == 6)
+ psi.display_start_weekday = 5;
+
+ day_start = time_day_begin (whence);
+ for (day = 0; day <= psi.days_shown; day++) {
+ psi.day_starts[day] = day_start;
+ day_start = time_add_day (day_start, 1);
+ }
+
+ /* Get the events from the server. */
+ client = gnome_calendar_get_cal_client (gcal);
+ cal_client_generate_instances (client, CALOBJ_TYPE_EVENT,
+ psi.day_starts[0],
+ psi.day_starts[psi.days_shown],
+ print_week_summary_cb, &psi);
+ qsort (psi.events->data, psi.events->len,
+ sizeof (EWeekViewEvent), e_week_view_event_sort_func);
+
+ /* Layout the events. */
+ spans = e_week_view_layout_events (psi.events, NULL,
+ psi.multi_week_view,
+ psi.weeks_shown,
+ psi.compress_weekend,
+ psi.display_start_weekday,
+ psi.day_starts, rows_per_day);
+
+ /* Calculate the size of the cells. */
+ if (multi_week_view) {
+ cell_width = (right - left) / (psi.compress_weekend ? 6 : 7);
+ cell_height = (top - bottom) / (weeks_shown * 2);
+ } else {
+ cell_width = (right - left) / 2;
+ cell_height = (top - bottom) / 6;
+ }
+
+ /* Calculate the row height, using the normal font and with room for
+ space or a rectangle around it. */
+ psi.row_height = font_size * 1.2;
+ psi.header_row_height = font_size * 1.5;
+
+ /* Calculate how many rows we can fit into each type of cell. */
+ psi.rows_per_cell = ((cell_height * 2) - psi.header_row_height)
+ / psi.row_height;
+ psi.rows_per_compressed_cell = (cell_height - psi.header_row_height)
+ / psi.row_height;
+
+ font = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, font_size);
+
+ /* Draw the grid and the day names/numbers. */
+ print_week_view_background (pc, font, &psi, left, top,
+ cell_width, cell_height);
+
+ /* Print the events. */
+ for (event_num = 0; event_num < psi.events->len; event_num++) {
+ event = &g_array_index (psi.events, EWeekViewEvent, event_num);
+ print_week_event (pc, font, &psi, left, top,
+ cell_width, cell_height, event, spans);
+ }
+
+ gtk_object_unref (GTK_OBJECT (font));
+
+ /* Free everything. */
+ for (event_num = 0; event_num < psi.events->len; event_num++) {
+ event = &g_array_index (psi.events, EWeekViewEvent, event_num);
+ gtk_object_unref (GTK_OBJECT (event->comp));
+ }
+ g_array_free (psi.events, TRUE);
+ g_array_free (spans, TRUE);
+}
+
+
static void
print_year_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
- double left, double right, double top, double bottom, int morerows)
+ double left, double right, double top, double bottom,
+ int morerows)
{
- double y, x, l, r, t, b;
+ double row_height, col_width, l, r, t, b;
time_t now;
- int xx, yy, rows, cols;
+ int col, row, rows, cols;
l = left;
t = top;
+
+ /* If morerows is set we do 4 rows and 3 columns instead of 3 rows and
+ 4 columns. This is useful if we switch paper orientation. */
if (morerows) {
- rows=4;
- cols=3;
+ rows = 4;
+ cols = 3;
} else {
- rows=3;
- cols=4;
+ rows = 3;
+ cols = 4;
}
- y = (top-bottom)/rows;
- x = (right-left)/cols;
- r = l+x;
- b = top-y;
- now = time_year_begin(whence);
- for (yy = 0; yy < rows; yy++) {
- t = top - y * yy;
- b = t - y;
- for (xx = 0; xx < cols; xx++) {
- l = left + x * xx;
- r = l + x;
+
+ row_height = (top - bottom) / rows;
+ col_width = (right - left) / cols;
+ r = l + col_width;
+ b = top - row_height;
+ now = time_year_begin (whence);
+
+ for (row = 0; row < rows; row++) {
+ t = top - row_height * row;
+ b = t - row_height;
+ for (col = 0; col < cols; col++) {
+ l = left + col_width * col;
+ r = l + col_width;
print_month_small (pc, gcal, now,
- l + 8, r - 8, t - 8, b + 8, DATE_MONTH, 0, 0, TRUE);
+ l + 8, r - 8, t - 8, b + 8,
+ DATE_MONTH, 0, 0, TRUE);
now = time_add_month (now, 1);
}
}
@@ -882,54 +1755,75 @@ static void
print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
double left, double right, double top, double bottom)
{
- time_t now, today;
- int days[42];
- int day;
+ time_t date;
struct tm tm;
- int x, y;
- char buf[100];
- GnomeFont *font_days;
+ char buffer[100];
+ GnomeFont *font;
+ gboolean compress_weekend;
+ int columns, col, weekday, len, month;
+ double font_size, cell_width, x1, x2, y1, y2;
- now = time_month_begin(whence);
- tm = *localtime (&now);
+ weekday = calendar_config_get_week_start_day ();
+ compress_weekend = calendar_config_get_compress_weekend ();
- /* get month days */
- build_month(tm.tm_mon, tm.tm_year+1900, WEEK_STARTS_ON_MONDAY, days, 0, 0);
+ /* Remember which month we want. */
+ tm = *localtime (&whence);
+ month = tm.tm_mon;
+
+ /* Find the start of the month, and then the start of the week on
+ or before that day. */
+ date = time_month_begin (whence);
+ date = time_week_begin (date, weekday);
+
+ /* If weekends are compressed then we can't start on a Sunday. */
+ if (compress_weekend && weekday == 0)
+ date = time_add_day (date, -1);
- /* a little margin */
- top -= 4;
+ tm = *localtime (&date);
/* do day names ... */
- font_days = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0, 10);
- gnome_print_setfont(pc, font_days);
- for (x=0;x<7;x++) {
- today = time_add_day(now, days[6+x]);
- format_date(today, DATE_DAYNAME, buf, 100);
- print_text(pc, font_days, buf, ALIGN_CENTRE,
- (right-left)*x/7+left, (right-left)*(x+1)/7+left,
- top, top-gnome_font_get_size(font_days));
- }
- top -= gnome_font_get_size(font_days)*1.5;
- gtk_object_unref (GTK_OBJECT (font_days));
-
- for (y=0;y<6;y++) {
- for (x=0;x<7;x++) {
- day = days[y*7+x];
- if (day!=0) {
- print_day_summary (pc, gcal, now,
- (right-left)*x/7+left,
- (right-left)*(x+1)/7+left,
- top - (top-bottom)*y/6,
- top - (top-bottom)*(y+1)/6, 6, FALSE,
- day==1?(DATE_DAY|DATE_MONTH):DATE_DAY);
- now = time_add_day(now, 1);
- }
+ font = gnome_font_new_closest ("Times", GNOME_FONT_BOLD, 0,
+ MONTH_NORMAL_FONT_SIZE);
+ font_size = gnome_font_get_size (font);
+ gnome_print_setfont (pc, font);
+
+ columns = compress_weekend ? 6 : 7;
+ cell_width = (right - left) / columns;
+ y1 = top;
+ y2 = top - font_size * 1.5;
+
+ for (col = 0; col < columns; col++) {
+ if (tm.tm_wday == 6 && compress_weekend) {
+ strftime (buffer, sizeof (buffer), "%a/", &tm);
+ len = strlen (buffer);
+ tm.tm_mday++;
+ mktime (&tm);
+ strftime (buffer + len, sizeof (buffer) - len,
+ "%a", &tm);
+ } else {
+ strftime (buffer, sizeof (buffer), "%A", &tm);
}
+
+ x1 = left + cell_width * col;
+ x2 = x1 + cell_width;
+
+ print_border (pc, x1, x2, y1, y2, 1.0, -1.0);
+ print_text (pc, font, buffer, ALIGN_CENTER, x1, x2, y1, y2);
+
+ tm.tm_mday++;
+ mktime (&tm);
}
+ gtk_object_unref (GTK_OBJECT (font));
+
+ top = y2;
+ print_week_summary (pc, gcal, date, TRUE, 6, month,
+ MONTH_NORMAL_FONT_SIZE,
+ left, right, top, bottom);
}
static void
-print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, time_t end,
+print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal,
+ time_t start, time_t end,
double left, double right, double top, double bottom)
{
CalClient *client;
@@ -937,16 +1831,18 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, ti
GList *l;
GnomeFont *font_summary;
double y, yend, x, xend;
+ struct icaltimetype *tt;
- client = gnome_calendar_get_cal_client (gcal);
+ client = gnome_calendar_get_task_pad_cal_client (gcal);
- font_summary = gnome_font_new_closest ("Times", GNOME_FONT_BOOK, 0, 10);
+ font_summary = gnome_font_new_closest ("Times", GNOME_FONT_BOOK,
+ 0, 10);
gnome_print_setrgbcolor (pc, 0, 0, 0);
gnome_print_setlinewidth (pc, 0.0);
- titled_box (pc, _("Tasks"), font_summary,
- ALIGN_CENTRE | ALIGN_BORDER, &left, &right, &top, &bottom, 1.0);
+ titled_box (pc, _("Tasks"), font_summary, ALIGN_CENTER | ALIGN_BORDER,
+ &left, &right, &top, &bottom, 1.0);
y = top - 3;
yend = bottom - 2;
@@ -991,10 +1887,27 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, ti
if (y < bottom)
break;
- y = bound_text (pc, font_summary, summary.value, x + 2, xend, y, yend, 0);
- y += gnome_font_get_size (font_summary);
- gnome_print_moveto (pc, x, y - 3);
- gnome_print_lineto (pc, xend, y - 3);
+ /* Print the box to put the tick in. */
+ print_border (pc, x + 2, x + 8, y - 3, y - 11, 0.0, -1.0);
+
+ /* If the task is complete, print a tick in the box. */
+ cal_component_get_completed (comp, &tt);
+ if (tt) {
+ cal_component_free_icaltimetype (tt);
+
+ gnome_print_setrgbcolor (pc, 0, 0, 0);
+ gnome_print_setlinewidth (pc, 1.0);
+ gnome_print_moveto (pc, x + 3, y - 8);
+ gnome_print_lineto (pc, x + 5, y - 10);
+ gnome_print_lineto (pc, x + 7, y - 3.5);
+ gnome_print_stroke (pc);
+ }
+
+ y = bound_text (pc, font_summary, summary.value,
+ x + 10, xend, y, yend, 0);
+ y += gnome_font_get_size (font_summary) - 6;
+ gnome_print_moveto (pc, x, y);
+ gnome_print_lineto (pc, xend, y);
gnome_print_stroke (pc);
y -= 3;
}
@@ -1004,47 +1917,6 @@ print_todo_details (GnomePrintContext *pc, GnomeCalendar *gcal, time_t start, ti
gtk_object_unref (GTK_OBJECT (font_summary));
}
-#if 0
-
-static GnomePrintContext *
-print_context (int preview, char *paper)
-{
- GtkWidget *toplevel, *canvas, *sw;
- GnomePrinter *printer;
- GnomePrintContext *pc;
-
- if (preview) {
- gtk_widget_push_colormap (gdk_rgb_get_cmap ());
- gtk_widget_push_visual (gdk_rgb_get_visual ());
-
- toplevel = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_usize (toplevel, 700, 700);
- sw = gtk_scrolled_window_new (NULL, NULL);
- canvas = gnome_canvas_new_aa ();
- gtk_container_add (GTK_CONTAINER (toplevel), sw);
- gtk_container_add (GTK_CONTAINER (sw), canvas);
-
- gnome_canvas_set_pixels_per_unit((GnomeCanvas *)canvas, 1);
-
- pc = gnome_print_preview_new ((GnomeCanvas *)canvas, paper);
-
- gtk_widget_show_all (toplevel);
-
- gtk_widget_pop_visual ();
- gtk_widget_pop_colormap ();
- } else {
- printer = gnome_printer_dialog_new_modal ();
-
- if (!printer)
- return NULL;
-
- pc = gnome_print_context_new_with_paper_size (printer, paper);
- }
-
- return pc;
-}
-
-#endif
/* Value for the PrintView enum */
static const int print_view_map[] = {
@@ -1068,6 +1940,7 @@ range_selector_new (GtkWidget *dialog, time_t at, int *view)
struct tm tm;
time_t week_begin, week_end;
struct tm week_begin_tm, week_end_tm;
+ gint week_start_day;
box = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
@@ -1082,8 +1955,13 @@ range_selector_new (GtkWidget *dialog, time_t at, int *view)
/* Week */
- week_begin = time_week_begin (at);
- week_end = time_add_day (time_week_end (at), -1);
+ week_start_day = calendar_config_get_week_start_day ();
+ week_begin = time_week_begin (at, week_start_day);
+ /* If the week starts on a Sunday, we have to show the Saturday first,
+ since the weekend is compressed. */
+ if (week_start_day == 0)
+ week_begin = time_add_day (week_begin, -1);
+ week_end = time_add_day (week_end, 6);
week_begin_tm = *localtime (&week_begin);
week_end_tm = *localtime (&week_end);
@@ -1129,17 +2007,195 @@ range_selector_new (GtkWidget *dialog, time_t at, int *view)
return box;
}
+
+static void
+print_day_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
+ double left, double right, double top, double bottom)
+{
+ int i, days = 1;
+ double todo, header, l;
+ char buf[100];
+
+ for (i = 0; i < days; i++) {
+ todo = (right - left) * 0.75 + left;
+ header = top - HEADER_HEIGHT;
+
+ /* FIXME: What is the name supposed to be for? */
+ gnome_print_beginpage (pc, "Calendar Day View");
+
+ /* Print the main view with all the events in. */
+ print_day_details (pc, gcal, date,
+ left, todo - 2.0, header, bottom);
+
+ /* Print the TaskPad down the right. */
+ print_todo_details (pc, gcal, 0, INT_MAX,
+ todo, right, header, bottom);
+
+ /* Print the filled border around the header. */
+ print_border (pc, left, right, top, header + 2.0, 1.0, 0.9);
+
+ /* Print the 2 mini calendar-months. */
+ l = right - SMALL_MONTH_PAD - SMALL_MONTH_WIDTH * 2
+ - SMALL_MONTH_SPACING;
+ print_month_small (pc, gcal, date,
+ l, l + SMALL_MONTH_WIDTH,
+ top - 4, header + 4,
+ DATE_MONTH | DATE_YEAR, date, date, FALSE);
+
+ l += SMALL_MONTH_SPACING + SMALL_MONTH_WIDTH;
+ print_month_small (pc, gcal, time_add_month (date, 1),
+ l, l + SMALL_MONTH_WIDTH,
+ top - 4, header + 4,
+ DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
+
+ /* Print the date, e.g. '8th May, 2001'. */
+ format_date (date, DATE_DAY | DATE_MONTH | DATE_YEAR,
+ buf, 100);
+ print_text_size (pc, 24, buf, ALIGN_LEFT,
+ left + 4, todo, top - 4, top - 4 - 24);
+
+ /* Print the day, e.g. 'Tuesday'. */
+ format_date (date, DATE_DAYNAME, buf, 100);
+ print_text_size (pc, 18, buf, ALIGN_LEFT,
+ left + 4, todo, top - 32, top - 32 - 18);
+
+ gnome_print_showpage (pc);
+ date = time_add_day (date, 1);
+ }
+}
+
+
+static void
+print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
+ double left, double right, double top, double bottom)
+{
+ double header, l;
+ char buf[100];
+ time_t when;
+ gint week_start_day;
+
+ header = top - HEADER_HEIGHT;
+
+ /* FIXME: What is the name supposed to be for? */
+ gnome_print_beginpage (pc, "Calendar Week View");
+
+ week_start_day = calendar_config_get_week_start_day ();
+ when = time_week_begin (date, week_start_day);
+ /* If the week starts on a Sunday, we have to show the Saturday first,
+ since the weekend is compressed. */
+ if (week_start_day == 0)
+ when = time_add_day (when, -1);
+
+ /* Print the main week view. */
+ print_week_summary (pc, gcal, when, FALSE, 1, 0,
+ WEEK_NORMAL_FONT_SIZE,
+ left, right, header, bottom);
+
+ /* Print the border around the main view. */
+ print_border (pc, left, right, header, bottom, 1.0, -1.0);
+
+ /* Print the border around the header area. */
+ print_border (pc, left, right, top, header + 2.0, 1.0, 0.9);
+
+ /* Print the 2 mini calendar-months. */
+ l = right - SMALL_MONTH_PAD - SMALL_MONTH_WIDTH * 2
+ - SMALL_MONTH_SPACING;
+ print_month_small (pc, gcal, when,
+ l, l + SMALL_MONTH_WIDTH,
+ top - 4, header + 4,
+ DATE_MONTH | DATE_YEAR, when,
+ time_add_week (when, 1), FALSE);
+
+ l += SMALL_MONTH_SPACING + SMALL_MONTH_WIDTH;
+ print_month_small (pc, gcal, time_add_month (when, 1),
+ l, l + SMALL_MONTH_WIDTH,
+ top - 4, header + 4,
+ DATE_MONTH | DATE_YEAR, when,
+ time_add_week (when, 1), FALSE);
+
+ /* Print the start day of the week, e.g. '7th May 2001'. */
+ format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
+ print_text_size (pc, 24, buf, ALIGN_LEFT,
+ left + 3, right, top - 4, top - 4 - 24);
+
+ /* Print the end day of the week, e.g. '13th May 2001'. */
+ when = time_add_day (when, 6);
+ format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
+ print_text_size (pc, 24, buf, ALIGN_LEFT,
+ left + 3, right, top - 24 - 3, top - 24 - 3 - 24);
+
+ gnome_print_showpage (pc);
+}
+
+
+static void
+print_month_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
+ double left, double right, double top, double bottom)
+{
+ double header;
+ char buf[100];
+
+ header = top - HEADER_HEIGHT;
+
+ /* FIXME: What is the name supposed to be for? */
+ gnome_print_beginpage (pc, "Calendar Month View");
+
+ /* Print the main month view. */
+ print_month_summary (pc, gcal, date, left, right, header, bottom);
+
+ /* Print the border around the header. */
+ print_border (pc, left, right, top, header, 1.0, 0.9);
+
+ /* Print the 2 mini calendar-months. */
+ print_month_small (pc, gcal, time_add_month (date, 1),
+ right - (right - left) / 7 + 2, right - 8,
+ top - 4, header,
+ DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
+ print_month_small (pc, gcal, time_add_month (date, -1),
+ left + 8, left + (right - left) / 7 - 2,
+ top - 4, header,
+ DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
+
+ /* Print the month, e.g. 'May 2001'. */
+ format_date (date, DATE_MONTH | DATE_YEAR, buf, 100);
+ print_text_size (pc, 24, buf, ALIGN_CENTER,
+ left + 3, right - 3, top - 3, top - 3 - 24);
+
+ gnome_print_showpage (pc);
+}
+
+
+static void
+print_year_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
+ double left, double right, double top, double bottom)
+{
+ char buf[100];
+
+ /* FIXME: What is the name supposed to be for? */
+ gnome_print_beginpage (pc, "Calendar Year View");
+
+ print_year_summary (pc, gcal, date, left, right, top - 50, bottom,
+ TRUE);
+
+ /* centered title */
+ format_date (date, DATE_YEAR, buf, 100);
+ print_text_size (pc, 24, buf, ALIGN_CENTER,
+ left+3, right, top-3, top - 27);
+
+ gnome_print_showpage(pc);
+}
+
+
void
-print_calendar (GnomeCalendar *gcal, gboolean preview, time_t at, PrintView default_view)
+print_calendar (GnomeCalendar *gcal, gboolean preview, time_t date,
+ PrintView default_view)
{
GnomePrinter *printer;
GnomePrintMaster *gpm;
GnomePrintContext *pc;
int copies, collate;
const GnomePaper *paper_info;
- double l, r, t, b, todo, header;
- char buf[100];
- time_t when;
+ double l, r, t, b;
g_return_if_fail (gcal != NULL);
g_return_if_fail (GNOME_IS_CALENDAR (gcal));
@@ -1154,13 +2210,15 @@ print_calendar (GnomeCalendar *gcal, gboolean preview, time_t at, PrintView defa
int view;
gpd = gnome_print_dialog_new (_("Print Calendar"),
- GNOME_PRINT_DIALOG_RANGE | GNOME_PRINT_DIALOG_COPIES);
+ GNOME_PRINT_DIALOG_RANGE
+ | GNOME_PRINT_DIALOG_COPIES);
view = (int) default_view;
- range = range_selector_new (gpd, at, &view);
+ range = range_selector_new (gpd, date, &view);
gnome_print_dialog_construct_range_custom (GNOME_PRINT_DIALOG (gpd), range);
- gnome_dialog_set_default (GNOME_DIALOG (gpd), GNOME_PRINT_PRINT);
+ gnome_dialog_set_default (GNOME_DIALOG (gpd),
+ GNOME_PRINT_PRINT);
/* Run dialog */
@@ -1183,7 +2241,8 @@ print_calendar (GnomeCalendar *gcal, gboolean preview, time_t at, PrintView defa
e_dialog_get_values (gpd);
default_view = (PrintView) view;
- gnome_print_dialog_get_copies (GNOME_PRINT_DIALOG (gpd), &copies, &collate);
+ gnome_print_dialog_get_copies (GNOME_PRINT_DIALOG (gpd),
+ &copies, &collate);
printer = gnome_print_dialog_get_printer (GNOME_PRINT_DIALOG (gpd));
gnome_dialog_close (GNOME_DIALOG (gpd));
@@ -1204,111 +2263,29 @@ print_calendar (GnomeCalendar *gcal, gboolean preview, time_t at, PrintView defa
pc = gnome_print_master_get_context (gpm);
l = gnome_paper_lmargin (paper_info);
- r = gnome_paper_pswidth (paper_info) - gnome_paper_rmargin (paper_info);
- t = gnome_paper_psheight (paper_info) - gnome_paper_tmargin (paper_info);
+ r = gnome_paper_pswidth (paper_info)
+ - gnome_paper_rmargin (paper_info);
+ t = gnome_paper_psheight (paper_info)
+ - gnome_paper_tmargin (paper_info);
b = gnome_paper_bmargin (paper_info);
/* depending on the view, do a different output */
switch (default_view) {
- case PRINT_VIEW_DAY: {
- int i, days = 1;
-
- for (i = 0; i < days; i++) {
- todo = ((r - l) / 5) * 4 + l;
- header = t - 70;
- print_todo_details (pc, gcal, 0, INT_MAX, todo, r, header, b);
- print_day_details (pc, gcal, at, l, todo - 2.0, header, b);
-
- print_border (pc, l, r, t, header + 2.0, 1.0, 0.9);
-
- print_month_small (pc, gcal, at, r - 190, r - 104, t - 4,
- header + 8, DATE_MONTH | DATE_YEAR, at, at, FALSE);
- print_month_small (pc, gcal, time_add_month (at, 1), r - 90, r - 4, t - 4,
- header + 8, DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
-
- format_date (at, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
- print_text_size (pc, 24, buf, ALIGN_LEFT, l + 3, todo, t - 3, header);
-
- format_date (at, DATE_DAYNAME, buf, 100);
- print_text_size (pc, 18, buf, ALIGN_LEFT, l + 3, todo, t - 27 - 4, header);
- gnome_print_showpage (pc);
- at = time_add_day (at, 1);
- }
+ case PRINT_VIEW_DAY:
+ print_day_view (pc, gcal, date, l, r, t, b);
break;
- }
-
case PRINT_VIEW_WEEK:
- header = t - 70;
- print_week_summary (pc, gcal, at, l, r, header, b);
-
- /* more solid total outline */
- print_border (pc, l, r, header, b, 1.0, -1.0);
-
- /* header border */
- print_border (pc, l, r, t, header + 2.0, 1.0, 0.9);
-
- when = time_week_begin (at);
- when = time_add_day (when, 1);
-
- print_month_small (pc, gcal, at, r - 90, r - 4, t - 4,
- header + 8, DATE_MONTH | DATE_YEAR, when, time_add_week (when, 1),
- FALSE);
- print_month_small (pc, gcal, time_add_month (at, -1), r - 190, r - 104, t - 4,
- header + 8, DATE_MONTH | DATE_YEAR, when, time_add_week (when, 1),
- FALSE);
-
- format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
- print_text_size (pc, 24, buf, ALIGN_LEFT, l + 3, r, t - 4, header);
-
- when = time_add_day (when, 6);
- format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
- print_text_size (pc, 24, buf, ALIGN_LEFT, l + 3, r, t - 24 - 3, header);
- gnome_print_showpage (pc);
+ print_week_view (pc, gcal, date, l, r, t, b);
break;
-
case PRINT_VIEW_MONTH:
- header = t - 70;
gnome_print_rotate (pc, 90);
- gnome_print_translate (pc, 0, -gnome_paper_pswidth (paper_info));
- /*print_month_summary(pc, cal, at, l, r, header, b);*/
- print_month_summary (pc, gcal, at, b, t, r - 70, l);
-
- print_border (pc, b, t, r, r - 72.0, 1.0, 0.9);
-
- print_month_small (pc, gcal, time_add_month (at, 1),
- t - (t - b) / 7 + 2, t - 8, r - 4, r - 68,
- DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
- print_month_small (pc, gcal, time_add_month (at, -1),
- b + 8, b + (t - b) / 7 - 2, r - 4, r - 68,
- DATE_MONTH | DATE_YEAR, 0, 0, FALSE);
-
- /* centered title */
- format_date (at, DATE_MONTH | DATE_YEAR, buf, 100);
- print_text_size (pc, 24, buf, ALIGN_CENTRE, b + 3, t, r - 3, l);
- gnome_print_showpage (pc);
+ gnome_print_translate (pc, 0,
+ -gnome_paper_pswidth (paper_info));
+ print_month_view (pc, gcal, date, b, t, r, l);
break;
-
case PRINT_VIEW_YEAR:
-#if 0
- /* landscape */
- gnome_print_rotate(pc, 90);
- gnome_print_translate(pc, 0, -gnome_paper_pswidth(paper_info));
- print_year_summary(pc, gcal, at, b, t, r-50, l, FALSE);
-
- /* centered title */
- format_date(at, DATE_YEAR, buf, 100);
- print_text_size(pc, 24, buf, ALIGN_CENTRE, b+3, t, r-3, l);
-#else
- /* portrait */
- print_year_summary(pc, gcal, at, l, r, t-50, b, TRUE);
-
- /* centered title */
- format_date(at, DATE_YEAR, buf, 100);
- print_text_size(pc, 24, buf, ALIGN_CENTRE, l+3, r, t-3, b);
-#endif
- gnome_print_showpage(pc);
+ print_year_view (pc, gcal, date, l, r, t, b);
break;
-
default:
g_assert_not_reached ();
}
@@ -1318,10 +2295,12 @@ print_calendar (GnomeCalendar *gcal, gboolean preview, time_t at, PrintView defa
if (preview) {
GnomePrintMasterPreview *gpmp;
- gpmp = gnome_print_master_preview_new (gpm, _("Print Preview"));
+ gpmp = gnome_print_master_preview_new (gpm,
+ _("Print Preview"));
gtk_widget_show (GTK_WIDGET (gpmp));
- } else
+ } else {
gnome_print_master_print (gpm);
+ }
gtk_object_unref (GTK_OBJECT (gpm));
}