[evolution/clutter-calendar-v2] Add Clutter texture to time line.
- From: Srinivasa Ragavan <sragavan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/clutter-calendar-v2] Add Clutter texture to time line.
- Date: Thu, 26 Aug 2010 17:09:30 +0000 (UTC)
commit 45cd0eacf2586e19a1d1c9685ea1c032734435df
Author: Srinivasa Ragavan <sragavan gnome org>
Date: Thu Aug 26 22:35:58 2010 +0530
Add Clutter texture to time line.
calendar/gui/Makefile.am | 4 +
calendar/gui/e-day-view-clutter-time-item.c | 1147 +++++++++++++++++++++++++++
calendar/gui/e-day-view-clutter-time-item.h | 90 +++
calendar/gui/e-day-view.c | 107 +++-
calendar/gui/e-day-view.h | 21 +-
5 files changed, 1364 insertions(+), 5 deletions(-)
---
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index a168582..5631234 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -71,6 +71,7 @@ libevolution_calendar_la_CPPFLAGS = \
-DPREFIX=\""$(prefix)"\" \
$(GNOME_PLATFORM_CFLAGS) \
$(LIBSOUP_CFLAGS) \
+ $(CLUTTER_CFLAGS) \
$(EVOLUTION_CALENDAR_CFLAGS) \
$(CAMEL_CFLAGS)
@@ -85,6 +86,8 @@ etspec_DATA = \
e-memo-table.etspec
libevolution_calendar_la_SOURCES = \
+ e-day-view-clutter-time-item.c \
+ e-day-view-clutter-time-item.h \
cal-editor-utils.c \
cal-editor-utils.h \
calendar-config.c \
@@ -227,6 +230,7 @@ libevolution_calendar_la_LIBADD = \
$(top_builddir)/filter/libfilter.la \
$(top_builddir)/e-util/libeutil.la \
$(CAMEL_LIBS) \
+ $(CLUTTER_LIBS) \
$(LIBSOUP_LIBS) \
$(EVOLUTION_CALENDAR_LIBS) \
$(GNOME_PLATFORM_LIBS)
diff --git a/calendar/gui/e-day-view-clutter-time-item.c b/calendar/gui/e-day-view-clutter-time-item.c
new file mode 100644
index 0000000..09179f9
--- /dev/null
+++ b/calendar/gui/e-day-view-clutter-time-item.c
@@ -0,0 +1,1147 @@
+/*
+ * 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)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include "e-day-view-clutter-time-item.h"
+#include "calendar-config.h"
+#include <libecal/e-cal-time-util.h>
+#include <widgets/e-timezone-dialog/e-timezone-dialog.h>
+#include <libedataserver/e-data-server-util.h>
+
+/* The spacing between items in the time column. GRID_X_PAD is the space down
+ either side of the column, i.e. outside the main horizontal grid lines.
+ HOUR_L_PAD & HOUR_R_PAD are the spaces on the left & right side of the
+ big hour number (this is inside the horizontal grid lines).
+ MIN_X_PAD is the spacing either side of the minute number. The smaller
+ horizontal grid lines match with this.
+ 60_MIN_X_PAD is the space either side of the HH:MM display used when
+ we are displaying 60 mins per row (inside the main grid lines).
+ LARGE_HOUR_Y_PAD is the offset of the large hour string from the top of the
+ row.
+ SMALL_FONT_Y_PAD is the offset of the small time/minute string from the top
+ of the row. */
+
+#define E_DVTMI_TIME_GRID_X_PAD 4
+#define E_DVTMI_HOUR_L_PAD 4
+#define E_DVTMI_HOUR_R_PAD 2
+#define E_DVTMI_MIN_X_PAD 2
+#define E_DVTMI_60_MIN_X_PAD 4
+#define E_DVTMI_LARGE_HOUR_Y_PAD 1
+#define E_DVTMI_SMALL_FONT_Y_PAD 1
+
+#define E_DAY_VIEW_CLUTTER_TIME_ITEM_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM, EDayViewClutterTimeItemPrivate))
+
+struct _EDayViewClutterTimeItemPrivate {
+ /* The parent EDayView widget. */
+ EDayView *day_view;
+
+ /* The width of the time column. */
+ gint column_width;
+
+ /* TRUE if we are currently dragging the selection times. */
+ gboolean dragging_selection;
+
+ /* The second timezone if shown, or else NULL. */
+ guint second_zone_changed_id;
+ icaltimezone *second_zone;
+
+ gdouble line_width;
+ ClutterActor *mb_line;
+ ClutterActor *mb_line_alt;
+};
+
+static void e_day_view_clutter_time_item_draw (ClutterActor *item);
+static double e_day_view_clutter_time_item_point (ClutterActor *item,
+ double x, double y,
+ gint cx, gint cy,
+ ClutterActor **actual_item);
+static gint e_day_view_clutter_time_item_event (ClutterActor *item,
+ ClutterEvent *event);
+static void e_day_view_clutter_time_item_increment_time (gint *hour,
+ gint *minute,
+ gint mins_per_row);
+static void e_day_view_clutter_time_item_show_popup_menu (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event);
+static void e_day_view_clutter_time_item_on_set_divisions (GtkWidget *item,
+ EDayViewClutterTimeItem *time_item);
+static void e_day_view_clutter_time_item_on_button_press (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event);
+static void e_day_view_clutter_time_item_on_button_release (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event);
+static void e_day_view_clutter_time_item_on_motion_notify (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event);
+static gint e_day_view_clutter_time_item_convert_position_to_row (EDayViewClutterTimeItem *time_item,
+ gint y);
+
+static void edvti_second_zone_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data);
+
+enum {
+ PROP_0,
+ PROP_DAY_VIEW
+};
+
+static gpointer parent_class;
+
+static void
+day_view_clutter_time_item_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DAY_VIEW:
+ e_day_view_clutter_time_item_set_day_view (
+ E_DAY_VIEW_CLUTTER_TIME_ITEM (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+day_view_clutter_time_item_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_DAY_VIEW:
+ g_value_set_object (
+ value, e_day_view_clutter_time_item_get_day_view (
+ E_DAY_VIEW_CLUTTER_TIME_ITEM (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+day_view_clutter_time_item_dispose (GObject *object)
+{
+ EDayViewClutterTimeItemPrivate *priv;
+
+ priv = E_DAY_VIEW_CLUTTER_TIME_ITEM_GET_PRIVATE (object);
+
+ if (priv->day_view != NULL) {
+ g_object_unref (priv->day_view);
+ priv->day_view = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+day_view_clutter_time_item_finalize (GObject *object)
+{
+ EDayViewClutterTimeItem *time_item;
+
+ time_item = E_DAY_VIEW_CLUTTER_TIME_ITEM (object);
+
+ if (time_item->priv->second_zone_changed_id)
+ calendar_config_remove_notification (time_item->priv->second_zone_changed_id);
+ time_item->priv->second_zone_changed_id = 0;
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+day_view_clutter_time_item_class_init (EDayViewClutterTimeItemClass *class)
+{
+ GObjectClass *object_class;
+ ClutterCairoTextureClass *item_class;
+ ClutterActorClass *actor_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EDayViewClutterTimeItemPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = day_view_clutter_time_item_set_property;
+ object_class->get_property = day_view_clutter_time_item_get_property;
+ object_class->dispose = day_view_clutter_time_item_dispose;
+ object_class->finalize = day_view_clutter_time_item_finalize;
+
+ item_class = CLUTTER_CAIRO_TEXTURE_CLASS (class);
+ actor_class = CLUTTER_ACTOR_CLASS (class);
+/* item_class->update = e_day_view_clutter_time_item_update;
+ item_class->draw = e_day_view_clutter_time_item_draw;
+ item_class->point = e_day_view_clutter_time_item_point;
+*/
+ actor_class->event = e_day_view_clutter_time_item_event;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_DAY_VIEW,
+ g_param_spec_object (
+ "day-view",
+ "Day View",
+ NULL,
+ E_TYPE_DAY_VIEW,
+ G_PARAM_READWRITE));
+}
+
+static void
+day_view_clutter_time_item_init (EDayViewClutterTimeItem *time_item)
+{
+ gchar *last;
+
+ time_item->priv = E_DAY_VIEW_CLUTTER_TIME_ITEM_GET_PRIVATE (time_item);
+
+ time_item->priv->dragging_selection = FALSE;
+ time_item->priv->second_zone = NULL;
+
+ last = calendar_config_get_day_second_zone ();
+
+ if (last) {
+ if (*last)
+ time_item->priv->second_zone = icaltimezone_get_builtin_timezone (last);
+ g_free (last);
+ }
+
+ time_item->priv->second_zone_changed_id = calendar_config_add_notification_day_second_zone (edvti_second_zone_changed_cb, time_item);
+}
+
+GType
+e_day_view_clutter_time_item_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ const GTypeInfo type_info = {
+ sizeof (EDayViewClutterTimeItemClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) day_view_clutter_time_item_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EDayViewClutterTimeItem),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) day_view_clutter_time_item_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ CLUTTER_TYPE_CAIRO_TEXTURE, "EDayViewClutterTimeItem",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+/* Draw Marcus Bains */
+static void
+edvti_draw_marcus_bains (ClutterActor *canvas_item,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint x_offset,
+ icaltimezone *use_zone)
+
+{
+ struct icaltimetype time_now;
+ gint marcus_bains_y;
+ EDayView *day_view;
+ EDayViewClutterTimeItem *time_item;
+ cairo_t *cr;
+ ClutterActor *mb;
+ gint long_line_x1, long_line_x2;
+ ClutterActor *stage;
+ GdkColor mb_color;
+
+ time_item = E_DAY_VIEW_CLUTTER_TIME_ITEM (canvas_item);
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ stage = time_item->stage;
+ long_line_x1 = (use_zone ? 0 : E_DVTMI_TIME_GRID_X_PAD) - x + x_offset;
+ long_line_x2 = time_item->priv->column_width - E_DVTMI_TIME_GRID_X_PAD - x - (use_zone ? E_DVTMI_TIME_GRID_X_PAD : 0) + x_offset;
+
+ if ((use_zone && !time_item->priv->mb_line_alt) ||
+ (!use_zone && !time_item->priv->mb_line)) {
+ mb = clutter_cairo_texture_new (long_line_x2-long_line_x1, (int)time_item->priv->line_width);
+ clutter_container_add_actor ((ClutterContainer *)stage, mb);
+ clutter_actor_show (mb);
+
+ if (use_zone)
+ time_item->priv->mb_line_alt = mb;
+ else
+ time_item->priv->mb_line = mb;
+ } else {
+ if (use_zone)
+ mb = time_item->priv->mb_line_alt;
+ else
+ mb = time_item->priv->mb_line;
+ }
+
+ cr = clutter_cairo_texture_create ((ClutterCairoTexture *)mb);
+ cairo_save (cr);
+ gdk_cairo_set_source_color (cr, &day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE]);
+
+ if (day_view->marcus_bains_time_bar_color && gdk_color_parse (day_view->marcus_bains_time_bar_color, &mb_color)) {
+ GdkColormap *colormap;
+
+ colormap = gtk_widget_get_colormap (GTK_WIDGET (day_view));
+ if (gdk_colormap_alloc_color (colormap, &mb_color, TRUE, TRUE)) {
+ gdk_cairo_set_source_color (cr, &mb_color);
+ }
+ } else
+ mb_color = day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE];
+
+ time_now = icaltime_current_time_with_zone (e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view)));
+ marcus_bains_y = (time_now.hour * 60 + time_now.minute) * day_view->row_height / day_view->mins_per_row - y;
+ cairo_set_line_width (cr, 1.5);
+ cairo_move_to (cr, long_line_x1 - (use_zone ? E_DVTMI_TIME_GRID_X_PAD : 0), 0);
+ cairo_line_to (cr, long_line_x2, 0);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ cairo_destroy (cr);
+
+ clutter_actor_set_position (mb, long_line_x1, y);
+}
+
+/*
+ * DRAWING ROUTINES - functions to paint the canvas item.
+ */
+static void
+edvti_draw_zone (ClutterActor *canvas_item,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint x_offset,
+ icaltimezone *use_zone)
+{
+ EDayView *day_view;
+ EDayViewClutterTimeItem *time_item;
+ ECalModel *model;
+ GtkStyle *style;
+ const gchar *suffix;
+ gchar buffer[64], *midnight_day = NULL, *midnight_month = NULL;
+ gint hour, display_hour, minute, row;
+ gint row_y, start_y, large_hour_y_offset, small_font_y_offset;
+ gint long_line_x1, long_line_x2, short_line_x1;
+ gint large_hour_x2, minute_x2;
+ gint hour_width, minute_width, suffix_width;
+ gint max_suffix_width, max_minute_or_suffix_width;
+ PangoLayout *layout;
+ PangoContext *context;
+ PangoFontDescription *small_font_desc;
+ PangoFontMetrics *large_font_metrics, *small_font_metrics;
+ cairo_t *cr;
+ GdkColor fg, dark;
+ GdkColor mb_color;
+
+ cr = clutter_cairo_texture_create ((ClutterCairoTexture *)canvas_item);
+
+ time_item = E_DAY_VIEW_CLUTTER_TIME_ITEM (canvas_item);
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ time_item->priv->line_width = cairo_get_line_width (cr);
+
+ model = e_calendar_view_get_model (E_CALENDAR_VIEW (day_view));
+
+ style = gtk_widget_get_style (GTK_WIDGET (day_view));
+ small_font_desc = style->font_desc;
+
+ context = gtk_widget_get_pango_context (GTK_WIDGET (day_view));
+ large_font_metrics = pango_context_get_metrics (context, day_view->large_font_desc,
+ pango_context_get_language (context));
+ small_font_metrics = pango_context_get_metrics (context, small_font_desc,
+ pango_context_get_language (context));
+
+ fg = style->fg[GTK_STATE_NORMAL];
+ dark = style->dark[GTK_STATE_NORMAL];
+
+ /* The start and end of the long horizontal line between hours. */
+ long_line_x1 = (use_zone ? 0 : E_DVTMI_TIME_GRID_X_PAD) - x + x_offset;
+ long_line_x2 = time_item->priv->column_width - E_DVTMI_TIME_GRID_X_PAD - x - (use_zone ? E_DVTMI_TIME_GRID_X_PAD : 0) + x_offset;
+
+ if (day_view->mins_per_row == 60) {
+ /* The right edge of the complete time string in 60-min
+ divisions, e.g. "14:00" or "2 pm". */
+ minute_x2 = long_line_x2 - E_DVTMI_60_MIN_X_PAD;
+
+ /* These aren't used for 60-minute divisions, but we initialize
+ them to keep gcc happy. */
+ short_line_x1 = 0;
+ large_hour_x2 = 0;
+ } else {
+ max_suffix_width = MAX (day_view->am_string_width,
+ day_view->pm_string_width);
+
+ max_minute_or_suffix_width = MAX (max_suffix_width,
+ day_view->max_minute_width);
+
+ /* The start of the short horizontal line between the periods
+ within each hour. */
+ short_line_x1 = long_line_x2 - E_DVTMI_MIN_X_PAD * 2
+ - max_minute_or_suffix_width;
+
+ /* The right edge of the large hour string. */
+ large_hour_x2 = short_line_x1 - E_DVTMI_HOUR_R_PAD;
+
+ /* The right edge of the minute part of the time. */
+ minute_x2 = long_line_x2 - E_DVTMI_MIN_X_PAD;
+ }
+
+ /* Start with the first hour & minute shown in the EDayView. */
+ hour = day_view->first_hour_shown;
+ minute = day_view->first_minute_shown;
+
+ if (use_zone) {
+ /* shift time with a difference between local time and the other timezone */
+ icaltimezone *cal_zone = e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view));
+ struct icaltimetype tt;
+ gint diff;
+ struct tm mn;
+
+ tt = icaltime_from_timet_with_zone (day_view->day_starts[0], 0, cal_zone);
+
+ /* diff is number of minutes */
+ diff = (icaltimezone_get_utc_offset (use_zone, &tt, NULL) -
+ icaltimezone_get_utc_offset (cal_zone, &tt, NULL)
+ ) / 60;
+
+ tt = icaltime_from_timet_with_zone (day_view->day_starts[0], 0, cal_zone);
+ tt.is_date = FALSE;
+ icaltime_set_timezone (&tt, cal_zone);
+ tt = icaltime_convert_to_zone (tt, use_zone);
+
+ if (diff != 0) {
+ /* shows the next midnight */
+ icaltime_adjust (&tt, 1, 0, 0, 0);
+ }
+
+ mn = icaltimetype_to_tm (&tt);
+
+ /* up to two characters/numbers */
+ e_utf8_strftime (buffer, sizeof (buffer), "%d", &mn);
+ midnight_day = g_strdup (buffer);
+ /* up to three characters, abbreviated month name */
+ e_utf8_strftime (buffer, sizeof (buffer), "%b", &mn);
+ midnight_month = g_strdup (buffer);
+
+ minute += (diff % 60);
+ hour += (diff / 60) + (minute / 60);
+
+ minute = minute % 60;
+ if (minute < 0) {
+ hour--;
+ minute += 60;
+ }
+
+ hour = (hour + 48) % 24;
+ }
+
+ /* The offset of the large hour string from the top of the row. */
+ large_hour_y_offset = E_DVTMI_LARGE_HOUR_Y_PAD;
+
+ /* The offset of the small time/minute string from top of row. */
+ small_font_y_offset = E_DVTMI_SMALL_FONT_Y_PAD;
+
+ /* Calculate the minimum y position of the first row we need to draw.
+ This is normally one row height above the 0 position, but if we
+ are using the large font we may have to go back a bit further. */
+ start_y = 0 - MAX (day_view->row_height,
+ (pango_font_metrics_get_ascent (large_font_metrics) +
+ pango_font_metrics_get_descent (large_font_metrics)) / PANGO_SCALE +
+ E_DVTMI_LARGE_HOUR_Y_PAD);
+
+ /* Draw the Marcus Bains Line first, so it appears under other elements. */
+ if (e_day_view_marcus_bains_get_show_line (day_view)) {
+ edvti_draw_marcus_bains (canvas_item,
+ x, y,
+ width, height,
+ x_offset, use_zone);
+ } else {
+ mb_color = day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE];
+
+ if (day_view->marcus_bains_time_bar_color && gdk_color_parse (day_view->marcus_bains_time_bar_color, &mb_color)) {
+ GdkColormap *colormap;
+
+ colormap = gtk_widget_get_colormap (GTK_WIDGET (day_view));
+ if (gdk_colormap_alloc_color (colormap, &mb_color, TRUE, TRUE)) {
+ gdk_cairo_set_source_color (cr, &mb_color);
+ }
+ }
+ }
+
+ /* Step through each row, drawing the times and the horizontal lines
+ between them. */
+ for (row = 0, row_y = 0 - y;
+ row < day_view->rows && row_y < height;
+ row++, row_y += day_view->row_height) {
+ gboolean show_midnight_date = use_zone && hour == 0 && (minute == 0 || day_view->mins_per_row == 60) && midnight_day && midnight_month;
+
+ /* If the row is above the first row we want to draw just
+ increment the time and skip to the next row. */
+ if (row_y < start_y) {
+ e_day_view_clutter_time_item_increment_time (&hour, &minute,
+ day_view->mins_per_row);
+ continue;
+ }
+
+ /* Calculate the actual hour number to display. For 12-hour
+ format we convert 0-23 to 12-11am/12-11pm. */
+ e_day_view_convert_time_to_display (day_view, hour,
+ &display_hour,
+ &suffix, &suffix_width);
+
+ if (day_view->mins_per_row == 60) {
+ /* 60 minute intervals - draw a long horizontal line
+ between hours and display as one long string,
+ e.g. "14:00" or "2 pm". */
+ cairo_save (cr);
+ gdk_cairo_set_source_color (cr, &dark);
+ cairo_save (cr);
+ cairo_set_line_width (cr, 0.7);
+ cairo_move_to (cr, long_line_x1, row_y);
+ cairo_line_to (cr, long_line_x2, row_y);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ if (show_midnight_date) {
+ strcpy (buffer, midnight_day);
+ strcat (buffer, " ");
+ strcat (buffer, midnight_month);
+ } else if (e_cal_model_get_use_24_hour_format (model)) {
+ g_snprintf (buffer, sizeof (buffer), "%i:%02i",
+ display_hour, minute);
+ } else {
+ g_snprintf (buffer, sizeof (buffer), "%i %s",
+ display_hour, suffix);
+ }
+
+ cairo_save (cr);
+ if (show_midnight_date)
+ gdk_cairo_set_source_color (cr, &mb_color);
+ else
+ gdk_cairo_set_source_color (cr, &fg);
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text (layout, buffer, -1);
+ pango_layout_get_pixel_size (layout, &minute_width, NULL);
+ cairo_translate (cr, minute_x2 - minute_width, row_y + small_font_y_offset);
+ pango_cairo_update_layout (cr, layout);
+ pango_cairo_show_layout (cr, layout);
+ cairo_restore (cr);
+
+ g_object_unref (layout);
+ } else {
+ /* 5/10/15/30 minute intervals. */
+
+ if (minute == 0) {
+ /* On the hour - draw a long horizontal line
+ before the hour and display the hour in the
+ large font. */
+
+ cairo_save (cr);
+ gdk_cairo_set_source_color (cr, &dark);
+ if (show_midnight_date)
+ strcpy (buffer, midnight_day);
+ else
+ g_snprintf (buffer, sizeof (buffer), "%i",
+ display_hour);
+
+ cairo_set_line_width (cr, 0.7);
+ cairo_move_to (cr, long_line_x1, row_y);
+ cairo_line_to (cr, long_line_x2, row_y);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ cairo_save (cr);
+ if (show_midnight_date)
+ gdk_cairo_set_source_color (cr, &mb_color);
+ else
+ gdk_cairo_set_source_color (cr, &fg);
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text (layout, buffer, -1);
+ pango_layout_set_font_description (layout, day_view->large_font_desc);
+ pango_layout_get_pixel_size (layout, &hour_width, NULL);
+ cairo_translate (cr, large_hour_x2 - hour_width, row_y + large_hour_y_offset);
+ pango_cairo_update_layout (cr, layout);
+ pango_cairo_show_layout (cr, layout);
+ cairo_restore (cr);
+
+ g_object_unref (layout);
+ } else {
+ /* Within the hour - draw a short line before
+ the time. */
+ cairo_save (cr);
+ gdk_cairo_set_source_color (cr, &dark);
+ cairo_set_line_width (cr, 0.7);
+ cairo_move_to (cr, short_line_x1, row_y);
+ cairo_line_to (cr, long_line_x2, row_y);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ }
+
+ /* Normally we display the minute in each
+ interval, but when using 30-minute intervals
+ we don't display the '30'. */
+ if (day_view->mins_per_row != 30 || minute != 30) {
+ /* In 12-hour format we display 'am' or 'pm'
+ instead of '00'. */
+ if (show_midnight_date)
+ strcpy (buffer, midnight_month);
+ else if (minute == 0
+ && !e_cal_model_get_use_24_hour_format (model)) {
+ strcpy (buffer, suffix);
+ } else {
+ g_snprintf (buffer, sizeof (buffer),
+ "%02i", minute);
+ }
+
+ cairo_save (cr);
+ if (show_midnight_date)
+ gdk_cairo_set_source_color (cr, &mb_color);
+ else
+ gdk_cairo_set_source_color (cr, &fg);
+ layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text (layout, buffer, -1);
+ pango_layout_set_font_description (layout, day_view->small_font_desc);
+ pango_layout_get_pixel_size (layout, &minute_width, NULL);
+ cairo_translate (cr, minute_x2 - minute_width, row_y + small_font_y_offset);
+ pango_cairo_update_layout (cr, layout);
+ pango_cairo_show_layout (cr, layout);
+ cairo_restore (cr);
+
+ g_object_unref (layout);
+ }
+ }
+
+ e_day_view_clutter_time_item_increment_time (&hour, &minute,
+ day_view->mins_per_row);
+ }
+
+ pango_font_metrics_unref (large_font_metrics);
+ pango_font_metrics_unref (small_font_metrics);
+ cairo_destroy (cr);
+
+ g_free (midnight_day);
+ g_free (midnight_month);
+}
+
+static void
+e_day_view_clutter_time_item_draw (ClutterActor *canvas_item)
+{
+ EDayViewClutterTimeItem *time_item;
+ gint x=0;
+ gint y=0;
+ guint width;
+ guint height;
+
+ time_item = E_DAY_VIEW_CLUTTER_TIME_ITEM (canvas_item);
+ g_return_if_fail (time_item != NULL);
+
+ clutter_cairo_texture_get_surface_size ((ClutterCairoTexture *)canvas_item, &width, &height);
+
+ edvti_draw_zone (canvas_item, x, y, width, height, 0, NULL);
+
+ if (time_item->priv->second_zone)
+ edvti_draw_zone (canvas_item, x, y, width, height, time_item->priv->column_width, time_item->priv->second_zone);
+}
+
+void
+e_day_view_clutter_time_item_redraw (EDayViewClutterTimeItem *item)
+{
+ if (item->priv->mb_line)
+ clutter_cairo_texture_clear ((ClutterCairoTexture *)item->priv->mb_line);
+ if (item->priv->mb_line_alt)
+ clutter_cairo_texture_clear ((ClutterCairoTexture *)item->priv->mb_line_alt);
+ clutter_cairo_texture_clear ((ClutterCairoTexture *)item);
+ e_day_view_clutter_time_item_draw ((ClutterActor *)item);
+}
+
+void
+e_day_view_clutter_time_item_update (EDayViewClutterTimeItem *item)
+{
+ struct icaltimetype time_now;
+ gint marcus_bains_y;
+ int y = 0;
+ EDayView *day_view;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (item);
+
+ time_now = icaltime_current_time_with_zone (e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view)));
+ marcus_bains_y = (time_now.hour * 60 + time_now.minute) * day_view->row_height / day_view->mins_per_row - y;
+
+ if (item->priv->mb_line) {
+ clutter_actor_animate (item->priv->mb_line,
+ CLUTTER_LINEAR, 200,
+ "y", (float) marcus_bains_y,
+ NULL);
+ }
+ if (item->priv->mb_line_alt) {
+ clutter_actor_animate (item->priv->mb_line_alt,
+ CLUTTER_LINEAR, 200,
+ "y", (float) marcus_bains_y,
+ NULL);
+ }
+}
+
+/* Increment the time by the 5/10/15/30/60 minute interval.
+ Note that mins_per_row is never > 60, so we never have to
+ worry about adding more than 60 minutes. */
+static void
+e_day_view_clutter_time_item_increment_time (gint *hour,
+ gint *minute,
+ gint mins_per_row)
+{
+ *minute += mins_per_row;
+ if (*minute >= 60) {
+ *minute -= 60;
+ /* Currently we never wrap around to the next day, but
+ we may do if we display extra timezones. */
+ *hour = (*hour + 1) % 24;
+ }
+}
+
+static double
+e_day_view_clutter_time_item_point (ClutterActor *item, double x, double y,
+ gint cx, gint cy,
+ ClutterActor **actual_item)
+{
+ *actual_item = item;
+ return 0.0;
+}
+
+static gint
+e_day_view_clutter_time_item_event (ClutterActor *item,
+ ClutterEvent *event)
+{
+ EDayViewClutterTimeItem *time_item;
+
+ time_item = E_DAY_VIEW_CLUTTER_TIME_ITEM (item);
+
+ switch (event->type) {
+ case CLUTTER_BUTTON_PRESS:
+ if (event->button.button == 1) {
+ e_day_view_clutter_time_item_on_button_press (time_item, event);
+ } else if (event->button.button == 3) {
+ e_day_view_clutter_time_item_show_popup_menu (time_item, event);
+ return TRUE;
+ }
+ break;
+ case CLUTTER_BUTTON_RELEASE:
+ if (event->button.button == 1)
+ e_day_view_clutter_time_item_on_button_release (time_item,
+ event);
+ break;
+
+ case CLUTTER_MOTION:
+ e_day_view_clutter_time_item_on_motion_notify (time_item, event);
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+edvti_second_zone_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
+{
+ EDayViewClutterTimeItem *time_item = user_data;
+ EDayView *day_view;
+ gchar *location;
+
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (E_IS_DAY_VIEW_CLUTTER_TIME_ITEM (time_item));
+
+ location = calendar_config_get_day_second_zone ();
+ time_item->priv->second_zone = location ? icaltimezone_get_builtin_timezone (location) : NULL;
+ g_free (location);
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ gtk_widget_set_size_request (day_view->time_canvas, e_day_view_clutter_time_item_get_column_width (time_item), -1);
+ e_day_view_clutter_time_item_redraw (day_view->time_canvas_actor);
+}
+
+static void
+edvti_on_select_zone (GtkWidget *item, EDayViewClutterTimeItem *time_item)
+{
+ calendar_config_select_day_second_zone ();
+}
+
+static void
+edvti_on_set_zone (GtkWidget *item, EDayViewClutterTimeItem *time_item)
+{
+ if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
+ return;
+
+ calendar_config_set_day_second_zone (g_object_get_data (G_OBJECT (item), "timezone"));
+}
+
+static void
+e_day_view_clutter_time_item_show_popup_menu (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event)
+{
+ static gint divisions[] = { 60, 30, 15, 10, 5 };
+ EDayView *day_view;
+ GtkWidget *menu, *item, *submenu;
+ gchar buffer[256];
+ GSList *group = NULL, *recent_zones, *s;
+ gint current_divisions, i;
+ icaltimezone *zone;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ current_divisions = e_day_view_get_mins_per_row (day_view);
+
+ menu = gtk_menu_new ();
+
+ /* Make sure the menu is destroyed when it disappears. */
+ g_signal_connect (
+ menu, "selection-done",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (divisions); i++) {
+ g_snprintf (buffer, sizeof (buffer),
+ /* TO TRANSLATORS: %02i is the number of minutes; this is a context menu entry
+ * to change the length of the time division in the calendar day view, e.g.
+ * a day is displayed in 24 "60 minute divisions" or 48 "30 minute divisions"
+ */
+ _("%02i minute divisions"), divisions[i]);
+ item = gtk_radio_menu_item_new_with_label (group, buffer);
+ group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ if (current_divisions == divisions[i])
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
+
+ g_object_set_data (G_OBJECT (item), "divisions",
+ GINT_TO_POINTER (divisions[i]));
+
+ g_signal_connect (item, "toggled",
+ G_CALLBACK (e_day_view_clutter_time_item_on_set_divisions), time_item);
+ }
+
+ item = gtk_separator_menu_item_new ();
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+
+ submenu = gtk_menu_new ();
+ item = gtk_menu_item_new_with_label (_("Show the second time zone"));
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+
+ zone = e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view));
+ if (zone)
+ item = gtk_menu_item_new_with_label (icaltimezone_get_display_name (zone));
+ else
+ item = gtk_menu_item_new_with_label ("---");
+ gtk_widget_set_sensitive (item, FALSE);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+
+ item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+
+ group = NULL;
+ item = gtk_radio_menu_item_new_with_label (group, C_("cal-second-zone", "None"));
+ group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+ if (!time_item->priv->second_zone)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+ g_signal_connect (item, "toggled", G_CALLBACK (edvti_on_set_zone), time_item);
+
+ recent_zones = calendar_config_get_day_second_zones ();
+ for (s = recent_zones; s != NULL; s = s->next) {
+ zone = icaltimezone_get_builtin_timezone (s->data);
+ if (!zone)
+ continue;
+
+ item = gtk_radio_menu_item_new_with_label (group, icaltimezone_get_display_name (zone));
+ group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
+ /* both comes from builtin, thus no problem to compare pointers */
+ if (zone == time_item->priv->second_zone)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+ g_object_set_data_full (G_OBJECT (item), "timezone", g_strdup (s->data), g_free);
+ g_signal_connect (item, "toggled", G_CALLBACK (edvti_on_set_zone), time_item);
+ }
+ calendar_config_free_day_second_zones (recent_zones);
+
+ item = gtk_separator_menu_item_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+
+ item = gtk_menu_item_new_with_label (_("Select..."));
+ g_signal_connect (item, "activate", G_CALLBACK (edvti_on_select_zone), time_item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item);
+
+ gtk_widget_show_all (submenu);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button.button, event->button.time);
+}
+
+static void
+e_day_view_clutter_time_item_on_set_divisions (GtkWidget *item,
+ EDayViewClutterTimeItem *time_item)
+{
+ EDayView *day_view;
+ gint divisions;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
+ return;
+
+ divisions = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "divisions"));
+ e_day_view_set_mins_per_row (day_view, divisions);
+ calendar_config_set_time_divisions (divisions);
+}
+
+static void
+e_day_view_clutter_time_item_on_button_press (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event)
+{
+ GdkWindow *window;
+ EDayView *day_view;
+ gint row;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ row = e_day_view_clutter_time_item_convert_position_to_row (time_item,
+ event->button.y);
+
+ if (row == -1)
+ return;
+
+ if (!gtk_widget_has_focus (GTK_WIDGET (day_view)))
+ gtk_widget_grab_focus (GTK_WIDGET (day_view));
+
+ window = gtk_layout_get_bin_window ((GtkLayout *)day_view->time_canvas);
+
+ /* FIXME: This pointer grab seems unnecessary */
+ if (1 || gdk_pointer_grab (window, FALSE,
+ GDK_POINTER_MOTION_MASK
+ | GDK_BUTTON_RELEASE_MASK,
+ NULL, NULL, event->button.time) == 0) {
+ e_day_view_start_selection (day_view, -1, row);
+ time_item->priv->dragging_selection = TRUE;
+ }
+}
+
+static void
+e_day_view_clutter_time_item_on_button_release (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event)
+{
+ EDayView *day_view;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ if (time_item->priv->dragging_selection) {
+ /* gdk_pointer_ungrab (event->button.time); */
+ e_day_view_finish_selection (day_view);
+ e_day_view_stop_auto_scroll (day_view);
+ }
+
+ time_item->priv->dragging_selection = FALSE;
+}
+
+static void
+e_day_view_clutter_time_item_on_motion_notify (EDayViewClutterTimeItem *time_item,
+ ClutterEvent *event)
+{
+ EDayView *day_view;
+ gint y, row;
+
+ if (!time_item->priv->dragging_selection)
+ return;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_if_fail (day_view != NULL);
+
+ y = (gint)event->motion.y;
+ row = e_day_view_clutter_time_item_convert_position_to_row (time_item, y);
+
+ if (row != -1) {
+ /* FIXME: Check if this works well */
+ e_day_view_update_selection (day_view, -1, row);
+ e_day_view_check_auto_scroll (day_view, -1, (gint) y);
+ }
+}
+
+/* Returns the row corresponding to the y position, or -1. */
+static gint
+e_day_view_clutter_time_item_convert_position_to_row (EDayViewClutterTimeItem *time_item,
+ gint y)
+{
+ EDayView *day_view;
+ gint row;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_val_if_fail (day_view != NULL, -1);
+
+ if (y < 0)
+ return -1;
+
+ row = y / day_view->row_height;
+ if (row >= day_view->rows)
+ return -1;
+
+ return row;
+}
+
+EDayView *
+e_day_view_clutter_time_item_get_day_view (EDayViewClutterTimeItem *time_item)
+{
+ g_return_val_if_fail (E_IS_DAY_VIEW_CLUTTER_TIME_ITEM (time_item), NULL);
+
+ return time_item->priv->day_view;
+}
+
+void
+e_day_view_clutter_time_item_set_day_view (EDayViewClutterTimeItem *time_item,
+ EDayView *day_view)
+{
+ g_return_if_fail (E_IS_DAY_VIEW_CLUTTER_TIME_ITEM (time_item));
+ g_return_if_fail (E_IS_DAY_VIEW (day_view));
+
+ if (time_item->priv->day_view != NULL)
+ g_object_unref (time_item->priv->day_view);
+
+ time_item->priv->day_view = g_object_ref (day_view);
+
+ g_object_notify (G_OBJECT (time_item), "day-view");
+}
+
+/* Returns the minimum width needed for the column, by adding up all the
+ maximum widths of the strings. The string widths are all calculated in
+ the style_set handlers of EDayView and EDayViewClutterTimeCanvas. */
+gint
+e_day_view_clutter_time_item_get_column_width (EDayViewClutterTimeItem *time_item)
+{
+ EDayView *day_view;
+ GtkStyle *style;
+ gint digit, large_digit_width, max_large_digit_width = 0;
+ gint max_suffix_width, max_minute_or_suffix_width;
+ gint column_width_default, column_width_60_min_rows;
+
+ day_view = e_day_view_clutter_time_item_get_day_view (time_item);
+ g_return_val_if_fail (day_view != NULL, 0);
+
+ style = gtk_widget_get_style (GTK_WIDGET (day_view));
+ g_return_val_if_fail (style != NULL, 0);
+
+ /* Find the maximum width a digit can have. FIXME: We could use pango's
+ * approximation function, but I worry it won't be precise enough. Also
+ * it needs a language tag that I don't know where to get. */
+ for (digit = '0'; digit <= '9'; digit++) {
+ PangoLayout *layout;
+ gchar digit_str [2];
+
+ digit_str [0] = digit;
+ digit_str [1] = '\0';
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (day_view), digit_str);
+ pango_layout_set_font_description (layout, day_view->large_font_desc);
+ pango_layout_get_pixel_size (layout, &large_digit_width, NULL);
+
+ g_object_unref (layout);
+
+ max_large_digit_width = MAX (max_large_digit_width,
+ large_digit_width);
+ }
+
+ /* Calculate the width of each time column, using the maximum of the
+ default format with large hour numbers, and the 60-min divisions
+ format which uses small text. */
+ max_suffix_width = MAX (day_view->am_string_width,
+ day_view->pm_string_width);
+
+ max_minute_or_suffix_width = MAX (max_suffix_width,
+ day_view->max_minute_width);
+
+ column_width_default = max_large_digit_width * 2
+ + max_minute_or_suffix_width
+ + E_DVTMI_MIN_X_PAD * 2
+ + E_DVTMI_HOUR_L_PAD
+ + E_DVTMI_HOUR_R_PAD
+ + E_DVTMI_TIME_GRID_X_PAD * 2;
+
+ column_width_60_min_rows = day_view->max_small_hour_width
+ + day_view->colon_width
+ + max_minute_or_suffix_width
+ + E_DVTMI_60_MIN_X_PAD * 2
+ + E_DVTMI_TIME_GRID_X_PAD * 2;
+
+ time_item->priv->column_width =
+ MAX (column_width_default, column_width_60_min_rows);
+
+ if (time_item->priv->second_zone)
+ return (2 * time_item->priv->column_width) -
+ E_DVTMI_TIME_GRID_X_PAD;
+
+ return time_item->priv->column_width;
+}
+
+icaltimezone *
+e_day_view_clutter_time_item_get_second_zone (EDayViewClutterTimeItem *time_item)
+{
+ g_return_val_if_fail (E_IS_DAY_VIEW_CLUTTER_TIME_ITEM (time_item), NULL);
+
+ return time_item->priv->second_zone;
+}
+
+EDayViewClutterTimeItem *
+e_day_view_clutter_time_item_new (EDayView *day_view, gint width, gint height)
+{
+ EDayViewClutterTimeItem *item;
+
+ item = g_object_new (
+ E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM,
+ "EDayViewClutterTimeItem::day_view", day_view,
+ "surface-width", 50,
+ "surface-height", 300,
+ NULL);
+
+ e_day_view_clutter_time_item_draw ((ClutterActor *)item);
+
+ return item;
+}
+
+void
+e_day_view_clutter_time_item_set_size (EDayViewClutterTimeItem *item, int width, int height)
+{
+ clutter_cairo_texture_set_surface_size ((ClutterCairoTexture *)item, width, height);
+ e_day_view_clutter_time_item_redraw (item);
+}
+
diff --git a/calendar/gui/e-day-view-clutter-time-item.h b/calendar/gui/e-day-view-clutter-time-item.h
new file mode 100644
index 0000000..c246c44
--- /dev/null
+++ b/calendar/gui/e-day-view-clutter-time-item.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_DAY_VIEW_CLUTTER_TIME_ITEM_H
+#define E_DAY_VIEW_CLUTTER_TIME_ITEM_H
+
+#include "e-day-view.h"
+
+/* Standard GObject macros */
+#define E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM \
+ (e_day_view_clutter_time_item_get_type ())
+#define E_DAY_VIEW_CLUTTER_TIME_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM, EDayViewClutterTimeItem))
+#define E_DAY_VIEW_CLUTTER_TIME_ITEM_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM, EDayViewClutterTimeItemClass))
+#define E_IS_DAY_VIEW_CLUTTER_TIME_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM))
+#define E_IS_DAY_VIEW_CLUTTER_TIME_ITEM_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM))
+#define E_DAY_VIEW_CLUTTER_TIME_ITEM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM, EDayViewClutterTimeItemClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EDayViewClutterTimeItem EDayViewClutterTimeItem;
+typedef struct _EDayViewClutterTimeItemClass EDayViewClutterTimeItemClass;
+typedef struct _EDayViewClutterTimeItemPrivate EDayViewClutterTimeItemPrivate;
+
+struct _EDayViewClutterTimeItem {
+ ClutterCairoTexture parent;
+ EDayViewClutterTimeItemPrivate *priv;
+ ClutterActor *stage;
+};
+
+struct _EDayViewClutterTimeItemClass {
+ ClutterCairoTextureClass parent_class;
+};
+
+GType e_day_view_clutter_time_item_get_type (void);
+EDayView * e_day_view_clutter_time_item_get_day_view
+ (EDayViewClutterTimeItem *time_item);
+void e_day_view_clutter_time_item_set_day_view
+ (EDayViewClutterTimeItem *time_item,
+ EDayView *day_view);
+gint e_day_view_clutter_time_item_get_column_width
+ (EDayViewClutterTimeItem *time_item);
+icaltimezone * e_day_view_clutter_time_item_get_second_zone
+ (EDayViewClutterTimeItem *time_item);
+void e_day_view_clutter_time_item_redraw
+ (EDayViewClutterTimeItem *item);
+void e_day_view_clutter_time_item_update
+ (EDayViewClutterTimeItem *item);
+EDayViewClutterTimeItem *
+ e_day_view_clutter_time_item_new(EDayView *day_view,
+ gint width,
+ gint height);
+void e_day_view_clutter_time_item_set_size
+ (EDayViewClutterTimeItem *item,
+ int width,
+ int height);
+
+
+G_END_DECLS
+
+#endif /* E_DAY_VIEW_CLUTTER_TIME_ITEM_H */
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 95bd14b..cea0100 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -55,6 +55,9 @@
#include "calendar-config.h"
#include "goto.h"
#include "e-cal-model-calendar.h"
+#if HAVE_CLUTTER
+#include "e-day-view-clutter-time-item.h"
+#endif
#include "e-day-view-time-item.h"
#include "e-day-view-top-item.h"
#include "e-day-view-layout.h"
@@ -97,6 +100,7 @@
caption item and DnD space */
#define E_DAY_VIEW_MAX_ROWS_AT_TOP 6
+#define WITHOUT_CLUTTER (g_getenv("WITHOUT_CLUTTER") != NULL)
typedef struct {
EDayView *day_view;
ECalModelComponent *comp_data;
@@ -780,9 +784,19 @@ time_range_changed_cb (ECalModel *model, time_t start_time, time_t end_time, gpo
e_day_view_ensure_rows_visible (day_view, day_view->selection_start_row, day_view->selection_start_row);
/* update the time canvas to show proper date in it */
+#if HAVE_CLUTTER
+ if (WITHOUT_CLUTTER) {
+#endif
eti = E_DAY_VIEW_TIME_ITEM (day_view->time_canvas_item);
if (eti && e_day_view_time_item_get_second_zone (eti))
gtk_widget_queue_draw (day_view->time_canvas);
+#if HAVE_CLUTTER
+ } else {
+
+ if (day_view->time_canvas_actor && e_day_view_clutter_time_item_get_second_zone (day_view->time_canvas_actor))
+ e_day_view_clutter_time_item_redraw (day_view->time_canvas_actor);
+ }
+#endif
}
static void
@@ -979,6 +993,25 @@ timezone_changed_cb (ECalModel *cal_model, icaltimezone *old_zone,
e_day_view_update_query (day_view);
}
+static void
+time_canvas_set_canvas_size (GtkWidget *widget,
+ GtkAllocation *allocation,
+ EDayView *day_view)
+{
+ ClutterActor *stage = day_view->time_canvas_stage;
+ GtkWidget *embed = day_view->time_canvas_embed;
+ guint w,h;
+
+ gtk_layout_get_size ((GtkLayout *)day_view->main_canvas, &w, &h);
+
+ gtk_widget_set_size_request (embed, allocation->width, h);
+ gtk_layout_set_size ((GtkLayout *)widget, allocation->width, h);
+
+ clutter_actor_set_size (stage, allocation->width, h);
+ clutter_actor_set_size ((ClutterActor *)day_view->time_canvas_actor, allocation->width, h);
+ e_day_view_clutter_time_item_set_size ((EDayViewClutterTimeItem *)day_view->time_canvas_actor, allocation->width, h);
+}
+
static void
e_day_view_init (EDayView *day_view)
{
@@ -1243,11 +1276,26 @@ e_day_view_init (EDayView *day_view)
/*
* Times Canvas
*/
+#if HAVE_CLUTTER
+ if (WITHOUT_CLUTTER) {
+#endif
day_view->time_canvas = e_canvas_new ();
layout = GTK_LAYOUT (day_view->main_canvas);
adjustment = gtk_layout_get_vadjustment (layout);
layout = GTK_LAYOUT (day_view->time_canvas);
gtk_layout_set_vadjustment (layout, adjustment);
+#if HAVE_CLUTTER
+ } else {
+ layout = GTK_LAYOUT (day_view->main_canvas);
+ adjustment = gtk_layout_get_vadjustment (layout);
+ day_view->time_canvas = gtk_layout_new (NULL, adjustment);
+ day_view->time_canvas_embed = gtk_clutter_embed_new ();
+ gtk_widget_show (day_view->time_canvas_embed);
+ gtk_container_add ((GtkContainer *)day_view->time_canvas, day_view->time_canvas_embed);
+ day_view->time_canvas_stage = gtk_clutter_embed_get_stage ((GtkClutterEmbed *) day_view->time_canvas_embed);
+ g_signal_connect (day_view->time_canvas, "size-allocate", G_CALLBACK(time_canvas_set_canvas_size), day_view);
+ }
+#endif
gtk_table_attach (GTK_TABLE (day_view), day_view->time_canvas,
0, 1, 1, 2,
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -1255,14 +1303,29 @@ e_day_view_init (EDayView *day_view)
g_signal_connect_after (day_view->time_canvas, "scroll_event",
G_CALLBACK (e_day_view_on_time_canvas_scroll), day_view);
+#if HAVE_CLUTTER
+ if (WITHOUT_CLUTTER) {
+#endif
canvas_group = GNOME_CANVAS_GROUP (GNOME_CANVAS (day_view->time_canvas)->root);
-
day_view->time_canvas_item =
gnome_canvas_item_new (canvas_group,
e_day_view_time_item_get_type (),
"EDayViewTimeItem::day_view", day_view,
NULL);
-
+#if HAVE_CLUTTER
+ } else {
+ day_view->time_canvas_actor = g_object_new (
+ E_TYPE_DAY_VIEW_CLUTTER_TIME_ITEM,
+ "EDayViewClutterTimeItem::day_view", day_view,
+ "surface-width", 64,
+ "surface-height", 600,
+ NULL);
+ clutter_actor_set_reactive ((ClutterActor *)day_view->time_canvas_actor, TRUE);
+ ((EDayViewClutterTimeItem *)day_view->time_canvas_actor)->stage = day_view->time_canvas_stage;
+ clutter_container_add_actor ((ClutterContainer *)day_view->time_canvas_stage, (ClutterActor *)day_view->time_canvas_actor);
+ clutter_actor_show ((ClutterActor *)day_view->time_canvas_actor);
+ }
+#endif
/*
* Scrollbar.
*/
@@ -1764,7 +1827,15 @@ e_day_view_style_set (GtkWidget *widget,
pango_layout_get_pixel_size (layout, &day_view->pm_string_width, NULL);
/* Calculate the width of the time column. */
+#if HAVE_CLUTTER
+ if(WITHOUT_CLUTTER) {
+#endif
times_width = e_day_view_time_item_get_column_width (E_DAY_VIEW_TIME_ITEM (day_view->time_canvas_item));
+#if HAVE_CLUTTER
+ } else {
+ times_width = e_day_view_clutter_time_item_get_column_width (E_DAY_VIEW_CLUTTER_TIME_ITEM (day_view->time_canvas_actor));
+ }
+#endif
gtk_widget_set_size_request (day_view->time_canvas, times_width, -1);
g_object_unref (layout);
@@ -2751,10 +2822,32 @@ e_day_view_set_mins_per_row (EDayView *day_view,
/* We must layout the events before updating the scroll region, since
that will result in a redraw which would crash otherwise. */
e_day_view_check_layout (day_view);
- gtk_widget_queue_draw (day_view->time_canvas);
+
gtk_widget_queue_draw (day_view->main_canvas);
e_day_view_update_scroll_regions (day_view);
+#if HAVE_CLUTTER
+ if (WITHOUT_CLUTTER) {
+#endif
+ gtk_widget_queue_draw (day_view->time_canvas);
+#if HAVE_CLUTTER
+ } else {
+ ClutterActor *stage = day_view->time_canvas_stage;
+ GtkWidget *embed = day_view->time_canvas_embed;
+ guint w,h;
+ guint cw, ch;
+
+ gtk_layout_get_size ((GtkLayout *)day_view->main_canvas, &w, &h);
+ gtk_layout_get_size ((GtkLayout *)day_view->time_canvas, &cw, &ch);
+
+ gtk_widget_set_size_request (embed, cw, h);
+ gtk_layout_set_size ((GtkLayout *)day_view->time_canvas, cw, h);
+
+ clutter_actor_set_size (stage, cw, h);
+ clutter_actor_set_size ((ClutterActor *)day_view->time_canvas_actor, cw, h);
+ e_day_view_clutter_time_item_set_size ((EDayViewClutterTimeItem *)day_view->time_canvas_actor, cw, h);
+ }
+#endif
}
/* This specifies the working days in the week. The value is a bitwise
@@ -2920,7 +3013,15 @@ e_day_view_marcus_bains_update (EDayView *day_view)
{
g_return_if_fail (E_IS_DAY_VIEW (day_view));
gtk_widget_queue_draw (day_view->main_canvas);
+#if HAVE_CLUTTER
+ if (WITHOUT_CLUTTER) {
+#endif
gtk_widget_queue_draw (day_view->time_canvas);
+#if HAVE_CLUTTER
+ } else {
+ e_day_view_clutter_time_item_update (day_view->time_canvas_actor);
+ }
+#endif
}
gboolean
diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h
index aee8be0..dc9fc3a 100644
--- a/calendar/gui/e-day-view.h
+++ b/calendar/gui/e-day-view.h
@@ -31,6 +31,12 @@
#include "e-calendar-view.h"
#include "gnome-cal.h"
+#if HAVE_CLUTTER
+#include <clutter/clutter.h>
+#include <mx/mx.h>
+#include <clutter-gtk/clutter-gtk.h>
+#endif
+
G_BEGIN_DECLS
/*
@@ -215,7 +221,9 @@ struct _EDayView {
/* The top canvas where the dates and long appointments are shown. */
GtkWidget *top_canvas;
GnomeCanvasItem *top_canvas_item;
-
+#if HAVE_CLUTTER
+ ClutterActor *top_canvas_actor;
+#endif
/* scrollbar for top_canvas */
GtkWidget *tc_vscrollbar;
@@ -225,10 +233,19 @@ struct _EDayView {
/* The main canvas where the rest of the appointments are shown. */
GtkWidget *main_canvas;
GnomeCanvasItem *main_canvas_item;
-
+#if HAVE_CLUTTER
+ ClutterActor *main_canvas_actor;
+ GtkWidget *main_canvas_embed;
+ ClutterActor *main_canvas_stage;
+#endif
/* The canvas displaying the times of the day. */
GtkWidget *time_canvas;
GnomeCanvasItem *time_canvas_item;
+#if HAVE_CLUTTER
+ GtkWidget *time_canvas_embed;
+ ClutterActor *time_canvas_stage;
+ ClutterActor *time_canvas_actor;
+#endif
GtkWidget *vscrollbar;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]