[evolution/clutter-calendar-v2] Add text rendering to the month view.



commit bb356dbb27ed2e73ff48ef54f727c4fb1ce26432
Author: Srinivasa Ragavan <sragavan gnome org>
Date:   Tue Sep 14 14:00:00 2010 +0530

    Add text rendering to the month view.

 calendar/gui/Makefile.am                      |    2 +
 calendar/gui/e-week-view-clutter-event-item.c | 1368 +++++++++++++++++++++++++
 calendar/gui/e-week-view-clutter-event-item.h |   93 ++
 calendar/gui/e-week-view-layout.c             |    3 +
 calendar/gui/e-week-view.c                    |  164 +++-
 calendar/gui/e-week-view.h                    |    6 +
 6 files changed, 1622 insertions(+), 14 deletions(-)
---
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 72e68c9..0bf553e 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -96,6 +96,8 @@ libevolution_calendar_la_SOURCES = \
 	e-week-view-clutter-titles-item.h	\
 	e-week-view-clutter-main-item.c		\
 	e-week-view-clutter-main-item.h		\
+	e-week-view-clutter-event-item.c	\
+	e-week-view-clutter-event-item.h	\
 	cal-editor-utils.c			\
 	cal-editor-utils.h			\
 	calendar-config.c			\
diff --git a/calendar/gui/e-week-view-clutter-event-item.c b/calendar/gui/e-week-view-clutter-event-item.c
new file mode 100644
index 0000000..6450b42
--- /dev/null
+++ b/calendar/gui/e-week-view-clutter-event-item.c
@@ -0,0 +1,1368 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *		Srinivasa Ragavan <sragavan gnome org>
+ *
+ * Copyright (C) 2010 Intel Corporation. (www.intel.com)
+ *
+ */
+
+/*
+ * EWeekViewClutterEventItem - displays the background, times and icons for an event
+ * in the week/month views. A separate EText canvas item is used to display &
+ * edit the text.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-util/e-categories-config.h"
+#include "e-week-view-clutter-event-item.h"
+
+#include <gtk/gtk.h>
+#include "e-calendar-view.h"
+#include "calendar-config.h"
+#include "comp-util.h"
+
+#include <text/e-text.h>
+
+#include "e-util/gtk-compat.h"
+
+#define E_WEEK_VIEW_CLUTTER_EVENT_ITEM_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM, EWeekViewClutterEventItemPrivate))
+
+struct _EWeekViewClutterEventItemPrivate {
+	/* The event index in the EWeekView events array. */
+	gint event_num;
+
+	/* The span index within the event. */
+	gint span_num;
+
+	/* Text */
+	char *text;
+
+	/* Texture */
+	ClutterCairoTexture *texture;
+
+	/* Week View*/
+	EWeekView *week_view;
+
+	int x1;
+	int y1;
+	int x2;
+	int y2;
+	int spanx;
+	int spany;
+};
+
+enum {
+	PROP_0,
+	PROP_EVENT_NUM,
+	PROP_SPAN_NUM,
+	PROP_TEXT
+};
+
+static gpointer parent_class;
+
+static gboolean
+can_draw_in_region (GdkRegion *draw_region,
+                    gint x,
+                    gint y,
+                    gint width,
+                    gint height)
+{
+	GdkRectangle rect;
+
+	g_return_val_if_fail (draw_region != NULL, FALSE);
+
+	rect.x = x;
+	rect.y = y;
+	rect.width = width;
+	rect.height = height;
+
+	return gdk_region_rect_in (draw_region, &rect) !=
+		GDK_OVERLAP_RECTANGLE_OUT;
+}
+
+static ECalendarViewPosition
+week_view_clutter_event_item_get_position (EWeekViewClutterEventItem *event_item,
+                                   gdouble x,
+                                   gdouble y)
+{
+	EWeekView *week_view;
+	GnomeCanvasItem *item;
+
+	week_view = event_item->priv->week_view;
+
+	if (x < event_item->priv->x1 + E_WEEK_VIEW_EVENT_L_PAD
+	    || x >= event_item->priv->x2 - E_WEEK_VIEW_EVENT_R_PAD)
+		return E_CALENDAR_VIEW_POS_NONE;
+
+	/* Support left/right edge for long events only. */
+	if (!e_week_view_is_one_day_event (week_view, event_item->priv->event_num)) {
+		if (x < event_item->priv->x1 + E_WEEK_VIEW_EVENT_L_PAD
+		    + E_WEEK_VIEW_EVENT_BORDER_WIDTH
+		    + E_WEEK_VIEW_EVENT_EDGE_X_PAD)
+			return E_CALENDAR_VIEW_POS_LEFT_EDGE;
+
+		if (x >= event_item->priv->x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD
+		    - E_WEEK_VIEW_EVENT_BORDER_WIDTH
+		    - E_WEEK_VIEW_EVENT_EDGE_X_PAD)
+			return E_CALENDAR_VIEW_POS_RIGHT_EDGE;
+	}
+
+	return E_CALENDAR_VIEW_POS_EVENT;
+}
+
+static gboolean
+week_view_clutter_event_item_double_click (EWeekViewClutterEventItem *event_item,
+                                   ClutterEvent *bevent)
+{
+	EWeekView *week_view;
+	EWeekViewEvent *event;
+	GnomeCanvasItem *item;
+
+	week_view = event_item->priv->week_view;
+
+	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
+		return TRUE;
+
+	event = &g_array_index (
+		week_view->events, EWeekViewEvent,
+		event_item->priv->event_num);
+
+	if (!is_comp_data_valid (event))
+		return TRUE;
+
+	if (week_view->editing_event_num >= 0) {
+		EWeekViewEvent *editing;
+
+		if (!is_array_index_in_bounds (week_view->events, week_view->editing_event_num))
+			return TRUE;
+
+		editing = &g_array_index (
+			week_view->events, EWeekViewEvent,
+			week_view->editing_event_num);
+
+		/* Do not call edit of the component, if double clicked
+		 * on the component, which is not on the server. */
+		if (editing && event &&
+			editing->comp_data == event->comp_data &&
+			is_comp_data_valid (editing) &&
+			(!event->comp_data ||
+			 !is_icalcomp_on_the_server (
+				event->comp_data->icalcomp,
+				event->comp_data->client)))
+			return TRUE;
+	}
+
+	e_week_view_stop_editing_event (week_view);
+
+	e_calendar_view_edit_appointment (
+		E_CALENDAR_VIEW (week_view),
+		event->comp_data->client,
+		event->comp_data->icalcomp, FALSE);
+
+	return TRUE;
+}
+
+gboolean
+week_view_clutter_event_item_button_press (EWeekViewClutterEventItem *event_item,
+                                   ClutterEvent *bevent)
+{
+	EWeekView *week_view;
+	ECalendarViewPosition pos;
+	EWeekViewEvent *event;
+	EWeekViewEventSpan *span;
+
+	week_view = event_item->priv->week_view;
+
+	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
+		return FALSE;
+
+	event = &g_array_index (
+		week_view->events, EWeekViewEvent,
+		event_item->priv->event_num);
+
+	if (!is_array_index_in_bounds (
+		week_view->spans, event->spans_index +
+		event_item->priv->span_num))
+		return FALSE;
+
+	span = &g_array_index (week_view->spans, EWeekViewEventSpan,
+			       event->spans_index + event_item->priv->span_num);
+
+	pos = week_view_clutter_event_item_get_position (event_item, (gdouble)(bevent->button.x-(float)event_item->priv->spanx),
+						   (gdouble)(bevent->button.y - (float)event_item->priv->spany) );
+
+	if (pos == E_CALENDAR_VIEW_POS_NONE)
+		return FALSE;
+	
+	if (bevent->button.button == 1) {
+		week_view->pressed_event_num = event_item->priv->event_num;
+		week_view->pressed_span_num = event_item->priv->span_num;
+
+		/* Ignore clicks on the event while editing. */
+		if (span->text_item && E_TEXT (span->text_item)->editing)
+			return FALSE;
+
+		/* Remember the item clicked and the mouse position,
+		   so we can start a drag if the mouse moves. */
+		week_view->drag_event_x = (gint)bevent->button.x;
+		week_view->drag_event_y = (gint)bevent->button.y;
+
+		/* FIXME: Remember the day offset from the start of the event.
+		 */
+
+		return TRUE;
+	} else if (bevent->button.button == 3) {
+		GdkEventButton *gevent = (GdkEventButton *)gdk_event_new (GDK_BUTTON_PRESS);
+
+		if (!gtk_widget_has_focus (GTK_WIDGET (week_view)) && 0) {
+			gtk_widget_grab_focus (GTK_WIDGET (week_view));
+			if (week_view->event_destroyed) {
+				week_view->event_destroyed = FALSE;
+				return FALSE;
+			}
+
+		}
+
+		gevent->time = bevent->button.time;
+		gevent->button = bevent->button.button;
+
+		e_week_view_set_selected_time_range_visible (
+			week_view, event->start, event->end);
+
+		e_week_view_show_popup_menu (
+			week_view, (GdkEventButton*) gevent,
+			event_item->priv->event_num);
+		gdk_event_free (gevent);
+		//g_signal_stop_emission_by_name (
+		//	event_item->canvas, "button_press_event");
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+week_view_clutter_event_item_button_release (EWeekViewClutterEventItem *event_item,
+                                     ClutterEvent *event)
+{
+	EWeekView *week_view;
+
+
+	week_view = event_item->priv->week_view;
+
+	if (week_view->pressed_event_num != -1
+	    && week_view->pressed_event_num == event_item->priv->event_num
+	    && week_view->pressed_span_num == event_item->priv->span_num) {
+		e_week_view_start_editing_event (week_view,
+						 event_item->priv->event_num,
+						 event_item->priv->span_num,
+						 NULL);
+		week_view->pressed_event_num = -1;
+		return TRUE;
+	}
+
+	week_view->pressed_event_num = -1;
+
+	return FALSE;
+}
+
+static void
+week_view_draw_time (EWeekView *week_view,
+                     cairo_t *cr,
+		     gint time_x,
+                     gint time_y,
+                     gint hour,
+                     gint minute)
+{
+	ECalModel *model;
+	GtkStyle *style;
+	gint hour_to_display, suffix_width;
+	gint time_y_normal_font, time_y_small_font;
+	const gchar *suffix;
+	gchar buffer[128];
+	GdkColor *fg;
+	PangoLayout *layout;
+	PangoFontDescription *small_font_desc;
+
+	model = e_calendar_view_get_model (E_CALENDAR_VIEW (week_view));
+
+	style = gtk_widget_get_style (GTK_WIDGET (week_view));
+	small_font_desc = week_view->small_font_desc;
+
+	fg = &week_view->colors[E_WEEK_VIEW_COLOR_EVENT_TEXT];
+
+	layout = gtk_widget_create_pango_layout (GTK_WIDGET (week_view), NULL);
+
+	time_y_normal_font = time_y_small_font = time_y;
+	if (small_font_desc)
+		time_y_small_font = time_y;
+
+	e_week_view_convert_time_to_display (week_view, hour, &hour_to_display,
+					     &suffix, &suffix_width);
+
+	if (week_view->use_small_font && week_view->small_font_desc) {
+		g_snprintf (buffer, sizeof (buffer), "%2i:%02i",
+			    hour_to_display, minute);
+
+
+		cairo_save (cr);
+		gdk_cairo_set_source_color (cr, &fg);
+		/* Draw the hour. */
+		if (hour_to_display < 10) {
+			pango_layout_set_text (layout, buffer + 1, 1);
+			cairo_move_to (cr,
+				       time_x + week_view->digit_width,
+				       time_y_normal_font);
+			pango_cairo_show_layout (cr, layout);
+		} else {
+			pango_layout_set_text (layout, buffer, 2);
+			cairo_move_to (cr,			
+				       time_x,
+				       time_y_normal_font);
+			pango_cairo_show_layout (cr, layout);			
+		}
+		cairo_stroke (cr);
+		cairo_restore (cr);
+
+		time_x += week_view->digit_width * 2;
+
+		cairo_save (cr);
+		gdk_cairo_set_source_color (cr, &fg);
+		/* Draw the start minute, in the small font. */
+		pango_layout_set_font_description (layout, week_view->small_font_desc);
+		pango_layout_set_text (layout, buffer + 3, 2);
+		cairo_move_to (cr,
+			       time_x,
+			       time_y_small_font);
+		pango_cairo_show_layout (cr, layout);			
+		cairo_stroke (cr);
+		cairo_restore (cr);
+
+
+		cairo_save (cr);
+		gdk_cairo_set_source_color (cr, &fg);
+		pango_layout_set_font_description (layout, style->font_desc);
+
+		time_x += week_view->small_digit_width * 2;
+
+		/* Draw the 'am'/'pm' suffix, if 12-hour format. */
+		if (!e_cal_model_get_use_24_hour_format (model)) {
+			pango_layout_set_text (layout, suffix, -1);
+			cairo_move_to (cr,
+				       time_x,
+				       time_y_normal_font);
+			pango_cairo_show_layout (cr, layout);					
+		}
+		cairo_stroke (cr);
+		cairo_restore (cr);
+
+	} else {
+
+		cairo_save (cr);
+		gdk_cairo_set_source_color (cr, &fg);
+		/* Draw the start time in one go. */
+		g_snprintf (buffer, sizeof (buffer), "%2i:%02i%s",
+			    hour_to_display, minute, suffix);
+		if (hour_to_display < 10) {
+			pango_layout_set_text (layout, buffer + 1, -1);
+			cairo_move_to (cr,		
+				       time_x + week_view->digit_width,
+				       time_y_normal_font);
+			pango_cairo_show_layout (cr, layout);					
+		} else {
+			pango_layout_set_text (layout, buffer, -1);
+			cairo_move_to (cr,					
+				       time_x,
+				       time_y_normal_font);
+			pango_cairo_show_layout (cr, layout);					
+		}
+		cairo_stroke (cr);
+		cairo_restore (cr);
+
+	}
+	g_object_unref (layout);
+}
+
+static gint
+week_view_clutter_event_item_draw_icons (EWeekViewClutterEventItem *event_item,
+                                 cairo_t *cr,
+                                 gint icon_x,
+                                 gint icon_y,
+                                 gint x2,
+                                 gboolean right_align,
+                                 GdkRegion *draw_region)
+{
+	EWeekView *week_view;
+	EWeekViewEvent *event;
+	ECalComponent *comp;
+	GnomeCanvas *canvas;
+	gint num_icons = 0, icon_x_inc;
+	gboolean draw_reminder_icon = FALSE, draw_recurrence_icon = FALSE;
+	gboolean draw_timezone_icon = FALSE, draw_attach_icon = FALSE;
+	gboolean draw_meeting_icon = FALSE;
+	GSList *categories_pixbufs = NULL, *pixbufs;
+
+	week_view = event_item->priv->week_view;
+
+	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
+		return icon_x;
+
+	event = &g_array_index (week_view->events, EWeekViewEvent,
+				event_item->priv->event_num);
+
+	if (!is_comp_data_valid (event))
+		return icon_x;
+
+	comp = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (
+		comp, icalcomponent_new_clone (event->comp_data->icalcomp));
+
+	if (e_cal_component_has_alarms (comp)) {
+		draw_reminder_icon = TRUE;
+		num_icons++;
+	}
+
+	if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp)) {
+		draw_recurrence_icon = TRUE;
+		num_icons++;
+	}
+
+	if (e_cal_component_has_attachments (comp)) {
+		draw_attach_icon = TRUE;
+		num_icons++;
+	}
+
+	if (e_cal_component_has_attendees (comp)) {
+		draw_meeting_icon = TRUE;
+		num_icons++;
+	}
+
+	if (event->different_timezone) {
+		draw_timezone_icon = TRUE;
+		num_icons++;
+	}
+
+	num_icons += cal_comp_util_get_n_icons (comp, &categories_pixbufs);
+
+	icon_x_inc = E_WEEK_VIEW_ICON_WIDTH + E_WEEK_VIEW_ICON_X_PAD;
+
+	if (right_align)
+		icon_x -= icon_x_inc * num_icons;
+
+	#define draw_pixbuf(pf)							\
+		if (can_draw_in_region (draw_region, icon_x, icon_y,		\
+		    E_WEEK_VIEW_ICON_WIDTH, E_WEEK_VIEW_ICON_HEIGHT)) {		\
+			cairo_save (cr);					\
+			gdk_cairo_set_source_pixbuf (cr, pf, icon_x, icon_y);	\
+			cairo_paint (cr);					\
+			cairo_restore (cr);					\
+		}								\
+										\
+		icon_x += icon_x_inc;
+
+	if (draw_reminder_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
+		draw_pixbuf (week_view->reminder_icon);
+	}
+
+	if (draw_attach_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
+		draw_pixbuf (week_view->attach_icon);
+	}
+
+	if (draw_recurrence_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
+		draw_pixbuf (week_view->recurrence_icon);
+	}
+
+	if (draw_timezone_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
+		draw_pixbuf (week_view->timezone_icon);
+	}
+
+	if (draw_meeting_icon && icon_x + E_WEEK_VIEW_ICON_WIDTH <= x2) {
+		draw_pixbuf (week_view->meeting_icon);
+	}
+
+	/* draw categories icons */
+	for (pixbufs = categories_pixbufs;
+	     pixbufs;
+	     pixbufs = pixbufs->next) {
+		GdkPixbuf *pixbuf = pixbufs->data;
+
+		draw_pixbuf (pixbuf);
+	}
+
+	#undef draw_pixbuf
+
+	g_slist_foreach (categories_pixbufs, (GFunc)g_object_unref, NULL);
+	g_slist_free (categories_pixbufs);
+
+	g_object_unref(comp);
+
+	return icon_x;
+}
+
+/* This draws a little triangle to indicate that an event extends past
+   the days visible on screen. */
+static void
+week_view_clutter_event_item_draw_triangle (EWeekViewClutterEventItem *event_item,
+                                    cairo_t *cr,
+                                    GdkColor bg_color,
+                                    gint x,
+                                    gint y,
+                                    gint w,
+                                    gint h,
+                                    GdkRegion *draw_region)
+{
+	ECalModel *model;
+	EWeekView *week_view;
+	EWeekViewEvent *event;
+	GdkPoint points[3];
+	const gchar *color_spec;
+	gint c1, c2;
+
+	if (!can_draw_in_region (draw_region, x, y, w, h))
+		return;
+
+	week_view = event_item->priv->week_view;
+
+	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
+		return;
+
+	event = &g_array_index (week_view->events, EWeekViewEvent,
+				event_item->priv->event_num);
+
+	if (!is_comp_data_valid (event))
+		return;
+
+	points[0].x = x;
+	points[0].y = y;
+	points[1].x = x + w;
+	points[1].y = y + (h / 2);
+	points[2].x = x;
+	points[2].y = y + h - 1;
+
+	model = e_calendar_view_get_model (E_CALENDAR_VIEW (week_view));
+
+	color_spec =
+		e_cal_model_get_color_for_component (model, event->comp_data);
+
+	if (gdk_color_parse (color_spec, &bg_color)) {
+		GdkColormap *colormap;
+
+		colormap = gtk_widget_get_colormap (GTK_WIDGET (week_view));
+		if (gdk_colormap_alloc_color (colormap, &bg_color, TRUE, TRUE)) {
+			gdk_cairo_set_source_color (cr, &bg_color);
+		} else {
+			EWeekViewColors wvc;
+			GdkColor *color;
+
+			wvc = E_WEEK_VIEW_COLOR_EVENT_BACKGROUND;
+			color = &week_view->colors[wvc];
+
+			gdk_cairo_set_source_color (cr, color);
+		}
+	} else {
+		EWeekViewColors wvc;
+		GdkColor *color;
+
+		wvc = E_WEEK_VIEW_COLOR_EVENT_BACKGROUND;
+		color = &week_view->colors[wvc];
+
+		gdk_cairo_set_source_color (cr, color);
+	}
+
+	cairo_save (cr);
+	cairo_set_line_width (cr, 0.7);
+	cairo_move_to (cr, points[0].x, points[0].y);
+	cairo_line_to (cr, points[1].x, points[1].y);
+	cairo_line_to (cr, points[2].x, points[2].y);
+	cairo_line_to (cr, points[0].x, points[0].y);
+	cairo_fill (cr);
+	cairo_restore (cr);
+
+	cairo_save (cr);
+	gdk_cairo_set_source_color (cr, &week_view->colors[E_WEEK_VIEW_COLOR_EVENT_BORDER]);
+
+	/* If the height is odd we can use the same central point for both
+	   lines. If it is even we use different end-points. */
+	c1 = c2 = y + (h / 2);
+	if (h % 2 == 0)
+		c1--;
+
+	cairo_set_line_width (cr, 0.7);
+	cairo_move_to (cr, x, y);
+	cairo_line_to (cr, x + w, c1);
+	cairo_move_to (cr, x, y + h - 1);
+	cairo_line_to (cr, x + w, c2);
+	cairo_restore (cr);
+
+}
+
+static void
+week_view_clutter_event_item_set_property (GObject *object,
+                                   guint property_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_EVENT_NUM:
+			e_week_view_clutter_event_item_set_event_num (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object),
+				g_value_get_int (value));
+			return;
+
+		case PROP_SPAN_NUM:
+			e_week_view_clutter_event_item_set_span_num (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object),
+				g_value_get_int (value));
+		case PROP_TEXT:
+			e_week_view_clutter_event_item_set_text (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object),
+				g_value_get_string (value));			
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+week_view_clutter_event_item_get_property (GObject *object,
+                                   guint property_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_EVENT_NUM:
+			g_value_set_int (
+				value,
+				e_week_view_clutter_event_item_get_event_num (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object)));
+			return;
+
+		case PROP_SPAN_NUM:
+			g_value_set_int (
+				value,
+				e_week_view_clutter_event_item_get_span_num (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object)));
+		case PROP_TEXT:
+			g_value_set_string (
+				value,
+				e_week_view_clutter_event_item_get_text (
+				E_WEEK_VIEW_CLUTTER_EVENT_ITEM (object)));			
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+week_view_clutter_event_item_draw (EWeekViewClutterEventItem *canvas_item)
+{
+	EWeekViewClutterEventItem *event_item;
+	EWeekView *week_view;
+	EWeekViewEvent *event;
+	EWeekViewEventSpan *span;
+	ECalModel *model;
+	GdkGC *gc;
+	gint x1, y1, x2, y2, time_x, time_y;
+	gint icon_x, icon_y, time_width, min_end_time_x, max_icon_x;
+	gint rect_x, rect_w, rect_x2 = 0;
+	gboolean one_day_event, editing_span = FALSE;
+	gint start_hour, start_minute, end_hour, end_minute;
+	gboolean draw_start, draw_end;
+	gboolean draw_start_triangle = FALSE, draw_end_triangle = FALSE;
+	GdkRectangle clip_rect;
+	GdkColor bg_color;
+	cairo_t *cr;
+	cairo_pattern_t *pat;
+	guint16 red, green, blue;
+	gdouble radius, cx0, cy0, rect_height, rect_width;
+	gboolean gradient;
+	gdouble cc = 65535.0;
+	GdkRegion *draw_region;
+	GdkRectangle rect;
+	const gchar *color_spec;
+	int x=0,y=0;
+	int width, height;
+	gint span_x, span_y, span_w;
+
+	event_item = E_WEEK_VIEW_CLUTTER_EVENT_ITEM (canvas_item);
+
+	week_view = event_item->priv->week_view;
+
+	if (event_item->priv->event_num == -1 || event_item->priv->span_num == -1)
+		return;
+
+	g_return_if_fail (event_item->priv->event_num < week_view->events->len);
+
+	if (!is_array_index_in_bounds (week_view->events, event_item->priv->event_num))
+		return;
+
+	event = &g_array_index (week_view->events, EWeekViewEvent,
+				event_item->priv->event_num);
+
+	if (!is_comp_data_valid (event))
+		return;
+
+	g_return_if_fail (
+		event->spans_index + event_item->priv->span_num <
+		week_view->spans->len);
+
+	if (!is_array_index_in_bounds (
+		week_view->spans, event->spans_index +
+		event_item->priv->span_num))
+		return;
+
+	span = &g_array_index (
+		week_view->spans, EWeekViewEventSpan,
+		event->spans_index + event_item->priv->span_num);
+
+	if (e_week_view_get_span_position (
+		week_view, event_item->priv->event_num, event_item->priv->span_num,
+		&span_x, &span_y, &span_w)) {
+		x1 = 0;
+		y1 = 0;
+		x2 = span_w - 1;
+		y2 = week_view->row_height - 1;
+	} 
+	
+	event_item->priv->x1 = 0;
+	event_item->priv->y1 = 0;
+	event_item->priv->x2 = span_w;
+	event_item->priv->y2 = week_view->row_height;
+	event_item->priv->spanx = span_x;
+	event_item->priv->spany = span_y;
+	gc = week_view->main_gc;
+
+	if (x1 == x2 || y1 == y2)
+		return;
+
+	rect.x = 0;
+	rect.y = 0;
+	rect.width = x2-x1;
+	rect.height = y2-y1;
+	draw_region = gdk_region_rectangle (&rect);
+	x1 = 0; y1 = 0;
+	x2 = rect.width;
+	clutter_cairo_texture_set_surface_size (event_item->priv->texture, rect.width, rect.height);
+	clutter_actor_set_position (event_item, span_x, span_y);
+	if (!can_draw_in_region (draw_region, x1, y1, x2 - x1, y2 - y1)) {
+		gdk_region_destroy (draw_region);
+		return;
+	}
+
+	clutter_cairo_texture_clear (event_item->priv->texture);	
+	cr = clutter_cairo_texture_create (event_item->priv->texture);
+	gradient = calendar_config_get_display_events_gradient ();
+
+	icon_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT + E_WEEK_VIEW_ICON_Y_PAD;
+
+	/* Get the start & end times in 24-hour format. */
+	start_hour = event->start_minute / 60;
+	start_minute = event->start_minute % 60;
+
+	/* Modulo 24 because a midnight end time will be '24' */
+	end_hour = (event->end_minute / 60) % 24;
+	end_minute = event->end_minute % 60;
+
+	time_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT
+		+ E_WEEK_VIEW_EVENT_TEXT_Y_PAD;
+
+	time_width = e_week_view_get_time_string_width (week_view);
+
+	one_day_event = e_week_view_is_one_day_event (week_view, event_item->priv->event_num);
+
+	model = e_calendar_view_get_model (E_CALENDAR_VIEW (week_view));
+
+	color_spec =
+		e_cal_model_get_color_for_component (model, event->comp_data);
+
+	bg_color = week_view->colors[E_WEEK_VIEW_COLOR_EVENT_BACKGROUND];
+	if (gdk_color_parse (color_spec, &bg_color)) {
+		GdkColormap *colormap;
+
+		colormap = gtk_widget_get_colormap (GTK_WIDGET (week_view));
+		if (!gdk_colormap_alloc_color (colormap, &bg_color, TRUE, TRUE)) {
+			bg_color = week_view->colors[E_WEEK_VIEW_COLOR_EVENT_BACKGROUND];
+		}
+	}
+
+	red = bg_color.red;
+	green = bg_color.green;
+	blue = bg_color.blue;
+
+	if (one_day_event) {
+		time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD + 1;
+		rect_x = x1 + E_WEEK_VIEW_EVENT_L_PAD;
+		rect_w = x2 - x1 - E_WEEK_VIEW_EVENT_L_PAD - E_WEEK_VIEW_EVENT_R_PAD + 1;
+
+		/* Here we draw the border around the event*/
+		cx0	   = rect_x;
+		cy0	   = y1 + 1;
+		rect_width  = rect_w;
+		rect_height = y2 - y1 - 1;
+
+		radius = 12;
+
+		if (can_draw_in_region (draw_region, cx0, cy0, rect_width, rect_height)) {
+			cairo_save (cr);
+			draw_curved_rectangle (cr, cx0, cy0, rect_width, rect_height, radius);
+			cairo_set_line_width (cr, 2.0);
+			cairo_set_source_rgb (cr, red/cc, green/cc, blue/cc);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		/* Fill it in the Event */
+
+		cx0	   = rect_x + 1.5;
+		cy0	   = y1 + 2.75;
+		rect_width  = rect_w - 3.;
+		rect_height = y2 - y1 - 4.5;
+
+		radius = 8;
+
+		if (can_draw_in_region (draw_region, cx0, cy0, rect_width, rect_height)) {
+			cairo_save (cr);
+			draw_curved_rectangle (cr, cx0, cy0, rect_width, rect_height, radius);
+
+			if (gradient) {
+				pat = cairo_pattern_create_linear (rect_x + 2, y1 + 1, rect_x + 2, y2 - 7.25);
+				cairo_pattern_add_color_stop_rgba (pat, 1, red/cc, green/cc, blue/cc, 0.8);
+				cairo_pattern_add_color_stop_rgba (pat, 0, red/cc, green/cc, blue/cc, 0.4);
+				cairo_set_source (cr, pat);
+				cairo_fill_preserve (cr);
+				cairo_pattern_destroy (pat);
+			} else {
+				cairo_set_source_rgba (cr, red/cc, green/cc, blue/cc, 0.8);
+				cairo_fill_preserve (cr);
+			}
+			cairo_set_source_rgba (cr, red/cc, green/cc, blue/cc, 0.2);
+			cairo_set_line_width (cr, 0.5);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		/* Draw the start and end times, as required. */
+		switch (week_view->time_format) {
+		case E_WEEK_VIEW_TIME_BOTH_SMALL_MIN:
+		case E_WEEK_VIEW_TIME_BOTH:
+			draw_start = TRUE;
+			draw_end = TRUE;
+			break;
+
+		case E_WEEK_VIEW_TIME_START_SMALL_MIN:
+		case E_WEEK_VIEW_TIME_START:
+			draw_start = TRUE;
+			draw_end = FALSE;
+			break;
+
+		case E_WEEK_VIEW_TIME_NONE:
+			draw_start = FALSE;
+			draw_end = FALSE;
+			break;
+		default:
+			g_return_if_reached ();
+			draw_start = FALSE;
+			draw_end = FALSE;
+			break;
+		}
+
+		if (draw_start) {
+			week_view_draw_time (
+				week_view, cr, time_x,
+				time_y, start_hour, start_minute);
+			time_x += time_width;
+		}
+
+		if (draw_end) {
+			time_x += E_WEEK_VIEW_EVENT_TIME_SPACING;
+			week_view_draw_time (
+				week_view, cr, time_x,
+				time_y, end_hour, end_minute);
+			time_x += time_width;
+		}
+
+		icon_x = time_x;
+		if (draw_start)
+			icon_x += E_WEEK_VIEW_EVENT_TIME_X_PAD;
+
+		/* Draw the icons. */
+		icon_x = week_view_clutter_event_item_draw_icons (
+			event_item, cr, icon_x,
+			icon_y, x2, FALSE, draw_region);
+
+		/* Draw text */
+		if (icon_x < x2) {
+			PangoLayout *layout;
+			GdkColor col = e_week_view_get_text_color (week_view, event, week_view);
+			
+			cairo_save (cr);
+			gdk_cairo_set_source_color (cr, &col);
+			
+			icon_x += E_WEEK_VIEW_EVENT_TIME_X_PAD;
+
+			cairo_rectangle (cr, icon_x , 0, x2-icon_x, week_view->row_height);
+			cairo_clip (cr);
+			layout = gtk_widget_create_pango_layout (GTK_WIDGET (week_view), NULL);
+			pango_layout_set_text (layout, event_item->priv->text, -1);
+			cairo_move_to (cr,
+				       icon_x, 
+				       E_WEEK_VIEW_EVENT_BORDER_HEIGHT + E_WEEK_VIEW_ICON_Y_PAD);
+			
+			pango_cairo_show_layout (cr, layout);
+
+			cairo_stroke (cr);
+			cairo_restore (cr);
+			g_object_unref (layout);
+		}
+
+		
+	} else {
+		rect_x = x1 + E_WEEK_VIEW_EVENT_L_PAD;
+		rect_w = x2 - x1 - E_WEEK_VIEW_EVENT_L_PAD
+			- E_WEEK_VIEW_EVENT_R_PAD + 1;
+
+		/* Draw the triangles at the start & end, if needed.
+		   They also use the first few pixels at the edge of the
+		   event so we update rect_x & rect_w so we don't draw over
+		   them. */
+		if (event->start < week_view->day_starts[span->start_day]) {
+			draw_start_triangle = TRUE;
+			rect_x += 2;
+			rect_w -= 2;
+		}
+
+		if (event->end > week_view->day_starts[span->start_day
+						      + span->num_days]) {
+			draw_end_triangle = TRUE;
+			rect_w -= 2;
+		}
+
+		/* Here we draw the border around the event */
+
+		cx0	   = rect_x;
+		cy0	   = y1 + 1;
+		rect_width  = rect_w;
+		rect_height = y2 - y1 - 1;
+
+		radius = 12;
+
+		if (can_draw_in_region (draw_region, cx0, cy0, rect_width, rect_height)) {
+			cairo_save (cr);
+			draw_curved_rectangle (cr, cx0, cy0, rect_width, rect_height, radius);
+			cairo_set_line_width (cr, 2.0);
+			cairo_set_source_rgb (cr, red/cc, green/cc, blue/cc);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		/* Here we fill it in the event*/
+
+		cx0	   = rect_x + 1.5;
+		cy0	   = y1 + 2.75;
+		rect_width  = rect_w - 3.;
+		rect_height = y2 - y1 - 4.5;
+
+		radius = 8;
+
+		if (can_draw_in_region (draw_region, cx0, cy0, rect_width, rect_height)) {
+			cairo_save (cr);
+			draw_curved_rectangle (cr, cx0, cy0, rect_width, rect_height, radius);
+
+			if (gradient) {
+				pat = cairo_pattern_create_linear (rect_x + 2, y1 + 1, rect_x + 2, y2 - 7.25);
+				cairo_pattern_add_color_stop_rgba (pat, 1, red/cc, green/cc, blue/cc, 0.8);
+				cairo_pattern_add_color_stop_rgba (pat, 0, red/cc, green/cc, blue/cc, 0.4);
+				cairo_set_source (cr, pat);
+				cairo_fill_preserve (cr);
+				cairo_pattern_destroy (pat);
+			} else {
+				cairo_set_source_rgba (cr, red/cc, green/cc, blue/cc, 0.8);
+				cairo_fill_preserve (cr);
+			}
+			cairo_set_source_rgba (cr, red/cc, green/cc, blue/cc, 0.2);
+			cairo_set_line_width (cr, 0.5);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		if (draw_start_triangle) {
+			week_view_clutter_event_item_draw_triangle (
+				event_item, cr, bg_color,
+				x1 + E_WEEK_VIEW_EVENT_L_PAD + 2,
+				y1, -3, y2 - y1 + 1, draw_region);
+		} else if (can_draw_in_region (draw_region, rect_x, y1, 1, y2 - y1)) {
+			EWeekViewColors wvc;
+			GdkColor *color;
+
+			wvc = E_WEEK_VIEW_COLOR_EVENT_BORDER;
+			color = &week_view->colors[wvc];
+
+			cairo_save (cr);
+			gdk_cairo_set_source_color (cr, color);
+			cairo_set_line_width (cr, 0.7);
+			cairo_move_to (cr, rect_x, y1);
+			cairo_line_to (cr, rect_x, y2);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		if (draw_end_triangle) {
+			week_view_clutter_event_item_draw_triangle (
+				event_item, cr, bg_color,
+				x2 - E_WEEK_VIEW_EVENT_R_PAD - 2,
+				y1, 3, y2 - y1 + 1, draw_region);
+		} else if (can_draw_in_region (draw_region, rect_x2, y2, 1, 1)) {
+			EWeekViewColors wvc;
+			GdkColor *color;
+
+			wvc = E_WEEK_VIEW_COLOR_EVENT_BORDER;
+			color = &week_view->colors[wvc];
+
+			cairo_save (cr);
+			gdk_cairo_set_source_color (cr, color);
+			cairo_set_line_width (cr, 0.7);
+			/* rect_x2 is used uninitialized here */
+			cairo_move_to (cr, rect_x2, y2);
+			cairo_line_to (cr, rect_x2, y2);
+			cairo_stroke (cr);
+			cairo_restore (cr);
+		}
+
+		if (span->text_item && E_TEXT (span->text_item)->editing)
+			editing_span = TRUE;
+
+		/* Draw the start & end times, if they are not on day
+		   boundaries. The start time would always be shown if it was
+		   needed, though it may be clipped as the window shrinks.
+		   The end time is only displayed if there is enough room.
+		   We calculate the minimum position for the end time, which
+		   depends on whether the start time is displayed. If the end
+		   time doesn't fit, then we don't draw it. */
+		min_end_time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD
+			+ E_WEEK_VIEW_EVENT_BORDER_WIDTH
+			+ E_WEEK_VIEW_EVENT_EDGE_X_PAD;
+		time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD
+				+ E_WEEK_VIEW_EVENT_BORDER_WIDTH
+				+ E_WEEK_VIEW_EVENT_EDGE_X_PAD;
+		if (!editing_span
+		    && event->start > week_view->day_starts[span->start_day]) {
+			time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD
+				+ E_WEEK_VIEW_EVENT_BORDER_WIDTH
+				+ E_WEEK_VIEW_EVENT_EDGE_X_PAD;
+				
+			clip_rect.x = x1;
+			clip_rect.y = y1;
+			clip_rect.width = x2 - x1 - E_WEEK_VIEW_EVENT_R_PAD
+				- E_WEEK_VIEW_EVENT_BORDER_WIDTH + 1;
+			clip_rect.height = y2 - y1 + 1;
+
+			week_view_draw_time (
+				week_view, cr, time_x,
+				time_y, start_hour, start_minute);
+
+			/* We don't want the end time to be drawn over the
+			   start time, so we increase the minimum position. */
+			min_end_time_x += time_width
+				+ E_WEEK_VIEW_EVENT_TIME_X_PAD;
+		} 
+
+		max_icon_x = x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD
+			- E_WEEK_VIEW_EVENT_BORDER_WIDTH
+			- E_WEEK_VIEW_EVENT_EDGE_X_PAD;
+		
+		time_x = x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD
+				- E_WEEK_VIEW_EVENT_BORDER_WIDTH
+				- E_WEEK_VIEW_EVENT_EDGE_X_PAD
+				- time_width;
+		if (!editing_span
+		    && event->end < week_view->day_starts[span->start_day
+							 + span->num_days]) {
+			/* Calculate where the end time should be displayed. */
+			time_x = x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD
+				- E_WEEK_VIEW_EVENT_BORDER_WIDTH
+				- E_WEEK_VIEW_EVENT_EDGE_X_PAD
+				- time_width;
+
+			/* Draw the end time, if the position is greater than
+			   the minimum calculated above. */
+			if (time_x >= min_end_time_x) {
+				week_view_draw_time (
+					week_view, cr, time_x,
+					time_y, end_hour, end_minute);
+				max_icon_x -= time_width
+					+ E_WEEK_VIEW_EVENT_TIME_X_PAD;
+			}
+		}
+		
+		icon_x = min_end_time_x;
+		/* Draw the icons. */
+		if ( 
+		     (week_view->editing_event_num != event_item->priv->event_num
+			|| week_view->editing_span_num != event_item->priv->span_num)) {
+			icon_x = min_end_time_x;
+			icon_x += E_WEEK_VIEW_EVENT_TIME_X_PAD;
+			icon_x = week_view_clutter_event_item_draw_icons (
+				event_item, cr, icon_x,
+				icon_y, max_icon_x, FALSE, draw_region);
+		}
+
+		/* Draw text */
+		if (icon_x < time_x) {
+			PangoLayout *layout;
+			GdkColor col = e_week_view_get_text_color (week_view, event, week_view);
+			
+			cairo_save (cr);
+			gdk_cairo_set_source_color (cr, &col);
+			
+			icon_x += E_WEEK_VIEW_EVENT_TIME_X_PAD;
+
+			cairo_rectangle (cr, icon_x , 0, time_x-icon_x, week_view->row_height);
+			cairo_clip (cr);
+			layout = gtk_widget_create_pango_layout (GTK_WIDGET (week_view), NULL);
+			pango_layout_set_text (layout, event_item->priv->text, -1);
+			cairo_move_to (cr,
+				       icon_x, 
+				       E_WEEK_VIEW_EVENT_BORDER_HEIGHT + E_WEEK_VIEW_ICON_Y_PAD);
+			
+			pango_cairo_show_layout (cr, layout);
+
+			cairo_stroke (cr);
+			cairo_restore (cr);
+			g_object_unref (layout);
+		}
+		
+	}
+	cairo_destroy (cr);
+
+	gdk_region_destroy (draw_region);
+}
+
+static gint
+week_view_clutter_event_item_event (GnomeCanvasItem *item,
+                            ClutterEvent *event)
+{
+	EWeekViewClutterEventItem *event_item;
+
+	event_item = E_WEEK_VIEW_CLUTTER_EVENT_ITEM (item);
+
+	switch (event->type) {
+	case CLUTTER_BUTTON_PRESS:
+		if (event->button.click_count > 1)
+			return week_view_clutter_event_item_double_click (event_item, event);
+		else
+			return week_view_clutter_event_item_button_press (event_item, event);
+	case CLUTTER_BUTTON_RELEASE:
+		return week_view_clutter_event_item_button_release (event_item, event);
+	case CLUTTER_MOTION:
+		break;
+	default:
+		break;
+	}
+
+	return FALSE;
+}
+
+static void
+week_view_clutter_event_item_class_init (EWeekViewClutterEventItemClass *class)
+{
+	GObjectClass *object_class;
+	MxBoxLayoutClass *item_class;
+	ClutterActorClass *widget_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (EWeekViewClutterEventItemPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = week_view_clutter_event_item_set_property;
+	object_class->get_property = week_view_clutter_event_item_get_property;
+
+	item_class = MX_BOX_LAYOUT_CLASS (class);
+	//item_class->update = week_view_clutter_event_item_update;
+	//item_class->draw = week_view_clutter_event_item_draw;
+	//item_class->point = week_view_clutter_event_item_point;
+	CLUTTER_ACTOR_CLASS(item_class)->event = week_view_clutter_event_item_event;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_EVENT_NUM,
+		g_param_spec_int (
+			"event-num",
+			"Event Num",
+			NULL,
+			G_MININT,
+			G_MAXINT,
+			-1,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_SPAN_NUM,
+		g_param_spec_int (
+			"span-num",
+			"Span Num",
+			NULL,
+			G_MININT,
+			G_MAXINT,
+			-1,
+			G_PARAM_READWRITE));
+	g_object_class_install_property (
+		object_class,
+		PROP_TEXT,
+		g_param_spec_string (
+			"text",
+			"Summry Text",
+			NULL,
+			NULL,
+			G_PARAM_READWRITE));	
+}
+
+static void
+week_view_clutter_event_item_init (EWeekViewClutterEventItem *event_item)
+{
+	event_item->priv = E_WEEK_VIEW_CLUTTER_EVENT_ITEM_GET_PRIVATE (event_item);
+
+	event_item->priv->event_num = -1;
+	event_item->priv->span_num = -1;
+}
+
+GType
+e_week_view_clutter_event_item_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		const GTypeInfo type_info = {
+			sizeof (EWeekViewClutterEventItemClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) week_view_clutter_event_item_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (EWeekViewClutterEventItem),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) week_view_clutter_event_item_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			MX_TYPE_BOX_LAYOUT, "EWeekViewClutterEventItem",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+gint
+e_week_view_clutter_event_item_get_event_num (EWeekViewClutterEventItem *event_item)
+{
+	g_return_val_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item), -1);
+
+	return event_item->priv->event_num;
+}
+
+void
+e_week_view_clutter_event_item_set_event_num (EWeekViewClutterEventItem *event_item,
+                                      gint event_num)
+{
+	g_return_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item));
+
+	event_item->priv->event_num = event_num;
+	week_view_clutter_event_item_draw (event_item);
+
+	g_object_notify (G_OBJECT (event_item), "event-num");
+}
+
+const char *
+e_week_view_clutter_event_item_get_text (EWeekViewClutterEventItem *event_item)
+{
+	g_return_val_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item), -1);
+
+	return event_item->priv->text;
+}
+
+void
+e_week_view_clutter_event_item_set_text (EWeekViewClutterEventItem *event_item,
+				 	 const char *txt)
+{
+	g_return_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item));
+
+	if (event_item->priv->text)
+		g_free (event_item->priv->text);
+
+	event_item->priv->text = g_strdup (txt); 
+	week_view_clutter_event_item_draw (event_item);
+
+	g_object_notify (G_OBJECT (event_item), "text");
+}
+
+gint
+e_week_view_clutter_event_item_get_span_num (EWeekViewClutterEventItem *event_item)
+{
+	g_return_val_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item), -1);
+
+	return event_item->priv->span_num;
+}
+
+void
+e_week_view_clutter_event_item_set_span_num (EWeekViewClutterEventItem *event_item,
+                                     gint span_num)
+{
+	g_return_if_fail (E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM (event_item));
+
+	event_item->priv->span_num = span_num;
+	week_view_clutter_event_item_draw (event_item);
+
+	g_object_notify (G_OBJECT (event_item), "span-num");
+}
+
+EWeekViewClutterEventItem *
+e_week_view_clutter_event_item_new (EWeekView *view)
+{
+	EWeekViewClutterEventItem *item = g_object_new (E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM, NULL);
+	MxBoxLayout *box = (MxBoxLayout *)item;
+
+	item->priv->week_view = view;
+	item->priv->texture = clutter_cairo_texture_new (10, view->row_height);
+	clutter_actor_set_reactive (item->priv->texture, TRUE);
+	
+	mx_box_layout_set_orientation (box, MX_ORIENTATION_VERTICAL);
+	mx_box_layout_add_actor (box,
+                               item->priv->texture, -1);
+	clutter_container_child_set (CLUTTER_CONTAINER (box),
+                               item->priv->texture,
+			       "expand", TRUE,
+			       "x-fill", TRUE,
+			       "y-fill", TRUE,			       
+                               NULL);
+	clutter_actor_show_all (box);
+	clutter_actor_set_reactive (box, TRUE);
+
+	return item;
+}
+
+void		
+e_week_view_clutter_event_item_redraw  (EWeekViewClutterEventItem *item)
+{
+	week_view_clutter_event_item_draw (item);
+}
+
diff --git a/calendar/gui/e-week-view-clutter-event-item.h b/calendar/gui/e-week-view-clutter-event-item.h
new file mode 100644
index 0000000..e23a074
--- /dev/null
+++ b/calendar/gui/e-week-view-clutter-event-item.h
@@ -0,0 +1,93 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *		Srinivasa Ragavan <sragavan gnome org>
+ *
+ * Copyright (C) 2010 Intel Corporation. (www.intel.com)
+ *
+ */
+
+/*
+ * EWeekViewClutterEventItem - displays the background, times and icons for an event
+ * in the week/month views. A separate EText canvas item is used to display &
+ * edit the text.
+ */
+
+#ifndef E_WEEK_VIEW_CLUTTER_EVENT_ITEM_H
+#define E_WEEK_VIEW_CLUTTER_EVENT_ITEM_H
+
+#include "e-week-view.h"
+
+/* Standard GObject macros */
+#define E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM \
+	(e_week_view_clutter_event_item_get_type ())
+#define E_WEEK_VIEW_CLUTTER_EVENT_ITEM(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM, EWeekViewClutterEventItem))
+#define E_WEEK_VIEW_CLUTTER_EVENT_ITEM_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM, EWeekViewClutterEventItemClass))
+#define E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM))
+#define E_IS_WEEK_VIEW_CLUTTER_EVENT_ITEM_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM))
+#define E_WEEK_VIEW_CLUTTER_EVENT_ITEM_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_WEEK_VIEW_CLUTTER_EVENT_ITEM, EWeekViewClutterEventItemClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EWeekViewClutterEventItem EWeekViewClutterEventItem;
+typedef struct _EWeekViewClutterEventItemClass EWeekViewClutterEventItemClass;
+typedef struct _EWeekViewClutterEventItemPrivate EWeekViewClutterEventItemPrivate;
+
+struct _EWeekViewClutterEventItem {
+	MxBoxLayout parent;
+	EWeekViewClutterEventItemPrivate *priv;
+};
+
+struct _EWeekViewClutterEventItemClass {
+	MxBoxLayoutClass parent_class;
+};
+
+GType		e_week_view_clutter_event_item_get_type	(void);
+gint		e_week_view_clutter_event_item_get_event_num
+						(EWeekViewClutterEventItem *event_item);
+void		e_week_view_clutter_event_item_set_event_num
+						(EWeekViewClutterEventItem *event_item,
+						 gint event_num);
+gint		e_week_view_clutter_event_item_get_span_num
+						(EWeekViewClutterEventItem *event_item);
+void		e_week_view_clutter_event_item_set_span_num
+						(EWeekViewClutterEventItem *event_item,
+						 gint span_num);
+void		e_week_view_clutter_event_item_redraw 
+						(EWeekViewClutterEventItem *item);
+const char *	e_week_view_clutter_event_item_get_text 
+						(EWeekViewClutterEventItem *event_item);
+void		e_week_view_clutter_event_item_set_text 
+						(EWeekViewClutterEventItem *event_item,
+				 	 	 const char *txt);
+
+EWeekViewClutterEventItem * e_week_view_clutter_event_item_new (EWeekView *view);
+
+
+G_END_DECLS
+
+#endif /* E_WEEK_VIEW_CLUTTER_EVENT_ITEM_H */
diff --git a/calendar/gui/e-week-view-layout.c b/calendar/gui/e-week-view-layout.c
index 7863791..59f3280 100644
--- a/calendar/gui/e-week-view-layout.c
+++ b/calendar/gui/e-week-view-layout.c
@@ -187,6 +187,9 @@ e_week_view_layout_event	(EWeekViewEvent	*event,
 			span.num_days = span_end_day - span_start_day + 1;
 			span.row = free_row;
 			span.background_item = NULL;
+#if HAVE_CLUTTER
+			span.actor_item = NULL;
+#endif			
 			span.text_item = NULL;
 			if (event->num_spans > span_num) {
 				old_span = &g_array_index (
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 0db71c0..3769dda 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -65,6 +65,7 @@
 #if HAVE_CLUTTER
 #include "e-week-view-clutter-titles-item.h"
 #include "e-week-view-clutter-main-item.h"
+#include "e-week-view-clutter-event-item.h"
 #endif
 
 #define WITHOUT_CLUTTER (g_getenv("WITHOUT_CLUTTER") != NULL)
@@ -122,15 +123,31 @@ static void e_week_view_paste_text (ECalendarView *week_view);
 static void e_week_view_update_query (EWeekView *week_view);
 static void e_week_view_draw_shadow (EWeekView *week_view);
 
+#if HAVE_CLUTTER
+static gboolean
+week_view_clutter_button_press (ClutterActor *actor, 
+				ClutterEvent *event,
+				EWeekView *week_view);
+#endif
 static gboolean e_week_view_on_button_press (GtkWidget *widget,
 					     GdkEventButton *event,
 					     EWeekView *week_view);
+#if HAVE_CLUTTER
+static gboolean e_week_view_on_clutter_button_release (ClutterActor *actor,
+					       ClutterButtonEvent *event,
+					       EWeekView *week_view);
+#endif
 static gboolean e_week_view_on_button_release (GtkWidget *widget,
 					       GdkEventButton *event,
 					       EWeekView *week_view);
 static gboolean e_week_view_on_scroll (GtkWidget *widget,
 				       GdkEventScroll *scroll,
 				       EWeekView *week_view);
+#if HAVE_CLUTTER
+static gboolean e_week_view_on_clutter_motion (ClutterActor *actor,
+				       ClutterMotionEvent *event,
+				       EWeekView *week_view);
+#endif
 static gboolean e_week_view_on_motion (GtkWidget *widget,
 				       GdkEventMotion *event,
 				       EWeekView *week_view);
@@ -949,6 +966,12 @@ e_week_view_init (EWeekView *week_view)
 				       e_week_view_main_item_get_type (),
 				       "EWeekViewMainItem::week_view", week_view,
 				       NULL);
+	g_signal_connect_after (week_view->main_canvas, "button_press_event",
+				G_CALLBACK (e_week_view_on_button_press), week_view);
+	g_signal_connect (week_view->main_canvas, "button_release_event",
+			  G_CALLBACK (e_week_view_on_button_release), week_view);
+	g_signal_connect (week_view->main_canvas, "motion_notify_event",
+			  G_CALLBACK (e_week_view_on_motion), week_view);
 #if HAVE_CLUTTER
 	} else {
 	week_view->main_canvas_embed = gtk_clutter_embed_new ();
@@ -964,20 +987,21 @@ e_week_view_init (EWeekView *week_view)
                        "surface-width", 300,
                        "surface-height", 50,	
 		       NULL);
-	clutter_actor_set_reactive (week_view->main_canvas_actor, FALSE);
+	clutter_actor_set_reactive (week_view->main_canvas_actor, TRUE);
 	clutter_container_add_actor ((ClutterContainer *)week_view->main_canvas_stage, (ClutterActor *)week_view->main_canvas_actor);
 	clutter_actor_show ((ClutterActor *)week_view->main_canvas_actor);
-
+	g_signal_connect_after (week_view->main_canvas_actor, "button-press-event",
+				G_CALLBACK (week_view_clutter_button_press), week_view);
+	g_signal_connect (week_view->main_canvas_actor, "button-release-event",
+			  G_CALLBACK (e_week_view_on_clutter_button_release), week_view);
+	g_signal_connect (week_view->main_canvas_actor, "motion-event",
+			  G_CALLBACK (e_week_view_on_clutter_motion), week_view);
+	
 	}
 #endif	
-	g_signal_connect_after (week_view->main_canvas, "button_press_event",
-				G_CALLBACK (e_week_view_on_button_press), week_view);
-	g_signal_connect (week_view->main_canvas, "button_release_event",
-			  G_CALLBACK (e_week_view_on_button_release), week_view);
+
 	g_signal_connect (week_view->main_canvas, "scroll_event",
 			  G_CALLBACK (e_week_view_on_scroll), week_view);
-	g_signal_connect (week_view->main_canvas, "motion_notify_event",
-			  G_CALLBACK (e_week_view_on_motion), week_view);
 
 	/* Create the buttons to jump to each days. */
 	pixbuf = gdk_pixbuf_new_from_xpm_data ((const gchar **) jump_xpm);
@@ -1215,7 +1239,7 @@ get_digit_width (PangoLayout *layout)
 	return max_digit_width;
 }
 
-static GdkColor
+GdkColor
 e_week_view_get_text_color (EWeekView *week_view, EWeekViewEvent *event, GtkWidget *widget)
 {
 	GtkStyle *style;
@@ -2687,7 +2711,7 @@ e_week_view_on_button_press (GtkWidget *widget,
 
 		window = gtk_layout_get_bin_window (GTK_LAYOUT (widget));
 
-		if (gdk_pointer_grab (window, FALSE,
+		if (!WITHOUT_CLUTTER ||  gdk_pointer_grab (window, FALSE,
 				      GDK_POINTER_MOTION_MASK
 				      | GDK_BUTTON_RELEASE_MASK,
 				      NULL, NULL, event->time) == 0) {
@@ -2737,6 +2761,56 @@ e_week_view_on_button_press (GtkWidget *widget,
 	return TRUE;
 }
 
+#if HAVE_CLUTTER
+static gboolean
+week_view_clutter_button_press (ClutterActor *actor, 
+				ClutterEvent *event,
+				EWeekView *week_view)
+{
+	GdkEventButton *bevent;
+	gboolean ret;
+
+	if (event->button.click_count > 1 )
+		bevent = gdk_event_new (GDK_2BUTTON_PRESS);
+	else
+		bevent = gdk_event_new (GDK_BUTTON_PRESS);
+
+	bevent->time = event->button.time;
+	bevent->button = event->button.button;
+	bevent->x = (gfloat) event->button.x;
+	bevent->y = (gfloat) event->button.y;
+	ret = e_week_view_on_button_press (week_view->main_canvas, bevent, week_view);
+
+	gdk_event_free (bevent);
+	
+	return ret;
+}
+#endif
+
+#if HAVE_CLUTTER
+static gboolean
+e_week_view_on_clutter_button_release (ClutterActor *actor,
+			       ClutterButtonEvent *event,
+			       EWeekView *week_view)
+{
+	GdkEventButton *bevent;
+	gboolean ret;
+
+	bevent = gdk_event_new (GDK_BUTTON_RELEASE);
+
+	bevent->time = event->time;
+	bevent->button = event->button;
+	bevent->x = (gfloat) event->x;
+	bevent->y = (gfloat) event->y;
+	ret = e_week_view_on_button_release (week_view->main_canvas, bevent, week_view);
+
+	gdk_event_free (bevent);
+	
+	return ret;	
+}
+
+#endif
+
 static gboolean
 e_week_view_on_button_release (GtkWidget *widget,
 			       GdkEventButton *event,
@@ -2809,6 +2883,27 @@ e_week_view_on_scroll (GtkWidget *widget,
 	return TRUE;
 }
 
+#if HAVE_CLUTTER
+static gboolean
+e_week_view_on_clutter_motion (ClutterActor *actor,
+		       ClutterMotionEvent *event,
+		       EWeekView *week_view)
+{
+	GdkEventButton *bevent;
+	gboolean ret;
+
+	bevent = gdk_event_new (GDK_MOTION_NOTIFY);
+
+	bevent->time = event->time;
+	bevent->x = (gfloat) event->x;
+	bevent->y = (gfloat) event->y;
+	ret = e_week_view_on_motion (week_view->main_canvas, bevent, week_view);
+
+	gdk_event_free (bevent);
+	
+	return ret;	
+}
+#endif
 static gboolean
 e_week_view_on_motion (GtkWidget *widget,
 		       GdkEventMotion *mevent,
@@ -3306,7 +3401,7 @@ e_week_view_reshape_event_span (EWeekView *week_view,
 	gboolean one_day_event;
 	ECalComponent *comp;
 	gdouble text_x, text_y, text_w, text_h;
-	gchar *text, *end_of_line;
+	gchar *text=NULL, *end_of_line;
 	gint line_len, text_width;
 	PangoFontDescription *font_desc;
 	PangoContext *pango_context;
@@ -3377,14 +3472,16 @@ e_week_view_reshape_event_span (EWeekView *week_view,
 		num_icons += cal_comp_util_get_n_icons (comp, NULL);
 	}
 
+#if HAVE_CLUTTER
+	if (WITHOUT_CLUTTER) {
+#endif		
 	/* Create the background canvas item if necessary. */
 	if (!span->background_item) {
 		span->background_item =
 			gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (week_view->main_canvas)->root),
 					       e_week_view_event_item_get_type (),
 					       NULL);
-	}
-
+		
 	g_object_set_data ((GObject *)span->background_item, "event-num", GINT_TO_POINTER (event_num));
 	g_signal_connect (span->background_item, "event",
 			  G_CALLBACK (tooltip_event_cb),
@@ -3394,9 +3491,48 @@ e_week_view_reshape_event_span (EWeekView *week_view,
 			       "event_num", event_num,
 			       "span_num", span_num,
 			       NULL);
+	}
+#if HAVE_CLUTTER
+	} else {
+	char *summary;
+	gboolean free_text = FALSE;
+
+	summary = e_calendar_view_get_icalcomponent_summary (event->comp_data->client, event->comp_data->icalcomp, &free_text);
+
+	/* Create the background canvas item if necessary. */
+	if (!span->actor_item) {
+		span->actor_item = e_week_view_clutter_event_item_new (week_view);
+		
+	//g_object_set_data ((GObject *)span->background_item, "event-num", GINT_TO_POINTER (event_num));
+	//g_signal_connect (span->background_item, "event",
+	//		  G_CALLBACK (tooltip_event_cb),
+	//		  week_view);
+
+	g_object_set (span->actor_item,
+			       "event_num", event_num,
+			       "span_num", span_num,
+			       "text", summary ? summary : "",
+			       NULL);
+	e_week_view_clutter_event_item_redraw (span->actor_item);
+	clutter_container_add_actor (week_view->main_canvas_stage, span->actor_item);
+	clutter_actor_raise_top (span->actor_item);
+	} else {
+		g_object_set (span->actor_item,
+			       "event_num", event_num,
+			       "span_num", span_num,
+			       "text", summary ? summary : "",
+			       NULL);		
+		e_week_view_clutter_event_item_redraw (span->actor_item);
+	}
+	if (free_text)
+		g_free ((gchar *)summary);
+		
+	}
+#endif	
+	
 
 	/* Create the text item if necessary. */
-	if (!span->text_item) {
+	if (!span->text_item && 0) {
 		const gchar *summary;
 		GtkWidget *widget;
 		GdkColor color;
diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h
index 2115f7d..d4f0dfd 100644
--- a/calendar/gui/e-week-view.h
+++ b/calendar/gui/e-week-view.h
@@ -162,6 +162,9 @@ struct _EWeekViewEventSpan {
 	guint row : 7;
 	GnomeCanvasItem *background_item;
 	GnomeCanvasItem *text_item;
+#if HAVE_CLUTTER
+	ClutterActor *actor_item;
+#endif	
 };
 
 typedef struct _EWeekViewEvent EWeekViewEvent;
@@ -485,6 +488,9 @@ void		e_week_view_jump_to_button_item	(EWeekView *week_view,
 						 GnomeCanvasItem *item);
 void		e_week_view_scroll_a_step	(EWeekView *week_view,
 						 ECalViewMoveDirection direction);
+GdkColor	e_week_view_get_text_color 	(EWeekView *week_view, 
+						 EWeekViewEvent *event, 
+						 GtkWidget *widget);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]