2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 * Damon Chaplin <damon@ximian.com>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
23 * EWeekViewEventItem - displays the background, times and icons for an event
24 * in the week/month views. A separate EText canvas item is used to display &
28 #include "evolution-config.h"
30 #include "e-week-view-event-item.h"
34 #include "e-calendar-view.h"
35 #include "comp-util.h"
37 #define E_WEEK_VIEW_EVENT_ITEM_GET_PRIVATE(obj) \
38 (G_TYPE_INSTANCE_GET_PRIVATE \
39 ((obj), E_TYPE_WEEK_VIEW_EVENT_ITEM, EWeekViewEventItemPrivate))
41 struct _EWeekViewEventItemPrivate
{
42 /* The event index in the EWeekView events array. */
45 /* The span index within the event. */
57 e_week_view_event_item
,
58 GNOME_TYPE_CANVAS_ITEM
)
61 can_draw_in_region (cairo_region_t
*draw_region
,
69 g_return_val_if_fail (draw_region
!= NULL
, FALSE
);
76 return cairo_region_contains_rectangle (draw_region
, &rect
) !=
77 CAIRO_REGION_OVERLAP_OUT
;
80 static ECalendarViewPosition
81 week_view_event_item_get_position (EWeekViewEventItem
*event_item
,
86 GnomeCanvasItem
*item
;
89 item
= GNOME_CANVAS_ITEM (event_item
);
91 parent
= gtk_widget_get_parent (GTK_WIDGET (item
->canvas
));
92 g_return_val_if_fail (E_IS_WEEK_VIEW (parent
), E_CALENDAR_VIEW_POS_NONE
);
94 week_view
= E_WEEK_VIEW (parent
);
96 if (x
< item
->x1
+ E_WEEK_VIEW_EVENT_L_PAD
97 || x
>= item
->x2
- E_WEEK_VIEW_EVENT_R_PAD
)
98 return E_CALENDAR_VIEW_POS_NONE
;
100 /* Support left/right edge for long events only. */
101 if (!e_week_view_is_one_day_event (week_view
, event_item
->priv
->event_num
)) {
102 if (x
< item
->x1
+ E_WEEK_VIEW_EVENT_L_PAD
103 + E_WEEK_VIEW_EVENT_BORDER_WIDTH
104 + E_WEEK_VIEW_EVENT_EDGE_X_PAD
)
105 return E_CALENDAR_VIEW_POS_LEFT_EDGE
;
107 if (x
>= item
->x2
+ 1 - E_WEEK_VIEW_EVENT_R_PAD
108 - E_WEEK_VIEW_EVENT_BORDER_WIDTH
109 - E_WEEK_VIEW_EVENT_EDGE_X_PAD
)
110 return E_CALENDAR_VIEW_POS_RIGHT_EDGE
;
113 return E_CALENDAR_VIEW_POS_EVENT
;
117 week_view_event_item_double_click (EWeekViewEventItem
*event_item
,
118 GdkEvent
*button_event
)
120 EWeekView
*week_view
;
121 EWeekViewEvent
*event
;
122 GnomeCanvasItem
*item
;
125 item
= GNOME_CANVAS_ITEM (event_item
);
127 parent
= gtk_widget_get_parent (GTK_WIDGET (item
->canvas
));
128 g_return_val_if_fail (E_IS_WEEK_VIEW (parent
), FALSE
);
130 week_view
= E_WEEK_VIEW (parent
);
132 if (!is_array_index_in_bounds (week_view
->events
, event_item
->priv
->event_num
))
135 event
= &g_array_index (
136 week_view
->events
, EWeekViewEvent
,
137 event_item
->priv
->event_num
);
139 if (!is_comp_data_valid (event
))
142 if (week_view
->editing_event_num
>= 0) {
143 EWeekViewEvent
*editing
;
145 if (!is_array_index_in_bounds (
146 week_view
->events
, week_view
->editing_event_num
))
149 editing
= &g_array_index (
150 week_view
->events
, EWeekViewEvent
,
151 week_view
->editing_event_num
);
153 /* Do not call edit of the component, if double clicked
154 * on the component, which is not on the server. */
155 if (editing
&& event
&&
156 editing
->comp_data
== event
->comp_data
&&
157 is_comp_data_valid (editing
) &&
158 (!event
->comp_data
|| event
->comp_data
->is_new_component
))
162 e_week_view_stop_editing_event (week_view
);
164 e_calendar_view_edit_appointment (
165 E_CALENDAR_VIEW (week_view
),
166 event
->comp_data
->client
,
167 event
->comp_data
->icalcomp
, EDIT_EVENT_AUTODETECT
);
173 week_view_event_item_button_press (EWeekViewEventItem
*event_item
,
174 GdkEvent
*button_event
)
176 EWeekView
*week_view
;
177 ECalendarViewPosition pos
;
178 EWeekViewEvent
*event
;
179 EWeekViewEventSpan
*span
;
180 GnomeCanvasItem
*item
;
182 guint event_button
= 0;
183 gdouble event_x_win
= 0;
184 gdouble event_y_win
= 0;
186 gdk_event_get_button (button_event
, &event_button
);
187 gdk_event_get_coords (button_event
, &event_x_win
, &event_y_win
);
189 item
= GNOME_CANVAS_ITEM (event_item
);
191 parent
= gtk_widget_get_parent (GTK_WIDGET (item
->canvas
));
192 g_return_val_if_fail (E_IS_WEEK_VIEW (parent
), FALSE
);
194 week_view
= E_WEEK_VIEW (parent
);
196 if (!is_array_index_in_bounds (week_view
->events
, event_item
->priv
->event_num
))
199 event
= &g_array_index (
200 week_view
->events
, EWeekViewEvent
,
201 event_item
->priv
->event_num
);
203 if (!is_array_index_in_bounds (
204 week_view
->spans
, event
->spans_index
+
205 event_item
->priv
->span_num
))
208 span
= &g_array_index (week_view
->spans
, EWeekViewEventSpan
,
209 event
->spans_index
+ event_item
->priv
->span_num
);
211 pos
= week_view_event_item_get_position (
212 event_item
, event_x_win
, event_y_win
);
213 if (pos
== E_CALENDAR_VIEW_POS_NONE
)
216 if (event_button
== 1) {
217 week_view
->pressed_event_num
= event_item
->priv
->event_num
;
218 week_view
->pressed_span_num
= event_item
->priv
->span_num
;
220 /* Ignore clicks on the event while editing. */
221 if (E_TEXT (span
->text_item
)->editing
)
224 /* Remember the item clicked and the mouse position,
225 * so we can start a drag if the mouse moves. */
226 week_view
->drag_event_x
= event_x_win
;
227 week_view
->drag_event_y
= event_y_win
;
229 /* FIXME: Remember the day offset from the start of the event.
234 } else if (event_button
== 3) {
235 if (!gtk_widget_has_focus (GTK_WIDGET (week_view
))) {
236 gtk_widget_grab_focus (GTK_WIDGET (week_view
));
237 if (week_view
->event_destroyed
) {
238 week_view
->event_destroyed
= FALSE
;
244 e_week_view_set_selected_time_range_visible (
245 week_view
, event
->start
, event
->end
);
247 e_week_view_show_popup_menu (
248 week_view
, button_event
,
249 event_item
->priv
->event_num
);
250 g_signal_stop_emission_by_name (
251 item
->canvas
, "button_press_event");
260 week_view_event_item_button_release (EWeekViewEventItem
*event_item
,
263 EWeekView
*week_view
;
264 GnomeCanvasItem
*item
;
267 item
= GNOME_CANVAS_ITEM (event_item
);
269 parent
= gtk_widget_get_parent (GTK_WIDGET (item
->canvas
));
270 g_return_val_if_fail (E_IS_WEEK_VIEW (parent
), FALSE
);
272 week_view
= E_WEEK_VIEW (parent
);
274 if (week_view
->pressed_event_num
!= -1
275 && week_view
->pressed_event_num
== event_item
->priv
->event_num
276 && week_view
->pressed_span_num
== event_item
->priv
->span_num
) {
277 e_week_view_start_editing_event (
279 event_item
->priv
->event_num
,
280 event_item
->priv
->span_num
,
282 week_view
->pressed_event_num
= -1;
286 week_view
->pressed_event_num
= -1;
292 week_view_draw_time (EWeekView
*week_view
,
301 gint hour_to_display
, suffix_width
;
302 gint time_y_normal_font
, time_y_small_font
;
306 PangoFontDescription
*small_font_desc
;
307 PangoContext
*pango_context
;
312 if ((bg_rgba
.red
> 0.7) || (bg_rgba
.green
> 0.7) || (bg_rgba
.blue
> 0.7)) {
317 color
.red
= 65535.0f
;
318 color
.green
= 65535.0f
;
319 color
.blue
= 65535.0f
;
324 model
= e_calendar_view_get_model (E_CALENDAR_VIEW (week_view
));
326 small_font_desc
= week_view
->small_font_desc
;
328 gdk_cairo_set_source_color (cr
, &color
);
330 layout
= gtk_widget_create_pango_layout (GTK_WIDGET (week_view
), NULL
);
331 pango_context
= gtk_widget_create_pango_context (GTK_WIDGET (week_view
));
333 time_y_normal_font
= time_y_small_font
= time_y
;
335 time_y_small_font
= time_y
;
337 e_week_view_convert_time_to_display (
338 week_view
, hour
, &hour_to_display
,
339 &suffix
, &suffix_width
);
341 if (week_view
->use_small_font
&& week_view
->small_font_desc
) {
342 PangoFontDescription
*font_desc
;
344 font_desc
= pango_font_description_copy (pango_context_get_font_description (pango_context
));
347 buffer
, sizeof (buffer
), "%2i:%02i",
348 hour_to_display
, minute
);
351 if (hour_to_display
< 10) {
352 pango_layout_set_text (layout
, buffer
+ 1, 1);
355 time_x
+ week_view
->digit_width
,
357 pango_cairo_show_layout (cr
, layout
);
359 pango_layout_set_text (layout
, buffer
, 2);
364 pango_cairo_show_layout (cr
, layout
);
367 time_x
+= week_view
->digit_width
* 2;
369 /* Draw the start minute, in the small font. */
370 pango_layout_set_font_description (layout
, week_view
->small_font_desc
);
371 pango_layout_set_text (layout
, buffer
+ 3, 2);
376 pango_cairo_show_layout (cr
, layout
);
378 pango_layout_set_font_description (layout
, font_desc
);
380 time_x
+= week_view
->small_digit_width
* 2;
382 /* Draw the 'am'/'pm' suffix, if 12-hour format. */
383 if (!e_cal_model_get_use_24_hour_format (model
)) {
384 pango_layout_set_text (layout
, suffix
, -1);
390 pango_cairo_show_layout (cr
, layout
);
393 pango_font_description_free (font_desc
);
395 /* Draw the start time in one go. */
397 buffer
, sizeof (buffer
), "%2i:%02i%s",
398 hour_to_display
, minute
, suffix
);
399 if (hour_to_display
< 10) {
400 pango_layout_set_text (layout
, buffer
+ 1, -1);
403 time_x
+ week_view
->digit_width
,
405 pango_cairo_show_layout (cr
, layout
);
407 pango_layout_set_text (layout
, buffer
, -1);
412 pango_cairo_show_layout (cr
, layout
);
416 g_object_unref (pango_context
);
417 g_object_unref (layout
);
423 week_view_event_item_draw_icons (EWeekViewEventItem
*event_item
,
428 gboolean right_align
,
429 cairo_region_t
*draw_region
)
431 EWeekView
*week_view
;
432 EWeekViewEvent
*event
;
436 gint num_icons
= 0, icon_x_inc
;
437 gboolean draw_reminder_icon
= FALSE
, draw_recurrence_icon
= FALSE
;
438 gboolean draw_timezone_icon
= FALSE
, draw_attach_icon
= FALSE
;
439 gboolean draw_meeting_icon
= FALSE
;
440 GSList
*categories_pixbufs
= NULL
, *pixbufs
;
442 canvas
= GNOME_CANVAS_ITEM (event_item
)->canvas
;
443 parent
= gtk_widget_get_parent (GTK_WIDGET (canvas
));
444 week_view
= E_WEEK_VIEW (parent
);
446 if (e_week_view_get_multi_week_view (week_view
) &&
447 !e_week_view_get_show_icons_month_view (week_view
))
450 if (!is_array_index_in_bounds (week_view
->events
, event_item
->priv
->event_num
))
453 event
= &g_array_index (week_view
->events
, EWeekViewEvent
,
454 event_item
->priv
->event_num
);
456 if (!is_comp_data_valid (event
))
459 comp
= e_cal_component_new ();
460 e_cal_component_set_icalcomponent (
461 comp
, icalcomponent_new_clone (event
->comp_data
->icalcomp
));
463 if (e_cal_component_has_alarms (comp
)) {
464 draw_reminder_icon
= TRUE
;
468 if (e_cal_component_has_recurrences (comp
) ||
469 e_cal_component_is_instance (comp
)) {
470 draw_recurrence_icon
= TRUE
;
474 if (e_cal_component_has_attachments (comp
)) {
475 draw_attach_icon
= TRUE
;
479 if (e_cal_component_has_attendees (comp
)) {
480 draw_meeting_icon
= TRUE
;
484 if (event
->different_timezone
) {
485 draw_timezone_icon
= TRUE
;
489 num_icons
+= cal_comp_util_get_n_icons (comp
, &categories_pixbufs
);
491 icon_x_inc
= E_WEEK_VIEW_ICON_WIDTH
+ E_WEEK_VIEW_ICON_X_PAD
;
494 icon_x
-= icon_x_inc
* num_icons
;
496 #define draw_pixbuf(pf) \
497 if (can_draw_in_region (draw_region, icon_x, icon_y, \
498 E_WEEK_VIEW_ICON_WIDTH, E_WEEK_VIEW_ICON_HEIGHT)) { \
500 gdk_cairo_set_source_pixbuf (cr, pf, icon_x, icon_y); \
502 cairo_restore (cr); \
505 icon_x += icon_x_inc;
507 if (draw_reminder_icon
&& icon_x
+ E_WEEK_VIEW_ICON_WIDTH
<= x2
) {
508 draw_pixbuf (week_view
->reminder_icon
);
511 if (draw_attach_icon
&& icon_x
+ E_WEEK_VIEW_ICON_WIDTH
<= x2
) {
512 draw_pixbuf (week_view
->attach_icon
);
515 if (draw_recurrence_icon
&& icon_x
+ E_WEEK_VIEW_ICON_WIDTH
<= x2
) {
516 draw_pixbuf (week_view
->recurrence_icon
);
519 if (draw_timezone_icon
&& icon_x
+ E_WEEK_VIEW_ICON_WIDTH
<= x2
) {
520 draw_pixbuf (week_view
->timezone_icon
);
523 if (draw_meeting_icon
&& icon_x
+ E_WEEK_VIEW_ICON_WIDTH
<= x2
) {
524 draw_pixbuf (week_view
->meeting_icon
);
527 /* draw categories icons */
528 for (pixbufs
= categories_pixbufs
;
530 pixbufs
= pixbufs
->next
) {
531 GdkPixbuf
*pixbuf
= pixbufs
->data
;
533 draw_pixbuf (pixbuf
);
538 g_slist_foreach (categories_pixbufs
, (GFunc
) g_object_unref
, NULL
);
539 g_slist_free (categories_pixbufs
);
541 g_object_unref (comp
);
544 /* This draws a little triangle to indicate that an event extends past
545 * the days visible on screen. */
547 week_view_event_item_draw_triangle (EWeekViewEventItem
*event_item
,
554 cairo_region_t
*draw_region
)
556 EWeekView
*week_view
;
557 EWeekViewEvent
*event
;
563 if (!can_draw_in_region (draw_region
, x
, y
, w
, h
))
566 canvas
= GNOME_CANVAS_ITEM (event_item
)->canvas
;
567 parent
= gtk_widget_get_parent (GTK_WIDGET (canvas
));
568 week_view
= E_WEEK_VIEW (parent
);
570 if (!is_array_index_in_bounds (week_view
->events
, event_item
->priv
->event_num
))
573 event
= &g_array_index (week_view
->events
, EWeekViewEvent
,
574 event_item
->priv
->event_num
);
576 if (!is_comp_data_valid (event
))
582 points
[1].y
= y
+ (h
/ 2);
584 points
[2].y
= y
+ h
- 1;
586 gdk_cairo_set_source_rgba (cr
, &bg_rgba
);
589 cairo_set_line_width (cr
, 0.7);
590 cairo_move_to (cr
, points
[0].x
, points
[0].y
);
591 cairo_line_to (cr
, points
[1].x
, points
[1].y
);
592 cairo_line_to (cr
, points
[2].x
, points
[2].y
);
593 cairo_line_to (cr
, points
[0].x
, points
[0].y
);
598 gdk_cairo_set_source_color (
599 cr
, &week_view
->colors
[E_WEEK_VIEW_COLOR_EVENT_BORDER
]);
601 /* If the height is odd we can use the same central point for both
602 * lines. If it is even we use different end-points. */
603 c1
= c2
= y
+ (h
/ 2);
607 cairo_set_line_width (cr
, 0.7);
608 cairo_move_to (cr
, x
, y
);
609 cairo_line_to (cr
, x
+ w
, c1
);
610 cairo_move_to (cr
, x
, y
+ h
- 1);
611 cairo_line_to (cr
, x
+ w
, c2
);
616 week_view_event_item_set_property (GObject
*object
,
621 switch (property_id
) {
623 e_week_view_event_item_set_event_num (
624 E_WEEK_VIEW_EVENT_ITEM (object
),
625 g_value_get_int (value
));
629 e_week_view_event_item_set_span_num (
630 E_WEEK_VIEW_EVENT_ITEM (object
),
631 g_value_get_int (value
));
635 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
639 week_view_event_item_get_property (GObject
*object
,
644 switch (property_id
) {
648 e_week_view_event_item_get_event_num (
649 E_WEEK_VIEW_EVENT_ITEM (object
)));
655 e_week_view_event_item_get_span_num (
656 E_WEEK_VIEW_EVENT_ITEM (object
)));
660 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
664 week_view_event_item_update (GnomeCanvasItem
*item
,
665 const cairo_matrix_t
*i2c
,
668 GnomeCanvasItemClass
*canvas_item_class
;
669 EWeekViewEventItem
*event_item
;
670 EWeekView
*week_view
;
672 gint event_num
, span_num
;
673 gint span_x
, span_y
, span_w
;
675 event_item
= E_WEEK_VIEW_EVENT_ITEM (item
);
676 parent
= gtk_widget_get_parent (GTK_WIDGET (item
->canvas
));
677 g_return_if_fail (E_IS_WEEK_VIEW (parent
));
679 week_view
= E_WEEK_VIEW (parent
);
681 /* Chain up to parent's update() method. */
683 GNOME_CANVAS_ITEM_CLASS (e_week_view_event_item_parent_class
);
684 canvas_item_class
->update (item
, i2c
, flags
);
691 event_num
= e_week_view_event_item_get_event_num (event_item
);
692 span_num
= e_week_view_event_item_get_span_num (event_item
);
694 if (event_num
!= -1 && span_num
!= -1) {
695 if (e_week_view_get_span_position (
696 week_view
, event_num
, span_num
,
697 &span_x
, &span_y
, &span_w
)) {
700 item
->x2
= span_x
+ span_w
- 1;
701 item
->y2
= span_y
+ week_view
->row_height
- 1;
707 week_view_event_item_draw (GnomeCanvasItem
*canvas_item
,
714 EWeekViewEventItem
*event_item
;
715 EWeekView
*week_view
;
716 EWeekViewEvent
*event
;
717 EWeekViewEventSpan
*span
;
720 gint x1
, y1
, x2
, y2
, time_x
, time_y
;
721 gint icon_x
, icon_y
, time_width
, min_end_time_x
, max_icon_x
;
722 gint rect_x
, rect_w
, rect_x2
= 0;
723 gboolean one_day_event
, editing_span
= FALSE
;
724 gint start_hour
, start_minute
, end_hour
, end_minute
;
725 gboolean draw_start
, draw_end
;
726 gboolean draw_start_triangle
= FALSE
, draw_end_triangle
= FALSE
;
728 cairo_pattern_t
*pat
;
729 gdouble radius
, cx0
, cy0
, rect_height
, rect_width
;
730 cairo_region_t
*draw_region
;
732 gboolean draw_flat_events
;
734 event_item
= E_WEEK_VIEW_EVENT_ITEM (canvas_item
);
735 parent
= gtk_widget_get_parent (GTK_WIDGET (canvas_item
->canvas
));
736 g_return_if_fail (E_IS_WEEK_VIEW (parent
));
738 week_view
= E_WEEK_VIEW (parent
);
740 if (event_item
->priv
->event_num
== -1 || event_item
->priv
->span_num
== -1)
743 g_return_if_fail (event_item
->priv
->event_num
< week_view
->events
->len
);
745 if (!is_array_index_in_bounds (week_view
->events
, event_item
->priv
->event_num
))
748 event
= &g_array_index (week_view
->events
, EWeekViewEvent
,
749 event_item
->priv
->event_num
);
751 if (!is_comp_data_valid (event
))
755 event
->spans_index
+ event_item
->priv
->span_num
<
756 week_view
->spans
->len
);
758 if (!is_array_index_in_bounds (
759 week_view
->spans
, event
->spans_index
+
760 event_item
->priv
->span_num
))
763 span
= &g_array_index (
764 week_view
->spans
, EWeekViewEventSpan
,
765 event
->spans_index
+ event_item
->priv
->span_num
);
767 x1
= canvas_item
->x1
- x
;
768 y1
= canvas_item
->y1
- y
;
769 x2
= canvas_item
->x2
- x
;
770 y2
= canvas_item
->y2
- y
;
772 if (x1
== x2
|| y1
== y2
)
778 rect
.height
= height
;
779 if (rect
.width
> 0 && rect
.height
> 0)
780 draw_region
= cairo_region_create_rectangle (&rect
);
782 draw_region
= cairo_region_create ();
784 if (!can_draw_in_region (draw_region
, x1
, y1
, x2
- x1
, y2
- y1
)) {
785 cairo_region_destroy (draw_region
);
789 draw_flat_events
= e_week_view_get_draw_flat_events (week_view
);
791 icon_y
= y1
+ E_WEEK_VIEW_EVENT_BORDER_HEIGHT
+ E_WEEK_VIEW_ICON_Y_PAD
;
793 /* Get the start & end times in 24-hour format. */
794 start_hour
= event
->start_minute
/ 60;
795 start_minute
= event
->start_minute
% 60;
797 /* Modulo 24 because a midnight end time will be '24' */
798 end_hour
= (event
->end_minute
/ 60) % 24;
799 end_minute
= event
->end_minute
% 60;
801 time_y
= y1
+ E_WEEK_VIEW_EVENT_BORDER_HEIGHT
802 + E_WEEK_VIEW_EVENT_TEXT_Y_PAD
;
804 time_width
= e_week_view_get_time_string_width (week_view
);
806 one_day_event
= e_week_view_is_one_day_event (
807 week_view
, event_item
->priv
->event_num
);
809 model
= e_calendar_view_get_model (E_CALENDAR_VIEW (week_view
));
811 if (!e_cal_model_get_rgba_for_component (model
, event
->comp_data
, &bg_rgba
)) {
812 gdouble cc
= 65535.0;
814 bg_rgba
.red
= week_view
->colors
[E_WEEK_VIEW_COLOR_EVENT_BACKGROUND
].red
/ cc
;
815 bg_rgba
.green
= week_view
->colors
[E_WEEK_VIEW_COLOR_EVENT_BACKGROUND
].green
/ cc
;
816 bg_rgba
.blue
= week_view
->colors
[E_WEEK_VIEW_COLOR_EVENT_BACKGROUND
].blue
/ cc
;
821 time_x
= x1
+ E_WEEK_VIEW_EVENT_L_PAD
+ 1;
822 rect_x
= x1
+ E_WEEK_VIEW_EVENT_L_PAD
;
823 rect_w
= x2
- x1
- E_WEEK_VIEW_EVENT_L_PAD
- E_WEEK_VIEW_EVENT_R_PAD
+ 1;
828 rect_height
= y2
- y1
- 1;
830 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
831 if (draw_flat_events
) {
833 cairo_rectangle (cr
, cx0
, cy0
, rect_width
, rect_height
);
834 gdk_cairo_set_source_rgba (cr
, &bg_rgba
);
838 /* Here we draw the border around the event*/
842 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
844 draw_curved_rectangle (cr
, cx0
, cy0
, rect_width
, rect_height
, radius
);
845 cairo_set_line_width (cr
, 2.0);
846 gdk_cairo_set_source_rgba (cr
, &bg_rgba
);
851 /* Fill it in the Event */
855 rect_width
= rect_w
- 3.;
856 rect_height
= y2
- y1
- 4.5;
860 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
862 draw_curved_rectangle (
863 cr
, cx0
, cy0
, rect_width
, rect_height
, radius
);
865 pat
= cairo_pattern_create_linear (
866 rect_x
+ 2, y1
+ 1, rect_x
+ 2, y2
- 7.25);
867 cairo_pattern_add_color_stop_rgba (pat
, 1, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.8 * bg_rgba
.alpha
);
868 cairo_pattern_add_color_stop_rgba (pat
, 0, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.4 * bg_rgba
.alpha
);
869 cairo_set_source (cr
, pat
);
870 cairo_fill_preserve (cr
);
871 cairo_pattern_destroy (pat
);
872 cairo_set_source_rgba (cr
, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.2 * bg_rgba
.alpha
);
873 cairo_set_line_width (cr
, 0.5);
880 /* Draw the start and end times, as required. */
881 switch (week_view
->time_format
) {
882 case E_WEEK_VIEW_TIME_BOTH_SMALL_MIN
:
883 case E_WEEK_VIEW_TIME_BOTH
:
888 case E_WEEK_VIEW_TIME_START_SMALL_MIN
:
889 case E_WEEK_VIEW_TIME_START
:
894 case E_WEEK_VIEW_TIME_NONE
:
899 g_warn_if_reached ();
906 week_view_draw_time (
907 week_view
, bg_rgba
, cr
, time_x
,
908 time_y
, start_hour
, start_minute
);
909 time_x
+= time_width
;
912 if (draw_end
&& (!draw_start
|| event
->start_minute
!= event
->end_minute
)) {
913 time_x
+= E_WEEK_VIEW_EVENT_TIME_SPACING
;
914 week_view_draw_time (
915 week_view
, bg_rgba
, cr
, time_x
,
916 time_y
, end_hour
, end_minute
);
917 time_x
+= time_width
;
922 icon_x
+= E_WEEK_VIEW_EVENT_TIME_X_PAD
;
924 /* Draw the icons. */
925 week_view_event_item_draw_icons (
926 event_item
, cr
, icon_x
,
927 icon_y
, x2
, FALSE
, draw_region
);
930 rect_x
= x1
+ E_WEEK_VIEW_EVENT_L_PAD
;
931 rect_w
= x2
- x1
- E_WEEK_VIEW_EVENT_L_PAD
932 - E_WEEK_VIEW_EVENT_R_PAD
+ 1;
934 /* Draw the triangles at the start & end, if needed.
935 * They also use the first few pixels at the edge of the
936 * event so we update rect_x & rect_w so we don't draw over
938 if (event
->start
< week_view
->day_starts
[span
->start_day
]) {
939 draw_start_triangle
= TRUE
;
944 if (event
->end
> week_view
->day_starts
[span
->start_day
946 draw_end_triangle
= TRUE
;
953 rect_height
= y2
- y1
- 1;
955 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
956 if (draw_flat_events
) {
958 gdk_cairo_set_source_rgba (cr
, &bg_rgba
);
959 cairo_rectangle (cr
, cx0
, cy0
, rect_width
, rect_height
);
964 /* Here we draw the border around the event */
968 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
970 draw_curved_rectangle (cr
, cx0
, cy0
, rect_width
, rect_height
, radius
);
971 cairo_set_line_width (cr
, 2.0);
972 gdk_cairo_set_source_rgba (cr
, &bg_rgba
);
977 /* Here we fill it in the event*/
981 rect_width
= rect_w
- 3.;
982 rect_height
= y2
- y1
- 4.5;
986 if (can_draw_in_region (draw_region
, cx0
, cy0
, rect_width
, rect_height
)) {
988 draw_curved_rectangle (
989 cr
, cx0
, cy0
, rect_width
, rect_height
, radius
);
991 pat
= cairo_pattern_create_linear (rect_x
+ 2, y1
+ 1, rect_x
+ 2, y2
- 7.25);
992 cairo_pattern_add_color_stop_rgba (pat
, 1, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.8 * bg_rgba
.alpha
);
993 cairo_pattern_add_color_stop_rgba (pat
, 0, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.4 * bg_rgba
.alpha
);
994 cairo_set_source (cr
, pat
);
995 cairo_fill_preserve (cr
);
996 cairo_pattern_destroy (pat
);
997 cairo_set_source_rgba (cr
, bg_rgba
.red
, bg_rgba
.green
, bg_rgba
.blue
, 0.2 * bg_rgba
.alpha
);
998 cairo_set_line_width (cr
, 0.5);
1005 if (draw_start_triangle
) {
1006 week_view_event_item_draw_triangle (
1007 event_item
, cr
, bg_rgba
,
1008 x1
+ E_WEEK_VIEW_EVENT_L_PAD
+ 2,
1009 y1
, -3, y2
- y1
+ 1, draw_region
);
1010 } else if (can_draw_in_region (draw_region
, rect_x
, y1
, 1, y2
- y1
)) {
1011 EWeekViewColors wvc
;
1014 wvc
= E_WEEK_VIEW_COLOR_EVENT_BORDER
;
1015 color
= &week_view
->colors
[wvc
];
1018 gdk_cairo_set_source_color (cr
, color
);
1019 cairo_set_line_width (cr
, 0.7);
1020 cairo_move_to (cr
, rect_x
, y1
);
1021 cairo_line_to (cr
, rect_x
, y2
);
1026 if (draw_end_triangle
) {
1027 week_view_event_item_draw_triangle (
1028 event_item
, cr
, bg_rgba
,
1029 x2
- E_WEEK_VIEW_EVENT_R_PAD
- 2,
1030 y1
, 3, y2
- y1
+ 1, draw_region
);
1031 } else if (can_draw_in_region (draw_region
, rect_x2
, y2
, 1, 1)) {
1032 EWeekViewColors wvc
;
1035 wvc
= E_WEEK_VIEW_COLOR_EVENT_BORDER
;
1036 color
= &week_view
->colors
[wvc
];
1039 gdk_cairo_set_source_color (cr
, color
);
1040 cairo_set_line_width (cr
, 0.7);
1041 /* rect_x2 is used uninitialized here */
1042 cairo_move_to (cr
, rect_x2
, y1
);
1043 cairo_line_to (cr
, rect_x2
, y2
);
1048 if (span
->text_item
&& E_TEXT (span
->text_item
)->editing
)
1049 editing_span
= TRUE
;
1051 /* Draw the start & end times, if they are not on day
1052 * boundaries. The start time would always be shown if it was
1053 * needed, though it may be clipped as the window shrinks.
1054 * The end time is only displayed if there is enough room.
1055 * We calculate the minimum position for the end time, which
1056 * depends on whether the start time is displayed. If the end
1057 * time doesn't fit, then we don't draw it. */
1058 min_end_time_x
= x1
+ E_WEEK_VIEW_EVENT_L_PAD
1059 + E_WEEK_VIEW_EVENT_BORDER_WIDTH
1060 + E_WEEK_VIEW_EVENT_EDGE_X_PAD
;
1062 && event
->start
> week_view
->day_starts
[span
->start_day
]) {
1063 time_x
= x1
+ E_WEEK_VIEW_EVENT_L_PAD
1064 + E_WEEK_VIEW_EVENT_BORDER_WIDTH
1065 + E_WEEK_VIEW_EVENT_EDGE_X_PAD
;
1072 x2
- x1
- E_WEEK_VIEW_EVENT_R_PAD
1073 - E_WEEK_VIEW_EVENT_BORDER_WIDTH
+ 1,
1077 week_view_draw_time (
1078 week_view
, bg_rgba
, cr
, time_x
,
1079 time_y
, start_hour
, start_minute
);
1083 /* We don't want the end time to be drawn over the
1084 * start time, so we increase the minimum position. */
1085 min_end_time_x
+= time_width
1086 + E_WEEK_VIEW_EVENT_TIME_X_PAD
;
1089 max_icon_x
= x2
+ 1 - E_WEEK_VIEW_EVENT_R_PAD
1090 - E_WEEK_VIEW_EVENT_BORDER_WIDTH
1091 - E_WEEK_VIEW_EVENT_EDGE_X_PAD
;
1094 && event
->end
< week_view
->day_starts
[span
->start_day
1095 + span
->num_days
]) {
1096 /* Calculate where the end time should be displayed. */
1097 time_x
= x2
+ 1 - E_WEEK_VIEW_EVENT_R_PAD
1098 - E_WEEK_VIEW_EVENT_BORDER_WIDTH
1099 - E_WEEK_VIEW_EVENT_EDGE_X_PAD
1102 /* Draw the end time, if the position is greater than
1103 * the minimum calculated above. */
1104 if (time_x
>= min_end_time_x
) {
1105 week_view_draw_time (
1106 week_view
, bg_rgba
, cr
, time_x
,
1107 time_y
, end_hour
, end_minute
);
1108 max_icon_x
-= time_width
1109 + E_WEEK_VIEW_EVENT_TIME_X_PAD
;
1113 /* Draw the icons. */
1115 && (week_view
->editing_event_num
!= event_item
->priv
->event_num
1116 || week_view
->editing_span_num
!= event_item
->priv
->span_num
)) {
1117 icon_x
= span
->text_item
->x1
- E_WEEK_VIEW_ICON_R_PAD
- x
;
1118 week_view_event_item_draw_icons (
1119 event_item
, cr
, icon_x
,
1120 icon_y
, max_icon_x
, TRUE
, draw_region
);
1124 cairo_region_destroy (draw_region
);
1127 static GnomeCanvasItem
*
1128 week_view_event_item_point (GnomeCanvasItem
*item
,
1138 week_view_event_item_event (GnomeCanvasItem
*item
,
1141 EWeekViewEventItem
*event_item
;
1143 event_item
= E_WEEK_VIEW_EVENT_ITEM (item
);
1145 switch (event
->type
) {
1146 case GDK_2BUTTON_PRESS
:
1147 return week_view_event_item_double_click (event_item
, event
);
1148 case GDK_BUTTON_PRESS
:
1149 return week_view_event_item_button_press (event_item
, event
);
1150 case GDK_BUTTON_RELEASE
:
1151 return week_view_event_item_button_release (event_item
, event
);
1152 case GDK_MOTION_NOTIFY
:
1162 e_week_view_event_item_class_init (EWeekViewEventItemClass
*class)
1164 GObjectClass
*object_class
;
1165 GnomeCanvasItemClass
*item_class
;
1167 g_type_class_add_private (class, sizeof (EWeekViewEventItemPrivate
));
1169 object_class
= G_OBJECT_CLASS (class);
1170 object_class
->set_property
= week_view_event_item_set_property
;
1171 object_class
->get_property
= week_view_event_item_get_property
;
1173 item_class
= GNOME_CANVAS_ITEM_CLASS (class);
1174 item_class
->update
= week_view_event_item_update
;
1175 item_class
->draw
= week_view_event_item_draw
;
1176 item_class
->point
= week_view_event_item_point
;
1177 item_class
->event
= week_view_event_item_event
;
1179 g_object_class_install_property (
1189 G_PARAM_READWRITE
));
1191 g_object_class_install_property (
1201 G_PARAM_READWRITE
));
1205 e_week_view_event_item_init (EWeekViewEventItem
*event_item
)
1207 event_item
->priv
= E_WEEK_VIEW_EVENT_ITEM_GET_PRIVATE (event_item
);
1209 event_item
->priv
->event_num
= -1;
1210 event_item
->priv
->span_num
= -1;
1214 e_week_view_event_item_get_event_num (EWeekViewEventItem
*event_item
)
1216 g_return_val_if_fail (E_IS_WEEK_VIEW_EVENT_ITEM (event_item
), -1);
1218 return event_item
->priv
->event_num
;
1222 e_week_view_event_item_set_event_num (EWeekViewEventItem
*event_item
,
1225 g_return_if_fail (E_IS_WEEK_VIEW_EVENT_ITEM (event_item
));
1227 if (event_item
->priv
->event_num
== event_num
)
1230 event_item
->priv
->event_num
= event_num
;
1231 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (event_item
));
1233 g_object_notify (G_OBJECT (event_item
), "event-num");
1237 e_week_view_event_item_get_span_num (EWeekViewEventItem
*event_item
)
1239 g_return_val_if_fail (E_IS_WEEK_VIEW_EVENT_ITEM (event_item
), -1);
1241 return event_item
->priv
->span_num
;
1245 e_week_view_event_item_set_span_num (EWeekViewEventItem
*event_item
,
1248 g_return_if_fail (E_IS_WEEK_VIEW_EVENT_ITEM (event_item
));
1250 if (event_item
->priv
->span_num
== span_num
)
1253 event_item
->priv
->span_num
= span_num
;
1254 gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (event_item
));
1256 g_object_notify (G_OBJECT (event_item
), "span-num");