2003-02-25 Hans Petter Jansson <hpj@ximian.com> * gui/print.c (print_calendar): Use fixed margins of 5% of page width/height. This is the same cheat as gtkhtml employs to get around the fact that GNOME_PRINT_KEY_PAGE_MARGIN_* don't return useful values (I think). It sort of sucks, but is better than no margins at all. (print_comp): Ditto. svn path=/trunk/; revision=20066
2661 lines
73 KiB
C
2661 lines
73 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||
|
||
/* Evolution calendar - Print support
|
||
*
|
||
* Copyright (C) 2000 Ximian, Inc.
|
||
*
|
||
* Authors: Michael Zucchi <notzed@ximian.com>
|
||
* Federico Mena-Quintero <federico@ximian.com>
|
||
* Damon Chaplin <damon@ximian.com>
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of version 2 of the GNU General Public
|
||
* License as published by the Free Software Foundation.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||
*/
|
||
|
||
#include <config.h>
|
||
#include <sys/stat.h>
|
||
#include <sys/time.h>
|
||
#include <math.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
#include <glib.h>
|
||
#include <gtk/gtkradiobutton.h>
|
||
#include <libgnome/gnome-i18n.h>
|
||
#include <libgnomeui/gnome-dialog.h>
|
||
#include <libgnomeui/gnome-uidefs.h>
|
||
#include <libgnomeui/gnome-stock-icons.h>
|
||
#include <libgnomeprint/gnome-print.h>
|
||
#include <libgnomeprint/gnome-print-paper.h>
|
||
#include <libgnomeprint/gnome-print-job.h>
|
||
#include <libgnomeprintui/gnome-print-job-preview.h>
|
||
#include <libgnomeprintui/gnome-print-paper-selector.h>
|
||
#include <libgnomeprintui/gnome-print-preview.h>
|
||
#include <libgnomeprintui/gnome-print-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.
|
||
*/
|
||
|
||
/* GtkHTML prints using a fixed margin. It has code to get the margins from
|
||
* gnome-print keys, but it's commented out. The corresponding code here
|
||
* doesn't seem to work either (getting zero margins), so we adopt
|
||
* gtkhtml's cheat. */
|
||
#define TEMP_MARGIN .05
|
||
|
||
/* The fonts to use */
|
||
#define REGULAR_FONT "Sans Regular"
|
||
#define BOLD_FONT "Sans Bold"
|
||
|
||
/* 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
|
||
|
||
/* Allowance for small errors in floating point comparisons. */
|
||
#define EPSILON 0.01
|
||
|
||
/* The weird month of September 1752, where 3 Sep through 13 Sep were
|
||
eliminated due to the Gregorian reformation. */
|
||
static const int sept_1752[42] = {
|
||
0, 0, 1, 2, 14, 15, 16,
|
||
17, 18, 19, 20, 21, 22, 23,
|
||
24, 25, 26, 27, 28, 29, 30,
|
||
0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0,
|
||
0, 0, 0, 0, 0, 0, 0
|
||
};
|
||
#define SEPT_1752_START 2 /* Start day within month */
|
||
#define SEPT_1752_END 20 /* End day within month */
|
||
|
||
|
||
struct pdinfo
|
||
{
|
||
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
|
||
{
|
||
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
|
||
{
|
||
GList *todos;
|
||
};
|
||
|
||
struct einfo
|
||
{
|
||
char *text;
|
||
time_t start;
|
||
time_t end;
|
||
int count;
|
||
};
|
||
|
||
static GnomePrintConfig *print_config = NULL;
|
||
|
||
|
||
/* Convenience function to help the transition to timezone functions.
|
||
It returns the current timezone. */
|
||
static icaltimezone*
|
||
get_timezone (void)
|
||
{
|
||
char *location = calendar_config_get_timezone ();
|
||
return icaltimezone_get_builtin_timezone (location);
|
||
}
|
||
|
||
|
||
/* Convenience function to help the transition to timezone functions.
|
||
It converts a time_t to a struct tm. */
|
||
static struct tm*
|
||
convert_timet_to_struct_tm (time_t time, icaltimezone *zone)
|
||
{
|
||
static struct tm my_tm;
|
||
struct icaltimetype tt;
|
||
|
||
/* Convert it to an icaltimetype. */
|
||
tt = icaltime_from_timet_with_zone (time, FALSE, zone);
|
||
|
||
/* Fill in the struct tm. */
|
||
my_tm.tm_year = tt.year - 1900;
|
||
my_tm.tm_mon = tt.month - 1;
|
||
my_tm.tm_mday = tt.day;
|
||
my_tm.tm_hour = tt.hour;
|
||
my_tm.tm_min = tt.minute;
|
||
my_tm.tm_sec = tt.second;
|
||
my_tm.tm_isdst = tt.is_daylight;
|
||
|
||
my_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1, tt.year);
|
||
|
||
return &my_tm;
|
||
}
|
||
|
||
|
||
/* Fills the 42-element days array with the day numbers for the specified month. Slots outside the
|
||
* bounds of the month are filled with zeros. The starting and ending indexes of the days are
|
||
* returned in the start and end arguments.
|
||
*/
|
||
static void
|
||
build_month (int month, int year, int *days, int *start, int *end)
|
||
{
|
||
int i;
|
||
int d_month, d_week, week_start_day;
|
||
|
||
/* Note that months are zero-based, so September is month 8 */
|
||
|
||
if ((year == 1752) && (month == 8)) {
|
||
memcpy (days, sept_1752, 42 * sizeof (int));
|
||
|
||
if (start)
|
||
*start = SEPT_1752_START;
|
||
|
||
if (end)
|
||
*end = SEPT_1752_END;
|
||
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < 42; i++)
|
||
days[i] = 0;
|
||
|
||
d_month = time_days_in_month (year, month);
|
||
/* Get the start weekday in the month, 0=Sun to 6=Sat. */
|
||
d_week = time_day_of_week (1, month, year);
|
||
|
||
/* 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;
|
||
|
||
if (start)
|
||
*start = d_week;
|
||
|
||
if (end)
|
||
*end = d_week + d_month - 1;
|
||
}
|
||
|
||
static GnomeFont *
|
||
get_font_for_size (double h, GnomeFontWeight weight, gboolean italic)
|
||
{
|
||
GnomeFontFace *face;
|
||
GnomeFont *font;
|
||
double asc, desc, size;
|
||
gchar *font_name;
|
||
|
||
if (weight <= GNOME_FONT_BOOK)
|
||
font_name = REGULAR_FONT;
|
||
else
|
||
font_name = BOLD_FONT;
|
||
|
||
if (italic)
|
||
font_name = g_strconcat (font_name, " Italic", NULL);
|
||
|
||
/* This function is broken in gnome-print (it doesn't find a suitable face).
|
||
* face = gnome_font_face_find_closest_from_weight_slant (DEFAULT_FONT, weight, italic); */
|
||
face = gnome_font_face_find (font_name);
|
||
|
||
asc = gnome_font_face_get_ascender (face);
|
||
desc = abs (gnome_font_face_get_descender (face));
|
||
size = h * 1000 / (asc + desc);
|
||
|
||
g_print ("Print Info: %f, %f, %f\n", asc, desc, size);
|
||
|
||
/* This function is broken in gnome-print (it doesn't find a suitable font).
|
||
* font = gnome_font_find_closest_from_weight_slant (DEFAULT_FONT, weight, italic, size); */
|
||
font = gnome_font_find_closest (font_name, size);
|
||
|
||
g_object_unref (face);
|
||
if (italic)
|
||
g_free (font_name);
|
||
return font;
|
||
}
|
||
|
||
enum align_box {
|
||
ALIGN_LEFT=1,
|
||
ALIGN_RIGHT,
|
||
ALIGN_CENTER,
|
||
ALIGN_BORDER= 1<<8
|
||
};
|
||
|
||
|
||
/* 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_with_triangles (GnomePrintContext *pc,
|
||
double l, double r, double t, double b,
|
||
double width, double fillcolor,
|
||
double left_triangle_width,
|
||
double right_triangle_width)
|
||
{
|
||
gnome_print_gsave (pc);
|
||
|
||
/* Fill in the interior of the rectangle, if desired. */
|
||
if (fillcolor >= -EPSILON) {
|
||
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 >= -EPSILON) {
|
||
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);
|
||
}
|
||
|
||
|
||
/* 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)
|
||
{
|
||
double w, x, y;
|
||
|
||
gnome_print_gsave (pc);
|
||
|
||
w = gnome_font_get_width_utf8 (font, text);
|
||
|
||
switch (align & 3) {
|
||
case ALIGN_LEFT:
|
||
default:
|
||
x = l;
|
||
break;
|
||
case ALIGN_RIGHT:
|
||
x = r - w;
|
||
break;
|
||
case ALIGN_CENTER:
|
||
x = l + ((r - l) - w) / 2;
|
||
break;
|
||
}
|
||
|
||
/* Make sure we don't go off the left edge. */
|
||
x = MAX (l, x);
|
||
|
||
/* Now calculate the baseline. */
|
||
y = t - gnome_font_get_ascender (font);
|
||
|
||
/* 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 book font */
|
||
static void
|
||
print_text_size(GnomePrintContext *pc, const char *text,
|
||
enum align_box align, double l, double r, double t, double b)
|
||
{
|
||
GnomeFont *font;
|
||
|
||
font = get_font_for_size (t - b, GNOME_FONT_BOOK, FALSE);
|
||
print_text(pc, font, text, align, l, r, t, b);
|
||
g_object_unref (font);
|
||
}
|
||
|
||
/* gets/frees the font for you, as a bold font */
|
||
static void
|
||
print_text_size_bold(GnomePrintContext *pc, const char *text,
|
||
enum align_box align, double l, double r, double t, double b)
|
||
{
|
||
GnomeFont *font;
|
||
|
||
font = get_font_for_size (t - b, GNOME_FONT_BOLD, FALSE);
|
||
print_text(pc, font, text, align, l, r, t, b);
|
||
g_object_unref (font);
|
||
}
|
||
|
||
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)
|
||
{
|
||
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, *t - size * 1.4);
|
||
*t -= size * 1.4;
|
||
}
|
||
|
||
enum datefmt {
|
||
DATE_MONTH = 1 << 0,
|
||
DATE_DAY = 1 << 1,
|
||
DATE_DAYNAME = 1 << 2,
|
||
DATE_YEAR = 1 << 3
|
||
};
|
||
|
||
static char *days[] = {
|
||
N_("1st"), N_("2nd"), N_("3rd"), N_("4th"), N_("5th"),
|
||
N_("6th"), N_("7th"), N_("8th"), N_("9th"), N_("10th"),
|
||
N_("11th"), N_("12th"), N_("13th"), N_("14th"), N_("15th"),
|
||
N_("16th"), N_("17th"), N_("18th"), N_("19th"), N_("20th"),
|
||
N_("21st"), N_("22nd"), N_("23rd"), N_("24th"), N_("25th"),
|
||
N_("26th"), N_("27th"), N_("28th"), N_("29th"), N_("30th"),
|
||
N_("31st")
|
||
};
|
||
|
||
/*
|
||
format the date 'nicely' and consistently for various headers
|
||
*/
|
||
static char *
|
||
format_date(time_t time, int flags, char *buffer, int bufflen)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
char fmt[64];
|
||
struct tm tm;
|
||
char *utf_str;
|
||
|
||
tm = *convert_timet_to_struct_tm (time, zone);
|
||
|
||
fmt[0] = 0;
|
||
if (flags & DATE_DAYNAME) {
|
||
strcat(fmt, "%A");
|
||
}
|
||
if (flags & DATE_DAY) {
|
||
if (flags & DATE_DAYNAME)
|
||
strcat(fmt, " ");
|
||
strcat(fmt, gettext(days[tm.tm_mday-1]));
|
||
}
|
||
if (flags & DATE_MONTH) {
|
||
if (flags & (DATE_DAY|DATE_DAYNAME))
|
||
strcat(fmt, " ");
|
||
strcat(fmt, "%B");
|
||
if ((flags & (DATE_DAY|DATE_YEAR)) == (DATE_DAY|DATE_YEAR))
|
||
strcat(fmt, ",");
|
||
}
|
||
if (flags & DATE_YEAR) {
|
||
if (flags & (DATE_DAY|DATE_DAYNAME|DATE_MONTH))
|
||
strcat(fmt, " ");
|
||
strcat(fmt, "%Y");
|
||
}
|
||
strftime(buffer, bufflen, fmt, &tm);
|
||
utf_str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
|
||
strncpy (buffer, utf_str, bufflen - 1);
|
||
buffer[bufflen - 1] = '\0';
|
||
g_free (utf_str);
|
||
return buffer;
|
||
}
|
||
|
||
|
||
/*
|
||
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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
CalClient *client;
|
||
GnomeFont *font, *font_bold, *font_normal;
|
||
time_t now, next;
|
||
int x, y;
|
||
int days[42];
|
||
int day, weekday, week_start_day;
|
||
char buf[100];
|
||
struct tm tm;
|
||
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 = get_font_for_size (header_size, GNOME_FONT_BOLD, FALSE);
|
||
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, top - header_size);
|
||
g_object_unref (font);
|
||
|
||
top -= header_size;
|
||
|
||
client = gnome_calendar_get_cal_client (gcal);
|
||
|
||
col_width = (right - left) / 7;
|
||
|
||
/* 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;
|
||
|
||
/* 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 = row_height;
|
||
|
||
/* get month days */
|
||
tm = *convert_timet_to_struct_tm (month, zone);
|
||
build_month (tm.tm_mon, tm.tm_year + 1900, days, 0, 0);
|
||
|
||
font_normal = get_font_for_size (font_size, GNOME_FONT_BOOK, FALSE);
|
||
font_bold = get_font_for_size (font_size, GNOME_FONT_BOLD, FALSE);
|
||
|
||
/* 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_utf8 (font_bold, "23");
|
||
text_xpad = (col_width - w) / 2;
|
||
|
||
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;
|
||
}
|
||
|
||
top -= row_height * 1.4;
|
||
|
||
now = time_month_begin_with_zone (month, zone);
|
||
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);
|
||
|
||
/* this is a slow messy way to do this ... but easy ... */
|
||
uids = cal_client_get_objects_in_range (client,
|
||
CALOBJ_TYPE_EVENT,
|
||
now, time_day_end_with_zone (now, zone));
|
||
font = uids ? font_bold : font_normal;
|
||
cal_obj_uid_list_free (uids);
|
||
|
||
next = time_add_day_with_zone (now, 1, zone);
|
||
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,
|
||
cell_left, text_right,
|
||
cell_top, cell_bottom);
|
||
|
||
now = next;
|
||
}
|
||
}
|
||
}
|
||
g_object_unref (font_normal);
|
||
g_object_unref (font_bold);
|
||
}
|
||
|
||
|
||
|
||
/* wraps text into the print context, not taking up more than its allowed space */
|
||
static double
|
||
bound_text(GnomePrintContext *pc, GnomeFont *font, const char *text,
|
||
double left, double right, double top, double bottom, double indent)
|
||
{
|
||
double maxwidth = right-left;
|
||
double width;
|
||
const char *p;
|
||
char *wordstart;
|
||
int c;
|
||
char *outbuffer, *o, *outbuffendmarker;
|
||
int outbufflen;
|
||
int dump=0;
|
||
int first=1;
|
||
|
||
g_return_val_if_fail(text!=NULL, top);
|
||
|
||
if (top<bottom) {
|
||
/* too much to fit in appointment printout */
|
||
return top;
|
||
}
|
||
|
||
outbufflen = 1024;
|
||
outbuffer = g_malloc(outbufflen);
|
||
outbuffendmarker = outbuffer+outbufflen-2;
|
||
|
||
top -= gnome_font_get_size (font);
|
||
gnome_print_setfont (pc, font);
|
||
|
||
width=0;
|
||
p = text;
|
||
wordstart = outbuffer;
|
||
o = outbuffer;
|
||
while ((c=*p)) {
|
||
if (c=='\n') {
|
||
wordstart=o;
|
||
dump=1;
|
||
} else {
|
||
/* grow output buffer if required */
|
||
if (o>=outbuffendmarker) {
|
||
char *newbuf;
|
||
outbufflen*=2;
|
||
newbuf = g_realloc(outbuffer, outbufflen);
|
||
o = newbuf+(o-outbuffer);
|
||
wordstart = newbuf+(o-outbuffer);
|
||
outbuffer = newbuf;
|
||
outbuffendmarker = outbuffer+outbufflen-2;
|
||
}
|
||
*o++=c;
|
||
if (c==' ')
|
||
wordstart = o;
|
||
width+=gnome_font_get_glyph_width(font, gnome_font_lookup_default (font, c));
|
||
if (width>maxwidth)
|
||
dump=1;
|
||
else
|
||
dump=0;
|
||
}
|
||
if (dump) {
|
||
if (wordstart==outbuffer)
|
||
wordstart=o;
|
||
c=*wordstart;
|
||
*wordstart=0;
|
||
gnome_print_moveto(pc, left, top);
|
||
gnome_print_show(pc, outbuffer);
|
||
*wordstart=c;
|
||
memcpy(outbuffer, wordstart, o-wordstart);
|
||
width = gnome_font_get_width_utf8_sized(font, outbuffer, o-wordstart);
|
||
o=outbuffer+(o-wordstart);
|
||
wordstart = outbuffer;
|
||
top -= gnome_font_get_size (font);
|
||
if (top<bottom) {
|
||
/* too much to fit, drop the rest */
|
||
g_free(outbuffer);
|
||
return top;
|
||
}
|
||
if (first) {
|
||
left += indent;
|
||
maxwidth -= indent;
|
||
first=0;
|
||
}
|
||
}
|
||
p++;
|
||
}
|
||
if (dump==0) {
|
||
*o=0;
|
||
gnome_print_moveto(pc, left, top);
|
||
gnome_print_show(pc, outbuffer);
|
||
top -= gnome_font_get_size (font);
|
||
}
|
||
g_free(outbuffer);
|
||
return top;
|
||
}
|
||
|
||
|
||
/* 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)
|
||
{
|
||
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];
|
||
const char *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);
|
||
|
||
/* 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);
|
||
|
||
/* 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;
|
||
hour_font_size = MIN (font_size, max_font_size);
|
||
font_hour = get_font_for_size (hour_font_size, GNOME_FONT_BOLD, FALSE);
|
||
|
||
font_size = yinc * 0.33;
|
||
max_font_size = width * 0.25;
|
||
minute_font_size = MIN (font_size, max_font_size);
|
||
font_minute = get_font_for_size (minute_font_size, GNOME_FONT_BOLD, FALSE);
|
||
|
||
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);
|
||
|
||
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;
|
||
}
|
||
|
||
/* 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);
|
||
|
||
row++;
|
||
}
|
||
|
||
g_object_unref (font_hour);
|
||
g_object_unref (font_minute);
|
||
}
|
||
|
||
|
||
/* 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)
|
||
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
EDayViewEvent event;
|
||
gint day, offset;
|
||
struct icaltimetype start_tt, end_tt;
|
||
|
||
#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_tt = icaltime_from_timet_with_zone (start, FALSE, zone);
|
||
end_tt = icaltime_from_timet_with_zone (end, FALSE, zone);
|
||
|
||
event.comp = comp;
|
||
g_object_ref (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_tt.hour * 60 + start_tt.minute - offset;
|
||
event.end_minute = end_tt.hour * 60 + end_tt.minute - offset;
|
||
|
||
event.start_row_or_col = 0;
|
||
event.num_columns = 0;
|
||
|
||
/* 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;
|
||
}
|
||
}
|
||
|
||
/* 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
|
||
free_event_array (GArray *array)
|
||
{
|
||
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));
|
||
g_object_unref (event->comp);
|
||
}
|
||
|
||
g_array_set_size (array, 0);
|
||
}
|
||
|
||
|
||
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.5, 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_utf8 (font, buffer);
|
||
}
|
||
|
||
/* 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_utf8 (font, buffer);
|
||
}
|
||
|
||
/* Print the text. */
|
||
cal_component_get_summary (event->comp, &summary);
|
||
text = summary.value ? (char*) summary.value : "";
|
||
|
||
x1 += 4;
|
||
x2 -= 4;
|
||
print_text (pc, font, text, ALIGN_CENTER, x1, x2, y1, y2);
|
||
}
|
||
|
||
|
||
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_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];
|
||
|
||
if (start_offset != start_row * pdi->mins_per_row
|
||
|| end_offset != (end_row + 1) * pdi->mins_per_row)
|
||
display_times = TRUE;
|
||
|
||
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;
|
||
|
||
#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
|
||
|
||
print_border (pc, x1, x2, y1, y2, 1.0, 0.95);
|
||
|
||
cal_component_get_summary (event->comp, &summary);
|
||
text = summary.value ? (char*) summary.value : "";
|
||
|
||
|
||
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;
|
||
|
||
e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
|
||
start_buffer, sizeof (start_buffer));
|
||
|
||
date_tm.tm_hour = event->end_minute / 60;
|
||
date_tm.tm_min = event->end_minute % 60;
|
||
|
||
e_time_format_time (&date_tm, pdi->use_24_hour_format, FALSE,
|
||
end_buffer, sizeof (end_buffer));
|
||
|
||
text = g_strdup_printf ("%s - %s %s ", start_buffer,
|
||
end_buffer, text);
|
||
|
||
free_text = TRUE;
|
||
}
|
||
|
||
bound_text (pc, font, text, x1 + 2, x2 - 2, y1, y2, 0);
|
||
|
||
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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
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_with_zone (whence, zone);
|
||
end = time_day_end_with_zone (start, zone);
|
||
|
||
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);
|
||
|
||
/* Also print events outside of work hours */
|
||
if (pdi.events[0]->len > 0) {
|
||
icaltimezone *zone = get_timezone ();
|
||
struct icaltimetype tt;
|
||
|
||
event = &g_array_index (pdi.events[0], EDayViewEvent, 0);
|
||
tt = icaltime_from_timet_with_zone (event->start, FALSE, zone);
|
||
if (tt.hour < pdi.start_hour)
|
||
pdi.start_hour = tt.hour;
|
||
pdi.start_minute_offset = pdi.start_hour * 60;
|
||
|
||
event = &g_array_index (pdi.events[0], EDayViewEvent, pdi.events[0]->len - 1);
|
||
tt = icaltime_from_timet_with_zone (event->end, FALSE, zone);
|
||
if (tt.hour > pdi.end_hour || tt.hour == 0) {
|
||
pdi.end_hour = tt.hour ? tt.hour : 24;
|
||
if (tt.minute > 0)
|
||
pdi.end_hour++;
|
||
}
|
||
pdi.end_minute_offset = pdi.end_hour * 60;
|
||
|
||
pdi.rows = (pdi.end_hour - pdi.start_hour) * 2;
|
||
}
|
||
|
||
/* 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 = get_font_for_size (12, GNOME_FONT_BOOK, FALSE);
|
||
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);
|
||
}
|
||
g_object_unref (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 = get_font_for_size (font_size, GNOME_FONT_BOOK, FALSE);
|
||
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);
|
||
}
|
||
g_object_unref (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);
|
||
}
|
||
|
||
|
||
/* 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)
|
||
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
EWeekViewEvent event;
|
||
struct icaltimetype start_tt, end_tt;
|
||
|
||
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_tt = icaltime_from_timet_with_zone (start, FALSE, zone);
|
||
end_tt = icaltime_from_timet_with_zone (end, FALSE, zone);
|
||
|
||
event.comp = comp;
|
||
g_object_ref (event.comp);
|
||
event.start = start;
|
||
event.end = end;
|
||
event.spans_index = 0;
|
||
event.num_spans = 0;
|
||
|
||
event.start_minute = start_tt.hour * 60 + start_tt.minute;
|
||
event.end_minute = end_tt.hour * 60 + end_tt.minute;
|
||
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_long_event (GnomePrintContext *pc, GnomeFont *font,
|
||
struct psinfo *psi,
|
||
double x1, double x2, double y1, double y2,
|
||
EWeekViewEvent *event, EWeekViewEventSpan *span,
|
||
char *text)
|
||
{
|
||
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_size (pc, buffer, ALIGN_LEFT, x1, x2, y1, y2);
|
||
x1 += gnome_font_get_width_utf8 (font, buffer);
|
||
}
|
||
|
||
/* 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_size (pc, buffer, ALIGN_RIGHT, x1, x2, y1, y2);
|
||
x2 -= gnome_font_get_width_utf8 (font, buffer);
|
||
}
|
||
|
||
x1 += 4;
|
||
x2 -= 4;
|
||
print_text_size (pc, 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_size (pc, buffer, ALIGN_LEFT, x1, x2, y1, y2);
|
||
x1 += gnome_font_get_width_utf8 (font, buffer);
|
||
|
||
x1 += 4;
|
||
print_text_size (pc, 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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
int day, day_x, day_y, day_h;
|
||
double x1, x2, y1, y2, font_size, fillcolor;
|
||
struct tm tm;
|
||
char *format_string, buffer[128], *utf_str;
|
||
|
||
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 = *convert_timet_to_struct_tm (psi->day_starts[day], zone);
|
||
|
||
/* 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.5);
|
||
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);
|
||
utf_str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
|
||
print_text_size (pc, utf_str, ALIGN_RIGHT,
|
||
x1, x2 - 4, y1 - 2, y1 - 2 - font_size);
|
||
g_free (utf_str);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
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. */
|
||
if (multi_week_view)
|
||
psi.compress_weekend = calendar_config_get_compress_weekend ();
|
||
else
|
||
psi.compress_weekend = TRUE;
|
||
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_with_zone (whence, zone);
|
||
for (day = 0; day <= psi.days_shown; day++) {
|
||
psi.day_starts[day] = day_start;
|
||
day_start = time_add_day_with_zone (day_start, 1, zone);
|
||
}
|
||
|
||
/* 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 = get_font_for_size (font_size, GNOME_FONT_BOOK, FALSE);
|
||
|
||
/* 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);
|
||
}
|
||
|
||
g_object_unref (font);
|
||
|
||
/* Free everything. */
|
||
for (event_num = 0; event_num < psi.events->len; event_num++) {
|
||
event = &g_array_index (psi.events, EWeekViewEvent, event_num);
|
||
g_object_unref (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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
double row_height, col_width, l, r, t, b;
|
||
time_t now;
|
||
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;
|
||
} else {
|
||
rows = 3;
|
||
cols = 4;
|
||
}
|
||
|
||
row_height = (top - bottom) / rows;
|
||
col_width = (right - left) / cols;
|
||
r = l + col_width;
|
||
b = top - row_height;
|
||
now = time_year_begin_with_zone (whence, zone);
|
||
|
||
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);
|
||
now = time_add_month_with_zone (now, 1, zone);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
print_month_summary (GnomePrintContext *pc, GnomeCalendar *gcal, time_t whence,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
time_t date;
|
||
struct tm tm;
|
||
struct icaltimetype tt;
|
||
char buffer[100];
|
||
GnomeFont *font;
|
||
gboolean compress_weekend;
|
||
int columns, col, weekday, len, month;
|
||
double font_size, cell_width, x1, x2, y1, y2;
|
||
|
||
weekday = calendar_config_get_week_start_day ();
|
||
compress_weekend = calendar_config_get_compress_weekend ();
|
||
|
||
/* Remember which month we want. */
|
||
tt = icaltime_from_timet_with_zone (whence, FALSE, zone);
|
||
month = tt.month - 1;
|
||
|
||
/* Find the start of the month, and then the start of the week on
|
||
or before that day. */
|
||
date = time_month_begin_with_zone (whence, zone);
|
||
date = time_week_begin_with_zone (date, weekday, zone);
|
||
|
||
/* If weekends are compressed then we can't start on a Sunday. */
|
||
if (compress_weekend && weekday == 0)
|
||
date = time_add_day_with_zone (date, -1, zone);
|
||
|
||
/* do day names ... */
|
||
|
||
/* We are only interested in outputting the weekday here, but we want
|
||
to be able to step through the week without worrying about
|
||
overflows making strftime choke, so we move near to the start of
|
||
the month. */
|
||
tm = *convert_timet_to_struct_tm (date, zone);
|
||
tm.tm_mday = (tm.tm_mday % 7) + 7;
|
||
|
||
font = get_font_for_size (MONTH_NORMAL_FONT_SIZE, GNOME_FONT_BOLD, FALSE);
|
||
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++) {
|
||
char *utf_str;
|
||
|
||
if (tm.tm_wday == 6 && compress_weekend) {
|
||
strftime (buffer, sizeof (buffer), "%a/", &tm);
|
||
len = strlen (buffer);
|
||
tm.tm_mday++;
|
||
tm.tm_wday = (tm.tm_wday + 1) % 7;
|
||
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);
|
||
utf_str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
|
||
print_text_size (pc, utf_str, ALIGN_CENTER, x1, x2, y1, y2);
|
||
g_free (utf_str);
|
||
|
||
tm.tm_mday++;
|
||
tm.tm_wday = (tm.tm_wday + 1) % 7;
|
||
}
|
||
g_object_unref (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,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
CalClient *client;
|
||
GnomeFont *font_summary;
|
||
double y, yend, x, xend;
|
||
struct icaltimetype *tt;
|
||
ECalendarTable *task_pad;
|
||
ETable *table;
|
||
CalendarModel *model;
|
||
gint rows, row;
|
||
|
||
/* We get the tasks directly from the TaskPad ETable. This means we
|
||
get them filtered & sorted for free. */
|
||
task_pad = gnome_calendar_get_task_pad (gcal);
|
||
table = e_calendar_table_get_table (task_pad);
|
||
model = e_calendar_table_get_model (task_pad);
|
||
client = gnome_calendar_get_task_pad_cal_client (gcal);
|
||
|
||
font_summary = get_font_for_size (10, GNOME_FONT_BOOK, FALSE);
|
||
|
||
gnome_print_setrgbcolor (pc, 0, 0, 0);
|
||
gnome_print_setlinewidth (pc, 0.0);
|
||
|
||
titled_box (pc, _("Tasks"), font_summary, ALIGN_CENTER | ALIGN_BORDER,
|
||
&left, &right, &top, &bottom, 1.0);
|
||
|
||
y = top - 3;
|
||
yend = bottom - 2;
|
||
|
||
rows = e_table_model_row_count (E_TABLE_MODEL (model));
|
||
for (row = 0; row < rows; row++) {
|
||
CalComponent *comp;
|
||
CalComponentText summary;
|
||
int model_row;
|
||
|
||
model_row = e_table_view_to_model_row (table, row);
|
||
comp = calendar_model_get_component (model, model_row);
|
||
|
||
cal_component_get_summary (comp, &summary);
|
||
|
||
if (!summary.value)
|
||
continue;
|
||
|
||
x = left;
|
||
xend = right - 2;
|
||
|
||
if (y < bottom)
|
||
break;
|
||
|
||
/* Print the box to put the tick in. */
|
||
print_border (pc, x + 2, x + 8, y - 3, y - 11, 0.1, -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;
|
||
}
|
||
|
||
g_object_unref (font_summary);
|
||
}
|
||
|
||
|
||
/* Value for the PrintView enum */
|
||
static const int print_view_map[] = {
|
||
PRINT_VIEW_DAY,
|
||
PRINT_VIEW_WEEK,
|
||
PRINT_VIEW_MONTH,
|
||
PRINT_VIEW_YEAR,
|
||
-1
|
||
};
|
||
|
||
/* Creates the range selector widget for printing a calendar */
|
||
static GtkWidget *
|
||
range_selector_new (GtkWidget *dialog, time_t at, int *view)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
GtkWidget *box;
|
||
GtkWidget *radio;
|
||
GSList *group;
|
||
char text[1024];
|
||
char str1[512];
|
||
char str2[512];
|
||
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);
|
||
|
||
tm = *convert_timet_to_struct_tm (at, zone);
|
||
|
||
/* Day */
|
||
|
||
strftime (text, sizeof (text), _("Selected day (%a %b %d %Y)"), &tm);
|
||
radio = gtk_radio_button_new_with_label (NULL, text);
|
||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
|
||
gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
|
||
|
||
/* Week */
|
||
|
||
week_start_day = calendar_config_get_week_start_day ();
|
||
week_begin = time_week_begin_with_zone (at, week_start_day, zone);
|
||
/* If the week starts on a Sunday, we have to show the Saturday first,
|
||
since the weekend is compressed. If the original date passed in was
|
||
a Saturday, we need to move on to the next Saturday, else we move
|
||
back to the last one. */
|
||
if (week_start_day == 0) {
|
||
if (tm.tm_wday == 6)
|
||
week_begin = time_add_day_with_zone (week_begin, 6, zone);
|
||
else
|
||
week_begin = time_add_day_with_zone (week_begin, -1, zone);
|
||
}
|
||
week_end = time_add_day_with_zone (week_begin, 6, zone);
|
||
|
||
week_begin_tm = *convert_timet_to_struct_tm (week_begin, zone);
|
||
week_end_tm = *convert_timet_to_struct_tm (week_end, zone);
|
||
|
||
if (week_begin_tm.tm_mon == week_end_tm.tm_mon) {
|
||
strftime (str1, sizeof (str1), _("%a %b %d"), &week_begin_tm);
|
||
strftime (str2, sizeof (str2), _("%a %d %Y"), &week_end_tm);
|
||
} else {
|
||
if (week_begin_tm.tm_year == week_end_tm.tm_year) {
|
||
strftime (str1, sizeof (str1), _("%a %b %d"), &week_begin_tm);
|
||
strftime (str2, sizeof (str2), _("%a %b %d %Y"), &week_end_tm);
|
||
} else {
|
||
strftime (str1, sizeof (str1), _("%a %b %d %Y"), &week_begin_tm);
|
||
strftime (str2, sizeof (str2), _("%a %b %d %Y"), &week_end_tm);
|
||
}
|
||
}
|
||
|
||
g_snprintf (text, sizeof (text), _("Selected week (%s - %s)"), str1, str2);
|
||
|
||
radio = gtk_radio_button_new_with_label (group, text);
|
||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
|
||
gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
|
||
|
||
/* Month */
|
||
|
||
strftime (text, sizeof (text), _("Selected month (%b %Y)"), &tm);
|
||
radio = gtk_radio_button_new_with_label (group, text);
|
||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
|
||
gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
|
||
|
||
/* Year */
|
||
|
||
strftime (text, sizeof (text), _("Selected year (%Y)"), &tm);
|
||
radio = gtk_radio_button_new_with_label (group, text);
|
||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
|
||
gtk_box_pack_start (GTK_BOX (box), radio, FALSE, FALSE, 0);
|
||
|
||
/* Select default */
|
||
|
||
e_dialog_widget_hook_value (dialog, radio, view, (gpointer) print_view_map);
|
||
|
||
gtk_widget_show_all (box);
|
||
return box;
|
||
}
|
||
|
||
|
||
static void
|
||
print_day_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
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;
|
||
|
||
gnome_print_beginpage (pc, NULL);
|
||
|
||
/* 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_with_zone (date, 1, zone),
|
||
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_bold (pc, 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_bold (pc, buf, ALIGN_LEFT,
|
||
left + 4, todo, top - 32, top - 32 - 18);
|
||
|
||
gnome_print_showpage (pc);
|
||
date = time_add_day_with_zone (date, 1, zone);
|
||
}
|
||
}
|
||
|
||
|
||
static void
|
||
print_week_view (GnomePrintContext *pc, GnomeCalendar *gcal, time_t date,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
double header, l;
|
||
char buf[100];
|
||
time_t when;
|
||
gint week_start_day;
|
||
struct tm tm;
|
||
|
||
header = top - HEADER_HEIGHT;
|
||
|
||
gnome_print_beginpage (pc, NULL);
|
||
|
||
tm = *convert_timet_to_struct_tm (date, zone);
|
||
week_start_day = calendar_config_get_week_start_day ();
|
||
when = time_week_begin_with_zone (date, week_start_day, zone);
|
||
/* If the week starts on a Sunday, we have to show the Saturday first,
|
||
since the weekend is compressed. */
|
||
if (week_start_day == 0) {
|
||
if (tm.tm_wday == 6)
|
||
when = time_add_day_with_zone (when, 6, zone);
|
||
else
|
||
when = time_add_day_with_zone (when, -1, zone);
|
||
}
|
||
|
||
/* 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_with_zone (when, 1, zone), FALSE);
|
||
|
||
l += SMALL_MONTH_SPACING + SMALL_MONTH_WIDTH;
|
||
print_month_small (pc, gcal,
|
||
time_add_month_with_zone (when, 1, zone),
|
||
l, l + SMALL_MONTH_WIDTH,
|
||
top - 4, header + 4,
|
||
DATE_MONTH | DATE_YEAR, when,
|
||
time_add_week_with_zone (when, 1, zone), 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_bold (pc, 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_with_zone (when, 6, zone);
|
||
format_date (when, DATE_DAY | DATE_MONTH | DATE_YEAR, buf, 100);
|
||
print_text_size_bold (pc, 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)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
double header;
|
||
char buf[100];
|
||
|
||
header = top - HEADER_HEIGHT;
|
||
|
||
gnome_print_beginpage (pc, NULL);
|
||
|
||
/* 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_with_zone (date, 1, zone),
|
||
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_with_zone (date, -1, zone),
|
||
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_bold (pc, 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];
|
||
|
||
gnome_print_beginpage (pc, NULL);
|
||
|
||
print_year_summary (pc, gcal, date, left, right, top - 50, bottom,
|
||
TRUE);
|
||
|
||
/* centered title */
|
||
format_date (date, DATE_YEAR, buf, 100);
|
||
print_text_size_bold (pc, buf, ALIGN_CENTER,
|
||
left+3, right, top-3, top - 27);
|
||
|
||
gnome_print_showpage (pc);
|
||
}
|
||
|
||
static void
|
||
write_label_piece (time_t t, char *buffer, int size, char *stext, char *etext)
|
||
{
|
||
icaltimezone *zone = get_timezone ();
|
||
struct tm *tmp_tm;
|
||
int len;
|
||
|
||
tmp_tm = convert_timet_to_struct_tm (t, zone);
|
||
|
||
if (stext != NULL)
|
||
strcat (buffer, stext);
|
||
|
||
len = strlen (buffer);
|
||
e_time_format_date_and_time (tmp_tm,
|
||
calendar_config_get_24_hour_format (),
|
||
FALSE, FALSE,
|
||
&buffer[len], size - len);
|
||
if (etext != NULL)
|
||
strcat (buffer, etext);
|
||
}
|
||
|
||
static icaltimezone*
|
||
get_zone_from_tzid (CalClient *client, const char *tzid)
|
||
{
|
||
icaltimezone *zone;
|
||
|
||
/* Note that the timezones may not be on the server, so we try to get
|
||
the builtin timezone with the TZID first. */
|
||
zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
|
||
if (!zone) {
|
||
CalClientGetStatus status;
|
||
|
||
status = cal_client_get_timezone (client, tzid, &zone);
|
||
/* FIXME: Handle error better. */
|
||
if (status != CAL_CLIENT_GET_SUCCESS)
|
||
g_warning ("Couldn't get timezone from server: %s",
|
||
tzid ? tzid : "");
|
||
}
|
||
|
||
return zone;
|
||
}
|
||
|
||
static void
|
||
print_date_label (GnomePrintContext *pc, CalComponent *comp, CalClient *client,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
icaltimezone *start_zone, *end_zone, *due_zone, *completed_zone;
|
||
CalComponentDateTime datetime;
|
||
time_t start = 0, end = 0, complete = 0, due = 0;
|
||
static char buffer[1024], *utf_text;
|
||
|
||
cal_component_get_dtstart (comp, &datetime);
|
||
if (datetime.value) {
|
||
start_zone = get_zone_from_tzid (client, datetime.tzid);
|
||
start = icaltime_as_timet_with_zone (*datetime.value,
|
||
start_zone);
|
||
}
|
||
cal_component_free_datetime (&datetime);
|
||
|
||
cal_component_get_dtend (comp, &datetime);
|
||
if (datetime.value) {
|
||
end_zone = get_zone_from_tzid (client, datetime.tzid);
|
||
end = icaltime_as_timet_with_zone (*datetime.value,
|
||
end_zone);
|
||
}
|
||
cal_component_free_datetime (&datetime);
|
||
|
||
cal_component_get_due (comp, &datetime);
|
||
if (datetime.value) {
|
||
due_zone = get_zone_from_tzid (client, datetime.tzid);
|
||
due = icaltime_as_timet_with_zone (*datetime.value,
|
||
due_zone);
|
||
}
|
||
cal_component_free_datetime (&datetime);
|
||
|
||
cal_component_get_completed (comp, &datetime.value);
|
||
if (datetime.value) {
|
||
completed_zone = icaltimezone_get_utc_timezone ();
|
||
complete = icaltime_as_timet_with_zone (*datetime.value,
|
||
completed_zone);
|
||
cal_component_free_icaltimetype (datetime.value);
|
||
}
|
||
|
||
buffer[0] = '\0';
|
||
|
||
if (start > 0)
|
||
write_label_piece (start, buffer, 1024, NULL, NULL);
|
||
|
||
if (end > 0 && start > 0)
|
||
write_label_piece (end, buffer, 1024, _(" to "), NULL);
|
||
|
||
if (complete > 0) {
|
||
if (start > 0)
|
||
write_label_piece (complete, buffer, 1024, _(" (Completed "), ")");
|
||
else
|
||
write_label_piece (complete, buffer, 1024, _("Completed "), NULL);
|
||
}
|
||
|
||
if (due > 0 && complete == 0) {
|
||
if (start > 0)
|
||
write_label_piece (due, buffer, 1024, _(" (Due "), ")");
|
||
else
|
||
write_label_piece (due, buffer, 1024, _("Due "), NULL);
|
||
}
|
||
|
||
utf_text = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
|
||
print_text_size_bold (pc, utf_text, ALIGN_LEFT,
|
||
left, right, top, top - 15);
|
||
g_free (utf_text);
|
||
}
|
||
|
||
static void
|
||
print_comp_item (GnomePrintContext *pc, CalComponent *comp, CalClient *client,
|
||
double left, double right, double top, double bottom)
|
||
{
|
||
GnomeFont *font;
|
||
CalComponentVType vtype;
|
||
CalComponentText text;
|
||
GSList *desc, *l;
|
||
const char *title, *categories;
|
||
char *categories_string;
|
||
GSList *contact_list, *elem;
|
||
gint header_size;
|
||
|
||
vtype = cal_component_get_vtype (comp);
|
||
|
||
/* We should only be asked to print VEVENTs or VTODOs. */
|
||
if (vtype == CAL_COMPONENT_EVENT)
|
||
title = _("Appointment");
|
||
else if (vtype == CAL_COMPONENT_TODO)
|
||
title = _("Task");
|
||
else
|
||
return;
|
||
|
||
gnome_print_beginpage (pc, NULL);
|
||
|
||
/* Print the title in a box at the top of the page. */
|
||
font = get_font_for_size (18, GNOME_FONT_BOLD, FALSE);
|
||
header_size = 50;
|
||
print_border (pc, left, right, top, top - header_size,
|
||
1.0, 0.9);
|
||
print_text (pc, font, title, ALIGN_CENTER, left, right,
|
||
top - header_size * 0.1, top - header_size);
|
||
g_object_unref (font);
|
||
|
||
top -= header_size + 10;
|
||
|
||
/* Summary */
|
||
font = get_font_for_size (18, GNOME_FONT_BOLD, FALSE);
|
||
cal_component_get_summary (comp, &text);
|
||
top = bound_text (pc, font, text.value, left, right,
|
||
top - 3, bottom, 0);
|
||
g_object_unref (font);
|
||
|
||
/* Date information */
|
||
print_date_label (pc, comp, client, left, right, top-3, top - 15);
|
||
top -= 20;
|
||
|
||
font = get_font_for_size (12, GNOME_FONT_BOOK, FALSE);
|
||
|
||
/* For a VTODO we print the Status, Priority, % Complete and URL. */
|
||
if (vtype == CAL_COMPONENT_TODO) {
|
||
icalproperty_status status;
|
||
const char *status_string = NULL;
|
||
int *percent;
|
||
int *priority;
|
||
const char *url;
|
||
|
||
/* Status */
|
||
cal_component_get_status (comp, &status);
|
||
if (status != ICAL_STATUS_NONE) {
|
||
switch (status) {
|
||
case ICAL_STATUS_NEEDSACTION:
|
||
status_string = _("Not Started");
|
||
break;
|
||
case ICAL_STATUS_INPROCESS:
|
||
status_string = _("In Progress");
|
||
break;
|
||
case ICAL_STATUS_COMPLETED:
|
||
status_string = _("Completed");
|
||
break;
|
||
case ICAL_STATUS_CANCELLED:
|
||
status_string = _("Cancelled");
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (status_string) {
|
||
char *text = g_strdup_printf (_("Status: %s"),
|
||
status_string);
|
||
top = bound_text (pc, font, text,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
g_free (text);
|
||
}
|
||
}
|
||
|
||
/* Priority */
|
||
cal_component_get_priority (comp, &priority);
|
||
if (priority && *priority >= 0) {
|
||
char *priority_string, *priority_utf8, *text;
|
||
|
||
priority_string = cal_util_priority_to_string (*priority);
|
||
cal_component_free_priority (priority);
|
||
|
||
priority_utf8 = g_locale_to_utf8 (priority_string, -1, NULL, NULL, NULL);
|
||
text = g_strdup_printf (_("Priority: %s"),
|
||
priority_utf8);
|
||
top = bound_text (pc, font, text,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
g_free (text);
|
||
g_free (priority_utf8);
|
||
}
|
||
|
||
/* Percent Complete */
|
||
cal_component_get_percent (comp, &percent);
|
||
if (percent) {
|
||
char *percent_string;
|
||
|
||
percent_string = g_strdup_printf (_("Percent Complete: %i"), *percent);
|
||
cal_component_free_percent (percent);
|
||
|
||
top = bound_text (pc, font, percent_string,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
}
|
||
|
||
|
||
/* URL */
|
||
cal_component_get_url (comp, &url);
|
||
if (url && url[0]) {
|
||
char *url_string = g_strdup_printf (_("URL: %s"),
|
||
url);
|
||
|
||
top = bound_text (pc, font, url_string,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
|
||
g_free (url_string);
|
||
}
|
||
}
|
||
|
||
/* Categories */
|
||
cal_component_get_categories (comp, &categories);
|
||
if (categories && categories[0]) {
|
||
categories_string = g_strdup_printf (_("Categories: %s"),
|
||
categories);
|
||
top = bound_text (pc, font, categories_string,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
g_free (categories_string);
|
||
}
|
||
|
||
/* Contacts */
|
||
cal_component_get_contact_list (comp, &contact_list);
|
||
if (contact_list) {
|
||
GString *contacts = g_string_new (_("Contacts: "));
|
||
for (elem = contact_list; elem; elem = elem->next) {
|
||
CalComponentText *t = elem->data;
|
||
/* Put a comma between contacts. */
|
||
if (elem != contact_list)
|
||
g_string_append (contacts, ", ");
|
||
g_string_append (contacts, t->value);
|
||
}
|
||
cal_component_free_text_list (contact_list);
|
||
|
||
top = bound_text (pc, font, contacts->str,
|
||
left, right, top, bottom, 0);
|
||
top += gnome_font_get_size (font) - 6;
|
||
|
||
g_string_free (contacts, TRUE);
|
||
}
|
||
|
||
top -= 16;
|
||
|
||
/* Description */
|
||
cal_component_get_description_list (comp, &desc);
|
||
for (l = desc; l != NULL; l = l->next) {
|
||
CalComponentText *text = l->data;
|
||
|
||
if (text->value != NULL)
|
||
top = bound_text (pc, font, text->value, left, right, top-3, bottom, 0);
|
||
}
|
||
cal_component_free_text_list (desc);
|
||
g_object_unref (font);
|
||
|
||
gnome_print_showpage (pc);
|
||
}
|
||
|
||
void
|
||
print_calendar (GnomeCalendar *gcal, gboolean preview, time_t date,
|
||
PrintView default_view)
|
||
{
|
||
GnomePrintJob *gpm;
|
||
GnomePrintContext *pc;
|
||
int copies, collate;
|
||
double l, r, t, b, temp_d;
|
||
gchar *old_orientation;
|
||
|
||
g_return_if_fail (gcal != NULL);
|
||
g_return_if_fail (GNOME_IS_CALENDAR (gcal));
|
||
|
||
if (!print_config)
|
||
print_config = gnome_print_config_default ();
|
||
|
||
copies = 1;
|
||
collate = FALSE;
|
||
|
||
gpm = gnome_print_job_new (print_config);
|
||
|
||
if (!preview) {
|
||
GtkWidget *gpd;
|
||
GtkWidget *range;
|
||
int view;
|
||
|
||
gpd = gnome_print_dialog_new (gpm, _("Print"), 0);
|
||
|
||
view = (int) default_view;
|
||
range = range_selector_new (gpd, date, &view);
|
||
gnome_print_dialog_construct_range_custom (GNOME_PRINT_DIALOG (gpd), range);
|
||
|
||
gtk_dialog_set_default_response (GTK_DIALOG (gpd),
|
||
GNOME_PRINT_DIALOG_RESPONSE_PRINT);
|
||
|
||
/* Run dialog */
|
||
|
||
switch (gtk_dialog_run (GTK_DIALOG (gpd))) {
|
||
case GNOME_PRINT_DIALOG_RESPONSE_PRINT:
|
||
break;
|
||
|
||
case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW:
|
||
preview = TRUE;
|
||
break;
|
||
|
||
case -1:
|
||
return;
|
||
|
||
default:
|
||
gtk_widget_destroy (gpd);
|
||
return;
|
||
}
|
||
|
||
e_dialog_get_values (gpd);
|
||
default_view = (PrintView) view;
|
||
|
||
gtk_widget_destroy (gpd);
|
||
}
|
||
|
||
old_orientation = gnome_print_config_get (print_config, GNOME_PRINT_KEY_PAGE_ORIENTATION);
|
||
|
||
if (default_view == PRINT_VIEW_MONTH)
|
||
gnome_print_config_set (print_config, GNOME_PRINT_KEY_PAGE_ORIENTATION, "R90");
|
||
|
||
pc = gnome_print_job_get_context (gpm);
|
||
gnome_print_config_get_page_size (print_config, &r, &t);
|
||
|
||
/* See top of source for an explanation of this */
|
||
|
||
/* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_TOP, &temp_d);
|
||
* t -= temp_d;
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT, &temp_d);
|
||
* r -= temp_d;
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM, &b);
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_LEFT, &l);
|
||
* b = l = TEMP_MARGIN; */
|
||
|
||
b = t * TEMP_MARGIN;
|
||
l = r * TEMP_MARGIN;
|
||
t *= (1.0 - TEMP_MARGIN);
|
||
r *= (1.0 - TEMP_MARGIN);
|
||
|
||
/* depending on the view, do a different output */
|
||
switch (default_view) {
|
||
case PRINT_VIEW_DAY:
|
||
print_day_view (pc, gcal, date, l, r, t, b);
|
||
break;
|
||
case PRINT_VIEW_WEEK:
|
||
print_week_view (pc, gcal, date, l, r, t, b);
|
||
break;
|
||
case PRINT_VIEW_MONTH:
|
||
print_month_view (pc, gcal, date, l, r, t, b);
|
||
break;
|
||
case PRINT_VIEW_YEAR:
|
||
print_year_view (pc, gcal, date, l, r, t, b);
|
||
break;
|
||
default:
|
||
g_assert_not_reached ();
|
||
}
|
||
|
||
gnome_print_job_close (gpm);
|
||
|
||
if (preview) {
|
||
GtkWidget *gpmp;
|
||
|
||
gpmp = gnome_print_job_preview_new (gpm, _("Print Preview"));
|
||
gtk_widget_show (gpmp);
|
||
} else {
|
||
gnome_print_job_print (gpm);
|
||
}
|
||
|
||
gnome_print_config_set (print_config, GNOME_PRINT_KEY_PAGE_ORIENTATION, old_orientation);
|
||
g_free (old_orientation);
|
||
g_object_unref (gpm);
|
||
}
|
||
|
||
|
||
void
|
||
print_comp (CalComponent *comp, CalClient *client, gboolean preview)
|
||
{
|
||
GnomePrintJob *gpm;
|
||
GnomePrintContext *pc;
|
||
int copies, collate;
|
||
double l, r, t, b, temp_d;
|
||
|
||
g_return_if_fail (comp != NULL);
|
||
g_return_if_fail (IS_CAL_COMPONENT (comp));
|
||
|
||
if (!print_config)
|
||
print_config = gnome_print_config_default ();
|
||
|
||
copies = 1;
|
||
collate = FALSE;
|
||
|
||
gpm = gnome_print_job_new (print_config);
|
||
|
||
if (!preview) {
|
||
GtkWidget *gpd;
|
||
|
||
gpd = gnome_print_dialog_new (gpm, _("Print Item"),
|
||
GNOME_PRINT_DIALOG_COPIES);
|
||
|
||
gtk_dialog_set_default_response (GTK_DIALOG (gpd),
|
||
GNOME_PRINT_DIALOG_RESPONSE_PRINT);
|
||
|
||
/* Run dialog */
|
||
|
||
switch (gtk_dialog_run (GTK_DIALOG (gpd))) {
|
||
case GNOME_PRINT_DIALOG_RESPONSE_PRINT:
|
||
break;
|
||
|
||
case GNOME_PRINT_DIALOG_RESPONSE_PREVIEW:
|
||
preview = TRUE;
|
||
break;
|
||
|
||
case -1:
|
||
return;
|
||
|
||
default:
|
||
gtk_widget_destroy (gpd);
|
||
return;
|
||
}
|
||
|
||
e_dialog_get_values (gpd);
|
||
gtk_widget_destroy (gpd);
|
||
}
|
||
|
||
pc = gnome_print_job_get_context (gpm);
|
||
gnome_print_config_get_page_size (print_config, &r, &t);
|
||
|
||
/* See top of source for an explanation of this */
|
||
|
||
/* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_TOP, &temp_d);
|
||
* t -= temp_d;
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_RIGHT, &temp_d);
|
||
* r -= temp_d;
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_BOTTOM, &b);
|
||
* gnome_print_config_get_double (print_config, GNOME_PRINT_KEY_PAGE_MARGIN_LEFT, &l);
|
||
* b = l = TEMP_MARGIN; */
|
||
|
||
b = t * TEMP_MARGIN;
|
||
l = r * TEMP_MARGIN;
|
||
t *= (1.0 - TEMP_MARGIN);
|
||
r *= (1.0 - TEMP_MARGIN);
|
||
|
||
print_comp_item (pc, comp, client, l, r, t, b);
|
||
gnome_print_job_close (gpm);
|
||
|
||
if (preview) {
|
||
GtkWidget *gpmp;
|
||
|
||
gpmp = gnome_print_job_preview_new (gpm, _("Print Preview"));
|
||
gtk_widget_show (gpmp);
|
||
} else {
|
||
gnome_print_job_print (gpm);
|
||
}
|
||
|
||
g_object_unref (gpm);
|
||
}
|
||
|
||
void
|
||
print_setup (void)
|
||
{
|
||
GtkWidget *ps;
|
||
|
||
if (!print_config)
|
||
print_config = gnome_print_config_default ();
|
||
|
||
ps = gnome_paper_selector_new (print_config);
|
||
gtk_widget_show (ps);
|
||
|
||
#if 0
|
||
dlg = gtk_dialog_new_with_buttons (_("Print Setup"),
|
||
NULL, /* FIXME: Set a sensible parent */
|
||
0,
|
||
GNOME_STOCK_BUTTON_OK,
|
||
GNOME_STOCK_BUTTON_CANCEL,
|
||
NULL);
|
||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), ps, TRUE, TRUE, 2);
|
||
|
||
btn = gtk_dialog_run (GTK_DIALOG (dlg));
|
||
if (btn == 0) {
|
||
gchar *name;
|
||
|
||
print_config = gnome_paper_selector_get_config (ps);
|
||
|
||
name = gnome_paper_selector_get_name (GNOME_PAPER_SELECTOR (ps));
|
||
paper_info = gnome_paper_with_name (name);
|
||
}
|
||
|
||
gtk_widget_destroy (dlg);
|
||
#endif
|
||
}
|