Bug 793125 - Crash due to popup menus left attached too long
[evolution.git] / src / calendar / gui / e-week-view-titles-item.c
blob746c2a38a11312d9664056d2d3e7d39da7afe84a
1 /*
2 * EWeekViewTitlesItem - displays the 'Monday', 'Tuesday' etc. at the top of
3 * the Month calendar view.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Authors:
18 * Damon Chaplin <damon@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
23 #include "evolution-config.h"
25 #include <string.h>
26 #include <e-util/e-util.h>
27 #include "e-week-view-titles-item.h"
29 #define E_WEEK_VIEW_TITLES_ITEM_GET_PRIVATE(obj) \
30 (G_TYPE_INSTANCE_GET_PRIVATE \
31 ((obj), E_TYPE_WEEK_VIEW_TITLES_ITEM, EWeekViewTitlesItemPrivate))
33 struct _EWeekViewTitlesItemPrivate {
34 EWeekView *week_view;
37 enum {
38 PROP_0,
39 PROP_WEEK_VIEW
42 G_DEFINE_TYPE (
43 EWeekViewTitlesItem,
44 e_week_view_titles_item,
45 GNOME_TYPE_CANVAS_ITEM)
47 static void
48 week_view_titles_item_set_property (GObject *object,
49 guint property_id,
50 const GValue *value,
51 GParamSpec *pspec)
53 switch (property_id) {
54 case PROP_WEEK_VIEW:
55 e_week_view_titles_item_set_week_view (
56 E_WEEK_VIEW_TITLES_ITEM (object),
57 g_value_get_object (value));
58 return;
61 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
64 static void
65 week_view_titles_item_get_property (GObject *object,
66 guint property_id,
67 GValue *value,
68 GParamSpec *pspec)
70 switch (property_id) {
71 case PROP_WEEK_VIEW:
72 g_value_set_object (
73 value,
74 e_week_view_titles_item_get_week_view (
75 E_WEEK_VIEW_TITLES_ITEM (object)));
76 return;
79 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
82 static void
83 week_view_titles_item_dispose (GObject *object)
85 EWeekViewTitlesItemPrivate *priv;
87 priv = E_WEEK_VIEW_TITLES_ITEM_GET_PRIVATE (object);
89 if (priv->week_view != NULL) {
90 g_object_unref (priv->week_view);
91 priv->week_view = NULL;
94 /* Chain up to parent's dispose() method. */
95 G_OBJECT_CLASS (e_week_view_titles_item_parent_class)->dispose (object);
98 static void
99 week_view_titles_item_update (GnomeCanvasItem *item,
100 const cairo_matrix_t *i2c,
101 gint flags)
103 GnomeCanvasItemClass *canvas_item_class;
105 /* Chain up to parent's update() method. */
106 canvas_item_class =
107 GNOME_CANVAS_ITEM_CLASS (e_week_view_titles_item_parent_class);
108 canvas_item_class->update (item, i2c, flags);
110 /* The item covers the entire canvas area. */
111 item->x1 = 0;
112 item->y1 = 0;
113 item->x2 = INT_MAX;
114 item->y2 = INT_MAX;
117 static void
118 week_view_titles_item_draw (GnomeCanvasItem *canvas_item,
119 cairo_t *cr,
120 gint x,
121 gint y,
122 gint width,
123 gint height)
125 EWeekViewTitlesItem *titles_item;
126 EWeekView *week_view;
127 GdkRGBA bg_bg, light_bg, dark_bg;
128 gint col_width, col, date_width, date_x;
129 gchar buffer[128];
130 GtkAllocation allocation;
131 gboolean abbreviated;
132 gboolean compress_weekend;
133 GDateWeekday weekday;
134 PangoLayout *layout;
136 titles_item = E_WEEK_VIEW_TITLES_ITEM (canvas_item);
137 week_view = e_week_view_titles_item_get_week_view (titles_item);
138 g_return_if_fail (week_view != NULL);
140 compress_weekend = e_week_view_get_compress_weekend (week_view);
142 cairo_save (cr);
143 cairo_set_line_width (cr, 1.0);
145 gtk_widget_get_allocation (
146 GTK_WIDGET (canvas_item->canvas), &allocation);
148 e_utils_get_theme_color (GTK_WIDGET (week_view), "theme_bg_color", E_UTILS_DEFAULT_THEME_BG_COLOR, &bg_bg);
149 e_utils_shade_color (&bg_bg, &dark_bg, E_UTILS_DARKNESS_MULT);
150 e_utils_shade_color (&bg_bg, &light_bg, E_UTILS_LIGHTNESS_MULT);
152 layout = gtk_widget_create_pango_layout (GTK_WIDGET (week_view), NULL);
154 /* Draw the shadow around the dates. */
155 gdk_cairo_set_source_rgba (cr, &light_bg);
156 cairo_move_to (cr, 1.5 - x, 1.5 - y);
157 cairo_rel_line_to (cr, allocation.width - 1, 0);
158 cairo_move_to (cr, 1.5 - x, 2.5 - y);
159 cairo_rel_line_to (cr, 0, allocation.height - 1);
160 cairo_stroke (cr);
162 gdk_cairo_set_source_rgba (cr, &dark_bg);
163 cairo_rectangle (cr, 0.5 - x, 0.5 - y, allocation.width - 1, allocation.height);
164 cairo_stroke (cr);
166 /* Determine the format to use. */
167 col_width = allocation.width / week_view->columns;
168 abbreviated = (week_view->max_day_width + 2 >= col_width);
170 /* Shift right one pixel to account for the shadow around the main
171 * canvas. */
172 x--;
174 /* Draw the date. Set a clipping rectangle so we don't draw over the
175 * next day. */
176 weekday = e_week_view_get_display_start_day (week_view);
177 for (col = 0; col < week_view->columns; col++) {
178 if (weekday == G_DATE_SATURDAY && compress_weekend)
179 g_snprintf (
180 buffer, sizeof (buffer), "%s/%s",
181 e_get_weekday_name (G_DATE_SATURDAY, TRUE),
182 e_get_weekday_name (G_DATE_SUNDAY, TRUE));
183 else
184 g_snprintf (
185 buffer, sizeof (buffer), "%s",
186 e_get_weekday_name (weekday, abbreviated));
188 cairo_save (cr);
190 cairo_rectangle (
192 week_view->col_offsets[col] - x, 2 - y,
193 week_view->col_widths[col], allocation.height - 2);
194 cairo_clip (cr);
196 if (weekday == G_DATE_SATURDAY && compress_weekend)
197 date_width = week_view->abbr_day_widths[5]
198 + week_view->slash_width
199 + week_view->abbr_day_widths[6];
200 else if (abbreviated)
201 date_width = week_view->abbr_day_widths[weekday];
202 else
203 date_width = week_view->day_widths[weekday];
205 date_x = week_view->col_offsets[col]
206 + (week_view->col_widths[col] - date_width) / 2;
207 date_x = MAX (date_x, week_view->col_offsets[col]);
209 pango_layout_set_text (layout, buffer, -1);
210 cairo_move_to (cr, date_x - x, 3 - y);
211 pango_cairo_show_layout (cr, layout);
213 cairo_restore (cr);
215 /* Draw the lines down the left and right of the date cols. */
216 if (col != 0) {
217 gdk_cairo_set_source_rgba (cr, &light_bg);
218 cairo_move_to (cr, week_view->col_offsets[col] - x + 0.5, 4.5 - y);
219 cairo_rel_line_to (cr, 0, allocation.height - 8);
220 cairo_stroke (cr);
222 gdk_cairo_set_source_rgba (cr, &dark_bg);
223 cairo_move_to (cr, week_view->col_offsets[col] - x - 0.5, 4.5 - y);
224 cairo_rel_line_to (cr, 0, allocation.height - 8);
225 cairo_stroke (cr);
228 /* Draw the lines between each column. */
229 if (col != 0) {
230 cairo_set_source_rgb (cr, 0, 0, 0);
231 cairo_rectangle (
232 cr, week_view->col_offsets[col] - x,
233 allocation.height - y, 1, 1);
234 cairo_fill (cr);
237 weekday = e_weekday_get_next (weekday);
238 if (weekday == G_DATE_SUNDAY && compress_weekend)
239 weekday = e_weekday_get_next (weekday);
242 g_object_unref (layout);
243 cairo_restore (cr);
246 static GnomeCanvasItem *
247 week_view_titles_item_point (GnomeCanvasItem *item,
248 gdouble x,
249 gdouble y,
250 gint cx,
251 gint cy)
253 return item;
256 static void
257 e_week_view_titles_item_class_init (EWeekViewTitlesItemClass *class)
259 GObjectClass *object_class;
260 GnomeCanvasItemClass *item_class;
262 g_type_class_add_private (class, sizeof (EWeekViewTitlesItemPrivate));
264 object_class = G_OBJECT_CLASS (class);
265 object_class->set_property = week_view_titles_item_set_property;
266 object_class->get_property = week_view_titles_item_get_property;
267 object_class->dispose = week_view_titles_item_dispose;
269 item_class = GNOME_CANVAS_ITEM_CLASS (class);
270 item_class->update = week_view_titles_item_update;
271 item_class->draw = week_view_titles_item_draw;
272 item_class->point = week_view_titles_item_point;
274 g_object_class_install_property (
275 object_class,
276 PROP_WEEK_VIEW,
277 g_param_spec_object (
278 "week-view",
279 "Week View",
280 NULL,
281 E_TYPE_WEEK_VIEW,
282 G_PARAM_READWRITE));
285 static void
286 e_week_view_titles_item_init (EWeekViewTitlesItem *titles_item)
288 titles_item->priv = E_WEEK_VIEW_TITLES_ITEM_GET_PRIVATE (titles_item);
291 EWeekView *
292 e_week_view_titles_item_get_week_view (EWeekViewTitlesItem *titles_item)
294 g_return_val_if_fail (E_IS_WEEK_VIEW_TITLES_ITEM (titles_item), NULL);
296 return titles_item->priv->week_view;
299 void
300 e_week_view_titles_item_set_week_view (EWeekViewTitlesItem *titles_item,
301 EWeekView *week_view)
303 g_return_if_fail (E_IS_WEEK_VIEW_TITLES_ITEM (titles_item));
304 g_return_if_fail (E_IS_WEEK_VIEW (week_view));
306 if (titles_item->priv->week_view == week_view)
307 return;
309 if (titles_item->priv->week_view != NULL)
310 g_object_unref (titles_item->priv->week_view);
312 titles_item->priv->week_view = g_object_ref (week_view);
314 g_object_notify (G_OBJECT (titles_item), "week-view");