[evolution/calendar-xfb: 5/5] EMeetingTimeSelector: added XFB tooltip to the freebusy canvas



commit 99631b3c9e9d799b9c6d58dbbebc0e32a9e82ef8
Author: Christian Hilberg <chilberg src gnome org>
Date:   Fri Nov 9 11:10:07 2012 +0100

    EMeetingTimeSelector: added XFB tooltip to the freebusy canvas
    
    * the busy periods in the scheduling page of the meeting
      time selector are no individual GtkWidgets, so we add
      the tooltip to the canvas they're painted into and let
      the tooltip callback function decide whether or not to
      show a tooltip (only shown if the busy period we're
      hovering over actually carries XFB information)
    * there is intentionally no formatting or (translatable)
      string additions nor styling involved to restrict the tooltip
      to the absolute minimum, in order not to be confusing
      or overloaded

 calendar/gui/e-meeting-time-sel.c |  143 +++++++++++++++++++++++++++++++++++++
 1 files changed, 143 insertions(+), 0 deletions(-)
---
diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c
index eb7a1fc..7506fa1 100644
--- a/calendar/gui/e-meeting-time-sel.c
+++ b/calendar/gui/e-meeting-time-sel.c
@@ -196,6 +196,12 @@ static void e_meeting_time_selector_update_end_date_edit (EMeetingTimeSelector *
 static void e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelector *mts);
 static void e_meeting_time_selector_update_dates_shown (EMeetingTimeSelector *mts);
 static gboolean e_meeting_time_selector_on_canvas_scroll_event (GtkWidget *widget, GdkEventScroll *event, EMeetingTimeSelector *mts);
+static gboolean e_meeting_time_selector_on_canvas_query_tooltip (GtkWidget *widget,
+                                                                 gint x,
+                                                                 gint y,
+                                                                 gboolean keyboard_mode,
+                                                                 GtkTooltip *tooltip,
+                                                                 gpointer user_data);
 
 static void row_inserted_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
 static void row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
@@ -517,6 +523,15 @@ e_meeting_time_selector_construct (EMeetingTimeSelector *mts,
 	g_signal_connect (
 		mts->display_main, "scroll-event",
 		G_CALLBACK (e_meeting_time_selector_on_canvas_scroll_event), mts);
+	/* used for displaying extended free/busy (XFB) display when hovering
+	 * over a busy period which carries XFB information */
+	g_signal_connect (mts->display_main,
+	                  "query-tooltip",
+	                  G_CALLBACK (e_meeting_time_selector_on_canvas_query_tooltip),
+	                  mts);
+	g_object_set (G_OBJECT (mts->display_main),
+	              "has-tooltip", TRUE,
+	              NULL);
 
 	scrollable = GTK_SCROLLABLE (mts->display_main);
 
@@ -2607,6 +2622,134 @@ e_meeting_time_selector_on_canvas_scroll_event (GtkWidget *widget,
 	return return_val;
 }
 
+/* Sets a tooltip for the busy periods canvas. If the mouse pointer
+ * hovers over a busy period for which extended free/busy (XFB) data
+ * could be extracted from the vfreebusy calendar object, the tooltip
+ * will be shown (currently displays the summary and the location of
+ * for the busy period, if available). See EMeetingXfbData for a reference.
+ *
+ */
+static gboolean
+e_meeting_time_selector_on_canvas_query_tooltip (GtkWidget *widget,
+                                                 gint x,
+                                                 gint y,
+                                                 gboolean keyboard_mode,
+                                                 GtkTooltip *tooltip,
+                                                 gpointer user_data)
+{
+	EMeetingTimeSelector *mts = NULL;
+	EMeetingAttendee *attendee = NULL;
+	EMeetingFreeBusyPeriod *period = NULL;
+	EMeetingXfbData *xfb = NULL;
+	GtkScrollable *scrollable = NULL;
+	GtkAdjustment *adjustment = NULL;
+	const GArray *periods = NULL;
+	gint scroll_x = 0;
+	gint scroll_y = 0;
+	gint mouse_x = 0;
+	gint row = 0;
+	gint first_idx = 0;
+	gint ii = 0;
+	gchar *tt_text = NULL;
+	gchar *summary = NULL;
+	gchar *location = NULL;
+	
+	g_return_val_if_fail (GNOME_IS_CANVAS (widget), FALSE);
+	g_return_val_if_fail (GTK_IS_TOOLTIP (tooltip), FALSE);
+	g_return_val_if_fail (E_IS_MEETING_TIME_SELECTOR (user_data), FALSE);
+
+	mts = E_MEETING_TIME_SELECTOR (user_data);
+	
+	scrollable = GTK_SCROLLABLE (widget);
+	adjustment = gtk_scrollable_get_hadjustment (scrollable);
+	scroll_x = (gint) gtk_adjustment_get_value (adjustment);
+	adjustment = gtk_scrollable_get_vadjustment (scrollable);
+	scroll_y = (gint) gtk_adjustment_get_value (adjustment);
+	
+	/* calculate the attendee index (row) we're at */
+	row = (scroll_y + y) / mts->row_height;
+
+	/* no tooltip if we have no attendee in the row */
+	if (row > e_meeting_store_count_actual_attendees (mts->model) - 1)
+		return FALSE;
+
+	/* no tooltip if attendee has no calendar info */
+	attendee = e_meeting_store_find_attendee_at_row (mts->model, row);
+	g_return_val_if_fail (E_IS_MEETING_ATTENDEE (attendee), FALSE);
+	if (! e_meeting_attendee_get_has_calendar_info (attendee))
+		return FALSE;
+
+	/* get the attendee's busy times array */
+	periods = e_meeting_attendee_get_busy_periods (attendee);
+	g_return_val_if_fail (periods != NULL, FALSE);
+	g_return_val_if_fail (periods->len > 0, FALSE);
+
+	/* no tooltip if no busy period reaches into the current canvas area */
+	first_idx = e_meeting_attendee_find_first_busy_period (attendee,
+	                                                       &(mts->first_date_shown));
+	if (first_idx < 0)
+		return FALSE;
+
+	/* calculate the mouse tip x position in the canvas area */
+	mouse_x = x + scroll_x;
+
+	/* find out whether mouse_x lies inside a busy
+	 * period (we start with the index of the first
+	 * one reaching into the current canvas area)
+	 */
+	for (ii = first_idx; ii < periods->len; ii++) {
+		EMeetingFreeBusyPeriod *p = NULL;
+		gint sx = 0;
+		gint ex = 0;
+		
+		p = &(g_array_index (periods,
+		                     EMeetingFreeBusyPeriod,
+		                     ii));
+		/* meeting start time x position */
+		sx = e_meeting_time_selector_calculate_time_position (mts,
+		                                                      &(p->start));
+		/* meeting end time x position */
+		ex = e_meeting_time_selector_calculate_time_position (mts,
+		                                                      &(p->end));
+		if ((mouse_x >= sx) && (mouse_x <= ex)) {
+			/* found busy period the mouse tip is over */
+			period = p;
+			break;
+		}
+	}
+
+	/* no tooltip if we did not find a busy period under
+	 * the mouse pointer
+	 */
+	if (period == NULL)
+		return FALSE;
+
+	/* get the extended free/busy data
+	 * (no tooltip if none available)
+	 */
+	xfb = &(period->xfb);
+	if ((xfb->summary == NULL) && (xfb->location == NULL))
+		return FALSE;
+
+	/* Create the tooltip text. The data sent by the server will
+	 * have been validated for UTF-8 conformance (and possibly
+	 * forced into) as well as length-limited by a call to the
+	 * e_meeting_xfb_utf8_string_new_from_ical() function in
+	 * process_free_busy_comp_get_xfb() (e-meeting-store.c)
+	 */
+	summary = (xfb->summary == NULL) ? g_strdup ("") : g_strdup (xfb->summary);
+	location = (xfb->location == NULL) ? g_strdup ("") : g_strdup (xfb->location);
+	tt_text = g_strdup_printf ("%s\n\n%s", summary, location);
+	g_free (summary);
+	g_free (location);
+
+	/* set XFB information as tooltip text */
+	gtk_tooltip_set_text (tooltip, tt_text);
+	g_free (tt_text);
+	
+	return TRUE;
+}
+
 /* This updates the canvas scroll regions according to the number of attendees.
  * If the total height needed is less than the height of the canvas, we must
  * use the height of the canvas, or it causes problems. */



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