1 /*
2  *
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10  * for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public License
13  * along with this program; if not, see <http://www.gnu.org/licenses/>.
14  *
15  *
16  * Authors:
17  *		Damon Chaplin <damon@ximian.com>
18  *
19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20  *
21  */
22 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
23 
24 #if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION)
25 #error "Only <e-util/e-util.h> should be included directly."
26 #endif
27 
28 #ifndef _E_CALENDAR_ITEM_H_
29 #define _E_CALENDAR_ITEM_H_
30 
31 #include <libgnomecanvas/gnome-canvas.h>
32 
33 G_BEGIN_DECLS
34 
35 /*
36  * ECalendarItem - canvas item displaying a calendar.
37  */
38 
39 #define	E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME	1
40 #define	E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME	1
41 
42 /* The number of rows & columns of days in each month. */
43 #define E_CALENDAR_ROWS_PER_MONTH	6
44 #define E_CALENDAR_COLS_PER_MONTH	7
45 
46 /* Used to mark days as bold in e_calendar_item_mark_day(). */
47 #define E_CALENDAR_ITEM_MARK_BOLD	(1 << 0)
48 #define E_CALENDAR_ITEM_MARK_ITALIC     (1 << 1)
49 
50 /*
51  * These are the padding sizes between various pieces of the calendar.
52  */
53 
54 /* The minimum padding around the numbers in each cell/day. */
55 #define	E_CALENDAR_ITEM_MIN_CELL_XPAD	4
56 #define	E_CALENDAR_ITEM_MIN_CELL_YPAD	0
57 
58 /* Vertical padding. */
59 #define	E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS		1
60 #define	E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS		0
61 #define	E_CALENDAR_ITEM_YPAD_ABOVE_CELLS		1
62 #define	E_CALENDAR_ITEM_YPAD_BELOW_CELLS		2
63 
64 /* Horizontal padding in the heading bars. */
65 #define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME_WITH_BUTTON	10
66 #define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME			3
67 #define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME			3
68 #define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME_WITH_BUTTON	10
69 
70 /* Horizontal padding in the month displays. */
71 #define	E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS	4
72 #define	E_CALENDAR_ITEM_XPAD_AFTER_WEEK_NUMBERS		2
73 #define	E_CALENDAR_ITEM_XPAD_BEFORE_CELLS		1
74 #define	E_CALENDAR_ITEM_XPAD_AFTER_CELLS		4
75 
76 /* These index our colors array. */
77 typedef enum
78 {
79 	E_CALENDAR_ITEM_COLOR_TODAY_BOX,
80 	E_CALENDAR_ITEM_COLOR_SELECTION_FG,
81 	E_CALENDAR_ITEM_COLOR_SELECTION_BG_FOCUSED,
82 	E_CALENDAR_ITEM_COLOR_SELECTION_BG,
83 	E_CALENDAR_ITEM_COLOR_PREV_OR_NEXT_MONTH_FG,
84 
85 	E_CALENDAR_ITEM_COLOR_LAST
86 } ECalendarItemColors;
87 
88 typedef struct _ECalendarItem       ECalendarItem;
89 typedef struct _ECalendarItemClass  ECalendarItemClass;
90 
91 /* The type of the callback function optionally used to get the colors to
92  * use for each day. */
93 typedef void (*ECalendarItemStyleCallback)   (ECalendarItem	*calitem,
94 					      gint		 year,
95 					      gint		 month,
96 					      gint		 day,
97 					      gint		 day_style,
98 					      gboolean		 today,
99 					      gboolean		 prev_or_next_month,
100 					      gboolean		 selected,
101 					      gboolean		 has_focus,
102 					      gboolean		 drop_target,
103 					      GdkColor	       **bg_color,
104 					      GdkColor	       **fg_color,
105 					      GdkColor	       **box_color,
106 					      gboolean		*bold,
107 					      gboolean		*italic,
108 					      gpointer		 data);
109 
110 /* The type of the callback function optionally used to get the current time.
111  */
112 typedef struct tm (*ECalendarItemGetTimeCallback) (ECalendarItem *calitem,
113 						   gpointer	  data);
114 
115 /* Standard GObject macros */
116 #define E_TYPE_CALENDAR_ITEM \
117 	(e_calendar_item_get_type ())
118 #define E_CALENDAR_ITEM(obj) \
119 	(G_TYPE_CHECK_INSTANCE_CAST \
120 	((obj), E_TYPE_CALENDAR_ITEM, ECalendarItem))
121 #define E_CALENDAR_ITEM_CLASS(cls) \
122 	(G_TYPE_CHECK_CLASS_CAST \
123 	((cls), E_TYPE_CALENDAR_ITEM, ECalendarItemClass))
124 #define E_IS_CALENDAR_ITEM(obj) \
125 	(G_TYPE_CHECK_INSTANCE_TYPE \
126 	((obj), E_TYPE_CALENDAR_ITEM))
127 #define E_IS_CALENDAR_ITEM_CLASS(cls) \
128 	(G_TYPE_CHECK_CLASS_TYPE \
129 	((cls), E_TYPE_CALENDAR_ITEM))
130 #define E_CALENDAR_ITEM_GET_CLASS(obj) \
131 	(G_TYPE_INSTANCE_GET_CLASS \
132 	((obj), E_TYPE_CALENDAR_ITEM, ECalendarItemClass))
133 
134 struct _ECalendarItem {
135 	GnomeCanvasItem canvas_item;
136 
137 	/* The year & month of the first calendar being displayed. */
138 	gint year;
139 	gint month;	/* 0 to 11 */
140 
141 	/* Points to an array of styles, one gchar for each day. We use 32
142 	 * chars for each month, with n + 2 months, where n is the number of
143 	 * complete months shown (since we show some days before the first
144 	 * month and after the last month grayes out).
145 	 * A value of 0 is the default, and 1 is bold. */
146 	guint8 *styles;
147 
148 	/*
149 	 * Options.
150 	 */
151 
152 	/* The minimum & maximum number of rows & columns of months.
153 	 * If the maximum values are -1 then there is no maximum.
154 	 * The minimum valies default to 1. The maximum values to -1. */
155 	gint min_rows;
156 	gint min_cols;
157 	gint max_rows;
158 	gint max_cols;
159 
160 	/* The actual number of rows & columns of months. */
161 	gint rows;
162 	gint cols;
163 
164 	/* Whether we show week nubers. */
165 	gboolean show_week_numbers;
166 	/* whether to keep same week days selected on week number click */
167 	gboolean keep_wdays_on_weeknum_click;
168 
169 	/* The first day of the week. */
170 	GDateWeekday week_start_day;
171 
172 	/* Whether the cells expand to fill extra space. */
173 	gboolean expand;
174 
175 	/* The maximum number of days that can be selected. Defaults to 1. */
176 	gint max_days_selected;
177 
178 	/* The number of days selected before we switch to selecting whole
179 	 * weeks, or -1 if we never switch. Defaults to -1. */
180 	gint days_to_start_week_selection;
181 
182 	/* Whether the selection is moved when we move back/forward one month.
183 	 * Used for things like the EDateEdit which only want the selection to
184 	 * be changed when the user explicitly selects a day. */
185 	gboolean move_selection_when_moving;
186 
187 	/* Whether the selection day is preserved when we  move back/forward
188 	 * one month. Used for the work week and week view. */
189 	gboolean preserve_day_when_moving;
190 
191 	/* Whether to display the pop-up, TRUE by default */
192 	gboolean display_popup;
193 
194 	/*
195 	 * Internal stuff.
196 	 */
197 
198 	/* Bounds of item. */
199 	gdouble x1, y1, x2, y2;
200 
201 	/* The minimum size of each month, based on the fonts used. */
202 	gint min_month_width;
203 	gint min_month_height;
204 
205 	/* The actual size of each month, after dividing extra space. */
206 	gint month_width;
207 	gint month_height;
208 
209 	/* The offset to the left edge of the first calendar. */
210 	gint x_offset;
211 
212 	/* The padding around each calendar month. */
213 	gint month_lpad, month_rpad;
214 	gint month_tpad, month_bpad;
215 
216 	/* The size of each cell. */
217 	gint cell_width;
218 	gint cell_height;
219 
220 	/* The current selection. The month offsets are from 0, which is the
221 	 * top-left calendar month view. Note that -1 is used for the last days
222 	 * from the previous month. The days are real month days. */
223 	gboolean selecting;
224 	GDate *selecting_axis;
225 	gboolean selection_dragging_end;
226 	gboolean selection_from_full_week;
227 	gboolean selection_set;
228 	gint selection_start_month_offset;
229 	gint selection_start_day;
230 	gint selection_end_month_offset;
231 	gint selection_end_day;
232 	gint selection_real_start_month_offset;
233 	gint selection_real_start_day;
234 
235 	/* Widths of the day characters. */
236 	gint day_widths[8]; /* indexed by GDateWeekday */
237 	gint max_day_width;
238 
239 	/* Widths of the digits, '0' .. '9'. */
240 	gint digit_widths[10];
241 	gint max_digit_width;
242 
243 	gint week_number_digit_widths[10];
244 	gint max_week_number_digit_width;
245 
246 	gint max_month_name_width;
247 
248 	/* Fonts for drawing text. If font isn't set it uses the font from the
249 	 * canvas widget. If week_number_font isn't set it uses font. */
250 	PangoFontDescription *font_desc;
251 	PangoFontDescription *week_number_font_desc;
252 
253 	ECalendarItemStyleCallback style_callback;
254 	gpointer style_callback_data;
255 	GDestroyNotify style_callback_destroy;
256 
257 	ECalendarItemGetTimeCallback time_callback;
258 	gpointer time_callback_data;
259 	GDestroyNotify time_callback_destroy;
260 
261 	/* Colors for drawing. */
262 	GdkColor colors[E_CALENDAR_ITEM_COLOR_LAST];
263 
264 	/* Our idle handler for emitting signals. */
265 	gint signal_emission_idle_id;
266 
267 	/* A flag to indicate that the selection or date range has changed.
268 	 * When set the idle function will emit the signal and reset it to
269 	 * FALSE. This is so we don't emit it several times when args are set
270 	 * etc. */
271 	gboolean selection_changed;
272 	gboolean date_range_changed;
273 };
274 
275 struct _ECalendarItemClass {
276 	GnomeCanvasItemClass parent_class;
277 
278 	void (* date_range_changed)	(ECalendarItem *calitem);
279 	void (* selection_changed)	(ECalendarItem *calitem);
280 	void (* selection_preview_changed)	(ECalendarItem *calitem);
281 };
282 
283 GType	e_calendar_item_get_type		(void) G_GNUC_CONST;
284 
285 /* FIXME: months are 0-11 throughout, but 1-12 may be better. */
286 
287 void	e_calendar_item_get_first_month		(ECalendarItem *calitem,
288 						 gint *year,
289 						 gint *month);
290 void	e_calendar_item_set_first_month		(ECalendarItem *calitem,
291 						 gint year,
292 						 gint month);
293 
294 /* Get the maximum number of days selectable */
295 gint	e_calendar_item_get_max_days_sel	(ECalendarItem *calitem);
296 
297 /* Set the maximum number of days selectable */
298 void	e_calendar_item_set_max_days_sel	(ECalendarItem *calitem,
299 						 gint days);
300 
301 /* Get the maximum number of days selectable */
302 gint	e_calendar_item_get_days_start_week_sel	(ECalendarItem *calitem);
303 
304 /* Set the maximum number of days selectable */
305 void	e_calendar_item_set_days_start_week_sel	(ECalendarItem *calitem,
306 						 gint days);
307 
308 /* Set the maximum number of days before whole weeks are selected */
309 gboolean
310 	e_calendar_item_get_display_popup	(ECalendarItem *calitem);
311 
312 /* Get the maximum number of days before whole weeks are selected */
313 void	e_calendar_item_set_display_popup	(ECalendarItem *calitem,
314 						 gboolean display);
315 
316 /* Gets the range of dates actually shown. Months are 0 to 11.
317  * This also includes the last days of the previous month and the first days
318  * of the following month, which are normally shown in gray.
319  * It returns FALSE if no dates are currently shown. */
320 gboolean
321 	e_calendar_item_get_date_range		(ECalendarItem *calitem,
322 						 gint *start_year,
323 						 gint *start_month,
324 						 gint *start_day,
325 						 gint *end_year,
326 						 gint *end_month,
327 						 gint *end_day);
328 
329 /* Returns the selected date range. It returns FALSE if no days are currently
330  * selected. */
331 gboolean
332 	e_calendar_item_get_selection		(ECalendarItem *calitem,
333 						 GDate *start_date,
334 						 GDate *end_date);
335 /* Sets the selected date range, and changes the date range shown so at least
336  * the start of the selection is shown. If start_date is NULL it clears the
337  * selection. */
338 void	e_calendar_item_set_selection		(ECalendarItem *calitem,
339 						 const GDate *start_date,
340 						 const GDate *end_date);
341 
342 /* Marks a particular day. Passing E_CALENDAR_ITEM_MARK_BOLD as the day style
343  * will result in the day being shown as bold by default. The style callback
344  * could support more day_styles, or the style callback could determine the
345  * colors itself, without needing to mark days. */
346 void	e_calendar_item_clear_marks		(ECalendarItem *calitem);
347 void	e_calendar_item_mark_day		(ECalendarItem *calitem,
348 						 gint year,
349 						 gint month,
350 						 gint day,
351 						 guint8 day_style,
352 						 gboolean add_day_style);
353 
354 /* Mark a range of days. Any days outside the currently shown range are
355  * ignored. */
356 void	e_calendar_item_mark_days		(ECalendarItem *calitem,
357 						 gint start_year,
358 						 gint start_month,
359 						 gint start_day,
360 						 gint end_year,
361 						 gint end_month,
362 						 gint end_day,
363 						 guint8 day_style,
364 						 gboolean add_day_style);
365 
366 /* Sets the function to call to get the colors to use for a particular day. */
367 void	e_calendar_item_set_style_callback	(ECalendarItem *calitem,
368 						 ECalendarItemStyleCallback cb,
369 						 gpointer data,
370 						 GDestroyNotify  destroy);
371 
372 /* Sets a callback to use to get the current time. This is useful if the
373  * application needs to use its own timezone data rather than rely on the
374  * Unix timezone. */
375 void	e_calendar_item_set_get_time_callback	(ECalendarItem *calitem,
376 						 ECalendarItemGetTimeCallback cb,
377 						 gpointer data,
378 						 GDestroyNotify  destroy);
379 void	e_calendar_item_normalize_date		(ECalendarItem *calitem,
380 						 gint *year,
381 						 gint *month);
382 gint	e_calendar_item_get_week_number		(ECalendarItem *calitem,
383 						 gint day,
384 						 gint month,
385 						 gint year);
386 void	e_calendar_item_style_updated		(GtkWidget *widget,
387 						 ECalendarItem *calitem);
388 gboolean
389 	e_calendar_item_convert_position_to_date
390 						(ECalendarItem *calitem,
391 						 gint event_x,
392 						 gint event_y,
393 						 GDate *date);
394 
395 G_END_DECLS
396 
397 #endif /* _E_CALENDAR_ITEM_H_ */
398