Bug 793125 - Crash due to popup menus left attached too long
[evolution.git] / src / calendar / gui / ea-day-view.c
blobb082d11c45c084bb7cd0fcef12976cf31df1b204
1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 * Authors:
16 * Bolian Yin <bolian.yin@sun.com>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
22 #include "evolution-config.h"
24 #include "ea-day-view.h"
25 #include "ea-cal-view-event.h"
27 #include "ea-calendar-helpers.h"
28 #include <glib/gi18n.h>
30 static const gchar * ea_day_view_get_name (AtkObject *accessible);
31 static const gchar * ea_day_view_get_description (AtkObject *accessible);
32 static gint ea_day_view_get_n_children (AtkObject *obj);
33 static AtkObject * ea_day_view_ref_child (AtkObject *obj,
34 gint i);
35 static gpointer parent_class = NULL;
37 G_DEFINE_TYPE (EaDayView, ea_day_view, EA_TYPE_CAL_VIEW)
39 static void
40 ea_day_view_init (EaDayView *view)
44 static void
45 ea_day_view_class_init (EaDayViewClass *klass)
47 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
49 parent_class = g_type_class_peek_parent (klass);
51 class->get_name = ea_day_view_get_name;
52 class->get_description = ea_day_view_get_description;
54 class->get_n_children = ea_day_view_get_n_children;
55 class->ref_child = ea_day_view_ref_child;
58 AtkObject *
59 ea_day_view_new (GtkWidget *widget)
61 GObject *object;
62 AtkObject *accessible;
64 g_return_val_if_fail (E_IS_DAY_VIEW (widget), NULL);
66 object = g_object_new (EA_TYPE_DAY_VIEW, NULL);
68 accessible = ATK_OBJECT (object);
69 atk_object_initialize (accessible, widget);
71 #ifdef ACC_DEBUG
72 printf ("EvoAcc: ea_day_view created %p\n", (gpointer) accessible);
73 #endif
75 return accessible;
78 static const gchar *
79 ea_day_view_get_name (AtkObject *accessible)
81 EDayView *day_view;
82 gchar *label_text;
83 GtkWidget *widget;
84 gint n_events;
85 gchar *event_str, *name_str;
87 g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL);
89 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
90 if (widget == NULL)
91 return NULL;
93 day_view = E_DAY_VIEW (widget);
95 label_text = e_calendar_view_get_description_text (E_CALENDAR_VIEW (day_view));
97 n_events = atk_object_get_n_accessible_children (accessible);
98 /* the child main item is always there */
99 --n_events;
100 if (n_events >= 1)
101 event_str = g_strdup_printf (
102 ngettext (
103 /* To translators: Here, "It" is either like "Work Week View: July
104 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */
105 "It has %d event.",
106 "It has %d events.",
107 n_events),
108 n_events);
109 else
110 /* To translators: Here, "It" is either like "Work Week View: July
111 10th - July 14th, 2006." or "Day View: Thursday July 13th, 2006." */
112 event_str = g_strdup (_("It has no events."));
114 if (e_day_view_get_work_week_view (day_view))
115 name_str = g_strdup_printf (
116 /* To translators: First %s is the week, for example "July 10th -
117 July 14th, 2006". Second %s is the number of events in this work
118 week, for example "It has %d event/events." or "It has no events." */
119 _("Work Week View: %s. %s"),
120 label_text, event_str);
121 else
122 name_str = g_strdup_printf (
123 /* To translators: First %s is the day, for example "Thursday July
124 13th, 2006". Second %s is the number of events on this day, for
125 example "It has %d event/events." or "It has no events." */
126 _("Day View: %s. %s"),
127 label_text, event_str);
129 ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str);
130 g_free (name_str);
131 g_free (event_str);
132 g_free (label_text);
134 return accessible->name;
137 static const gchar *
138 ea_day_view_get_description (AtkObject *accessible)
140 EDayView *day_view;
141 GtkWidget *widget;
143 g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL);
145 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
146 if (widget == NULL)
147 return NULL;
149 day_view = E_DAY_VIEW (widget);
151 if (accessible->description)
152 return accessible->description;
153 else {
154 if (e_day_view_get_work_week_view (day_view))
155 return _("calendar view for a work week");
156 else
157 return _("calendar view for one or more days");
161 static gint
162 ea_day_view_get_n_children (AtkObject *accessible)
164 EDayView *day_view;
165 GtkWidget *widget;
166 gint day;
167 gint days_shown;
168 gint child_num = 0;
170 g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), -1);
172 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
173 if (widget == NULL)
174 return -1;
176 day_view = E_DAY_VIEW (widget);
177 days_shown = e_day_view_get_days_shown (day_view);
179 child_num += day_view->long_events->len;
181 for (day = 0; day < days_shown; day++) {
182 child_num += day_view->events[day]->len;
185 /* "+1" for the main item */
186 return child_num + 1;
189 static AtkObject *
190 ea_day_view_ref_child (AtkObject *accessible,
191 gint index)
193 EDayView *day_view;
194 gint child_num;
195 gint day;
196 AtkObject *atk_object = NULL;
197 EDayViewEvent *event = NULL;
198 GtkWidget *widget;
200 g_return_val_if_fail (EA_IS_DAY_VIEW (accessible), NULL);
202 child_num = atk_object_get_n_accessible_children (accessible);
203 if (child_num <= 0 || index < 0 || index >= child_num)
204 return NULL;
206 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
207 if (widget == NULL)
208 return NULL;
210 day_view = E_DAY_VIEW (widget);
212 if (index == 0) {
213 /* index == 0 is the main item */
214 atk_object = atk_gobject_accessible_for_object (
215 G_OBJECT (day_view->main_canvas_item));
216 g_object_ref (atk_object);
218 else {
219 --index;
220 /* a long event */
221 if (index < day_view->long_events->len) {
222 event = &g_array_index (day_view->long_events,
223 EDayViewEvent, index);
225 else {
226 index -= day_view->long_events->len;
227 day = 0;
228 while (index >= day_view->events[day]->len) {
229 index -= day_view->events[day]->len;
230 ++day;
233 event = &g_array_index (day_view->events[day],
234 EDayViewEvent, index);
236 if (event && event->canvas_item) {
237 /* Not use atk_gobject_accessible_for_object here,
238 * we need to do special thing here
240 atk_object = ea_calendar_helpers_get_accessible_for (
241 event->canvas_item);
242 g_object_ref (atk_object);
245 return atk_object;