evolution-3.6.4/calendar/gui/ea-cal-view.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Bolian Yin <bolian.yin@sun.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include "ea-cal-view.h"
 28 #include "ea-calendar-helpers.h"
 29 #include "e-day-view.h"
 30 #include "e-week-view.h"
 31 #include "dialogs/goto-dialog.h"
 32 #include <glib/gi18n.h>
 33 
 34 static void ea_cal_view_class_init (EaCalViewClass *klass);
 35 
 36 static AtkObject * ea_cal_view_get_parent (AtkObject *accessible);
 37 static void ea_cal_view_real_initialize (AtkObject *accessible, gpointer data);
 38 
 39 static void ea_cal_view_event_changed_cb (ECalendarView *cal_view,
 40                                           ECalendarViewEvent *event,
 41                                           gpointer data);
 42 static void ea_cal_view_event_added_cb (ECalendarView *cal_view,
 43                                         ECalendarViewEvent *event,
 44                                         gpointer data);
 45 
 46 static gboolean idle_dates_changed (gpointer data);
 47 static void ea_cal_view_dates_change_cb (GnomeCalendar *gcal, gpointer data);
 48 
 49 static void atk_action_interface_init (AtkActionIface *iface);
 50 static gboolean action_interface_do_action (AtkAction *action, gint i);
 51 static gint action_interface_get_n_actions (AtkAction *action);
 52 static const gchar *
 53 		action_interface_get_description
 54 						(AtkAction *action,
 55 						 gint i);
 56 static const gchar *
 57 		action_interface_get_keybinding
 58 						(AtkAction *action,
 59 						 gint i);
 60 static const gchar *
 61 		action_interface_action_get_name
 62 						(AtkAction *action,
 63 						 gint i);
 64 
 65 static gpointer parent_class = NULL;
 66 
 67 GType
 68 ea_cal_view_get_type (void)
 69 {
 70 	static GType type = 0;
 71 	AtkObjectFactory *factory;
 72 	GTypeQuery query;
 73 	GType derived_atk_type;
 74 
 75 	if (!type) {
 76 		static GTypeInfo tinfo = {
 77 			sizeof (EaCalViewClass),
 78 			(GBaseInitFunc) NULL, /* base init */
 79 			(GBaseFinalizeFunc) NULL, /* base finalize */
 80 			(GClassInitFunc) ea_cal_view_class_init, /* class init */
 81 			(GClassFinalizeFunc) NULL, /* class finalize */
 82 			NULL, /* class data */
 83 			sizeof (EaCalView), /* instance size */
 84 			0, /* nb preallocs */
 85 			(GInstanceInitFunc) NULL, /* instance init */
 86 			NULL /* value table */
 87 		};
 88 
 89 		static const GInterfaceInfo atk_action_info = {
 90 			(GInterfaceInitFunc) atk_action_interface_init,
 91 			(GInterfaceFinalizeFunc) NULL,
 92 			NULL
 93 		};
 94 
 95 		/*
 96 		 * Figure out the size of the class and instance
 97 		 * we are run-time deriving from (GailWidget, in this case)
 98 		 */
 99 
100 		factory = atk_registry_get_factory (
101 			atk_get_default_registry (),
102 			GTK_TYPE_WIDGET);
103 		derived_atk_type = atk_object_factory_get_accessible_type (factory);
104 		g_type_query (derived_atk_type, &query);
105 
106 		tinfo.class_size = query.class_size;
107 		tinfo.instance_size = query.instance_size;
108 
109 		type = g_type_register_static (
110 			derived_atk_type,
111 			"EaCalView", &tinfo, 0);
112 		g_type_add_interface_static (
113 			type, ATK_TYPE_ACTION,
114 			&atk_action_info);
115 	}
116 
117 	return type;
118 }
119 
120 static void
121 ea_cal_view_class_init (EaCalViewClass *klass)
122 {
123 	AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
124 
125 	parent_class = g_type_class_peek_parent (klass);
126 
127 	class->get_parent = ea_cal_view_get_parent;
128 	class->initialize = ea_cal_view_real_initialize;
129 }
130 
131 AtkObject *
132 ea_cal_view_new (GtkWidget *widget)
133 {
134 	GObject *object;
135 	AtkObject *accessible;
136 
137 	g_return_val_if_fail (E_IS_CALENDAR_VIEW (widget), NULL);
138 
139 	object = g_object_new (EA_TYPE_CAL_VIEW, NULL);
140 
141 	accessible = ATK_OBJECT (object);
142 	atk_object_initialize (accessible, widget);
143 
144 	return accessible;
145 }
146 
147 static void
148 ea_cal_view_real_initialize (AtkObject *accessible,
149                              gpointer data)
150 {
151 	ECalendarView *cal_view;
152 	GnomeCalendar *gcal;
153 	static AtkRole role = ATK_ROLE_INVALID;
154 
155 	g_return_if_fail (EA_IS_CAL_VIEW (accessible));
156 	g_return_if_fail (E_IS_CALENDAR_VIEW (data));
157 
158 	ATK_OBJECT_CLASS (parent_class)->initialize (accessible, data);
159 	if (role == ATK_ROLE_INVALID)
160 		role = atk_role_register ("Calendar View");
161 	accessible->role = role;
162 	cal_view = E_CALENDAR_VIEW (data);
163 
164 	/* add listener for event_changed, event_added
165 	 * we don't need to listen on event_removed. When the e_text
166 	 * of the event is removed, the cal_view_event will go to the state
167 	 * of "defunct" (changed by weak ref callback of atkgobjectaccessible
168 	 */
169 	g_signal_connect (
170 		cal_view, "event_changed",
171 		G_CALLBACK (ea_cal_view_event_changed_cb), NULL);
172 	g_signal_connect (
173 		cal_view, "event_added",
174 		G_CALLBACK (ea_cal_view_event_added_cb), NULL);
175 
176 	/* listen for date changes of calendar */
177 	gcal = e_calendar_view_get_calendar (cal_view);
178 
179 	if (gcal)
180 		g_signal_connect (
181 			gcal, "dates_shown_changed",
182 			G_CALLBACK (ea_cal_view_dates_change_cb), accessible);
183 }
184 
185 static AtkObject *
186 ea_cal_view_get_parent (AtkObject *accessible)
187 {
188 	ECalendarView *cal_view;
189 	GtkWidget *widget;
190 
191 	g_return_val_if_fail (EA_IS_CAL_VIEW (accessible), NULL);
192 
193 	widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
194 	if (widget == NULL)
195 		return NULL;
196 
197 	cal_view = E_CALENDAR_VIEW (widget);
198 
199 	return gtk_widget_get_accessible (gtk_widget_get_parent (GTK_WIDGET (cal_view)));
200 }
201 
202 static void
203 ea_cal_view_event_changed_cb (ECalendarView *cal_view,
204                               ECalendarViewEvent *event,
205                               gpointer data)
206 {
207 	AtkObject *atk_obj;
208 	AtkObject *event_atk_obj = NULL;
209 
210 	g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view));
211 
212 	atk_obj = gtk_widget_get_accessible (GTK_WIDGET (cal_view));
213 	if (!EA_IS_CAL_VIEW (atk_obj))
214 		return;
215 
216 	if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) {
217 		event_atk_obj =
218 			ea_calendar_helpers_get_accessible_for (event->canvas_item);
219 	}
220 	else if ((E_IS_WEEK_VIEW (cal_view)) && event) {
221 		EWeekViewEventSpan *span;
222 		EWeekViewEvent *week_view_event = (EWeekViewEvent *) event;
223 		EWeekView *week_view = E_WEEK_VIEW (cal_view);
224 		/* get the first span of the event */
225 		span = &g_array_index (week_view->spans, EWeekViewEventSpan,
226 				       week_view_event->spans_index);
227 		if (span && span->text_item)
228 			event_atk_obj =
229 				ea_calendar_helpers_get_accessible_for (
230 				span->text_item);
231 	}
232 	if (event_atk_obj) {
233 #ifdef ACC_DEBUG
234 		printf ("AccDebug: event=%p changed\n", (gpointer) event);
235 #endif
236 		g_object_notify (G_OBJECT (event_atk_obj), "accessible-name");
237 		g_signal_emit_by_name (event_atk_obj, "visible_data_changed");
238 	}
239 
240 }
241 
242 static void
243 ea_cal_view_event_added_cb (ECalendarView *cal_view,
244                             ECalendarViewEvent *event,
245                             gpointer data)
246 {
247 	AtkObject *atk_obj;
248 	AtkObject *event_atk_obj = NULL;
249 	gint index;
250 
251 	g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view));
252 
253 	atk_obj = gtk_widget_get_accessible (GTK_WIDGET (cal_view));
254 	if (!EA_IS_CAL_VIEW (atk_obj))
255 		return;
256 
257 	if ((E_IS_DAY_VIEW (cal_view)) && event && event->canvas_item) {
258 		event_atk_obj =
259 			ea_calendar_helpers_get_accessible_for (event->canvas_item);
260 	}
261 	else if ((E_IS_WEEK_VIEW (cal_view)) && event) {
262 		EWeekViewEventSpan *span;
263 		EWeekViewEvent *week_view_event = (EWeekViewEvent *) event;
264 		EWeekView *week_view = E_WEEK_VIEW (cal_view);
265 		/* get the first span of the event */
266 		span = &g_array_index (
267 			week_view->spans, EWeekViewEventSpan,
268 			week_view_event->spans_index);
269 		if (span && span->text_item)
270 			event_atk_obj =
271 				ea_calendar_helpers_get_accessible_for (
272 				span->text_item);
273 
274 	}
275 	if (event_atk_obj) {
276 		index = atk_object_get_index_in_parent (event_atk_obj);
277 		if (index < 0)
278 			return;
279 #ifdef ACC_DEBUG
280 		printf ("AccDebug: event=%p added\n", (gpointer) event);
281 #endif
282 		g_signal_emit_by_name (
283 			atk_obj, "children_changed::add",
284 			index, event_atk_obj, NULL);
285 	}
286 }
287 
288 static gboolean
289 idle_dates_changed (gpointer data)
290 {
291 	AtkObject *ea_cal_view;
292 
293 	g_return_val_if_fail (data, FALSE);
294 	g_return_val_if_fail (EA_IS_CAL_VIEW (data), FALSE);
295 
296 	ea_cal_view = ATK_OBJECT (data);
297 
298 	if (ea_cal_view->name) {
299 		g_free (ea_cal_view->name);
300 		ea_cal_view->name = NULL;
301 	}
302 	g_object_notify (G_OBJECT (ea_cal_view), "accessible-name");
303 	g_signal_emit_by_name (ea_cal_view, "visible_data_changed");
304 	g_signal_emit_by_name (ea_cal_view, "children_changed", NULL, NULL, NULL);
305 #ifdef ACC_DEBUG
306 	printf ("AccDebug: cal view date changed\n");
307 #endif
308 
309 	return FALSE;
310 }
311 
312 static void
313 ea_cal_view_dates_change_cb (GnomeCalendar *gcal,
314                              gpointer data)
315 {
316 	g_idle_add (idle_dates_changed, data);
317 }
318 
319 /* atk action interface */
320 
321 #define CAL_VIEW_ACTION_NUM 5
322 
323 static const gchar * action_name[CAL_VIEW_ACTION_NUM] = {
324 	N_("New Appointment"),
325 	N_("New All Day Event"),
326 	N_("New Meeting"),
327 	N_("Go to Today"),
328 	N_("Go to Date")
329 };
330 
331 static void
332 atk_action_interface_init (AtkActionIface *iface)
333 {
334 	g_return_if_fail (iface != NULL);
335 
336 	iface->do_action = action_interface_do_action;
337 	iface->get_n_actions = action_interface_get_n_actions;
338 	iface->get_description = action_interface_get_description;
339 	iface->get_keybinding = action_interface_get_keybinding;
340 	iface->get_name = action_interface_action_get_name;
341 }
342 
343 static gboolean
344 action_interface_do_action (AtkAction *action,
345                             gint index)
346 {
347 	GtkWidget *widget;
348 	gboolean return_value = TRUE;
349 	time_t dtstart, dtend;
350 	ECalendarView *cal_view;
351 
352 	widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
353 	if (widget == NULL)
354 		/*
355 		 * State is defunct
356 		 */
357 		return FALSE;
358 
359 	if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
360 		return FALSE;
361 
362 	cal_view = E_CALENDAR_VIEW (widget);
363 	 switch (index) {
364 	 case 0:
365 		 /* New Appointment */
366 		 e_calendar_view_new_appointment (cal_view);
367 		 break;
368 	 case 1:
369 		 /* New All Day Event */
370 		 e_calendar_view_get_selected_time_range (cal_view,
371 						     &dtstart, &dtend);
372 		 e_calendar_view_new_appointment_for (cal_view,
373 						 dtstart, dtend, TRUE, FALSE);
374 		 break;
375 	 case 2:
376 		 /* New Meeting */
377 		 e_calendar_view_get_selected_time_range (cal_view,
378 						     &dtstart, &dtend);
379 		 e_calendar_view_new_appointment_for (cal_view,
380 						 dtstart, dtend, FALSE, TRUE);
381 		 break;
382 #if 0  /* FIXME Have to go through GnomeCalendar */
383 	 case 3:
384 		 /* Go to today */
385 		 break;
386 		 calendar_goto_today (e_calendar_view_get_calendar (cal_view));
387 	 case 4:
388 		 /* Go to date */
389 		 goto_dialog (e_calendar_view_get_calendar (cal_view));
390 		 break;
391 #endif
392 	 default:
393 		 return_value = FALSE;
394 		 break;
395 	 }
396 	 return return_value;
397 }
398 
399 static gint
400 action_interface_get_n_actions (AtkAction *action)
401 {
402 	return CAL_VIEW_ACTION_NUM;
403 }
404 
405 static const gchar *
406 action_interface_get_description (AtkAction *action,
407                                   gint index)
408 {
409 	return action_interface_action_get_name (action, index);
410 }
411 
412 static const gchar *
413 action_interface_get_keybinding (AtkAction *action,
414                                  gint index)
415 {
416 	GtkWidget *widget;
417 
418 	widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
419 	if (widget == NULL)
420 		/*
421 		 * State is defunct
422 		 */
423 		return NULL;
424 
425 	if (!gtk_widget_get_sensitive (widget) || !gtk_widget_get_visible (widget))
426 		return NULL;
427 
428 	 switch (index) {
429 	 case 0:
430 		 /* New Appointment */
431 		 return "<Alt>fna;<Control>n";
432 	 case 1:
433 		 /* New Event */
434 		 return "<Alt>fnd;<Shift><Control>d";
435 	 case 2:
436 		 /* New Meeting */
437 		 return "<Alt>fne;<Shift><Control>e";
438 	 case 3:
439 		 /* Go to today */
440 		 return "<Alt>vt;<Alt><Control>t";
441 	 case 4:
442 		 /* Go to date */
443 		 return "<Alt>vd;<Alt><Control>g";
444 	 default:
445 		 break;
446 	 }
447 	 return NULL;
448 }
449 
450 static const gchar *
451 action_interface_action_get_name (AtkAction *action,
452                                   gint i)
453 {
454 	if (i >= 0 && i < CAL_VIEW_ACTION_NUM)
455 		return action_name[i];
456 	return NULL;
457 }