From 83cd87ef500a992f1a196f4cac1a0536320b0296 Mon Sep 17 00:00:00 2001 From: Srinivasa Ragavan Date: Thu, 4 May 2006 15:25:13 +0000 Subject: Committing a patch to build without cairo and fixed a issue where entire evolution might showup with bold text. svn path=/trunk/; revision=31955 --- widgets/misc/ChangeLog | 10 + widgets/misc/e-calendar-item.c | 793 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 725 insertions(+), 78 deletions(-) diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog index 49612fec96..b25c679250 100644 --- a/widgets/misc/ChangeLog +++ b/widgets/misc/ChangeLog @@ -1,3 +1,13 @@ +2006-05-04 Rajeev Ramanathan + + Added patch to enable build without cairo using ENABLE_CAIRO macro. + Also it fixes a bold issue, where entire evolution appears with bold + text. + + * e-calendar-item.c: (e_calendar_item_draw), + (e_calendar_item_draw_month), (e_calendar_item_draw_day_numbers), + (layout_set_day_text): + 2006-04-27 Boby Wang ** Fixes bug #339138 diff --git a/widgets/misc/e-calendar-item.c b/widgets/misc/e-calendar-item.c index 389ee45334..05dbe3c583 100644 --- a/widgets/misc/e-calendar-item.c +++ b/widgets/misc/e-calendar-item.c @@ -47,6 +47,8 @@ #include #include +#define ENABLE_CAIRO 1 + static const int e_calendar_item_days_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -862,7 +864,7 @@ e_calendar_item_update (GnomeCanvasItem *item, /* * DRAWING ROUTINES - functions to paint the canvas item. */ - +#ifndef ENABLE_CAIRO static void e_calendar_item_draw (GnomeCanvasItem *canvas_item, GdkDrawable *drawable, @@ -879,8 +881,6 @@ e_calendar_item_draw (GnomeCanvasItem *canvas_item, PangoFontDescription *font_desc; PangoContext *pango_context; PangoFontMetrics *font_metrics; - cairo_t *cr; - GdkColor base, bg; #if 0 g_print ("In e_calendar_item_draw %i,%i %ix%i\n", @@ -905,19 +905,11 @@ e_calendar_item_draw (GnomeCanvasItem *canvas_item, base_gc = style->base_gc[GTK_STATE_NORMAL]; bg_gc = style->bg_gc[GTK_STATE_NORMAL]; - base = style->base[GTK_STATE_NORMAL]; - bg = style->bg[GTK_STATE_NORMAL]; - cr = gdk_cairo_create (drawable); - - /* Clear the entire background. */ - cairo_save (cr); - gdk_cairo_set_source_color (cr, &base); - cairo_rectangle (cr, calitem->x1 - x, calitem->y1 - y, + gdk_draw_rectangle (drawable, base_gc, TRUE, + calitem->x1 - x, calitem->y1 - y, calitem->x2 - calitem->x1 + 1, - calitem->y2 - calitem->y1 + 1); - cairo_fill (cr); - cairo_restore (cr); + calitem->y2 - calitem->y1 + 1); /* Draw the shadow around the entire item. */ gtk_paint_shadow (style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, @@ -935,14 +927,11 @@ e_calendar_item_draw (GnomeCanvasItem *canvas_item, /* Draw the background for the title bars and the shadow around it, and the vertical lines between columns. */ - cairo_save (cr); - gdk_cairo_set_source_color (cr, &bg); - cairo_rectangle (cr, calitem->x1 + xthickness - x, row_y - y, + gdk_draw_rectangle (drawable, bg_gc, TRUE, + calitem->x1 + xthickness - x, row_y - y, calitem->x2 - calitem->x1 + 1 - xthickness * 2, bar_height); - cairo_fill (cr); - cairo_restore (cr); gtk_paint_shadow (style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, @@ -1023,8 +1012,6 @@ e_calendar_item_draw_month (ECalendarItem *calitem, PangoContext *pango_context; PangoFontMetrics *font_metrics; PangoLayout *layout; - cairo_t *cr; - GdkColor fg; #if 0 g_print ("In e_calendar_item_draw_month: %i,%i %ix%i row:%i col:%i\n", @@ -1034,8 +1021,6 @@ e_calendar_item_draw_month (ECalendarItem *calitem, widget = GTK_WIDGET (item->canvas); style = widget->style; - cr = gdk_cairo_create (drawable); - /* Set up Pango prerequisites */ font_desc = calitem->font_desc; if (!font_desc) @@ -1051,8 +1036,6 @@ e_calendar_item_draw_month (ECalendarItem *calitem, ythickness = style->ythickness; fg_gc = style->fg_gc[GTK_STATE_NORMAL]; - fg = style->fg[GTK_STATE_NORMAL]; - pango_font_metrics_unref (font_metrics); /* Calculate the top-left position of the entire month display. */ @@ -1142,6 +1125,7 @@ e_calendar_item_draw_month (ECalendarItem *calitem, gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); + /* Draw the day initials across the top of the month. */ min_cell_width = calitem->max_digit_width * 2 + E_CALENDAR_ITEM_MIN_CELL_XPAD; @@ -1163,43 +1147,40 @@ e_calendar_item_draw_month (ECalendarItem *calitem, + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1 + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS; - cairo_save (cr); - gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_SELECTED]); - cairo_rectangle (cr, cells_x , - text_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1, - calitem->cell_width * 7 , cells_y - text_y ); - cairo_fill (cr); - cairo_restore (cr); - day_index = calitem->week_start_day; pango_layout_set_font_description (layout, font_desc); - gdk_gc_set_foreground (fg_gc, &style->text[GTK_STATE_ACTIVE]); for (day = 0; day < 7; day++) { layout_set_day_text (calitem, layout, day_index); gdk_draw_layout (drawable, fg_gc, text_x - calitem->day_widths [day_index], text_y, layout); + text_x += calitem->cell_width; day_index++; if (day_index == 7) day_index = 0; } + + /* Draw the horizontal line beneath the day initials. */ + gdk_draw_line (drawable, fg_gc, + cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS, + cells_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1, + cells_x + E_CALENDAR_COLS_PER_MONTH * calitem->cell_width - 1, + cells_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1); + e_calendar_item_draw_day_numbers (calitem, drawable, width, height, row, col, year, month, start_weekday, cells_x, cells_y); /* Draw the vertical line after the week number. */ if (calitem->show_week_numbers) { - cairo_save (cr); - gdk_cairo_set_source_color (cr, &fg); - cairo_move_to (cr, cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS - 1, - cells_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1); - cairo_line_to (cr, cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS - 1, + gdk_draw_line (drawable, fg_gc, + cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS - 1, + cells_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1, + cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS - 1, cells_y + E_CALENDAR_ROWS_PER_MONTH * calitem->cell_height - 1); - cairo_stroke (cr); - cairo_restore (cr); } gdk_gc_set_clip_rectangle (fg_gc, NULL); @@ -1242,14 +1223,11 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, PangoContext *pango_context; PangoFontMetrics *font_metrics; PangoLayout *layout; - cairo_t *cr; item = GNOME_CANVAS_ITEM (calitem); widget = GTK_WIDGET (item->canvas); style = widget->style; - cr = gdk_cairo_create (drawable); - /* Set up Pango prerequisites */ font_desc = calitem->font_desc; if (!font_desc) @@ -1271,7 +1249,7 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, + E_CALENDAR_ITEM_MIN_CELL_XPAD; min_cell_height = char_height + E_CALENDAR_ITEM_MIN_CELL_YPAD; - layout = pango_cairo_create_layout (cr); + layout = gtk_widget_create_pango_layout (widget, NULL); /* Calculate the number of days in the previous, current, and next months. */ @@ -1354,15 +1332,15 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, text_x -= calitem->week_number_digit_widths[digit]; buffer[num_chars++] = digit + '0'; - cairo_save (cr); - gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); + gdk_gc_set_foreground (fg_gc, + &style->fg[GTK_STATE_NORMAL]); pango_layout_set_font_description (layout, wkfont_desc); pango_layout_set_text (layout, buffer, num_chars); - cairo_translate (cr, text_x, text_y); - pango_cairo_update_layout (cr, layout); - pango_cairo_show_layout (cr, layout); - cairo_restore (cr); + gdk_draw_layout (drawable, fg_gc, + text_x, + text_y, + layout); } for (dcol = 0; dcol < 7; dcol++) { @@ -1428,25 +1406,22 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, /* Draw the background, if set. */ if (bg_color) { - cairo_save (cr); - gdk_cairo_set_source_color (cr, bg_color); - cairo_rectangle (cr, day_x , day_y, + gdk_gc_set_foreground (fg_gc, bg_color); + gdk_draw_rectangle (drawable, fg_gc, + TRUE, + day_x, day_y, calitem->cell_width, calitem->cell_height); - cairo_fill (cr); - cairo_restore (cr); } /* Draw the box, if set. */ if (box_color) { - cairo_save (cr); - gdk_cairo_set_source_color (cr, box_color); - cairo_rectangle (cr, day_x , day_y, + gdk_gc_set_foreground (fg_gc, box_color); + gdk_draw_rectangle (drawable, fg_gc, + FALSE, + day_x, day_y, calitem->cell_width - 1, - calitem->cell_height - 1); -// cairo_set_line_width (cr, 0.7); - cairo_stroke (cr); - cairo_restore (cr); + calitem->cell_height - 1); } /* Draw the 1- or 2-digit day number. */ @@ -1465,27 +1440,31 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, digit = day_num % 10; day_x -= calitem->digit_widths[digit]; buffer[num_chars++] = digit + '0'; - - cairo_save (cr); + if (fg_color) { - gdk_cairo_set_source_color (cr, fg_color); + gdk_gc_set_foreground (fg_gc, + fg_color); } else { - gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); + gdk_gc_set_foreground (fg_gc, + &style->fg[GTK_STATE_NORMAL]); } - if (bold) { - pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); - } else { - pango_font_description_set_weight (font_desc, PANGO_WEIGHT_NORMAL); - } pango_layout_set_font_description (layout, font_desc); pango_layout_set_text (layout, buffer, num_chars); - cairo_translate (cr, day_x, day_y); - pango_cairo_update_layout (cr, layout); - pango_cairo_show_layout (cr, layout); - cairo_restore (cr); + gdk_draw_layout (drawable, fg_gc, + day_x, + day_y, + layout); + + /* We use a stupid technique for bold. Just + draw it again 1 pixel to the left. */ + if (bold) + gdk_draw_layout (drawable, fg_gc, + day_x - 1, + day_y, + layout); } - + /* See if we've reached the end of a month. */ if (day_num == days_in_month[mon]) { month_offset++; @@ -1514,10 +1493,668 @@ e_calendar_item_draw_day_numbers (ECalendarItem *calitem, gdk_gc_set_foreground (fg_gc, &style->fg[GTK_STATE_NORMAL]); g_object_unref (layout); - pango_font_metrics_unref (font_metrics); } +#endif + +#ifdef ENABLE_CAIRO +static void +e_calendar_item_draw (GnomeCanvasItem *canvas_item, + GdkDrawable *drawable, + int x, + int y, + int width, + int height) +{ + ECalendarItem *calitem; + GtkStyle *style; + GdkGC *base_gc, *bg_gc; + gint char_height, row, col, row_y, bar_height, col_x; + gint xthickness, ythickness; + PangoFontDescription *font_desc; + PangoContext *pango_context; + PangoFontMetrics *font_metrics; + cairo_t *cr; + GdkColor base, bg; + +#if 0 + g_print ("In e_calendar_item_draw %i,%i %ix%i\n", + x, y, width, height); +#endif + calitem = E_CALENDAR_ITEM (canvas_item); + style = GTK_WIDGET (canvas_item->canvas)->style; + + /* Set up Pango prerequisites */ + font_desc = calitem->font_desc; + if (!font_desc) + font_desc = style->font_desc; + pango_context = gtk_widget_get_pango_context (GTK_WIDGET (canvas_item->canvas)); + font_metrics = pango_context_get_metrics (pango_context, font_desc, + pango_context_get_language (pango_context)); + + char_height = + PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); + xthickness = style->xthickness; + ythickness = style->ythickness; + base_gc = style->base_gc[GTK_STATE_NORMAL]; + bg_gc = style->bg_gc[GTK_STATE_NORMAL]; + + base = style->base[GTK_STATE_NORMAL]; + bg = style->bg[GTK_STATE_NORMAL]; + cr = gdk_cairo_create (drawable); + + + /* Clear the entire background. */ + cairo_save (cr); + gdk_cairo_set_source_color (cr, &base); + cairo_rectangle (cr, calitem->x1 - x, calitem->y1 - y, + calitem->x2 - calitem->x1 + 1, + calitem->y2 - calitem->y1 + 1); + cairo_fill (cr); + cairo_restore (cr); + + /* Draw the shadow around the entire item. */ + gtk_paint_shadow (style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, + NULL, NULL, "entry", + calitem->x1 - x, calitem->y1 - y, + calitem->x2 - calitem->x1 + 1, + calitem->y2 - calitem->y1 + 1); + + row_y = canvas_item->y1 + ythickness; + bar_height = ythickness * 2 + + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME + char_height + + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME; + + for (row = 0; row < calitem->rows; row++) { + /* Draw the background for the title bars and the shadow around + it, and the vertical lines between columns. */ + + cairo_save (cr); + gdk_cairo_set_source_color (cr, &bg); + cairo_rectangle (cr, calitem->x1 + xthickness - x, row_y - y, + calitem->x2 - calitem->x1 + 1 + - xthickness * 2, + bar_height); + cairo_fill (cr); + cairo_restore (cr); + + gtk_paint_shadow (style, drawable, + GTK_STATE_NORMAL, GTK_SHADOW_OUT, + NULL, NULL, "calendar-header", + calitem->x1 + xthickness - x, row_y - y, + calitem->x2 - calitem->x1 + 1 + - xthickness * 2, + bar_height); + + + for (col = 0; col < calitem->cols; col++) { + if (col != 0) { + col_x = calitem->x1 + calitem->x_offset + + calitem->month_width * col; + gtk_paint_vline (style, drawable, + GTK_STATE_NORMAL, + NULL, NULL, + "calendar-separator", + row_y + ythickness + 1 - y, + row_y + bar_height + - ythickness - 2 - y, + col_x - 1 - x); + } + + + e_calendar_item_draw_month (calitem, drawable, x, y, + width, height, row, col); + } + + row_y += calitem->month_height; + } + + pango_font_metrics_unref (font_metrics); + cairo_destroy (cr); +} + + +static void +layout_set_day_text (ECalendarItem *calitem, PangoLayout *layout, int day_index) +{ + char *day; + int char_size = 0; + + day = g_utf8_offset_to_pointer (calitem->days, day_index); + + /* we use strlen because we actually want to count bytes */ + if (day_index == 6) + char_size = strlen (day); + else + char_size = strlen (day) - strlen (g_utf8_find_next_char (day, NULL)); + + pango_layout_set_text (layout, day, char_size); +} + +static void +e_calendar_item_draw_month (ECalendarItem *calitem, + GdkDrawable *drawable, + int x, + int y, + int width, + int height, + int row, + int col) +{ + GnomeCanvasItem *item; + GtkWidget *widget; + GtkStyle *style; + PangoFontDescription *font_desc; + GdkGC *fg_gc; + struct tm tmp_tm; + GdkRectangle clip_rect; + gint char_height, xthickness, ythickness, start_weekday; + gint year, month; + gint month_x, month_y, month_w, month_h; + gint min_x, max_x, text_x, text_y; + gint day, day_index, cells_x, cells_y, min_cell_width, text_width; + gint clip_width, clip_height; + gchar buffer[64]; + PangoContext *pango_context; + PangoFontMetrics *font_metrics; + PangoLayout *layout; + cairo_t *cr; + GdkColor fg; + +#if 0 + g_print ("In e_calendar_item_draw_month: %i,%i %ix%i row:%i col:%i\n", + x, y, width, height, row, col); +#endif + item = GNOME_CANVAS_ITEM (calitem); + widget = GTK_WIDGET (item->canvas); + style = widget->style; + + cr = gdk_cairo_create (drawable); + /* Set up Pango prerequisites */ + font_desc = calitem->font_desc; + if (!font_desc) + font_desc = style->font_desc; + pango_context = gtk_widget_get_pango_context (widget); + font_metrics = pango_context_get_metrics (pango_context, font_desc, + pango_context_get_language (pango_context)); + + char_height = + PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); + xthickness = style->xthickness; + ythickness = style->ythickness; + fg_gc = style->fg_gc[GTK_STATE_NORMAL]; + + fg = style->fg[GTK_STATE_NORMAL]; + + pango_font_metrics_unref (font_metrics); + + /* Calculate the top-left position of the entire month display. */ + month_x = item->x1 + xthickness + calitem->x_offset + + col * calitem->month_width - x; + month_w = item->x2 - item->x1 - xthickness * 2; + month_w = MIN (month_w, calitem->month_width); + month_y = item->y1 + ythickness + row * calitem->month_height - y; + month_h = item->y2 - item->y1 - ythickness * 2; + month_h = MIN (month_h, calitem->month_height); + + /* Just return if the month is outside the given area. */ + if (month_x >= width || month_x + calitem->month_width <= 0 + || month_y >= height || month_y + calitem->month_height <= 0) + return; + + month = calitem->month + row * calitem->cols + col; + year = calitem->year + month / 12; + month %= 12; + + /* Draw the month name & year, with clipping. Note that the top row + needs extra space around it for the buttons. */ + + layout = gtk_widget_create_pango_layout (widget, NULL); + + if (row == 0 && col == 0) + min_x = E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME_WITH_BUTTON; + else + min_x = E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME; + + max_x = month_w; + if (row == 0 && col == calitem->cols - 1) + max_x -= E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME_WITH_BUTTON; + else + max_x -= E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME; + + text_y = month_y + style->ythickness + + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME; + clip_rect.x = month_x + min_x; + clip_rect.x = MAX (0, clip_rect.x); + clip_rect.y = MAX (0, text_y); + + memset (&tmp_tm, 0, sizeof (tmp_tm)); + tmp_tm.tm_year = year - 1900; + tmp_tm.tm_mon = month; + tmp_tm.tm_mday = 1; + tmp_tm.tm_isdst = -1; + mktime (&tmp_tm); + start_weekday = (tmp_tm.tm_wday + 6) % 7; + + if (month_x + max_x - clip_rect.x > 0) { + clip_rect.width = month_x + max_x - clip_rect.x; + clip_rect.height = text_y + char_height - clip_rect.y; + gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); + + /* This is a strftime() format. %B = Month name, %Y = Year. */ + e_utf8_strftime (buffer, sizeof (buffer), _("%B %Y"), &tmp_tm); + + pango_layout_set_font_description (layout, font_desc); + pango_layout_set_text (layout, buffer, -1); + + /* Ideally we place the text centered in the month, but we + won't go to the left of the minimum x position. */ + pango_layout_get_pixel_size (layout, &text_width, NULL); + text_x = (calitem->month_width - text_width) / 2; + text_x = MAX (min_x, text_x); + + gdk_draw_layout (drawable, fg_gc, + month_x + text_x, + text_y, + layout); + } + + /* Set the clip rectangle for the main month display. */ + clip_rect.x = MAX (0, month_x); + clip_rect.y = MAX (0, month_y); + clip_width = month_x + month_w - clip_rect.x; + clip_height = month_y + month_h - clip_rect.y; + + if (clip_width <= 0 || clip_height <= 0) { + g_object_unref (layout); + return; + } + + clip_rect.width = clip_width; + clip_rect.height = clip_height; + + gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); + + /* Draw the day initials across the top of the month. */ + min_cell_width = calitem->max_digit_width * 2 + + E_CALENDAR_ITEM_MIN_CELL_XPAD; + + cells_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS + calitem->month_lpad + + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS; + if (calitem->show_week_numbers) + cells_x += calitem->max_week_number_digit_width * 2 + + E_CALENDAR_ITEM_XPAD_AFTER_WEEK_NUMBERS + 1; + text_x = cells_x + calitem->cell_width + - (calitem->cell_width - min_cell_width) / 2; + text_x -= E_CALENDAR_ITEM_MIN_CELL_XPAD / 2; + text_y = month_y + ythickness * 2 + + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME + + char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME + + E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad; + + cells_y = text_y + char_height + + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1 + + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS; + + cairo_save (cr); + gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_SELECTED]); + cairo_rectangle (cr, cells_x , + text_y - E_CALENDAR_ITEM_YPAD_ABOVE_CELLS - 1, + calitem->cell_width * 7 , cells_y - text_y ); + cairo_fill (cr); + cairo_restore (cr); + + day_index = calitem->week_start_day; + pango_layout_set_font_description (layout, font_desc); + gdk_gc_set_foreground (fg_gc, &style->text[GTK_STATE_ACTIVE]); + for (day = 0; day < 7; day++) { + layout_set_day_text (calitem, layout, day_index); + gdk_draw_layout (drawable, fg_gc, + text_x - calitem->day_widths [day_index], + text_y, + layout); + text_x += calitem->cell_width; + day_index++; + if (day_index == 7) + day_index = 0; + } + + /* Draw the rectangle around the week number. */ + if (calitem->show_week_numbers) { + cairo_save (cr); + gdk_cairo_set_source_color (cr, &style->base[GTK_STATE_SELECTED]); + cairo_rectangle (cr, cells_x, cells_y - (cells_y - text_y + 2) , + -20, E_CALENDAR_ROWS_PER_MONTH * calitem->cell_height + 18); + cairo_fill (cr); + cairo_restore (cr); + } + + e_calendar_item_draw_day_numbers (calitem, drawable, width, height, + row, col, year, month, start_weekday, + cells_x, cells_y); + + gdk_gc_set_clip_rectangle (fg_gc, NULL); + g_object_unref (layout); + cairo_destroy (cr); +} + + +static void +e_calendar_item_draw_day_numbers (ECalendarItem *calitem, + GdkDrawable *drawable, + int width, + int height, + int row, + int col, + int year, + int month, + int start_weekday, + gint cells_x, + gint cells_y) +{ + GnomeCanvasItem *item; + GtkWidget *widget; + GtkStyle *style; + PangoFontDescription *font_desc, *wkfont_desc; + GdkGC *fg_gc; + GdkColor *bg_color, *fg_color, *box_color; + struct tm today_tm; + time_t t; + gint char_height, min_cell_width, min_cell_height; + gint day_num, drow, dcol, day_x, day_y; + gint text_x, text_y; + gint num_chars, digit; + gint week_num, mon, days_from_week_start; + gint years[3], months[3], days_in_month[3]; + gboolean today, selected, has_focus, drop_target = FALSE; + gboolean bold, draw_day, finished = FALSE; + gint today_year, today_month, today_mday, month_offset; + gchar buffer[2]; + gint day_style = 0; + PangoContext *pango_context; + PangoFontMetrics *font_metrics; + PangoLayout *layout; + cairo_t *cr; + + item = GNOME_CANVAS_ITEM (calitem); + widget = GTK_WIDGET (item->canvas); + style = widget->style; + + cr = gdk_cairo_create (drawable); + + /* Set up Pango prerequisites */ + font_desc = calitem->font_desc; + if (!font_desc) + font_desc = style->font_desc; + wkfont_desc = calitem->week_number_font_desc; + if (!wkfont_desc) + wkfont_desc = font_desc; + fg_gc = style->fg_gc[GTK_STATE_NORMAL]; + + pango_context = gtk_widget_get_pango_context (widget); + font_metrics = pango_context_get_metrics (pango_context, font_desc, + pango_context_get_language (pango_context)); + + char_height = + PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); + + min_cell_width = calitem->max_digit_width * 2 + + E_CALENDAR_ITEM_MIN_CELL_XPAD; + min_cell_height = char_height + E_CALENDAR_ITEM_MIN_CELL_YPAD; + + layout = pango_cairo_create_layout (cr); + + /* Calculate the number of days in the previous, current, and next + months. */ + years[0] = years[1] = years[2] = year; + months[0] = month - 1; + months[1] = month; + months[2] = month + 1; + if (months[0] == -1) { + months[0] = 11; + years[0]--; + } + if (months[2] == 12) { + months[2] = 0; + years[2]++; + } + + days_in_month[0] = DAYS_IN_MONTH (years[0], months[0]); + days_in_month[1] = DAYS_IN_MONTH (years[1], months[1]); + days_in_month[2] = DAYS_IN_MONTH (years[2], months[2]); + + /* Mon 0 is the previous month, which we may show the end of. Mon 1 is + the current month, and mon 2 is the next month. */ + mon = 0; + + month_offset = row * calitem->cols + col - 1; + day_num = days_in_month[0]; + days_from_week_start = (start_weekday + 7 - calitem->week_start_day) + % 7; + /* For the top-left month we show the end of the previous month, and + if the new month starts on the first day of the week we show a + complete week from the previous month. */ + if (days_from_week_start == 0) { + if (row == 0 && col == 0) { + day_num -= 6; + } else { + mon++; + month_offset++; + day_num = 1; + } + } else { + day_num -= days_from_week_start - 1; + } + + /* Get today's date, so we can highlight it. */ + if (calitem->time_callback) { + today_tm = (*calitem->time_callback) (calitem, calitem->time_callback_data); + } else { + t = time (NULL); + today_tm = *localtime (&t); + } + today_year = today_tm.tm_year + 1900; + today_month = today_tm.tm_mon; + today_mday = today_tm.tm_mday; + + /* We usually skip the last days of the previous month (mon = 0), + except for the top-left month displayed. */ + draw_day = (mon == 1 || (row == 0 && col == 0)); + + for (drow = 0; drow < 6; drow++) { + /* Draw the week number. */ + if (calitem->show_week_numbers) { + week_num = e_calendar_item_get_week_number (calitem, + day_num, + months[mon], + years[mon]); + + text_x = cells_x - E_CALENDAR_ITEM_XPAD_BEFORE_CELLS - 1 + - E_CALENDAR_ITEM_XPAD_AFTER_WEEK_NUMBERS; + text_y = cells_y + drow * calitem->cell_height + + + (calitem->cell_height - min_cell_height + 1) / 2; + + num_chars = 0; + if (week_num >= 10) { + digit = week_num / 10; + text_x -= calitem->week_number_digit_widths[digit]; + buffer[num_chars++] = digit + '0'; + } + + digit = week_num % 10; + text_x -= calitem->week_number_digit_widths[digit] + 6; + buffer[num_chars++] = digit + '0'; + + cairo_save (cr); + gdk_cairo_set_source_color (cr, &style->text[GTK_STATE_ACTIVE]); + pango_layout_set_font_description (layout, font_desc); + pango_layout_set_text (layout, buffer, num_chars); + cairo_translate (cr, text_x, text_y); + pango_cairo_update_layout (cr, layout); + pango_cairo_show_layout (cr, layout); + cairo_restore (cr); + } + + for (dcol = 0; dcol < 7; dcol++) { + if (draw_day) { + day_x = cells_x + dcol * calitem->cell_width; + day_y = cells_y + drow * calitem->cell_height; + + today = years[mon] == today_year + && months[mon] == today_month + && day_num == today_mday; + + selected = calitem->selection_set + && (calitem->selection_start_month_offset < month_offset + || (calitem->selection_start_month_offset == month_offset + && calitem->selection_start_day <= day_num)) + && (calitem->selection_end_month_offset > month_offset + || (calitem->selection_end_month_offset == month_offset + && calitem->selection_end_day >= day_num)); + + if (calitem->styles) + day_style = calitem->styles[(month_offset + 1) * 32 + day_num]; + + /* Get the colors & style to use for the day.*/ + if ((GTK_WIDGET_HAS_FOCUS(item->canvas)) && + item->canvas->focused_item == item) + has_focus = TRUE; + else + has_focus = FALSE; + + if (calitem->style_callback) + (*calitem->style_callback) + (calitem, + years[mon], + months[mon], + day_num, + day_style, + today, + mon != 1, + selected, + has_focus, + drop_target, + &bg_color, + &fg_color, + &box_color, + &bold, + calitem->style_callback_data); + else + e_calendar_item_get_day_style + (calitem, + years[mon], + months[mon], + day_num, + day_style, + today, + mon != 1, + selected, + has_focus, + drop_target, + &bg_color, + &fg_color, + &box_color, + &bold); + + /* Draw the background, if set. */ + if (bg_color) { + cairo_save (cr); + gdk_cairo_set_source_color (cr, bg_color); + cairo_rectangle (cr, day_x , day_y, + calitem->cell_width, + calitem->cell_height); + cairo_fill (cr); + cairo_restore (cr); + } + + /* Draw the box, if set. */ + if (box_color) { + cairo_save (cr); + gdk_cairo_set_source_color (cr, box_color); + cairo_rectangle (cr, day_x , day_y, + calitem->cell_width - 1, + calitem->cell_height - 1); + cairo_stroke (cr); + cairo_restore (cr); + } + + /* Draw the 1- or 2-digit day number. */ + day_x += calitem->cell_width - (calitem->cell_width - min_cell_width) / 2; + day_x -= E_CALENDAR_ITEM_MIN_CELL_XPAD / 2; + day_y += (calitem->cell_height - min_cell_height + 1) / 2; + day_y += E_CALENDAR_ITEM_MIN_CELL_YPAD / 2; + + num_chars = 0; + if (day_num >= 10) { + digit = day_num / 10; + day_x -= calitem->digit_widths[digit]; + buffer[num_chars++] = digit + '0'; + } + + digit = day_num % 10; + day_x -= calitem->digit_widths[digit]; + buffer[num_chars++] = digit + '0'; + + cairo_save (cr); + if (fg_color) { + gdk_cairo_set_source_color (cr, fg_color); + } else { + gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); + } + + if (bold) { + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD); + } else { + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_NORMAL); + } + pango_layout_set_font_description (layout, font_desc); + pango_layout_set_text (layout, buffer, num_chars); + cairo_translate (cr, day_x, day_y); + pango_cairo_update_layout (cr, layout); + pango_cairo_show_layout (cr, layout); + cairo_restore (cr); + } + + /* See if we've reached the end of a month. */ + if (day_num == days_in_month[mon]) { + month_offset++; + mon++; + /* We only draw the start of the next month + for the bottom-right month displayed. */ + if (mon == 2 && (row != calitem->rows - 1 + || col != calitem->cols - 1)) { + /* Set a flag so we exit the loop. */ + finished = TRUE; + break; + } + day_num = 1; + draw_day = TRUE; + } else { + day_num++; + } + } + + /* Exit the loop if the flag is set. */ + if (finished) + break; + } + + /* Reset pango weight */ + pango_font_description_set_weight (font_desc, PANGO_WEIGHT_NORMAL); + + /* Reset the foreground color. */ + gdk_gc_set_foreground (fg_gc, &style->fg[GTK_STATE_NORMAL]); + + g_object_unref (layout); + + pango_font_metrics_unref (font_metrics); + cairo_destroy (cr); +} +#endif gint e_calendar_item_get_week_number (ECalendarItem *calitem, -- cgit v1.2.3