2 * EWeekViewMainItem - displays the background grid and dates for the Week and
3 * Month calendar views.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 * Damon Chaplin <damon@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
23 #include "evolution-config.h"
26 #include <glib/gi18n.h>
28 #include "e-week-view-main-item.h"
29 #include "ea-calendar.h"
30 #include "calendar-config.h"
32 #define E_WEEK_VIEW_MAIN_ITEM_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_WEEK_VIEW_MAIN_ITEM, EWeekViewMainItemPrivate))
36 struct _EWeekViewMainItemPrivate
{
47 e_week_view_main_item
,
48 GNOME_TYPE_CANVAS_ITEM
)
51 week_view_main_item_draw_day (EWeekViewMainItem
*main_item
,
62 gint right_edge
, bottom_edge
, date_width
, date_x
, line_y
;
63 gboolean show_day_name
, show_month_name
, selected
;
64 gchar buffer
[128], *format_string
;
65 gint month
, day_of_month
, max_width
;
68 PangoFontDescription
*font_desc
;
69 PangoContext
*pango_context
;
70 PangoFontMetrics
*font_metrics
;
72 gboolean today
= FALSE
;
73 gboolean multi_week_view
;
75 week_view
= e_week_view_main_item_get_week_view (main_item
);
76 model
= e_calendar_view_get_model (E_CALENDAR_VIEW (week_view
));
78 multi_week_view
= e_week_view_get_multi_week_view (week_view
);
80 /* Set up Pango prerequisites */
81 pango_context
= gtk_widget_get_pango_context (GTK_WIDGET (week_view
));
82 font_desc
= pango_font_description_copy (pango_context_get_font_description (pango_context
));
83 font_metrics
= pango_context_get_metrics (
84 pango_context
, font_desc
,
85 pango_context_get_language (pango_context
));
87 month
= g_date_get_month (date
);
88 weekday
= g_date_get_weekday (date
);
89 day_of_month
= g_date_get_day (date
);
90 line_y
= y
+ E_WEEK_VIEW_DATE_T_PAD
+
91 PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics
)) +
92 PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics
)) +
93 E_WEEK_VIEW_DATE_LINE_T_PAD
;
97 struct icaltimetype tt
;
98 const icaltimezone
*zone
;
100 view
= E_CALENDAR_VIEW (week_view
);
101 zone
= e_calendar_view_get_timezone (view
);
103 /* Check if we are drawing today */
104 tt
= icaltime_from_timet_with_zone (
105 time (NULL
), FALSE
, zone
);
106 today
= g_date_get_year (date
) == tt
.year
107 && g_date_get_month (date
) == tt
.month
108 && g_date_get_day (date
) == tt
.day
;
111 /* Draw the background of the day. In the month view odd months are
112 * one color and even months another, so you can easily see when each
113 * month starts (defaults are white for odd - January, March, ... and
114 * light gray for even). In the week view the background is always the
115 * same color, the color used for the odd months in the month view. */
117 bg_color
= &week_view
->colors
[E_WEEK_VIEW_COLOR_TODAY_BACKGROUND
];
118 else if (!e_cal_model_get_work_day (model
, weekday
))
119 bg_color
= &week_view
->colors
[E_WEEK_VIEW_COLOR_MONTH_NONWORKING_DAY
];
120 else if (multi_week_view
&& (month
% 2 == 0))
121 bg_color
= &week_view
->colors
[E_WEEK_VIEW_COLOR_EVEN_MONTHS
];
123 bg_color
= &week_view
->colors
[E_WEEK_VIEW_COLOR_ODD_MONTHS
];
126 gdk_cairo_set_source_color (cr
, bg_color
);
127 cairo_rectangle (cr
, x
, y
, width
, height
);
131 /* Draw the lines on the right and bottom of the cell. The canvas is
132 * sized so that the lines on the right & bottom edges will be off the
133 * edge of the canvas, so we don't have to worry about them. */
134 right_edge
= x
+ width
- 1;
135 bottom_edge
= y
+ height
- 1;
138 gdk_cairo_set_source_color (cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_GRID
]);
139 cairo_set_line_width (cr
, 0.5);
140 cairo_move_to (cr
, right_edge
+ 0.5, y
);
141 cairo_line_to (cr
, right_edge
+ 0.5, bottom_edge
);
142 cairo_move_to (cr
, x
, bottom_edge
+ 0.5);
143 cairo_line_to (cr
, right_edge
, bottom_edge
+ 0.5);
147 /* If the day is selected, draw the blue background. */
150 if (week_view
->selection_start_day
== -1
151 || week_view
->selection_start_day
> day
152 || week_view
->selection_end_day
< day
)
155 if (gtk_widget_has_focus (GTK_WIDGET (week_view
))) {
156 gdk_cairo_set_source_color (
157 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_SELECTED
]);
159 gdk_cairo_set_source_color (
160 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_SELECTED_UNFOCUSSED
]);
163 if (multi_week_view
) {
167 E_WEEK_VIEW_DATE_T_PAD
- 1 +
168 PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics
)) +
169 PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics
)));
174 width
- 5, line_y
- y
);
180 /* Display the date in the top of the cell.
181 * In the week view, display the long format "10 January" in all cells,
182 * or abbreviate it to "10 Jan" or "10" if that doesn't fit.
183 * In the month view, only use the long format for the first cell and
184 * the 1st of each month, otherwise use "10". */
185 show_day_name
= FALSE
;
186 show_month_name
= FALSE
;
187 if (!multi_week_view
) {
188 show_day_name
= TRUE
;
189 show_month_name
= TRUE
;
190 } else if ((day
% 7) == 0 || day_of_month
== 1) {
191 show_month_name
= TRUE
;
194 /* Now find the longest form of the date that will fit. */
195 max_width
= width
- 4;
196 format_string
= NULL
;
198 if (week_view
->max_day_width
+ week_view
->digit_width
* 2
199 + week_view
->space_width
* 2
200 + week_view
->month_widths
[month
- 1] < max_width
)
201 /* strftime format %A = full weekday name, %d = day of
202 * month, %B = full month name. You can change the
203 * order but don't change the specifiers or add
205 format_string
= _("%A %d %B");
206 else if (week_view
->max_abbr_day_width
207 + week_view
->digit_width
* 2
208 + week_view
->space_width
* 2
209 + week_view
->abbr_month_widths
[month
- 1] < max_width
)
210 /* strftime format %a = abbreviated weekday name,
211 * %d = day of month, %b = abbreviated month name.
212 * You can change the order but don't change the
213 * specifiers or add anything. */
214 format_string
= _("%a %d %b");
216 if (!format_string
&& show_month_name
) {
217 if (week_view
->digit_width
* 2 + week_view
->space_width
218 + week_view
->month_widths
[month
- 1] < max_width
)
219 /* strftime format %d = day of month, %B = full
220 * month name. You can change the order but don't
221 * change the specifiers or add anything. */
222 format_string
= _("%d %B");
223 else if (week_view
->digit_width
* 2 + week_view
->space_width
224 + week_view
->abbr_month_widths
[month
- 1] < max_width
)
225 /* strftime format %d = day of month, %b = abbreviated
226 * month name. You can change the order but don't
227 * change the specifiers or add anything. */
228 format_string
= _("%d %b");
233 gdk_cairo_set_source_color (
234 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_DATES_SELECTED
]);
235 } else if (multi_week_view
) {
237 gdk_cairo_set_source_color (
238 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_TODAY
]);
240 gdk_cairo_set_source_color (
241 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_DATES
]);
244 gdk_cairo_set_source_color (
245 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_DATES
]);
250 buffer
, sizeof (buffer
),
251 format_string
? format_string
: "<b>%d</b>", date
);
252 layout
= gtk_widget_create_pango_layout (GTK_WIDGET (week_view
), NULL
);
253 pango_layout_set_text (layout
, buffer
, -1);
254 pango_layout_set_markup (layout
, buffer
, strlen (buffer
));
257 buffer
, sizeof (buffer
),
258 format_string
? format_string
: "%d", date
);
259 layout
= gtk_widget_create_pango_layout (GTK_WIDGET (week_view
), NULL
);
260 pango_layout_set_text (layout
, buffer
, -1);
263 pango_layout_get_pixel_size (layout
, &date_width
, NULL
);
264 date_x
= x
+ width
- date_width
- E_WEEK_VIEW_DATE_R_PAD
;
265 date_x
= MAX (date_x
, x
+ 1);
267 cairo_translate (cr
, date_x
, y
+ E_WEEK_VIEW_DATE_T_PAD
);
268 pango_cairo_update_layout (cr
, layout
);
269 pango_cairo_show_layout (cr
, layout
);
271 g_object_unref (layout
);
273 /* Draw the line under the date. */
274 if (!multi_week_view
) {
276 gdk_cairo_set_source_color (
277 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_GRID
]);
278 cairo_set_line_width (cr
, 0.7);
279 cairo_move_to (cr
, x
+ E_WEEK_VIEW_DATE_LINE_L_PAD
, line_y
);
280 cairo_line_to (cr
, right_edge
, line_y
);
284 pango_font_metrics_unref (font_metrics
);
285 pango_font_description_free (font_desc
);
289 week_view_main_item_set_property (GObject
*object
,
294 switch (property_id
) {
296 e_week_view_main_item_set_week_view (
297 E_WEEK_VIEW_MAIN_ITEM (object
),
298 g_value_get_object (value
));
302 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
306 week_view_main_item_get_property (GObject
*object
,
311 switch (property_id
) {
314 value
, e_week_view_main_item_get_week_view (
315 E_WEEK_VIEW_MAIN_ITEM (object
)));
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
323 week_view_main_item_dispose (GObject
*object
)
325 EWeekViewMainItemPrivate
*priv
;
327 priv
= E_WEEK_VIEW_MAIN_ITEM_GET_PRIVATE (object
);
329 if (priv
->week_view
!= NULL
) {
330 g_object_unref (priv
->week_view
);
331 priv
->week_view
= NULL
;
334 /* Chain up to parent's dispose() method. */
335 G_OBJECT_CLASS (e_week_view_main_item_parent_class
)->dispose (object
);
339 week_view_main_item_update (GnomeCanvasItem
*item
,
340 const cairo_matrix_t
*i2c
,
343 GnomeCanvasItemClass
*canvas_item_class
;
345 /* Chain up to parent's update() method. */
347 GNOME_CANVAS_ITEM_CLASS (e_week_view_main_item_parent_class
);
348 canvas_item_class
->update (item
, i2c
, flags
);
350 /* The item covers the entire canvas area. */
358 week_view_main_item_draw (GnomeCanvasItem
*canvas_item
,
365 EWeekViewMainItem
*main_item
;
366 EWeekView
*week_view
;
368 gint num_days
, day
, day_x
, day_y
, day_w
, day_h
;
370 main_item
= E_WEEK_VIEW_MAIN_ITEM (canvas_item
);
371 week_view
= e_week_view_main_item_get_week_view (main_item
);
372 g_return_if_fail (week_view
!= NULL
);
374 /* Step through each of the days. */
375 e_week_view_get_first_day_shown (week_view
, &date
);
377 /* If no date has been set, we just use Dec 1999/January 2000. */
378 if (!g_date_valid (&date
))
379 g_date_set_dmy (&date
, 27, 12, 1999);
381 num_days
= e_week_view_get_weeks_shown (week_view
) * 7;
382 for (day
= 0; day
< num_days
; day
++) {
383 e_week_view_get_day_position (
387 /* Skip any days which are outside the area. */
388 if (day_x
< x
+ width
&& day_x
+ day_w
>= x
389 && day_y
< y
+ height
&& day_y
+ day_h
>= y
) {
390 week_view_main_item_draw_day (
391 main_item
, day
, &date
, cr
,
392 day_x
- x
, day_y
- y
, day_w
, day_h
);
394 g_date_add_days (&date
, 1);
398 static GnomeCanvasItem
*
399 week_view_main_item_point (GnomeCanvasItem
*item
,
409 e_week_view_main_item_class_init (EWeekViewMainItemClass
*class)
411 GObjectClass
*object_class
;
412 GnomeCanvasItemClass
*item_class
;
414 g_type_class_add_private (class, sizeof (EWeekViewMainItemPrivate
));
416 object_class
= G_OBJECT_CLASS (class);
417 object_class
->set_property
= week_view_main_item_set_property
;
418 object_class
->get_property
= week_view_main_item_get_property
;
419 object_class
->dispose
= week_view_main_item_dispose
;
421 item_class
= GNOME_CANVAS_ITEM_CLASS (class);
422 item_class
->update
= week_view_main_item_update
;
423 item_class
->draw
= week_view_main_item_draw
;
424 item_class
->point
= week_view_main_item_point
;
426 g_object_class_install_property (
429 g_param_spec_object (
436 /* init the accessibility support for e_week_view_main_item */
437 e_week_view_main_item_a11y_init ();
441 e_week_view_main_item_init (EWeekViewMainItem
*main_item
)
443 main_item
->priv
= E_WEEK_VIEW_MAIN_ITEM_GET_PRIVATE (main_item
);
447 e_week_view_main_item_get_week_view (EWeekViewMainItem
*main_item
)
449 g_return_val_if_fail (E_IS_WEEK_VIEW_MAIN_ITEM (main_item
), NULL
);
451 return main_item
->priv
->week_view
;
455 e_week_view_main_item_set_week_view (EWeekViewMainItem
*main_item
,
456 EWeekView
*week_view
)
458 g_return_if_fail (E_IS_WEEK_VIEW_MAIN_ITEM (main_item
));
459 g_return_if_fail (E_IS_WEEK_VIEW (week_view
));
461 if (main_item
->priv
->week_view
== week_view
)
464 if (main_item
->priv
->week_view
!= NULL
)
465 g_object_unref (main_item
->priv
->week_view
);
467 main_item
->priv
->week_view
= g_object_ref (week_view
);
469 g_object_notify (G_OBJECT (main_item
), "week-view");