1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Grönlund
8 * Copyright (c) 1995, 1996, 1997, 1998 by Steffen Beyer
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
34 #ifdef HAVE_SYS_TIME_H
40 #include <glib/gprintf.h>
42 #include "gtkcalendar.h"
45 #include "gtkmarshalers.h"
47 #include "gdk/gdkkeysyms.h"
49 /***************************************************************************/
50 /* The following date routines are taken from the lib_date package. Keep
51 * them seperate in case we want to update them if a newer lib_date comes
54 typedef unsigned int N_int;
55 typedef unsigned long N_long;
56 typedef signed long Z_long;
57 typedef enum { false = FALSE , true = TRUE } boolean;
59 #define and && /* logical (boolean) operators: lower case */
62 static const N_int month_length[2][13] =
64 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
65 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
68 static const N_int days_in_months[2][14] =
70 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
71 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
74 static Z_long calc_days(N_int year, N_int mm, N_int dd);
75 static N_int day_of_week(N_int year, N_int mm, N_int dd);
76 static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1,
77 N_int year2, N_int mm2, N_int dd2);
78 static N_int weeks_in_year(N_int year);
83 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
87 day_of_week(N_int year, N_int mm, N_int dd)
91 days = calc_days(year, mm, dd);
98 return( (N_int) days );
101 static N_int weeks_in_year(N_int year)
103 return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
107 check_date(N_int year, N_int mm, N_int dd)
109 if (year < 1) return(false);
110 if ((mm < 1) or (mm > 12)) return(false);
111 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
116 week_number(N_int year, N_int mm, N_int dd)
120 first = day_of_week(year,1,1) - 1;
121 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
126 year_to_days(N_int year)
128 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
133 calc_days(N_int year, N_int mm, N_int dd)
137 if (year < 1) return(0L);
138 if ((mm < 1) or (mm > 12)) return(0L);
139 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
140 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
144 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
146 if (check_date(*year,mm,dd))
148 *week = week_number(*year,mm,dd);
150 *week = weeks_in_year(--(*year));
151 else if (*week > weeks_in_year(*year))
162 dates_difference(N_int year1, N_int mm1, N_int dd1,
163 N_int year2, N_int mm2, N_int dd2)
165 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
168 /*** END OF lib_date routines ********************************************/
170 /* Spacing around day/week headers and main area, inside those windows */
171 #define CALENDAR_MARGIN 0
172 /* Spacing around day/week headers and main area, outside those windows */
173 #define INNER_BORDER 4
174 /* Separation between day headers and main area */
175 #define CALENDAR_YSEP 4
176 /* Separation between week headers and main area */
177 #define CALENDAR_XSEP 4
179 #define DAY_XSEP 0 /* not really good for small calendar */
180 #define DAY_YSEP 0 /* not really good for small calendar */
183 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
184 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
185 #define SELECTED_BG_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
186 #define SELECTED_FG_COLOR(widget) (& (widget)->style->text[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
187 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
188 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
189 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
190 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
191 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
192 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
208 MONTH_CHANGED_SIGNAL,
210 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
226 PROP_NO_MONTH_CHANGE,
227 PROP_SHOW_WEEK_NUMBERS,
228 PROP_WEEK_START_MONDAY,
232 static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
234 static GtkWidgetClass *parent_class = NULL;
236 typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;
237 struct _GtkCalendarPrivateData
239 GdkWindow *header_win;
240 GdkWindow *day_name_win;
243 GdkWindow *arrow_win[4];
249 guint arrow_state[4];
251 guint max_month_width;
252 guint max_year_width;
258 guint max_day_char_width;
259 guint max_day_char_ascent;
260 guint max_day_char_descent;
261 guint max_label_char_ascent;
262 guint max_label_char_descent;
263 guint max_week_char_width;
268 guint dirty_header : 1;
269 guint dirty_day_names : 1;
270 guint dirty_main : 1;
271 guint dirty_week : 1;
273 guint year_before : 1;
275 guint need_timer : 1;
281 #define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))
283 typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);
285 static void gtk_calendar_class_init (GtkCalendarClass *class);
286 static void gtk_calendar_init (GtkCalendar *calendar);
287 static void gtk_calendar_finalize (GObject *calendar);
288 static void gtk_calendar_destroy (GtkObject *calendar);
289 static void gtk_calendar_set_property (GObject *object,
293 static void gtk_calendar_get_property (GObject *object,
297 static void gtk_calendar_realize (GtkWidget *widget);
298 static void gtk_calendar_unrealize (GtkWidget *widget);
299 static void gtk_calendar_size_request (GtkWidget *widget,
300 GtkRequisition *requisition);
301 static void gtk_calendar_size_allocate (GtkWidget *widget,
302 GtkAllocation *allocation);
303 static gint gtk_calendar_expose (GtkWidget *widget,
304 GdkEventExpose *event);
305 static gint gtk_calendar_button_press (GtkWidget *widget,
306 GdkEventButton *event);
307 static gint gtk_calendar_button_release (GtkWidget *widget,
308 GdkEventButton *event);
309 static void gtk_calendar_main_button (GtkWidget *widget,
310 GdkEventButton *event);
311 static gint gtk_calendar_motion_notify (GtkWidget *widget,
312 GdkEventMotion *event);
313 static gint gtk_calendar_enter_notify (GtkWidget *widget,
314 GdkEventCrossing *event);
315 static gint gtk_calendar_leave_notify (GtkWidget *widget,
316 GdkEventCrossing *event);
317 static gint gtk_calendar_key_press (GtkWidget *widget,
319 static gint gtk_calendar_scroll (GtkWidget *widget,
320 GdkEventScroll *event);
321 static void gtk_calendar_grab_notify (GtkWidget *widget,
322 gboolean was_grabbed);
323 static void gtk_calendar_state_changed (GtkWidget *widget,
324 GtkStateType previous_state);
325 static void gtk_calendar_style_set (GtkWidget *widget,
326 GtkStyle *previous_style);
327 static void gtk_calendar_paint_header (GtkWidget *widget);
328 static void gtk_calendar_paint_day_names (GtkWidget *widget);
329 static void gtk_calendar_paint_week_numbers (GtkWidget *widget);
330 static void gtk_calendar_paint_main (GtkWidget *widget);
332 static void gtk_calendar_select_and_focus_day (GtkCalendar *calendar,
335 static void gtk_calendar_paint_arrow (GtkWidget *widget,
337 static void gtk_calendar_paint_day_num (GtkWidget *widget,
339 static void gtk_calendar_paint_day (GtkWidget *widget,
342 static void gtk_calendar_compute_days (GtkCalendar *calendar);
343 static gint left_x_for_column (GtkCalendar *calendar,
345 static gint top_y_for_row (GtkCalendar *calendar,
348 static char *default_abbreviated_dayname[7];
349 static char *default_monthname[12];
352 gtk_calendar_get_type (void)
354 static GType calendar_type = 0;
358 static const GTypeInfo calendar_info =
360 sizeof (GtkCalendarClass),
361 NULL, /* base_init */
362 NULL, /* base_finalize */
363 (GClassInitFunc) gtk_calendar_class_init,
364 NULL, /* class_finalize */
365 NULL, /* class_data */
366 sizeof (GtkCalendar),
368 (GInstanceInitFunc) gtk_calendar_init,
371 calendar_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCalendar",
375 return calendar_type;
379 gtk_calendar_class_init (GtkCalendarClass *class)
381 GObjectClass *gobject_class;
382 GtkObjectClass *object_class;
383 GtkWidgetClass *widget_class;
385 gobject_class = (GObjectClass*) class;
386 object_class = (GtkObjectClass*) class;
387 widget_class = (GtkWidgetClass*) class;
389 parent_class = g_type_class_peek_parent (class);
391 gobject_class->set_property = gtk_calendar_set_property;
392 gobject_class->get_property = gtk_calendar_get_property;
393 gobject_class->finalize = gtk_calendar_finalize;
395 object_class->destroy = gtk_calendar_destroy;
397 widget_class->realize = gtk_calendar_realize;
398 widget_class->unrealize = gtk_calendar_unrealize;
399 widget_class->expose_event = gtk_calendar_expose;
400 widget_class->size_request = gtk_calendar_size_request;
401 widget_class->size_allocate = gtk_calendar_size_allocate;
402 widget_class->button_press_event = gtk_calendar_button_press;
403 widget_class->button_release_event = gtk_calendar_button_release;
404 widget_class->motion_notify_event = gtk_calendar_motion_notify;
405 widget_class->enter_notify_event = gtk_calendar_enter_notify;
406 widget_class->leave_notify_event = gtk_calendar_leave_notify;
407 widget_class->key_press_event = gtk_calendar_key_press;
408 widget_class->scroll_event = gtk_calendar_scroll;
409 widget_class->style_set = gtk_calendar_style_set;
410 widget_class->state_changed = gtk_calendar_state_changed;
411 widget_class->grab_notify = gtk_calendar_grab_notify;
413 class->month_changed = NULL;
414 class->day_selected = NULL;
415 class->day_selected_double_click = NULL;
416 class->prev_month = NULL;
417 class->next_month = NULL;
418 class->prev_year = NULL;
419 class->next_year = NULL;
421 g_object_class_install_property (gobject_class,
423 g_param_spec_int ("year",
425 _("The selected year"),
428 g_object_class_install_property (gobject_class,
430 g_param_spec_int ("month",
432 _("The selected month (as a number between 0 and 11)"),
435 g_object_class_install_property (gobject_class,
437 g_param_spec_int ("day",
439 _("The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)"),
444 * GtkCalendar:show-heading:
446 * Determines whether a heading is displayed.
450 g_object_class_install_property (gobject_class,
452 g_param_spec_boolean ("show_heading",
454 _("If TRUE, a heading is displayed"),
459 * GtkCalendar:show-day-names:
461 * Determines whether day names are displayed.
465 g_object_class_install_property (gobject_class,
467 g_param_spec_boolean ("show_day_names",
469 _("If TRUE, day names are displayed"),
473 * GtkCalendar:no-month-change:
475 * Determines whether the selected month can be changed.
479 g_object_class_install_property (gobject_class,
480 PROP_NO_MONTH_CHANGE,
481 g_param_spec_boolean ("no_month_change",
482 _("No Month Change"),
483 _("If TRUE, the selected month can not be changed"),
488 * GtkCalendar:show-week-numbers:
490 * Determines whether week numbers are displayed.
494 g_object_class_install_property (gobject_class,
495 PROP_SHOW_WEEK_NUMBERS,
496 g_param_spec_boolean ("show_week_numbers",
497 _("Show Week Numbers"),
498 _("If TRUE, week numbers are displayed"),
503 * GtkCalendar:week-start-monday:
505 * If this is %TRUE, Monday is displayed as the first day of the week.
509 g_object_class_install_property (gobject_class,
510 PROP_WEEK_START_MONDAY,
511 g_param_spec_boolean ("week_start_monday",
512 _("Week Start Monday"),
513 _("If TRUE, Monday is displayed as the first day of the week"),
518 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
519 g_signal_new ("month_changed",
520 G_OBJECT_CLASS_TYPE (gobject_class),
522 G_STRUCT_OFFSET (GtkCalendarClass, month_changed),
524 _gtk_marshal_VOID__VOID,
526 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
527 g_signal_new ("day_selected",
528 G_OBJECT_CLASS_TYPE (gobject_class),
530 G_STRUCT_OFFSET (GtkCalendarClass, day_selected),
532 _gtk_marshal_VOID__VOID,
534 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
535 g_signal_new ("day_selected_double_click",
536 G_OBJECT_CLASS_TYPE (gobject_class),
538 G_STRUCT_OFFSET (GtkCalendarClass, day_selected_double_click),
540 _gtk_marshal_VOID__VOID,
542 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
543 g_signal_new ("prev_month",
544 G_OBJECT_CLASS_TYPE (gobject_class),
546 G_STRUCT_OFFSET (GtkCalendarClass, prev_month),
548 _gtk_marshal_VOID__VOID,
550 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
551 g_signal_new ("next_month",
552 G_OBJECT_CLASS_TYPE (gobject_class),
554 G_STRUCT_OFFSET (GtkCalendarClass, next_month),
556 _gtk_marshal_VOID__VOID,
558 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
559 g_signal_new ("prev_year",
560 G_OBJECT_CLASS_TYPE (gobject_class),
562 G_STRUCT_OFFSET (GtkCalendarClass, prev_year),
564 _gtk_marshal_VOID__VOID,
566 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
567 g_signal_new ("next_year",
568 G_OBJECT_CLASS_TYPE (gobject_class),
570 G_STRUCT_OFFSET (GtkCalendarClass, next_year),
572 _gtk_marshal_VOID__VOID,
577 gtk_calendar_init (GtkCalendar *calendar)
585 GtkCalendarPrivateData *private_data;
588 widget = GTK_WIDGET (calendar);
589 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
591 calendar->private_data = g_malloc (sizeof (GtkCalendarPrivateData));
592 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
594 if (!default_abbreviated_dayname[0])
597 tmp_time= (i+3)*86400;
598 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
599 default_abbreviated_dayname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
602 if (!default_monthname[0])
606 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
607 default_monthname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
612 tm = localtime (&secs);
613 calendar->month = tm->tm_mon;
614 calendar->year = 1900 + tm->tm_year;
617 calendar->marked_date[i] = FALSE;
618 calendar->num_marked_dates = 0;
619 calendar->selected_day = tm->tm_mday;
621 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
622 GTK_CALENDAR_SHOW_DAY_NAMES );
624 calendar->highlight_row = -1;
625 calendar->highlight_col = -1;
627 calendar->focus_row = -1;
628 calendar->focus_col = -1;
629 calendar->xor_gc = NULL;
631 private_data->max_year_width = 0;
632 private_data->max_month_width = 0;
633 private_data->max_day_char_width = 0;
634 private_data->max_week_char_width = 0;
636 private_data->max_day_char_ascent = 0;
637 private_data->max_day_char_descent = 0;
638 private_data->max_label_char_ascent = 0;
639 private_data->max_label_char_descent = 0;
641 private_data->arrow_width = 10;
643 private_data->freeze_count = 0;
645 private_data->dirty_header = 0;
646 private_data->dirty_day_names = 0;
647 private_data->dirty_week = 0;
648 private_data->dirty_main = 0;
650 private_data->need_timer = 0;
651 private_data->timer = 0;
652 private_data->click_child = -1;
654 private_data->year_before = 0;
656 /* Translate to calendar:YM if you want years to be displayed
657 * before months; otherwise translate to calendar:MY.
658 * Do *not* translate it to anything else, if it
659 * it isn't calendar:YM or calendar:MY it will not work.
661 * Note that this flipping is in top the text direction flipping,
662 * so if you have a default text direction of RTL and YM, then
663 * the year will appear on the right.
665 year_before = _("calendar:MY");
666 if (strcmp (year_before, "calendar:YM") == 0)
667 private_data->year_before = 1;
668 else if (strcmp (year_before, "calendar:MY") != 0)
669 g_warning ("Whoever translated calendar:MY did so wrongly.\n");
673 gtk_calendar_new (void)
675 return g_object_new (GTK_TYPE_CALENDAR, NULL);
678 /* column_from_x: returns the column 0-6 that the
679 * x pixel of the xwindow is in */
681 column_from_x (GtkCalendar *calendar,
685 gint x_left, x_right;
689 for (c = 0; c < 7; c++)
691 x_left = left_x_for_column (calendar, c);
692 x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
694 if (event_x >= x_left && event_x < x_right)
705 row_height (GtkCalendar *calendar)
707 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN
708 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
709 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
713 /* row_from_y: returns the row 0-5 that the
714 * y pixel of the xwindow is in */
716 row_from_y (GtkCalendar *calendar,
721 gint y_top, y_bottom;
723 height = row_height (calendar);
726 for (r = 0; r < 6; r++)
728 y_top = top_y_for_row (calendar, r);
729 y_bottom = y_top + height;
731 if (event_y >= y_top && event_y < y_bottom)
739 }/* left_x_for_column: returns the x coordinate
740 * for the left of the column */
742 left_x_for_column (GtkCalendar *calendar,
748 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
751 width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
752 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
753 x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column;
755 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
760 /* top_y_for_row: returns the y coordinate
761 * for the top of the row */
763 top_y_for_row (GtkCalendar *calendar,
767 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h
768 - (CALENDAR_MARGIN + (6 - row)
769 * row_height (calendar)));
772 /* This function should be done by the toolkit, but we don't like the
773 * GTK arrows because they don't look good on this widget */
775 draw_arrow_right (GdkWindow *window,
783 for (i = 0; i <= size / 2; i++)
785 gdk_draw_line (window, gc,
793 /* This function should be done by the toolkit, but we don't like the
794 * GTK arrows because they don't look good on this widget */
796 draw_arrow_left (GdkWindow *window,
804 for (i = 0; i <= size / 2; i++)
806 gdk_draw_line (window, gc,
815 gtk_calendar_set_month_prev (GtkCalendar *calendar)
819 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
822 if (calendar->month == 0)
824 calendar->month = 11;
830 month_len = month_length[leap (calendar->year)][calendar->month + 1];
832 gtk_calendar_freeze (calendar);
833 gtk_calendar_compute_days (calendar);
835 g_signal_emit (calendar,
836 gtk_calendar_signals[PREV_MONTH_SIGNAL],
838 g_signal_emit (calendar,
839 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
842 if (month_len < calendar->selected_day)
844 calendar->selected_day = 0;
845 gtk_calendar_select_day (calendar, month_len);
849 if (calendar->selected_day < 0)
850 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
851 gtk_calendar_select_day (calendar, calendar->selected_day);
854 gtk_widget_queue_draw (GTK_WIDGET (calendar));
855 gtk_calendar_thaw (calendar);
860 gtk_calendar_set_month_next (GtkCalendar *calendar)
864 g_return_if_fail (GTK_IS_WIDGET (calendar));
866 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
870 if (calendar->month == 11)
878 gtk_calendar_freeze (calendar);
879 gtk_calendar_compute_days (calendar);
880 g_signal_emit (calendar,
881 gtk_calendar_signals[NEXT_MONTH_SIGNAL],
883 g_signal_emit (calendar,
884 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
887 month_len = month_length[leap (calendar->year)][calendar->month + 1];
889 if (month_len < calendar->selected_day)
891 calendar->selected_day = 0;
892 gtk_calendar_select_day (calendar, month_len);
895 gtk_calendar_select_day (calendar, calendar->selected_day);
897 gtk_widget_queue_draw (GTK_WIDGET (calendar));
898 gtk_calendar_thaw (calendar);
902 gtk_calendar_set_year_prev (GtkCalendar *calendar)
906 g_return_if_fail (GTK_IS_WIDGET (calendar));
909 gtk_calendar_freeze (calendar);
910 gtk_calendar_compute_days (calendar);
911 g_signal_emit (calendar,
912 gtk_calendar_signals[PREV_YEAR_SIGNAL],
914 g_signal_emit (calendar,
915 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
918 month_len = month_length[leap (calendar->year)][calendar->month + 1];
920 if (month_len < calendar->selected_day)
922 calendar->selected_day = 0;
923 gtk_calendar_select_day (calendar, month_len);
926 gtk_calendar_select_day (calendar, calendar->selected_day);
928 gtk_widget_queue_draw (GTK_WIDGET (calendar));
929 gtk_calendar_thaw (calendar);
933 gtk_calendar_set_year_next (GtkCalendar *calendar)
938 g_return_if_fail (GTK_IS_WIDGET (calendar));
940 widget = GTK_WIDGET (calendar);
942 gtk_calendar_freeze (calendar);
945 gtk_calendar_compute_days (calendar);
946 g_signal_emit (calendar,
947 gtk_calendar_signals[NEXT_YEAR_SIGNAL],
949 g_signal_emit (calendar,
950 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
953 month_len = month_length[leap (calendar->year)][calendar->month + 1];
955 if (month_len < calendar->selected_day)
957 calendar->selected_day = 0;
958 gtk_calendar_select_day (calendar, month_len);
961 gtk_calendar_select_day (calendar, calendar->selected_day);
963 gtk_widget_queue_draw (GTK_WIDGET (calendar));
964 gtk_calendar_thaw (calendar);
968 gtk_calendar_main_button (GtkWidget *widget,
969 GdkEventButton *event)
971 GtkCalendar *calendar;
977 calendar = GTK_CALENDAR (widget);
979 x = (gint) (event->x);
980 y = (gint) (event->y);
982 row = row_from_y (calendar, y);
983 col = column_from_x (calendar, x);
985 /* If row or column isn't found, just return. */
986 if (row == -1 || col == -1)
989 day_month = calendar->day_month[row][col];
991 if (event->type == GDK_BUTTON_PRESS)
993 day = calendar->day[row][col];
995 if (day_month == MONTH_PREV)
996 gtk_calendar_set_month_prev (calendar);
997 else if (day_month == MONTH_NEXT)
998 gtk_calendar_set_month_next (calendar);
1000 if (!GTK_WIDGET_HAS_FOCUS (widget))
1001 gtk_widget_grab_focus (widget);
1003 gtk_calendar_select_and_focus_day (calendar, day);
1006 else if (event->type == GDK_2BUTTON_PRESS)
1008 if (day_month == MONTH_CURRENT)
1009 g_signal_emit (calendar,
1010 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL],
1016 gtk_calendar_realize_arrows (GtkWidget *widget)
1018 GtkCalendar *calendar;
1019 GtkCalendarPrivateData *private_data;
1020 GdkWindowAttr attributes;
1021 gint attributes_mask;
1025 g_return_if_fail (GTK_IS_CALENDAR (widget));
1027 calendar = GTK_CALENDAR (widget);
1028 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1030 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1031 year_left = private_data->year_before;
1033 year_left = !private_data->year_before;
1035 /* Arrow windows ------------------------------------- */
1036 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1037 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
1039 attributes.wclass = GDK_INPUT_OUTPUT;
1040 attributes.window_type = GDK_WINDOW_CHILD;
1041 attributes.visual = gtk_widget_get_visual (widget);
1042 attributes.colormap = gtk_widget_get_colormap (widget);
1043 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1044 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1045 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
1046 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1048 attributes.width = private_data->arrow_width;
1049 attributes.height = private_data->header_h - 7;
1050 for (i = 0; i < 4; i++)
1054 case ARROW_MONTH_LEFT:
1056 attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
1057 - (3 + 2*private_data->arrow_width
1058 + private_data->max_month_width));
1062 case ARROW_MONTH_RIGHT:
1064 attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
1065 - 3 - private_data->arrow_width);
1067 attributes.x = (private_data->arrow_width
1068 + private_data->max_month_width);
1070 case ARROW_YEAR_LEFT:
1074 attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
1075 - (3 + 2*private_data->arrow_width
1076 + private_data->max_year_width));
1078 case ARROW_YEAR_RIGHT:
1080 attributes.x = (private_data->arrow_width
1081 + private_data->max_year_width);
1083 attributes.x = (widget->allocation.width - 2 * widget->style->xthickness
1084 - 3 - private_data->arrow_width);
1087 private_data->arrow_win[i] = gdk_window_new (private_data->header_win,
1090 private_data->arrow_state[i] = GTK_STATE_NORMAL;
1091 gdk_window_set_background (private_data->arrow_win[i],
1092 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1093 gdk_window_show (private_data->arrow_win[i]);
1094 gdk_window_set_user_data (private_data->arrow_win[i], widget);
1099 for (i = 0; i < 4; i++)
1100 private_data->arrow_win[i] = NULL;
1105 gtk_calendar_realize_header (GtkWidget *widget)
1107 GtkCalendar *calendar;
1108 GtkCalendarPrivateData *private_data;
1109 GdkWindowAttr attributes;
1110 gint attributes_mask;
1112 g_return_if_fail (GTK_IS_CALENDAR (widget));
1114 calendar = GTK_CALENDAR (widget);
1115 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1117 /* Header window ------------------------------------- */
1118 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1120 attributes.wclass = GDK_INPUT_OUTPUT;
1121 attributes.window_type = GDK_WINDOW_CHILD;
1122 attributes.visual = gtk_widget_get_visual (widget);
1123 attributes.colormap = gtk_widget_get_colormap (widget);
1124 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1125 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1126 attributes.x = widget->style->xthickness;
1127 attributes.y = widget->style->ythickness;
1128 attributes.width = widget->allocation.width - 2 * attributes.x;
1129 attributes.height = private_data->header_h - 2 * attributes.y;
1130 private_data->header_win = gdk_window_new (widget->window,
1131 &attributes, attributes_mask);
1133 gdk_window_set_background (private_data->header_win,
1134 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1135 gdk_window_show (private_data->header_win);
1136 gdk_window_set_user_data (private_data->header_win, widget);
1141 private_data->header_win = NULL;
1143 gtk_calendar_realize_arrows (widget);
1147 gtk_calendar_realize_day_names (GtkWidget *widget)
1149 GtkCalendar *calendar;
1150 GtkCalendarPrivateData *private_data;
1151 GdkWindowAttr attributes;
1152 gint attributes_mask;
1154 g_return_if_fail (GTK_IS_CALENDAR (widget));
1156 calendar = GTK_CALENDAR (widget);
1157 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1159 /* Day names window --------------------------------- */
1160 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1162 attributes.wclass = GDK_INPUT_OUTPUT;
1163 attributes.window_type = GDK_WINDOW_CHILD;
1164 attributes.visual = gtk_widget_get_visual (widget);
1165 attributes.colormap = gtk_widget_get_colormap (widget);
1166 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1167 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1168 attributes.x = (widget->style->xthickness + INNER_BORDER);
1169 attributes.y = private_data->header_h + (widget->style->ythickness
1171 attributes.width = (widget->allocation.width
1172 - (widget->style->xthickness + INNER_BORDER)
1174 attributes.height = private_data->day_name_h;
1175 private_data->day_name_win = gdk_window_new (widget->window,
1178 gdk_window_set_background (private_data->day_name_win,
1179 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1180 gdk_window_show (private_data->day_name_win);
1181 gdk_window_set_user_data (private_data->day_name_win, widget);
1185 private_data->day_name_win = NULL;
1190 gtk_calendar_realize_week_numbers (GtkWidget *widget)
1192 GtkCalendar *calendar;
1193 GtkCalendarPrivateData *private_data;
1194 GdkWindowAttr attributes;
1195 gint attributes_mask;
1197 g_return_if_fail (GTK_IS_CALENDAR (widget));
1199 calendar = GTK_CALENDAR (widget);
1200 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1202 /* Week number window -------------------------------- */
1203 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1205 attributes.wclass = GDK_INPUT_OUTPUT;
1206 attributes.window_type = GDK_WINDOW_CHILD;
1207 attributes.visual = gtk_widget_get_visual (widget);
1208 attributes.colormap = gtk_widget_get_colormap (widget);
1209 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1211 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1212 attributes.x = widget->style->xthickness + INNER_BORDER;
1213 attributes.y = (private_data->header_h + private_data->day_name_h
1214 + (widget->style->ythickness + INNER_BORDER));
1215 attributes.width = private_data->week_width;
1216 attributes.height = private_data->main_h;
1217 private_data->week_win = gdk_window_new (widget->window,
1218 &attributes, attributes_mask);
1219 gdk_window_set_background (private_data->week_win,
1220 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1221 gdk_window_show (private_data->week_win);
1222 gdk_window_set_user_data (private_data->week_win, widget);
1226 private_data->week_win = NULL;
1231 gtk_calendar_realize (GtkWidget *widget)
1233 GtkCalendar *calendar;
1234 GtkCalendarPrivateData *private_data;
1235 GdkWindowAttr attributes;
1236 gint attributes_mask;
1239 calendar = GTK_CALENDAR (widget);
1240 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1242 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1243 gtk_calendar_compute_days (calendar);
1245 attributes.x = widget->allocation.x;
1246 attributes.y = widget->allocation.y;
1247 attributes.width = widget->allocation.width;
1248 attributes.height = widget->allocation.height;
1249 attributes.wclass = GDK_INPUT_OUTPUT;
1250 attributes.window_type = GDK_WINDOW_CHILD;
1251 attributes.event_mask = (gtk_widget_get_events (widget)
1252 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_MASK);
1253 attributes.visual = gtk_widget_get_visual (widget);
1254 attributes.colormap = gtk_widget_get_colormap (widget);
1256 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1257 widget->window = gdk_window_new (widget->parent->window,
1258 &attributes, attributes_mask);
1260 widget->style = gtk_style_attach (widget->style, widget->window);
1262 /* Header window ------------------------------------- */
1263 gtk_calendar_realize_header (widget);
1264 /* Day names window --------------------------------- */
1265 gtk_calendar_realize_day_names (widget);
1266 /* Week number window -------------------------------- */
1267 gtk_calendar_realize_week_numbers (widget);
1268 /* Main Window -------------------------------------- */
1269 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1270 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1271 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1273 attributes.x = private_data->week_width + (widget->style->ythickness + INNER_BORDER);
1274 attributes.y = (private_data->header_h + private_data->day_name_h
1275 + (widget->style->ythickness + INNER_BORDER));
1276 attributes.width = (widget->allocation.width - attributes.x
1277 - (widget->style->xthickness + INNER_BORDER));
1278 attributes.height = private_data->main_h;
1279 private_data->main_win = gdk_window_new (widget->window,
1280 &attributes, attributes_mask);
1281 gdk_window_set_background (private_data->main_win,
1282 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1283 gdk_window_show (private_data->main_win);
1284 gdk_window_set_user_data (private_data->main_win, widget);
1285 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1286 gdk_window_show (widget->window);
1287 gdk_window_set_user_data (widget->window, widget);
1289 /* Set widgets gc */
1290 calendar->gc = gdk_gc_new (widget->window);
1292 values.foreground = widget->style->white;
1293 values.function = GDK_XOR;
1294 calendar->xor_gc = gdk_gc_new_with_values (widget->window,
1301 gtk_calendar_unrealize (GtkWidget *widget)
1303 GtkCalendar *calendar;
1304 GtkCalendarPrivateData *private_data;
1307 calendar = GTK_CALENDAR (widget);
1308 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1310 if (private_data->header_win)
1312 for (i = 0; i < 4; i++)
1314 if (private_data->arrow_win[i])
1316 gdk_window_set_user_data (private_data->arrow_win[i], NULL);
1317 gdk_window_destroy (private_data->arrow_win[i]);
1318 private_data->arrow_win[i] = NULL;
1321 gdk_window_set_user_data (private_data->header_win, NULL);
1322 gdk_window_destroy (private_data->header_win);
1323 private_data->header_win = NULL;
1326 if (private_data->week_win)
1328 gdk_window_set_user_data (private_data->week_win, NULL);
1329 gdk_window_destroy (private_data->week_win);
1330 private_data->week_win = NULL;
1333 if (private_data->main_win)
1335 gdk_window_set_user_data (private_data->main_win, NULL);
1336 gdk_window_destroy (private_data->main_win);
1337 private_data->main_win = NULL;
1339 if (private_data->day_name_win)
1341 gdk_window_set_user_data (private_data->day_name_win, NULL);
1342 gdk_window_destroy (private_data->day_name_win);
1343 private_data->day_name_win = NULL;
1345 if (calendar->xor_gc)
1346 g_object_unref (calendar->xor_gc);
1348 g_object_unref (calendar->gc);
1350 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1351 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1355 gtk_calendar_size_request (GtkWidget *widget,
1356 GtkRequisition *requisition)
1358 GtkCalendar *calendar;
1359 GtkCalendarPrivateData *private_data;
1360 PangoLayout *layout;
1361 PangoRectangle logical_rect;
1366 gint calendar_margin = CALENDAR_MARGIN;
1367 gint header_width, main_width;
1368 gint max_header_height = 0;
1372 calendar = GTK_CALENDAR (widget);
1373 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1374 gtk_widget_style_get (GTK_WIDGET (widget),
1375 "focus-line-width", &focus_width,
1376 "focus-padding", &focus_padding,
1379 layout = gtk_widget_create_pango_layout (widget, NULL);
1382 * Calculate the requisition width for the widget.
1387 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1389 private_data->max_month_width = 0;
1390 for (i = 0; i < 12; i++)
1392 pango_layout_set_text (layout, default_monthname[i], -1);
1393 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1394 private_data->max_month_width = MAX (private_data->max_month_width,
1395 logical_rect.width + 8);
1396 max_header_height = MAX (max_header_height, logical_rect.height);
1398 private_data->max_year_width = 0;
1399 for (i=0; i<10; i++)
1401 g_snprintf (buffer, sizeof (buffer), "%d%d%d%d", i,i,i,i);
1402 pango_layout_set_text (layout, buffer, -1);
1403 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1404 private_data->max_year_width = MAX (private_data->max_year_width,
1405 logical_rect.width + 8);
1406 max_header_height = MAX (max_header_height, logical_rect.height);
1411 private_data->max_month_width = 0;
1412 private_data->max_year_width = 0;
1415 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1416 header_width = (private_data->max_month_width
1417 + private_data->max_year_width
1420 header_width = (private_data->max_month_width
1421 + private_data->max_year_width
1422 + 4 * private_data->arrow_width + 3 * 3);
1424 /* Mainwindow labels width */
1426 private_data->max_day_char_width = 0;
1427 private_data->min_day_width = 0;
1428 private_data->max_label_char_ascent = 0;
1429 private_data->max_label_char_descent = 0;
1431 for (i = 0; i < 9; i++)
1433 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1434 pango_layout_set_text (layout, buffer, -1);
1435 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1436 private_data->min_day_width = MAX (private_data->min_day_width,
1437 logical_rect.width);
1439 private_data->max_day_char_ascent = MAX (private_data->max_label_char_ascent,
1440 PANGO_ASCENT (logical_rect));
1441 private_data->max_day_char_descent = MAX (private_data->max_label_char_descent,
1442 PANGO_DESCENT (logical_rect));
1444 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1445 private_data->max_day_char_width = private_data->min_day_width / 2 + 1;
1447 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1448 for (i = 0; i < 7; i++)
1450 pango_layout_set_text (layout, default_abbreviated_dayname[i], -1);
1451 pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect);
1453 private_data->min_day_width = MAX (private_data->min_day_width, logical_rect.width);
1454 private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent,
1455 PANGO_ASCENT (logical_rect));
1456 private_data->max_label_char_descent = MAX (private_data->max_label_char_descent,
1457 PANGO_DESCENT (logical_rect));
1460 private_data->max_week_char_width = 0;
1461 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1462 for (i = 0; i < 9; i++)
1464 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1465 pango_layout_set_text (layout, buffer, -1);
1466 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1467 private_data->max_week_char_width = MAX (private_data->max_week_char_width,
1468 logical_rect.width / 2);
1471 main_width = (7 * (private_data->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1472 + (private_data->max_week_char_width
1473 ? private_data->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2
1477 requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2;
1480 * Calculate the requisition height for the widget.
1483 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1485 private_data->header_h = (max_header_height + CALENDAR_YSEP * 2);
1489 private_data->header_h = 0;
1492 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1494 private_data->day_name_h = (private_data->max_label_char_ascent
1495 + private_data->max_label_char_descent
1496 + 2 * (focus_padding + focus_width) + calendar_margin);
1497 calendar_margin = CALENDAR_YSEP;
1501 private_data->day_name_h = 0;
1504 private_data->main_h = (CALENDAR_MARGIN + calendar_margin
1505 + 6 * (private_data->max_day_char_ascent
1506 + private_data->max_day_char_descent
1507 + 2 * (focus_padding + focus_width))
1510 height = (private_data->header_h + private_data->day_name_h
1511 + private_data->main_h);
1513 requisition->height = height + (widget->style->ythickness + INNER_BORDER) * 2;
1515 g_object_unref (layout);
1519 gtk_calendar_size_allocate (GtkWidget *widget,
1520 GtkAllocation *allocation)
1522 GtkCalendar *calendar;
1523 GtkCalendarPrivateData *private_data;
1524 gint xthickness = widget->style->xthickness;
1525 gint ythickness = widget->style->xthickness;
1528 widget->allocation = *allocation;
1530 calendar = GTK_CALENDAR (widget);
1531 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1533 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1534 year_left = private_data->year_before;
1536 year_left = !private_data->year_before;
1538 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1540 private_data->day_width = (private_data->min_day_width
1541 * ((allocation->width - (xthickness + INNER_BORDER) * 2
1542 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2))
1543 / (7 * private_data->min_day_width + private_data->max_week_char_width * 2));
1544 private_data->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2
1545 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 )
1546 - private_data->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1550 private_data->day_width = (allocation->width
1551 - (xthickness + INNER_BORDER) * 2
1552 - (CALENDAR_MARGIN * 2)
1553 - (DAY_XSEP * 6))/7;
1554 private_data->week_width = 0;
1557 if (GTK_WIDGET_REALIZED (widget))
1559 gdk_window_move_resize (widget->window,
1560 allocation->x, allocation->y,
1561 allocation->width, allocation->height);
1562 if (private_data->header_win)
1563 gdk_window_move_resize (private_data->header_win,
1564 xthickness, ythickness,
1565 allocation->width - 2 * xthickness, private_data->header_h);
1566 if (private_data->arrow_win[ARROW_MONTH_LEFT])
1569 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
1570 (allocation->width - 2 * xthickness
1571 - (3 + 2*private_data->arrow_width
1572 + private_data->max_month_width)),
1574 private_data->arrow_width,
1575 private_data->header_h - 7);
1577 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
1579 private_data->arrow_width,
1580 private_data->header_h - 7);
1582 if (private_data->arrow_win[ARROW_MONTH_RIGHT])
1585 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
1586 (allocation->width - 2 * xthickness
1587 - 3 - private_data->arrow_width),
1589 private_data->arrow_width,
1590 private_data->header_h - 7);
1592 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
1593 (private_data->arrow_width
1594 + private_data->max_month_width),
1596 private_data->arrow_width,
1597 private_data->header_h - 7);
1599 if (private_data->arrow_win[ARROW_YEAR_LEFT])
1602 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
1604 private_data->arrow_width,
1605 private_data->header_h - 7);
1607 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
1608 (allocation->width - 2 * xthickness
1609 - (3 + 2*private_data->arrow_width
1610 + private_data->max_year_width)),
1612 private_data->arrow_width,
1613 private_data->header_h - 7);
1615 if (private_data->arrow_win[ARROW_YEAR_RIGHT])
1618 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
1619 (private_data->arrow_width
1620 + private_data->max_year_width),
1622 private_data->arrow_width,
1623 private_data->header_h - 7);
1625 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
1626 (allocation->width - 2 * xthickness
1627 - 3 - private_data->arrow_width),
1629 private_data->arrow_width,
1630 private_data->header_h - 7);
1632 if (private_data->day_name_win)
1633 gdk_window_move_resize (private_data->day_name_win,
1634 xthickness + INNER_BORDER,
1635 private_data->header_h + (widget->style->ythickness + INNER_BORDER),
1636 allocation->width - (xthickness + INNER_BORDER) * 2,
1637 private_data->day_name_h);
1638 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1640 if (private_data->week_win)
1641 gdk_window_move_resize (private_data->week_win,
1642 (xthickness + INNER_BORDER),
1643 private_data->header_h + private_data->day_name_h
1644 + (widget->style->ythickness + INNER_BORDER),
1645 private_data->week_width,
1646 private_data->main_h);
1647 gdk_window_move_resize (private_data->main_win,
1648 private_data->week_width + (xthickness + INNER_BORDER),
1649 private_data->header_h + private_data->day_name_h
1650 + (widget->style->ythickness + INNER_BORDER),
1652 - private_data->week_width
1653 - (xthickness + INNER_BORDER) * 2,
1654 private_data->main_h);
1658 gdk_window_move_resize (private_data->main_win,
1659 (xthickness + INNER_BORDER),
1660 private_data->header_h + private_data->day_name_h
1661 + (widget->style->ythickness + INNER_BORDER),
1663 - private_data->week_width
1664 - (xthickness + INNER_BORDER) * 2,
1665 private_data->main_h);
1666 if (private_data->week_win)
1667 gdk_window_move_resize (private_data->week_win,
1669 - private_data->week_width
1670 - (xthickness + INNER_BORDER),
1671 private_data->header_h + private_data->day_name_h
1672 + (widget->style->ythickness + INNER_BORDER),
1673 private_data->week_width,
1674 private_data->main_h);
1680 gtk_calendar_expose (GtkWidget *widget,
1681 GdkEventExpose *event)
1683 GtkCalendar *calendar;
1684 GtkCalendarPrivateData *private_data;
1686 calendar = GTK_CALENDAR (widget);
1687 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1689 if (GTK_WIDGET_DRAWABLE (widget))
1691 if (event->window == private_data->main_win)
1692 gtk_calendar_paint_main (widget);
1694 if (event->window == private_data->header_win)
1695 gtk_calendar_paint_header (widget);
1697 if (event->window == private_data->day_name_win)
1698 gtk_calendar_paint_day_names (widget);
1700 if (event->window == private_data->week_win)
1701 gtk_calendar_paint_week_numbers (widget);
1702 if (event->window == widget->window)
1704 gtk_paint_shadow (widget->style, widget->window, GTK_WIDGET_STATE (widget),
1705 GTK_SHADOW_IN, NULL, widget, "calendar",
1706 0, 0, widget->allocation.width, widget->allocation.height);
1714 gtk_calendar_paint_header (GtkWidget *widget)
1716 GtkCalendar *calendar;
1720 gint header_width, cal_height;
1721 gint max_month_width;
1722 gint max_year_width;
1723 GtkCalendarPrivateData *private_data;
1724 PangoLayout *layout;
1725 PangoRectangle logical_rect;
1728 calendar = GTK_CALENDAR (widget);
1729 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1731 if (private_data->freeze_count)
1733 private_data->dirty_header = 1;
1737 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1738 year_left = private_data->year_before;
1740 year_left = !private_data->year_before;
1742 private_data->dirty_header = 0;
1746 gdk_window_clear (private_data->header_win);
1748 header_width = widget->allocation.width - 2 * widget->style->xthickness;
1749 cal_height = widget->allocation.height;
1751 max_month_width = private_data->max_month_width;
1752 max_year_width = private_data->max_year_width;
1754 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1755 gtk_paint_shadow (widget->style, private_data->header_win,
1756 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1757 NULL, widget, "calendar",
1758 0, 0, header_width, private_data->header_h);
1761 g_snprintf (buffer, sizeof (buffer), "%d", calendar->year);
1762 layout = gtk_widget_create_pango_layout (widget, buffer);
1763 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1766 y = (private_data->header_h - logical_rect.height) / 2;
1768 /* Draw year and its arrows */
1770 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1772 x = 3 + (max_year_width - logical_rect.width)/2;
1774 x = header_width - (3 + max_year_width
1775 - (max_year_width - logical_rect.width)/2);
1778 x = 3 + private_data->arrow_width + (max_year_width - logical_rect.width)/2;
1780 x = header_width - (3 + private_data->arrow_width + max_year_width
1781 - (max_year_width - logical_rect.width)/2);
1784 gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1785 gdk_draw_layout (private_data->header_win, gc, x, y, layout);
1788 g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]);
1789 pango_layout_set_text (layout, buffer, -1);
1790 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1792 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1794 x = header_width - (3 + max_month_width
1795 - (max_month_width - logical_rect.width)/2);
1797 x = 3 + (max_month_width - logical_rect.width) / 2;
1800 x = header_width - (3 + private_data->arrow_width + max_month_width
1801 - (max_month_width - logical_rect.width)/2);
1803 x = 3 + private_data->arrow_width + (max_month_width - logical_rect.width)/2;
1805 gdk_draw_layout (private_data->header_win, gc, x, y, layout);
1807 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1809 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
1810 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
1811 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
1812 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
1814 g_object_unref (layout);
1818 gtk_calendar_paint_day_names (GtkWidget *widget)
1820 GtkCalendar *calendar;
1824 int day_width, cal_width;
1827 PangoLayout *layout;
1828 PangoRectangle logical_rect;
1829 GtkCalendarPrivateData *private_data;
1833 g_return_if_fail (GTK_IS_CALENDAR (widget));
1834 calendar = GTK_CALENDAR (widget);
1835 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1838 gtk_widget_style_get (GTK_WIDGET (widget),
1839 "focus-line-width", &focus_width,
1840 "focus-padding", &focus_padding,
1843 * Handle freeze/thaw functionality
1846 if (private_data->freeze_count)
1848 private_data->dirty_day_names = 1;
1851 private_data->dirty_day_names = 0;
1857 gdk_window_clear (private_data->day_name_win);
1859 day_width = private_data->day_width;
1860 cal_width = widget->allocation.width;
1861 cal_height = widget->allocation.height;
1862 day_wid_sep = day_width + DAY_XSEP;
1865 * Draw rectangles as inverted background for the labels.
1868 gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
1869 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1870 CALENDAR_MARGIN, CALENDAR_MARGIN,
1871 cal_width-CALENDAR_MARGIN * 2,
1872 private_data->day_name_h - CALENDAR_MARGIN);
1874 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1875 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1877 private_data->day_name_h - CALENDAR_YSEP,
1878 private_data->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1885 layout = gtk_widget_create_pango_layout (widget, NULL);
1887 gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
1888 for (i = 0; i < 7; i++)
1890 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
1894 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1896 g_snprintf (buffer, sizeof (buffer), "%s", default_abbreviated_dayname[day]);
1898 pango_layout_set_text (layout, buffer, -1);
1899 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1901 gdk_draw_layout (private_data->day_name_win, gc,
1903 + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
1904 (private_data->week_width + (private_data->week_width ? CALENDAR_XSEP : 0))
1907 + (day_width - logical_rect.width)/2),
1908 CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y,
1912 g_object_unref (layout);
1916 gtk_calendar_paint_week_numbers (GtkWidget *widget)
1918 GtkCalendar *calendar;
1920 gint row, week = 0, year;
1923 gint y_loc, day_height;
1924 GtkCalendarPrivateData *private_data;
1925 PangoLayout *layout;
1926 PangoRectangle logical_rect;
1930 g_return_if_fail (GTK_IS_CALENDAR (widget));
1931 g_return_if_fail (widget->window != NULL);
1932 calendar = GTK_CALENDAR (widget);
1933 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1937 * Handle freeze/thaw functionality
1940 if (private_data->freeze_count)
1942 private_data->dirty_week = 1;
1945 private_data->dirty_week = 0;
1947 gtk_widget_style_get (GTK_WIDGET (widget),
1948 "focus-line-width", &focus_width,
1949 "focus-padding", &focus_padding,
1956 gdk_window_clear (private_data->week_win);
1959 * Draw a rectangle as inverted background for the labels.
1962 gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
1963 if (private_data->day_name_win)
1964 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1967 private_data->week_width - CALENDAR_MARGIN,
1968 private_data->main_h - CALENDAR_MARGIN);
1970 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1973 private_data->week_width - CALENDAR_MARGIN,
1974 private_data->main_h - 2 * CALENDAR_MARGIN);
1980 layout = gtk_widget_create_pango_layout (widget, NULL);
1982 gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
1983 day_height = row_height (calendar);
1984 for (row = 0; row < 6; row++)
1986 year = calendar->year;
1987 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
1990 g_return_if_fail (week_of_year (&week, &year,
1991 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
1992 + calendar->month) % 12 + 1, calendar->day[row][6]));
1994 g_snprintf (buffer, sizeof (buffer), "%d", week);
1995 pango_layout_set_text (layout, buffer, -1);
1996 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1998 y_loc = top_y_for_row (calendar, row) + (day_height - logical_rect.height) / 2;
2000 x_loc = (private_data->week_width
2001 - logical_rect.width
2002 - CALENDAR_XSEP - focus_padding - focus_width);
2004 gdk_draw_layout (private_data->week_win, gc, x_loc, y_loc, layout);
2007 g_object_unref (layout);
2011 gtk_calendar_paint_day_num (GtkWidget *widget,
2014 GtkCalendar *calendar;
2015 gint r, c, row, col;
2017 g_return_if_fail (GTK_IS_CALENDAR (widget));
2019 calendar = GTK_CALENDAR (widget);
2023 for (r = 0; r < 6; r++)
2024 for (c = 0; c < 7; c++)
2025 if (calendar->day_month[r][c] == MONTH_CURRENT &&
2026 calendar->day[r][c] == day)
2032 g_return_if_fail (row != -1);
2033 g_return_if_fail (col != -1);
2035 gtk_calendar_paint_day (widget, row, col);
2039 gtk_calendar_paint_day (GtkWidget *widget,
2043 GtkCalendar *calendar;
2055 GtkCalendarPrivateData *private_data;
2056 PangoLayout *layout;
2057 PangoRectangle logical_rect;
2059 g_return_if_fail (GTK_IS_CALENDAR (widget));
2060 g_return_if_fail (row < 6);
2061 g_return_if_fail (col < 7);
2062 calendar = GTK_CALENDAR (widget);
2063 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2066 * Handle freeze/thaw functionality
2069 if (private_data->freeze_count)
2071 private_data->dirty_main = 1;
2075 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2077 day_height = row_height (calendar);
2079 day_xspace = private_data->day_width - private_data->max_day_char_width*2;
2081 day = calendar->day[row][col];
2083 x_left = left_x_for_column (calendar, col);
2084 x_loc = x_left + private_data->day_width / 2 + private_data->max_day_char_width;
2086 y_top = top_y_for_row (calendar, row);
2088 gdk_window_clear_area (private_data->main_win, x_left, y_top,
2089 private_data->day_width, day_height);
2093 if (calendar->day_month[row][col] == MONTH_PREV)
2095 gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
2097 else if (calendar->day_month[row][col] == MONTH_NEXT)
2099 gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
2104 if (calendar->highlight_row == row && calendar->highlight_col == col)
2106 gdk_gc_set_foreground (gc, HIGHLIGHT_BACK_COLOR (GTK_WIDGET (calendar)));
2107 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
2108 private_data->day_width, day_height);
2111 if (calendar->selected_day == day)
2113 gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar)));
2114 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
2115 private_data->day_width, day_height);
2118 if (calendar->marked_date[day-1])
2119 gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar)));
2121 gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
2123 if (calendar->selected_day == day)
2124 gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar)));
2126 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)]));
2130 g_snprintf (buffer, sizeof (buffer), "%d", day);
2131 layout = gtk_widget_create_pango_layout (widget, buffer);
2132 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2134 x_loc -= logical_rect.width;
2136 y_loc = y_top + (day_height - logical_rect.height) / 2;
2137 gdk_draw_layout (private_data->main_win, gc,
2138 x_loc, y_loc, layout);
2139 if (calendar->marked_date[day-1]
2140 && calendar->day_month[row][col] == MONTH_CURRENT)
2141 gdk_draw_layout (private_data->main_win, gc,
2142 x_loc-1, y_loc, layout);
2144 if (GTK_WIDGET_HAS_FOCUS (calendar)
2145 && calendar->focus_row == row && calendar->focus_col == col)
2149 if (calendar->selected_day == day)
2150 state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
2152 state = GTK_STATE_NORMAL;
2154 gtk_paint_focus (widget->style,
2155 private_data->main_win,
2156 (calendar->selected_day == day)
2157 ? GTK_STATE_SELECTED : GTK_STATE_NORMAL,
2158 NULL, widget, "calendar-day",
2160 private_data->day_width,
2164 g_object_unref (layout);
2169 gtk_calendar_paint_main (GtkWidget *widget)
2171 GtkCalendar *calendar;
2172 GtkCalendarPrivateData *private_data;
2175 g_return_if_fail (GTK_IS_CALENDAR (widget));
2176 g_return_if_fail (widget->window != NULL);
2178 calendar = GTK_CALENDAR (widget);
2179 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2181 if (private_data->freeze_count)
2183 private_data->dirty_main = 1;
2186 private_data->dirty_main = 0;
2187 gdk_window_clear (private_data->main_win);
2189 /* gtk_calendar_compute_days (calendar); */ /* REMOVE later */
2191 for (col = 0; col < 7; col++)
2192 for (row = 0; row < 6; row++)
2193 gtk_calendar_paint_day (widget, row, col);
2197 gtk_calendar_compute_days (GtkCalendar *calendar)
2201 gint ndays_in_month;
2202 gint ndays_in_prev_month;
2208 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2210 year = calendar->year;
2211 month = calendar->month + 1;
2213 ndays_in_month = month_length[leap (year)][month];
2215 first_day = day_of_week (year, month, 1);
2217 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
2223 /* Compute days of previous month */
2225 ndays_in_prev_month = month_length[leap (year)][month-1];
2227 ndays_in_prev_month = month_length[leap (year)][12];
2228 day = ndays_in_prev_month - first_day + 1;
2233 for (col = 0; col < first_day; col++)
2235 calendar->day[row][col] = day;
2236 calendar->day_month[row][col] = MONTH_PREV;
2241 /* Compute days of current month */
2243 for (day = 1; day <= ndays_in_month; day++)
2245 calendar->day[row][col] = day;
2246 calendar->day_month[row][col] = MONTH_CURRENT;
2256 /* Compute days of next month */
2258 for (; row <= 5; row++)
2260 for (; col <= 6; col++)
2262 calendar->day[row][col] = day;
2263 calendar->day_month[row][col] = MONTH_NEXT;
2271 gtk_calendar_display_options (GtkCalendar *calendar,
2272 GtkCalendarDisplayOptions flags)
2274 gtk_calendar_set_display_options (calendar, flags);
2278 * gtk_calendar_get_display_options:
2279 * @calendar: a #GtkCalendar
2281 * Returns the current display options of @calendar.
2283 * Return value: the display options.
2287 GtkCalendarDisplayOptions
2288 gtk_calendar_get_display_options (GtkCalendar *calendar)
2290 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), 0);
2292 return calendar->display_flags;
2296 * gtk_calendar_set_display_options:
2297 * @calendar: a #GtkCalendar
2298 * @flags: the display options to set
2300 * Sets display options (whether to display the heading and the month
2306 gtk_calendar_set_display_options (GtkCalendar *calendar,
2307 GtkCalendarDisplayOptions flags)
2309 GtkCalendarPrivateData *private_data;
2313 GtkCalendarDisplayOptions old_flags;
2315 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2317 widget = GTK_WIDGET (calendar);
2318 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2319 old_flags = calendar->display_flags;
2321 if (GTK_WIDGET_REALIZED (widget))
2323 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
2326 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2327 && (private_data->header_win))
2329 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
2330 gtk_calendar_realize_arrows (widget);
2334 for (i = 0; i < 4; i++)
2336 if (private_data->arrow_win[i])
2338 gdk_window_set_user_data (private_data->arrow_win[i],
2340 gdk_window_destroy (private_data->arrow_win[i]);
2341 private_data->arrow_win[i] = NULL;
2347 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
2351 if (flags & GTK_CALENDAR_SHOW_HEADING)
2353 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
2354 gtk_calendar_realize_header (widget);
2358 for (i = 0; i < 4; i++)
2360 if (private_data->arrow_win[i])
2362 gdk_window_set_user_data (private_data->arrow_win[i],
2364 gdk_window_destroy (private_data->arrow_win[i]);
2365 private_data->arrow_win[i] = NULL;
2368 gdk_window_set_user_data (private_data->header_win, NULL);
2369 gdk_window_destroy (private_data->header_win);
2370 private_data->header_win = NULL;
2375 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
2379 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
2381 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
2382 gtk_calendar_realize_day_names (widget);
2386 gdk_window_set_user_data (private_data->day_name_win, NULL);
2387 gdk_window_destroy (private_data->day_name_win);
2388 private_data->day_name_win = NULL;
2392 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2396 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2398 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
2399 gtk_calendar_realize_week_numbers (widget);
2403 gdk_window_set_user_data (private_data->week_win, NULL);
2404 gdk_window_destroy (private_data->week_win);
2405 private_data->week_win = NULL;
2409 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
2411 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
2412 calendar->display_flags &= ~GTK_CALENDAR_WEEK_START_MONDAY;
2414 calendar->display_flags |= GTK_CALENDAR_WEEK_START_MONDAY;
2416 gtk_calendar_compute_days (calendar);
2417 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2418 if (private_data->day_name_win)
2419 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2422 calendar->display_flags = flags;
2424 gtk_widget_queue_resize (GTK_WIDGET (calendar));
2428 calendar->display_flags = flags;
2430 g_object_freeze_notify (G_OBJECT (calendar));
2431 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
2432 g_object_notify (G_OBJECT (calendar), "show_heading");
2433 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
2434 g_object_notify (G_OBJECT (calendar), "show_day_names");
2435 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
2436 g_object_notify (G_OBJECT (calendar), "no_month_change");
2437 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2438 g_object_notify (G_OBJECT (calendar), "show_week_numbers");
2439 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
2440 g_object_notify (G_OBJECT (calendar), "week_start_monday");
2441 g_object_thaw_notify (G_OBJECT (calendar));
2445 gtk_calendar_select_month (GtkCalendar *calendar,
2449 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2450 g_return_val_if_fail (month <= 11, FALSE);
2452 calendar->month = month;
2453 calendar->year = year;
2455 gtk_calendar_compute_days (calendar);
2457 gtk_widget_queue_draw (GTK_WIDGET (calendar));
2459 g_object_freeze_notify (G_OBJECT (calendar));
2460 g_object_notify (G_OBJECT (calendar), "month");
2461 g_object_notify (G_OBJECT (calendar), "year");
2462 g_object_thaw_notify (G_OBJECT (calendar));
2464 g_signal_emit (calendar,
2465 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
2471 gtk_calendar_select_day (GtkCalendar *calendar,
2474 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2475 g_return_if_fail (day <= 31);
2477 /* gtk_calendar_compute_days (calendar); */
2479 /* Deselect the old day */
2480 if (calendar->selected_day > 0)
2484 selected_day = calendar->selected_day;
2485 calendar->selected_day = 0;
2486 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2487 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day);
2490 calendar->selected_day = day;
2492 /* Select the new day */
2495 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2496 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), day);
2499 g_object_notify (G_OBJECT (calendar), "day");
2501 g_signal_emit (calendar,
2502 gtk_calendar_signals[DAY_SELECTED_SIGNAL],
2507 gtk_calendar_select_and_focus_day (GtkCalendar *calendar,
2510 gint old_focus_row = calendar->focus_row;
2511 gint old_focus_col = calendar->focus_col;
2515 for (row = 0; row < 6; row ++)
2516 for (col = 0; col < 7; col++)
2518 if (calendar->day_month[row][col] == MONTH_CURRENT
2519 && calendar->day[row][col] == day)
2521 calendar->focus_row = row;
2522 calendar->focus_col = col;
2526 if (old_focus_row != -1 && old_focus_col != -1)
2527 gtk_calendar_paint_day (GTK_WIDGET (calendar), old_focus_row, old_focus_col);
2529 gtk_calendar_select_day (calendar, day);
2533 gtk_calendar_clear_marks (GtkCalendar *calendar)
2537 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2539 for (day = 0; day < 31; day++)
2541 calendar->marked_date[day] = FALSE;
2544 calendar->num_marked_dates = 0;
2546 if (GTK_WIDGET_DRAWABLE (calendar))
2548 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2553 gtk_calendar_mark_day (GtkCalendar *calendar,
2556 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2558 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE)
2560 calendar->marked_date[day - 1] = TRUE;
2561 calendar->num_marked_dates++;
2563 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2565 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2572 gtk_calendar_unmark_day (GtkCalendar *calendar,
2575 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2577 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE)
2579 calendar->marked_date[day - 1] = FALSE;
2580 calendar->num_marked_dates--;
2583 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2585 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2592 gtk_calendar_get_date (GtkCalendar *calendar,
2597 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2600 *year = calendar->year;
2603 *month = calendar->month;
2606 *day = calendar->selected_day;
2609 #define CALENDAR_INITIAL_TIMER_DELAY 200
2610 #define CALENDAR_TIMER_DELAY 20
2613 arrow_action (GtkCalendar *calendar,
2618 case ARROW_YEAR_LEFT:
2619 gtk_calendar_set_year_prev (calendar);
2621 case ARROW_YEAR_RIGHT:
2622 gtk_calendar_set_year_next (calendar);
2624 case ARROW_MONTH_LEFT:
2625 gtk_calendar_set_month_prev (calendar);
2627 case ARROW_MONTH_RIGHT:
2628 gtk_calendar_set_month_next (calendar);
2636 calendar_timer (gpointer data)
2638 GtkCalendar *calendar = data;
2639 GtkCalendarPrivateData *private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2640 gboolean retval = FALSE;
2642 GDK_THREADS_ENTER ();
2644 if (private_data->timer)
2646 arrow_action (calendar, private_data->click_child);
2648 if (private_data->need_timer)
2650 private_data->need_timer = FALSE;
2651 private_data->timer = g_timeout_add (CALENDAR_TIMER_DELAY,
2652 (GtkFunction) calendar_timer,
2653 (gpointer) calendar);
2659 GDK_THREADS_LEAVE ();
2665 start_spinning (GtkWidget *widget,
2668 GtkCalendarPrivateData *private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2670 private_data->click_child = click_child;
2672 if (!private_data->timer)
2674 private_data->need_timer = TRUE;
2675 private_data->timer = g_timeout_add (CALENDAR_INITIAL_TIMER_DELAY,
2682 stop_spinning (GtkWidget *widget)
2684 GtkCalendarPrivateData *private_data;
2686 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2688 if (private_data->timer)
2690 g_source_remove (private_data->timer);
2691 private_data->timer = 0;
2692 private_data->need_timer = FALSE;
2697 gtk_calendar_destroy (GtkObject *object)
2699 stop_spinning (GTK_WIDGET (object));
2701 GTK_OBJECT_CLASS (parent_class)->destroy (object);
2705 gtk_calendar_grab_notify (GtkWidget *widget,
2706 gboolean was_grabbed)
2709 stop_spinning (widget);
2713 gtk_calendar_button_press (GtkWidget *widget,
2714 GdkEventButton *event)
2716 GtkCalendar *calendar;
2717 GtkCalendarPrivateData *private_data;
2720 calendar = GTK_CALENDAR (widget);
2721 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2723 if (event->window == private_data->main_win)
2724 gtk_calendar_main_button (widget, event);
2726 if (!GTK_WIDGET_HAS_FOCUS (widget))
2727 gtk_widget_grab_focus (widget);
2729 for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++)
2731 if (event->window == private_data->arrow_win[arrow])
2734 /* only call the action on single click, not double */
2735 if (event->type == GDK_BUTTON_PRESS)
2737 arrow_action (calendar, arrow);
2739 if (event->button == 1)
2740 start_spinning (widget, arrow);
2751 gtk_calendar_button_release (GtkWidget *widget,
2752 GdkEventButton *event)
2754 if (event->button == 1)
2755 stop_spinning (widget);
2761 gtk_calendar_motion_notify (GtkWidget *widget,
2762 GdkEventMotion *event)
2764 GtkCalendar *calendar;
2765 GtkCalendarPrivateData *private_data;
2766 gint event_x, event_y;
2768 gint old_row, old_col;
2770 calendar = GTK_CALENDAR (widget);
2771 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2772 event_x = (gint) (event->x);
2773 event_y = (gint) (event->y);
2775 if (event->window == private_data->main_win)
2778 row = row_from_y (calendar, event_y);
2779 col = column_from_x (calendar, event_x);
2781 if (row != calendar->highlight_row || calendar->highlight_col != col)
2783 old_row = calendar->highlight_row;
2784 old_col = calendar->highlight_col;
2785 if (old_row > -1 && old_col > -1)
2787 calendar->highlight_row = -1;
2788 calendar->highlight_col = -1;
2789 gtk_calendar_paint_day (widget, old_row, old_col);
2792 calendar->highlight_row = row;
2793 calendar->highlight_col = col;
2795 if (row > -1 && col > -1)
2796 gtk_calendar_paint_day (widget, row, col);
2803 gtk_calendar_enter_notify (GtkWidget *widget,
2804 GdkEventCrossing *event)
2806 GtkCalendar *calendar;
2807 GtkCalendarPrivateData *private_data;
2809 calendar = GTK_CALENDAR (widget);
2810 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2812 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2814 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2815 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2818 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2820 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2821 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2824 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2826 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2827 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2830 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2832 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2833 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2840 gtk_calendar_leave_notify (GtkWidget *widget,
2841 GdkEventCrossing *event)
2843 GtkCalendar *calendar;
2844 GtkCalendarPrivateData *private_data;
2848 calendar = GTK_CALENDAR (widget);
2849 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2851 if (event->window == private_data->main_win)
2853 row = calendar->highlight_row;
2854 col = calendar->highlight_col;
2855 calendar->highlight_row = -1;
2856 calendar->highlight_col = -1;
2857 if (row > -1 && col > -1)
2858 gtk_calendar_paint_day (widget, row, col);
2861 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2863 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2864 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2867 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2869 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2870 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2873 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2875 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2876 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2879 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2881 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2882 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2889 gtk_calendar_paint_arrow (GtkWidget *widget,
2892 GtkCalendarPrivateData *private_data;
2895 GtkCalendar *calendar;
2899 calendar = GTK_CALENDAR (widget);
2900 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2902 if (private_data->freeze_count)
2904 private_data->dirty_header = 1;
2907 window = private_data->arrow_win[arrow];
2910 state = private_data->arrow_state[arrow];
2913 gdk_window_clear (window);
2914 gdk_window_set_background (window, &(widget)->style->bg[state]);
2915 gdk_drawable_get_size (window, &width, &height);
2916 gdk_window_clear_area (window,
2920 gdk_gc_set_foreground (gc, & (widget)->style->fg[state]);
2922 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2923 draw_arrow_left (window, gc, width/2 - 3, height/2 - 4, 8);
2925 draw_arrow_right (window, gc, width/2 - 2, height/2 - 4, 8);
2931 gtk_calendar_freeze (GtkCalendar *calendar)
2933 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2935 GTK_CALENDAR_PRIVATE_DATA (calendar)->freeze_count++;
2939 gtk_calendar_thaw (GtkCalendar *calendar)
2941 GtkCalendarPrivateData *private_data;
2943 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2945 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2947 if (private_data->freeze_count)
2948 if (!(--private_data->freeze_count))
2950 if (private_data->dirty_header)
2951 if (GTK_WIDGET_DRAWABLE (calendar))
2952 gtk_calendar_paint_header (GTK_WIDGET (calendar));
2954 if (private_data->dirty_day_names)
2955 if (GTK_WIDGET_DRAWABLE (calendar))
2956 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2958 if (private_data->dirty_week)
2959 if (GTK_WIDGET_DRAWABLE (calendar))
2960 gtk_calendar_paint_week_numbers (GTK_WIDGET (calendar));
2962 if (private_data->dirty_main)
2963 if (GTK_WIDGET_DRAWABLE (calendar))
2964 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2969 gtk_calendar_set_background (GtkWidget *widget)
2971 GtkCalendar *calendar;
2972 GtkCalendarPrivateData *private_data;
2975 calendar = GTK_CALENDAR (widget);
2976 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2978 if (GTK_WIDGET_REALIZED (widget))
2980 for (i = 0; i < 4; i++)
2982 if (private_data->arrow_win[i])
2983 gdk_window_set_background (private_data->arrow_win[i],
2984 HEADER_BG_COLOR (widget));
2986 if (private_data->header_win)
2987 gdk_window_set_background (private_data->header_win,
2988 HEADER_BG_COLOR (widget));
2989 if (private_data->day_name_win)
2990 gdk_window_set_background (private_data->day_name_win,
2991 BACKGROUND_COLOR (widget));
2992 if (private_data->week_win)
2993 gdk_window_set_background (private_data->week_win,
2994 BACKGROUND_COLOR (widget));
2995 if (private_data->main_win)
2996 gdk_window_set_background (private_data->main_win,
2997 BACKGROUND_COLOR (widget));
2999 gdk_window_set_background (widget->window,
3000 BACKGROUND_COLOR (widget));
3005 gtk_calendar_style_set (GtkWidget *widget,
3006 GtkStyle *previous_style)
3008 if (previous_style && GTK_WIDGET_REALIZED (widget))
3009 gtk_calendar_set_background(widget);
3013 gtk_calendar_state_changed (GtkWidget *widget,
3014 GtkStateType previous_state)
3016 if (!GTK_WIDGET_IS_SENSITIVE (widget))
3017 stop_spinning (widget);
3019 gtk_calendar_set_background (widget);
3023 gtk_calendar_finalize (GObject *object)
3025 GtkCalendarPrivateData *private_data;
3026 private_data = GTK_CALENDAR_PRIVATE_DATA (object);
3028 g_free (private_data);
3030 if (G_OBJECT_CLASS (parent_class)->finalize)
3031 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
3035 gtk_calendar_scroll (GtkWidget *widget,
3036 GdkEventScroll *event)
3038 GtkCalendar *calendar = GTK_CALENDAR (widget);
3040 if (event->direction == GDK_SCROLL_UP)
3042 if (!GTK_WIDGET_HAS_FOCUS (widget))
3043 gtk_widget_grab_focus (widget);
3044 gtk_calendar_set_month_prev (calendar);
3046 else if (event->direction == GDK_SCROLL_DOWN)
3048 if (!GTK_WIDGET_HAS_FOCUS (widget))
3049 gtk_widget_grab_focus (widget);
3050 gtk_calendar_set_month_next (calendar);
3059 move_focus (GtkCalendar *calendar,
3062 GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar));
3064 if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) ||
3065 (text_dir == GTK_TEXT_DIR_RTL && direction == 1))
3067 if (calendar->focus_col > 0)
3068 calendar->focus_col--;
3069 else if (calendar->focus_row > 0)
3071 calendar->focus_col = 6;
3072 calendar->focus_row--;
3077 if (calendar->focus_col < 6)
3078 calendar->focus_col++;
3079 else if (calendar->focus_row < 5)
3081 calendar->focus_col = 0;
3082 calendar->focus_row++;
3088 gtk_calendar_key_press (GtkWidget *widget,
3091 GtkCalendar *calendar;
3097 calendar = GTK_CALENDAR (widget);
3100 old_focus_row = calendar->focus_row;
3101 old_focus_col = calendar->focus_col;
3103 switch (event->keyval)
3108 if (event->state & GDK_CONTROL_MASK)
3109 gtk_calendar_set_month_prev (calendar);
3112 move_focus (calendar, -1);
3113 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
3114 gtk_calendar_paint_day (widget, calendar->focus_row,
3115 calendar->focus_col);
3121 if (event->state & GDK_CONTROL_MASK)
3122 gtk_calendar_set_month_next (calendar);
3125 move_focus (calendar, 1);
3126 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
3127 gtk_calendar_paint_day (widget, calendar->focus_row,
3128 calendar->focus_col);
3134 if (event->state & GDK_CONTROL_MASK)
3135 gtk_calendar_set_year_prev (calendar);
3138 if (calendar->focus_row > 0)
3139 calendar->focus_row--;
3140 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
3141 gtk_calendar_paint_day (widget, calendar->focus_row,
3142 calendar->focus_col);
3148 if (event->state & GDK_CONTROL_MASK)
3149 gtk_calendar_set_year_next (calendar);
3152 if (calendar->focus_row < 5)
3153 calendar->focus_row++;
3154 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
3155 gtk_calendar_paint_day (widget, calendar->focus_row,
3156 calendar->focus_col);
3161 row = calendar->focus_row;
3162 col = calendar->focus_col;
3163 day = calendar->day[row][col];
3165 if (row > -1 && col > -1)
3168 gtk_calendar_freeze (calendar);
3170 if (calendar->day_month[row][col] == MONTH_PREV)
3171 gtk_calendar_set_month_prev (calendar);
3172 else if (calendar->day_month[row][col] == MONTH_NEXT)
3173 gtk_calendar_set_month_next (calendar);
3175 gtk_calendar_select_and_focus_day (calendar, day);
3177 gtk_calendar_thaw (calendar);
3185 gtk_calendar_set_display_option (GtkCalendar *calendar,
3186 GtkCalendarDisplayOptions flag,
3189 GtkCalendarDisplayOptions flags;
3191 flags = calendar->display_flags | flag;
3193 flags = calendar->display_flags & ~flag;
3194 gtk_calendar_display_options (calendar, flags);
3198 gtk_calendar_get_display_option (GtkCalendar *calendar,
3199 GtkCalendarDisplayOptions flag)
3201 return (calendar->display_flags & flag) != 0;
3206 gtk_calendar_set_property (GObject *object,
3208 const GValue *value,
3211 GtkCalendar *calendar;
3213 calendar = GTK_CALENDAR (object);
3218 gtk_calendar_select_month (calendar,
3220 g_value_get_int (value));
3223 gtk_calendar_select_month (calendar,
3224 g_value_get_int (value),
3228 gtk_calendar_select_day (calendar,
3229 g_value_get_int (value));
3231 case PROP_SHOW_HEADING:
3232 gtk_calendar_set_display_option (calendar,
3233 GTK_CALENDAR_SHOW_HEADING,
3234 g_value_get_boolean (value));
3236 case PROP_SHOW_DAY_NAMES:
3237 gtk_calendar_set_display_option (calendar,
3238 GTK_CALENDAR_SHOW_DAY_NAMES,
3239 g_value_get_boolean (value));
3241 case PROP_NO_MONTH_CHANGE:
3242 gtk_calendar_set_display_option (calendar,
3243 GTK_CALENDAR_NO_MONTH_CHANGE,
3244 g_value_get_boolean (value));
3246 case PROP_SHOW_WEEK_NUMBERS:
3247 gtk_calendar_set_display_option (calendar,
3248 GTK_CALENDAR_SHOW_WEEK_NUMBERS,
3249 g_value_get_boolean (value));
3251 case PROP_WEEK_START_MONDAY:
3252 gtk_calendar_set_display_option (calendar,
3253 GTK_CALENDAR_WEEK_START_MONDAY,
3254 g_value_get_boolean (value));
3257 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3263 gtk_calendar_get_property (GObject *object,
3268 GtkCalendar *calendar;
3270 calendar = GTK_CALENDAR (object);
3275 g_value_set_int (value, calendar->year);
3278 g_value_set_int (value, calendar->month);
3281 g_value_set_int (value, calendar->selected_day);
3283 case PROP_SHOW_HEADING:
3284 g_value_set_boolean (value, gtk_calendar_get_display_option (calendar,
3285 GTK_CALENDAR_SHOW_HEADING));
3287 case PROP_SHOW_DAY_NAMES:
3288 g_value_set_boolean (value, gtk_calendar_get_display_option (calendar,
3289 GTK_CALENDAR_SHOW_DAY_NAMES));
3291 case PROP_NO_MONTH_CHANGE:
3292 g_value_set_boolean (value, gtk_calendar_get_display_option (calendar,
3293 GTK_CALENDAR_NO_MONTH_CHANGE));
3295 case PROP_SHOW_WEEK_NUMBERS:
3296 g_value_set_boolean (value, gtk_calendar_get_display_option (calendar,
3297 GTK_CALENDAR_SHOW_WEEK_NUMBERS));
3299 case PROP_WEEK_START_MONDAY:
3300 g_value_set_boolean (value, gtk_calendar_get_display_option (calendar,
3301 GTK_CALENDAR_WEEK_START_MONDAY));
3304 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);