1 /*
2  * EWeekViewTitlesItem - displays the 'Monday', 'Tuesday' etc. at the top of
3  * the Month calendar view.
4  *
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.
8  *
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.
13  *
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/>.
16  *
17  * Authors:
18  *		Damon Chaplin <damon@ximian.com>
19  *
20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21  */
22 
23 #include "evolution-config.h"
24 
25 #include <string.h>
26 #include <e-util/e-util.h>
27 #include "e-week-view-titles-item.h"
28 
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))
32 
33 struct _EWeekViewTitlesItemPrivate {
34 	EWeekView *week_view;
35 };
36 
37 enum {
38 	PROP_0,
39 	PROP_WEEK_VIEW
40 };
41 
G_DEFINE_TYPE(EWeekViewTitlesItem,e_week_view_titles_item,GNOME_TYPE_CANVAS_ITEM)42 G_DEFINE_TYPE (
43 	EWeekViewTitlesItem,
44 	e_week_view_titles_item,
45 	GNOME_TYPE_CANVAS_ITEM)
46 
47 static void
48 week_view_titles_item_set_property (GObject *object,
49                                     guint property_id,
50                                     const GValue *value,
51                                     GParamSpec *pspec)
52 {
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;
59 	}
60 
61 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
62 }
63 
64 static void
week_view_titles_item_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)65 week_view_titles_item_get_property (GObject *object,
66                                     guint property_id,
67                                     GValue *value,
68                                     GParamSpec *pspec)
69 {
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;
77 	}
78 
79 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
80 }
81 
82 static void
week_view_titles_item_dispose(GObject * object)83 week_view_titles_item_dispose (GObject *object)
84 {
85 	EWeekViewTitlesItemPrivate *priv;
86 
87 	priv = E_WEEK_VIEW_TITLES_ITEM_GET_PRIVATE (object);
88 	g_clear_object (&priv->week_view);
89 
90 	/* Chain up to parent's dispose() method. */
91 	G_OBJECT_CLASS (e_week_view_titles_item_parent_class)->dispose (object);
92 }
93 
94 static void
week_view_titles_item_update(GnomeCanvasItem * item,const cairo_matrix_t * i2c,gint flags)95 week_view_titles_item_update (GnomeCanvasItem *item,
96                               const cairo_matrix_t *i2c,
97                               gint flags)
98 {
99 	GnomeCanvasItemClass *canvas_item_class;
100 
101 	/* Chain up to parent's update() method. */
102 	canvas_item_class =
103 		GNOME_CANVAS_ITEM_CLASS (e_week_view_titles_item_parent_class);
104 	canvas_item_class->update (item, i2c, flags);
105 
106 	/* The item covers the entire canvas area. */
107 	item->x1 = 0;
108 	item->y1 = 0;
109 	item->x2 = INT_MAX;
110 	item->y2 = INT_MAX;
111 }
112 
113 static void
week_view_titles_item_draw(GnomeCanvasItem * canvas_item,cairo_t * cr,gint x,gint y,gint width,gint height)114 week_view_titles_item_draw (GnomeCanvasItem *canvas_item,
115                             cairo_t *cr,
116                             gint x,
117                             gint y,
118                             gint width,
119                             gint height)
120 {
121 	EWeekViewTitlesItem *titles_item;
122 	EWeekView *week_view;
123 	GdkRGBA bg_bg, light_bg, dark_bg, fg;
124 	gint col_width, col, date_width, date_x;
125 	gchar buffer[128];
126 	GtkAllocation allocation;
127 	gboolean abbreviated;
128 	gboolean compress_weekend;
129 	GDateWeekday weekday;
130 	PangoLayout *layout;
131 
132 	titles_item = E_WEEK_VIEW_TITLES_ITEM (canvas_item);
133 	week_view = e_week_view_titles_item_get_week_view (titles_item);
134 	g_return_if_fail (week_view != NULL);
135 
136 	compress_weekend = e_week_view_get_compress_weekend (week_view);
137 
138 	cairo_save (cr);
139 	cairo_set_line_width (cr, 1.0);
140 
141 	gtk_widget_get_allocation (
142 		GTK_WIDGET (canvas_item->canvas), &allocation);
143 
144 	e_utils_get_theme_color (GTK_WIDGET (week_view), "theme_bg_color", E_UTILS_DEFAULT_THEME_BG_COLOR, &bg_bg);
145 	e_utils_get_theme_color (GTK_WIDGET (week_view), "theme_fg_color", E_UTILS_DEFAULT_THEME_FG_COLOR, &fg);
146 	e_utils_shade_color (&bg_bg, &dark_bg, E_UTILS_DARKNESS_MULT);
147 	e_utils_shade_color (&bg_bg, &light_bg, E_UTILS_LIGHTNESS_MULT);
148 
149 	layout = gtk_widget_create_pango_layout (GTK_WIDGET (week_view), NULL);
150 
151 	/* Draw the shadow around the dates. */
152 	gdk_cairo_set_source_rgba (cr, &light_bg);
153 	cairo_move_to (cr, 1.5 - x, 1.5 - y);
154 	cairo_rel_line_to (cr, allocation.width - 1, 0);
155 	cairo_move_to (cr, 1.5 - x, 2.5 - y);
156 	cairo_rel_line_to (cr, 0, allocation.height - 1);
157 	cairo_stroke (cr);
158 
159 	gdk_cairo_set_source_rgba (cr, &dark_bg);
160 	cairo_rectangle (cr, 0.5 - x, 0.5 - y, allocation.width - 1, allocation.height);
161 	cairo_stroke (cr);
162 
163 	/* Determine the format to use. */
164 	col_width = allocation.width / week_view->columns;
165 	abbreviated = (week_view->max_day_width + 2 >= col_width);
166 
167 	/* Shift right one pixel to account for the shadow around the main
168 	 * canvas. */
169 	x--;
170 
171 	/* Draw the date. Set a clipping rectangle so we don't draw over the
172 	 * next day. */
173 	weekday = e_week_view_get_display_start_day (week_view);
174 	for (col = 0; col < week_view->columns; col++) {
175 		if (weekday == G_DATE_SATURDAY && compress_weekend)
176 			g_snprintf (
177 				buffer, sizeof (buffer), "%s/%s",
178 				e_get_weekday_name (G_DATE_SATURDAY, TRUE),
179 				e_get_weekday_name (G_DATE_SUNDAY, TRUE));
180 		else
181 			g_snprintf (
182 				buffer, sizeof (buffer), "%s",
183 				e_get_weekday_name (weekday, abbreviated));
184 
185 		cairo_save (cr);
186 
187 		cairo_rectangle (
188 			cr,
189 			week_view->col_offsets[col] - x, 2 - y,
190 			week_view->col_widths[col], allocation.height - 2);
191 		cairo_clip (cr);
192 
193 		if (weekday == G_DATE_SATURDAY && compress_weekend)
194 			date_width = week_view->abbr_day_widths[5]
195 				+ week_view->slash_width
196 				+ week_view->abbr_day_widths[6];
197 		else if (abbreviated)
198 			date_width = week_view->abbr_day_widths[weekday - 1];
199 		else
200 			date_width = week_view->day_widths[weekday - 1];
201 
202 		date_x = week_view->col_offsets[col]
203 			+ (week_view->col_widths[col] - date_width) / 2;
204 		date_x = MAX (date_x, week_view->col_offsets[col]);
205 
206 		gdk_cairo_set_source_rgba (cr, &fg);
207 		pango_layout_set_text (layout, buffer, -1);
208 		cairo_move_to (cr, date_x - x, 3 - y);
209 		pango_cairo_show_layout (cr, layout);
210 
211 		cairo_restore (cr);
212 
213 		/* Draw the lines down the left and right of the date cols. */
214 		if (col != 0) {
215 			gdk_cairo_set_source_rgba (cr, &light_bg);
216 			cairo_move_to (cr, week_view->col_offsets[col] - x + 0.5, 4.5 - y);
217 			cairo_rel_line_to (cr, 0, allocation.height - 8);
218 			cairo_stroke (cr);
219 
220 			gdk_cairo_set_source_rgba (cr, &dark_bg);
221 			cairo_move_to (cr, week_view->col_offsets[col] - x - 0.5, 4.5 - y);
222 			cairo_rel_line_to (cr, 0, allocation.height - 8);
223 			cairo_stroke (cr);
224 		}
225 
226 		/* Draw the lines between each column. */
227 		if (col != 0) {
228 			cairo_set_source_rgb (cr, 0, 0, 0);
229 			cairo_rectangle (
230 				cr, week_view->col_offsets[col] - x,
231 				allocation.height - y, 1, 1);
232 			cairo_fill (cr);
233 		}
234 
235 		weekday = e_weekday_get_next (weekday);
236 		if (weekday == G_DATE_SUNDAY && compress_weekend)
237 			weekday = e_weekday_get_next (weekday);
238 	}
239 
240 	g_object_unref (layout);
241 	cairo_restore (cr);
242 }
243 
244 static GnomeCanvasItem *
week_view_titles_item_point(GnomeCanvasItem * item,gdouble x,gdouble y,gint cx,gint cy)245 week_view_titles_item_point (GnomeCanvasItem *item,
246                              gdouble x,
247                              gdouble y,
248                              gint cx,
249                              gint cy)
250 {
251 	return item;
252 }
253 
254 static void
e_week_view_titles_item_class_init(EWeekViewTitlesItemClass * class)255 e_week_view_titles_item_class_init (EWeekViewTitlesItemClass *class)
256 {
257 	GObjectClass  *object_class;
258 	GnomeCanvasItemClass *item_class;
259 
260 	g_type_class_add_private (class, sizeof (EWeekViewTitlesItemPrivate));
261 
262 	object_class = G_OBJECT_CLASS (class);
263 	object_class->set_property = week_view_titles_item_set_property;
264 	object_class->get_property = week_view_titles_item_get_property;
265 	object_class->dispose = week_view_titles_item_dispose;
266 
267 	item_class = GNOME_CANVAS_ITEM_CLASS (class);
268 	item_class->update = week_view_titles_item_update;
269 	item_class->draw = week_view_titles_item_draw;
270 	item_class->point = week_view_titles_item_point;
271 
272 	g_object_class_install_property (
273 		object_class,
274 		PROP_WEEK_VIEW,
275 		g_param_spec_object (
276 			"week-view",
277 			"Week View",
278 			NULL,
279 			E_TYPE_WEEK_VIEW,
280 			G_PARAM_READWRITE));
281 }
282 
283 static void
e_week_view_titles_item_init(EWeekViewTitlesItem * titles_item)284 e_week_view_titles_item_init (EWeekViewTitlesItem *titles_item)
285 {
286 	titles_item->priv = E_WEEK_VIEW_TITLES_ITEM_GET_PRIVATE (titles_item);
287 }
288 
289 EWeekView *
e_week_view_titles_item_get_week_view(EWeekViewTitlesItem * titles_item)290 e_week_view_titles_item_get_week_view (EWeekViewTitlesItem *titles_item)
291 {
292 	g_return_val_if_fail (E_IS_WEEK_VIEW_TITLES_ITEM (titles_item), NULL);
293 
294 	return titles_item->priv->week_view;
295 }
296 
297 void
e_week_view_titles_item_set_week_view(EWeekViewTitlesItem * titles_item,EWeekView * week_view)298 e_week_view_titles_item_set_week_view (EWeekViewTitlesItem *titles_item,
299                                        EWeekView *week_view)
300 {
301 	g_return_if_fail (E_IS_WEEK_VIEW_TITLES_ITEM (titles_item));
302 	g_return_if_fail (E_IS_WEEK_VIEW (week_view));
303 
304 	if (titles_item->priv->week_view == week_view)
305 		return;
306 
307 	if (titles_item->priv->week_view != NULL)
308 		g_object_unref (titles_item->priv->week_view);
309 
310 	titles_item->priv->week_view = g_object_ref (week_view);
311 
312 	g_object_notify (G_OBJECT (titles_item), "week-view");
313 }
314