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 Groenlund
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
37 #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
43 #include <glib/gprintf.h>
45 #undef GTK_DISABLE_DEPRECATED
46 #include "gtkcalendar.h"
47 #define GTK_DISABLE_DEPRECATED
52 #include "gtkmarshalers.h"
53 #include "gtkprivate.h"
55 #include "gdk/gdkkeysyms.h"
58 /***************************************************************************/
59 /* The following date routines are taken from the lib_date package. Keep
60 * them separate in case we want to update them if a newer lib_date comes
63 typedef unsigned int N_int;
64 typedef unsigned long N_long;
65 typedef signed long Z_long;
66 typedef enum { false = FALSE , true = TRUE } boolean;
68 #define and && /* logical (boolean) operators: lower case */
71 static const N_int month_length[2][13] =
73 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
74 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
77 static const N_int days_in_months[2][14] =
79 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
80 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
83 static Z_long calc_days(N_int year, N_int mm, N_int dd);
84 static N_int day_of_week(N_int year, N_int mm, N_int dd);
85 static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1,
86 N_int year2, N_int mm2, N_int dd2);
87 static N_int weeks_in_year(N_int year);
92 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
96 day_of_week(N_int year, N_int mm, N_int dd)
100 days = calc_days(year, mm, dd);
107 return( (N_int) days );
110 static N_int weeks_in_year(N_int year)
112 return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
116 check_date(N_int year, N_int mm, N_int dd)
118 if (year < 1) return(false);
119 if ((mm < 1) or (mm > 12)) return(false);
120 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
125 week_number(N_int year, N_int mm, N_int dd)
129 first = day_of_week(year,1,1) - 1;
130 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
135 year_to_days(N_int year)
137 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
142 calc_days(N_int year, N_int mm, N_int dd)
146 if (year < 1) return(0L);
147 if ((mm < 1) or (mm > 12)) return(0L);
148 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
149 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
153 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
155 if (check_date(*year,mm,dd))
157 *week = week_number(*year,mm,dd);
159 *week = weeks_in_year(--(*year));
160 else if (*week > weeks_in_year(*year))
171 dates_difference(N_int year1, N_int mm1, N_int dd1,
172 N_int year2, N_int mm2, N_int dd2)
174 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
177 /*** END OF lib_date routines ********************************************/
179 /* Spacing around day/week headers and main area, inside those windows */
180 #define CALENDAR_MARGIN 0
181 /* Spacing around day/week headers and main area, outside those windows */
182 #define INNER_BORDER 4
183 /* Separation between day headers and main area */
184 #define CALENDAR_YSEP 4
185 /* Separation between week headers and main area */
186 #define CALENDAR_XSEP 4
188 #define DAY_XSEP 0 /* not really good for small calendar */
189 #define DAY_YSEP 0 /* not really good for small calendar */
192 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
193 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
194 #define SELECTED_BG_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
195 #define SELECTED_FG_COLOR(widget) (& (widget)->style->text[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
196 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
197 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
198 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
199 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
200 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
201 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
217 MONTH_CHANGED_SIGNAL,
219 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
235 PROP_NO_MONTH_CHANGE,
236 PROP_SHOW_WEEK_NUMBERS,
240 static guint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
242 struct _GtkCalendarPrivate
244 GdkWindow *header_win;
245 GdkWindow *day_name_win;
248 GdkWindow *arrow_win[4];
254 guint arrow_state[4];
256 guint max_month_width;
257 guint max_year_width;
263 guint max_day_char_width;
264 guint max_day_char_ascent;
265 guint max_day_char_descent;
266 guint max_label_char_ascent;
267 guint max_label_char_descent;
268 guint max_week_char_width;
271 guint year_before : 1;
273 guint need_timer : 1;
276 guint drag_highlight : 1;
287 #define GTK_CALENDAR_GET_PRIVATE(widget) (GTK_CALENDAR (widget)->priv)
289 static void gtk_calendar_finalize (GObject *calendar);
290 static void gtk_calendar_destroy (GtkObject *calendar);
291 static void gtk_calendar_set_property (GObject *object,
295 static void gtk_calendar_get_property (GObject *object,
300 static void gtk_calendar_realize (GtkWidget *widget);
301 static void gtk_calendar_unrealize (GtkWidget *widget);
302 static void gtk_calendar_size_request (GtkWidget *widget,
303 GtkRequisition *requisition);
304 static void gtk_calendar_size_allocate (GtkWidget *widget,
305 GtkAllocation *allocation);
306 static gboolean gtk_calendar_expose (GtkWidget *widget,
307 GdkEventExpose *event);
308 static gboolean gtk_calendar_button_press (GtkWidget *widget,
309 GdkEventButton *event);
310 static gboolean gtk_calendar_button_release (GtkWidget *widget,
311 GdkEventButton *event);
312 static gboolean gtk_calendar_motion_notify (GtkWidget *widget,
313 GdkEventMotion *event);
314 static gboolean gtk_calendar_enter_notify (GtkWidget *widget,
315 GdkEventCrossing *event);
316 static gboolean gtk_calendar_leave_notify (GtkWidget *widget,
317 GdkEventCrossing *event);
318 static gboolean gtk_calendar_scroll (GtkWidget *widget,
319 GdkEventScroll *event);
320 static gboolean gtk_calendar_key_press (GtkWidget *widget,
322 static gboolean gtk_calendar_focus_out (GtkWidget *widget,
323 GdkEventFocus *event);
324 static void gtk_calendar_grab_notify (GtkWidget *widget,
325 gboolean was_grabbed);
326 static void gtk_calendar_state_changed (GtkWidget *widget,
327 GtkStateType previous_state);
328 static void gtk_calendar_style_set (GtkWidget *widget,
329 GtkStyle *previous_style);
331 static void gtk_calendar_drag_data_get (GtkWidget *widget,
332 GdkDragContext *context,
333 GtkSelectionData *selection_data,
336 static void gtk_calendar_drag_data_received (GtkWidget *widget,
337 GdkDragContext *context,
340 GtkSelectionData *selection_data,
343 static gboolean gtk_calendar_drag_motion (GtkWidget *widget,
344 GdkDragContext *context,
348 static void gtk_calendar_drag_leave (GtkWidget *widget,
349 GdkDragContext *context,
351 static gboolean gtk_calendar_drag_drop (GtkWidget *widget,
352 GdkDragContext *context,
357 static void calendar_start_spinning (GtkCalendar *calendar,
359 static void calendar_stop_spinning (GtkCalendar *calendar);
361 static void calendar_invalidate_day (GtkCalendar *widget,
364 static void calendar_invalidate_day_num (GtkCalendar *widget,
366 static void calendar_invalidate_arrow (GtkCalendar *widget,
369 static void calendar_compute_days (GtkCalendar *calendar);
371 static char *default_abbreviated_dayname[7];
372 static char *default_monthname[12];
374 G_DEFINE_TYPE (GtkCalendar, gtk_calendar, GTK_TYPE_WIDGET)
377 gtk_calendar_class_init (GtkCalendarClass *class)
379 GObjectClass *gobject_class;
380 GtkObjectClass *object_class;
381 GtkWidgetClass *widget_class;
383 gobject_class = (GObjectClass*) class;
384 object_class = (GtkObjectClass*) class;
385 widget_class = (GtkWidgetClass*) class;
387 gobject_class->set_property = gtk_calendar_set_property;
388 gobject_class->get_property = gtk_calendar_get_property;
389 gobject_class->finalize = gtk_calendar_finalize;
391 object_class->destroy = gtk_calendar_destroy;
393 widget_class->realize = gtk_calendar_realize;
394 widget_class->unrealize = gtk_calendar_unrealize;
395 widget_class->expose_event = gtk_calendar_expose;
396 widget_class->size_request = gtk_calendar_size_request;
397 widget_class->size_allocate = gtk_calendar_size_allocate;
398 widget_class->button_press_event = gtk_calendar_button_press;
399 widget_class->button_release_event = gtk_calendar_button_release;
400 widget_class->motion_notify_event = gtk_calendar_motion_notify;
401 widget_class->enter_notify_event = gtk_calendar_enter_notify;
402 widget_class->leave_notify_event = gtk_calendar_leave_notify;
403 widget_class->key_press_event = gtk_calendar_key_press;
404 widget_class->scroll_event = gtk_calendar_scroll;
405 widget_class->style_set = gtk_calendar_style_set;
406 widget_class->state_changed = gtk_calendar_state_changed;
407 widget_class->grab_notify = gtk_calendar_grab_notify;
408 widget_class->focus_out_event = gtk_calendar_focus_out;
410 widget_class->drag_data_get = gtk_calendar_drag_data_get;
411 widget_class->drag_motion = gtk_calendar_drag_motion;
412 widget_class->drag_leave = gtk_calendar_drag_leave;
413 widget_class->drag_drop = gtk_calendar_drag_drop;
414 widget_class->drag_data_received = gtk_calendar_drag_data_received;
416 g_object_class_install_property (gobject_class,
418 g_param_spec_int ("year",
420 P_("The selected year"),
422 GTK_PARAM_READWRITE));
423 g_object_class_install_property (gobject_class,
425 g_param_spec_int ("month",
427 P_("The selected month (as a number between 0 and 11)"),
429 GTK_PARAM_READWRITE));
430 g_object_class_install_property (gobject_class,
432 g_param_spec_int ("day",
434 P_("The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)"),
436 GTK_PARAM_READWRITE));
439 * GtkCalendar:show-heading:
441 * Determines whether a heading is displayed.
445 g_object_class_install_property (gobject_class,
447 g_param_spec_boolean ("show-heading",
449 P_("If TRUE, a heading is displayed"),
451 GTK_PARAM_READWRITE));
454 * GtkCalendar:show-day-names:
456 * Determines whether day names are displayed.
460 g_object_class_install_property (gobject_class,
462 g_param_spec_boolean ("show-day-names",
463 P_("Show Day Names"),
464 P_("If TRUE, day names are displayed"),
466 GTK_PARAM_READWRITE));
468 * GtkCalendar:no-month-change:
470 * Determines whether the selected month can be changed.
474 g_object_class_install_property (gobject_class,
475 PROP_NO_MONTH_CHANGE,
476 g_param_spec_boolean ("no-month-change",
477 P_("No Month Change"),
478 P_("If TRUE, the selected month cannot be changed"),
480 GTK_PARAM_READWRITE));
483 * GtkCalendar:show-week-numbers:
485 * Determines whether week numbers are displayed.
489 g_object_class_install_property (gobject_class,
490 PROP_SHOW_WEEK_NUMBERS,
491 g_param_spec_boolean ("show-week-numbers",
492 P_("Show Week Numbers"),
493 P_("If TRUE, week numbers are displayed"),
495 GTK_PARAM_READWRITE));
497 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
498 g_signal_new (I_("month_changed"),
499 G_OBJECT_CLASS_TYPE (gobject_class),
501 G_STRUCT_OFFSET (GtkCalendarClass, month_changed),
503 _gtk_marshal_VOID__VOID,
505 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
506 g_signal_new (I_("day_selected"),
507 G_OBJECT_CLASS_TYPE (gobject_class),
509 G_STRUCT_OFFSET (GtkCalendarClass, day_selected),
511 _gtk_marshal_VOID__VOID,
513 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
514 g_signal_new (I_("day_selected_double_click"),
515 G_OBJECT_CLASS_TYPE (gobject_class),
517 G_STRUCT_OFFSET (GtkCalendarClass, day_selected_double_click),
519 _gtk_marshal_VOID__VOID,
521 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
522 g_signal_new (I_("prev_month"),
523 G_OBJECT_CLASS_TYPE (gobject_class),
525 G_STRUCT_OFFSET (GtkCalendarClass, prev_month),
527 _gtk_marshal_VOID__VOID,
529 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
530 g_signal_new (I_("next_month"),
531 G_OBJECT_CLASS_TYPE (gobject_class),
533 G_STRUCT_OFFSET (GtkCalendarClass, next_month),
535 _gtk_marshal_VOID__VOID,
537 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
538 g_signal_new (I_("prev_year"),
539 G_OBJECT_CLASS_TYPE (gobject_class),
541 G_STRUCT_OFFSET (GtkCalendarClass, prev_year),
543 _gtk_marshal_VOID__VOID,
545 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
546 g_signal_new (I_("next_year"),
547 G_OBJECT_CLASS_TYPE (gobject_class),
549 G_STRUCT_OFFSET (GtkCalendarClass, next_year),
551 _gtk_marshal_VOID__VOID,
554 g_type_class_add_private (gobject_class, sizeof (GtkCalendarPrivate));
558 gtk_calendar_init (GtkCalendar *calendar)
560 GtkWidget *widget = GTK_WIDGET (calendar);
566 GtkCalendarPrivate *priv;
568 gchar *week_start, week_startsub = 1;
571 priv = calendar->priv = G_TYPE_INSTANCE_GET_PRIVATE (calendar,
575 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
577 if (!default_abbreviated_dayname[0])
580 tmp_time= (i+3)*86400;
581 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
582 default_abbreviated_dayname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
585 if (!default_monthname[0])
589 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
590 default_monthname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
595 tm = localtime (&secs);
596 calendar->month = tm->tm_mon;
597 calendar->year = 1900 + tm->tm_year;
599 calendar_compute_days (calendar);
602 calendar->marked_date[i] = FALSE;
603 calendar->num_marked_dates = 0;
604 calendar->selected_day = tm->tm_mday;
606 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
607 GTK_CALENDAR_SHOW_DAY_NAMES );
609 calendar->highlight_row = -1;
610 calendar->highlight_col = -1;
612 calendar->focus_row = -1;
613 calendar->focus_col = -1;
615 priv->max_year_width = 0;
616 priv->max_month_width = 0;
617 priv->max_day_char_width = 0;
618 priv->max_week_char_width = 0;
620 priv->max_day_char_ascent = 0;
621 priv->max_day_char_descent = 0;
622 priv->max_label_char_ascent = 0;
623 priv->max_label_char_descent = 0;
625 priv->arrow_width = 10;
627 priv->need_timer = 0;
629 priv->click_child = -1;
632 priv->drag_highlight = 0;
634 gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY);
635 gtk_drag_dest_add_text_targets (widget);
637 priv->year_before = 0;
639 /* Translate to calendar:YM if you want years to be displayed
640 * before months; otherwise translate to calendar:MY.
641 * Do *not* translate it to anything else, if it
642 * it isn't calendar:YM or calendar:MY it will not work.
644 * Note that this flipping is in top the text direction flipping,
645 * so if you have a default text direction of RTL and YM, then
646 * the year will appear on the right.
648 year_before = _("calendar:MY");
649 if (strcmp (year_before, "calendar:YM") == 0)
650 priv->year_before = 1;
651 else if (strcmp (year_before, "calendar:MY") != 0)
652 g_warning ("Whoever translated calendar:MY did so wrongly.\n");
654 #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
655 week_start = nl_langinfo (_NL_TIME_FIRST_WEEKDAY);
656 week_origin = GPOINTER_TO_INT (nl_langinfo (_NL_TIME_WEEK_1STDAY));
657 if (week_origin == 19971130)
659 else if (week_origin == 19971201)
662 g_warning ("Unknown value of _NL_TIME_WEEK_1STDAY.\n");
664 priv->week_start = (*((unsigned char *) week_start) - week_startsub) % 7;
666 /* Translate to calendar:week_start:0 if you want Sunday to be the
667 * first day of the week to calendar:week_start:1 if you want Monday
668 * to be the first day of the week, and so on.
670 week_start = _("calendar:week_start:0");
672 if (strncmp (week_start, "calendar:week_start:", 20) == 0)
673 priv->week_start = *(week_start + 20) - '0';
675 priv->week_start = -1;
677 if (priv->week_start < 0 || priv->week_start > 6)
679 g_warning ("Whoever translated calendar:week_start:0 did so wrongly.\n");
680 priv->week_start = 0;
686 /****************************************
687 * Utility Functions *
688 ****************************************/
691 calendar_set_month_next (GtkCalendar *calendar)
695 g_return_if_fail (GTK_IS_WIDGET (calendar));
697 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
701 if (calendar->month == 11)
709 calendar_compute_days (calendar);
710 g_signal_emit (calendar,
711 gtk_calendar_signals[NEXT_MONTH_SIGNAL],
713 g_signal_emit (calendar,
714 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
717 month_len = month_length[leap (calendar->year)][calendar->month + 1];
719 if (month_len < calendar->selected_day)
721 calendar->selected_day = 0;
722 gtk_calendar_select_day (calendar, month_len);
725 gtk_calendar_select_day (calendar, calendar->selected_day);
727 gtk_widget_queue_draw (GTK_WIDGET (calendar));
731 calendar_set_year_prev (GtkCalendar *calendar)
735 g_return_if_fail (GTK_IS_WIDGET (calendar));
738 calendar_compute_days (calendar);
739 g_signal_emit (calendar,
740 gtk_calendar_signals[PREV_YEAR_SIGNAL],
742 g_signal_emit (calendar,
743 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
746 month_len = month_length[leap (calendar->year)][calendar->month + 1];
748 if (month_len < calendar->selected_day)
750 calendar->selected_day = 0;
751 gtk_calendar_select_day (calendar, month_len);
754 gtk_calendar_select_day (calendar, calendar->selected_day);
756 gtk_widget_queue_draw (GTK_WIDGET (calendar));
760 calendar_set_year_next (GtkCalendar *calendar)
765 g_return_if_fail (GTK_IS_WIDGET (calendar));
767 widget = GTK_WIDGET (calendar);
770 calendar_compute_days (calendar);
771 g_signal_emit (calendar,
772 gtk_calendar_signals[NEXT_YEAR_SIGNAL],
774 g_signal_emit (calendar,
775 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
778 month_len = month_length[leap (calendar->year)][calendar->month + 1];
780 if (month_len < calendar->selected_day)
782 calendar->selected_day = 0;
783 gtk_calendar_select_day (calendar, month_len);
786 gtk_calendar_select_day (calendar, calendar->selected_day);
788 gtk_widget_queue_draw (GTK_WIDGET (calendar));
792 calendar_compute_days (GtkCalendar *calendar)
794 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (GTK_WIDGET (calendar));
798 gint ndays_in_prev_month;
804 g_return_if_fail (GTK_IS_CALENDAR (calendar));
806 year = calendar->year;
807 month = calendar->month + 1;
809 ndays_in_month = month_length[leap (year)][month];
811 first_day = day_of_week (year, month, 1);
812 first_day = (first_day + 7 - priv->week_start) % 7;
814 /* Compute days of previous month */
816 ndays_in_prev_month = month_length[leap (year)][month-1];
818 ndays_in_prev_month = month_length[leap (year)][12];
819 day = ndays_in_prev_month - first_day + 1;
824 for (col = 0; col < first_day; col++)
826 calendar->day[row][col] = day;
827 calendar->day_month[row][col] = MONTH_PREV;
832 /* Compute days of current month */
834 for (day = 1; day <= ndays_in_month; day++)
836 calendar->day[row][col] = day;
837 calendar->day_month[row][col] = MONTH_CURRENT;
847 /* Compute days of next month */
849 for (; row <= 5; row++)
851 for (; col <= 6; col++)
853 calendar->day[row][col] = day;
854 calendar->day_month[row][col] = MONTH_NEXT;
862 calendar_select_and_focus_day (GtkCalendar *calendar,
865 gint old_focus_row = calendar->focus_row;
866 gint old_focus_col = calendar->focus_col;
870 for (row = 0; row < 6; row ++)
871 for (col = 0; col < 7; col++)
873 if (calendar->day_month[row][col] == MONTH_CURRENT
874 && calendar->day[row][col] == day)
876 calendar->focus_row = row;
877 calendar->focus_col = col;
881 if (old_focus_row != -1 && old_focus_col != -1)
882 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
884 gtk_calendar_select_day (calendar, day);
888 /****************************************
889 * Layout computation utilities *
890 ****************************************/
893 calendar_row_height (GtkCalendar *calendar)
895 return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h - CALENDAR_MARGIN
896 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
897 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
901 /* calendar_left_x_for_column: returns the x coordinate
902 * for the left of the column */
904 calendar_left_x_for_column (GtkCalendar *calendar,
910 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
913 width = GTK_CALENDAR_GET_PRIVATE (calendar)->day_width;
914 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
915 x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column;
917 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
922 /* column_from_x: returns the column 0-6 that the
923 * x pixel of the xwindow is in */
925 calendar_column_from_x (GtkCalendar *calendar,
929 gint x_left, x_right;
933 for (c = 0; c < 7; c++)
935 x_left = calendar_left_x_for_column (calendar, c);
936 x_right = x_left + GTK_CALENDAR_GET_PRIVATE (calendar)->day_width;
938 if (event_x >= x_left && event_x < x_right)
948 /* calendar_top_y_for_row: returns the y coordinate
949 * for the top of the row */
951 calendar_top_y_for_row (GtkCalendar *calendar,
955 return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h
956 - (CALENDAR_MARGIN + (6 - row)
957 * calendar_row_height (calendar)));
960 /* row_from_y: returns the row 0-5 that the
961 * y pixel of the xwindow is in */
963 calendar_row_from_y (GtkCalendar *calendar,
968 gint y_top, y_bottom;
970 height = calendar_row_height (calendar);
973 for (r = 0; r < 6; r++)
975 y_top = calendar_top_y_for_row (calendar, r);
976 y_bottom = y_top + height;
978 if (event_y >= y_top && event_y < y_bottom)
989 calendar_arrow_rectangle (GtkCalendar *calendar,
993 GtkWidget *widget = GTK_WIDGET (calendar);
994 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
997 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
998 year_left = priv->year_before;
1000 year_left = !priv->year_before;
1003 rect->width = priv->arrow_width;
1004 rect->height = priv->header_h - 7;
1008 case ARROW_MONTH_LEFT:
1010 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1011 - (3 + 2*priv->arrow_width
1012 + priv->max_month_width));
1016 case ARROW_MONTH_RIGHT:
1018 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1019 - 3 - priv->arrow_width);
1021 rect->x = (priv->arrow_width
1022 + priv->max_month_width);
1024 case ARROW_YEAR_LEFT:
1028 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1029 - (3 + 2*priv->arrow_width
1030 + priv->max_year_width));
1032 case ARROW_YEAR_RIGHT:
1034 rect->x = (priv->arrow_width
1035 + priv->max_year_width);
1037 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1038 - 3 - priv->arrow_width);
1044 calendar_day_rectangle (GtkCalendar *calendar,
1049 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1051 rect->x = calendar_left_x_for_column (calendar, col);
1052 rect->y = calendar_top_y_for_row (calendar, row);
1053 rect->height = calendar_row_height (calendar);
1054 rect->width = priv->day_width;
1058 calendar_set_month_prev (GtkCalendar *calendar)
1062 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1065 if (calendar->month == 0)
1067 calendar->month = 11;
1073 month_len = month_length[leap (calendar->year)][calendar->month + 1];
1075 calendar_compute_days (calendar);
1077 g_signal_emit (calendar,
1078 gtk_calendar_signals[PREV_MONTH_SIGNAL],
1080 g_signal_emit (calendar,
1081 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
1084 if (month_len < calendar->selected_day)
1086 calendar->selected_day = 0;
1087 gtk_calendar_select_day (calendar, month_len);
1091 if (calendar->selected_day < 0)
1092 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
1093 gtk_calendar_select_day (calendar, calendar->selected_day);
1096 gtk_widget_queue_draw (GTK_WIDGET (calendar));
1100 /****************************************
1101 * Basic object methods *
1102 ****************************************/
1105 gtk_calendar_finalize (GObject *object)
1107 (* G_OBJECT_CLASS (gtk_calendar_parent_class)->finalize) (object);
1111 gtk_calendar_destroy (GtkObject *object)
1113 calendar_stop_spinning (GTK_CALENDAR (object));
1115 GTK_OBJECT_CLASS (gtk_calendar_parent_class)->destroy (object);
1120 calendar_set_display_option (GtkCalendar *calendar,
1121 GtkCalendarDisplayOptions flag,
1124 GtkCalendarDisplayOptions flags;
1126 flags = calendar->display_flags | flag;
1128 flags = calendar->display_flags & ~flag;
1129 gtk_calendar_display_options (calendar, flags);
1133 calendar_get_display_option (GtkCalendar *calendar,
1134 GtkCalendarDisplayOptions flag)
1136 return (calendar->display_flags & flag) != 0;
1140 gtk_calendar_set_property (GObject *object,
1142 const GValue *value,
1145 GtkCalendar *calendar;
1147 calendar = GTK_CALENDAR (object);
1152 gtk_calendar_select_month (calendar,
1154 g_value_get_int (value));
1157 gtk_calendar_select_month (calendar,
1158 g_value_get_int (value),
1162 gtk_calendar_select_day (calendar,
1163 g_value_get_int (value));
1165 case PROP_SHOW_HEADING:
1166 calendar_set_display_option (calendar,
1167 GTK_CALENDAR_SHOW_HEADING,
1168 g_value_get_boolean (value));
1170 case PROP_SHOW_DAY_NAMES:
1171 calendar_set_display_option (calendar,
1172 GTK_CALENDAR_SHOW_DAY_NAMES,
1173 g_value_get_boolean (value));
1175 case PROP_NO_MONTH_CHANGE:
1176 calendar_set_display_option (calendar,
1177 GTK_CALENDAR_NO_MONTH_CHANGE,
1178 g_value_get_boolean (value));
1180 case PROP_SHOW_WEEK_NUMBERS:
1181 calendar_set_display_option (calendar,
1182 GTK_CALENDAR_SHOW_WEEK_NUMBERS,
1183 g_value_get_boolean (value));
1186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1192 gtk_calendar_get_property (GObject *object,
1197 GtkCalendar *calendar;
1199 calendar = GTK_CALENDAR (object);
1204 g_value_set_int (value, calendar->year);
1207 g_value_set_int (value, calendar->month);
1210 g_value_set_int (value, calendar->selected_day);
1212 case PROP_SHOW_HEADING:
1213 g_value_set_boolean (value, calendar_get_display_option (calendar,
1214 GTK_CALENDAR_SHOW_HEADING));
1216 case PROP_SHOW_DAY_NAMES:
1217 g_value_set_boolean (value, calendar_get_display_option (calendar,
1218 GTK_CALENDAR_SHOW_DAY_NAMES));
1220 case PROP_NO_MONTH_CHANGE:
1221 g_value_set_boolean (value, calendar_get_display_option (calendar,
1222 GTK_CALENDAR_NO_MONTH_CHANGE));
1224 case PROP_SHOW_WEEK_NUMBERS:
1225 g_value_set_boolean (value, calendar_get_display_option (calendar,
1226 GTK_CALENDAR_SHOW_WEEK_NUMBERS));
1229 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1235 /****************************************
1237 ****************************************/
1240 calendar_realize_arrows (GtkCalendar *calendar)
1242 GtkWidget *widget = GTK_WIDGET (calendar);
1243 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1244 GdkWindowAttr attributes;
1245 gint attributes_mask;
1248 /* Arrow windows ------------------------------------- */
1249 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1250 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
1252 attributes.wclass = GDK_INPUT_OUTPUT;
1253 attributes.window_type = GDK_WINDOW_CHILD;
1254 attributes.visual = gtk_widget_get_visual (widget);
1255 attributes.colormap = gtk_widget_get_colormap (widget);
1256 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1257 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1258 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
1259 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1260 for (i = 0; i < 4; i++)
1263 calendar_arrow_rectangle (calendar, i, &rect);
1265 attributes.x = rect.x;
1266 attributes.y = rect.y;
1267 attributes.width = rect.width;
1268 attributes.height = rect.height;
1269 priv->arrow_win[i] = gdk_window_new (priv->header_win,
1272 if (GTK_WIDGET_IS_SENSITIVE (widget))
1273 priv->arrow_state[i] = GTK_STATE_NORMAL;
1275 priv->arrow_state[i] = GTK_STATE_INSENSITIVE;
1276 gdk_window_set_background (priv->arrow_win[i],
1277 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1278 gdk_window_show (priv->arrow_win[i]);
1279 gdk_window_set_user_data (priv->arrow_win[i], widget);
1284 for (i = 0; i < 4; i++)
1285 priv->arrow_win[i] = NULL;
1290 calendar_realize_header (GtkCalendar *calendar)
1292 GtkWidget *widget = GTK_WIDGET (calendar);
1293 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1294 GdkWindowAttr attributes;
1295 gint attributes_mask;
1297 /* Header window ------------------------------------- */
1298 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1300 attributes.wclass = GDK_INPUT_OUTPUT;
1301 attributes.window_type = GDK_WINDOW_CHILD;
1302 attributes.visual = gtk_widget_get_visual (widget);
1303 attributes.colormap = gtk_widget_get_colormap (widget);
1304 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1305 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1306 attributes.x = widget->style->xthickness;
1307 attributes.y = widget->style->ythickness;
1308 attributes.width = widget->allocation.width - 2 * attributes.x;
1309 attributes.height = priv->header_h - 2 * attributes.y;
1310 priv->header_win = gdk_window_new (widget->window,
1311 &attributes, attributes_mask);
1313 gdk_window_set_background (priv->header_win,
1314 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1315 gdk_window_show (priv->header_win);
1316 gdk_window_set_user_data (priv->header_win, widget);
1321 priv->header_win = NULL;
1323 calendar_realize_arrows (calendar);
1327 calendar_realize_day_names (GtkCalendar *calendar)
1329 GtkWidget *widget = GTK_WIDGET (calendar);
1330 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1331 GdkWindowAttr attributes;
1332 gint attributes_mask;
1334 /* Day names window --------------------------------- */
1335 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1337 attributes.wclass = GDK_INPUT_OUTPUT;
1338 attributes.window_type = GDK_WINDOW_CHILD;
1339 attributes.visual = gtk_widget_get_visual (widget);
1340 attributes.colormap = gtk_widget_get_colormap (widget);
1341 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1342 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1343 attributes.x = (widget->style->xthickness + INNER_BORDER);
1344 attributes.y = priv->header_h + (widget->style->ythickness
1346 attributes.width = (widget->allocation.width
1347 - (widget->style->xthickness + INNER_BORDER)
1349 attributes.height = priv->day_name_h;
1350 priv->day_name_win = gdk_window_new (widget->window,
1353 gdk_window_set_background (priv->day_name_win,
1354 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1355 gdk_window_show (priv->day_name_win);
1356 gdk_window_set_user_data (priv->day_name_win, widget);
1360 priv->day_name_win = NULL;
1365 calendar_realize_week_numbers (GtkCalendar *calendar)
1367 GtkWidget *widget = GTK_WIDGET (calendar);
1368 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1369 GdkWindowAttr attributes;
1370 gint attributes_mask;
1372 /* Week number window -------------------------------- */
1373 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1375 attributes.wclass = GDK_INPUT_OUTPUT;
1376 attributes.window_type = GDK_WINDOW_CHILD;
1377 attributes.visual = gtk_widget_get_visual (widget);
1378 attributes.colormap = gtk_widget_get_colormap (widget);
1379 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1381 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1382 attributes.x = widget->style->xthickness + INNER_BORDER;
1383 attributes.y = (priv->header_h + priv->day_name_h
1384 + (widget->style->ythickness + INNER_BORDER));
1385 attributes.width = priv->week_width;
1386 attributes.height = priv->main_h;
1387 priv->week_win = gdk_window_new (widget->window,
1388 &attributes, attributes_mask);
1389 gdk_window_set_background (priv->week_win,
1390 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1391 gdk_window_show (priv->week_win);
1392 gdk_window_set_user_data (priv->week_win, widget);
1396 priv->week_win = NULL;
1401 gtk_calendar_realize (GtkWidget *widget)
1403 GtkCalendar *calendar = GTK_CALENDAR (widget);
1404 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1405 GdkWindowAttr attributes;
1406 gint attributes_mask;
1408 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1410 attributes.x = widget->allocation.x;
1411 attributes.y = widget->allocation.y;
1412 attributes.width = widget->allocation.width;
1413 attributes.height = widget->allocation.height;
1414 attributes.wclass = GDK_INPUT_OUTPUT;
1415 attributes.window_type = GDK_WINDOW_CHILD;
1416 attributes.event_mask = (gtk_widget_get_events (widget)
1417 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_MASK);
1418 attributes.visual = gtk_widget_get_visual (widget);
1419 attributes.colormap = gtk_widget_get_colormap (widget);
1421 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1422 widget->window = gdk_window_new (widget->parent->window,
1423 &attributes, attributes_mask);
1425 widget->style = gtk_style_attach (widget->style, widget->window);
1427 /* Header window ------------------------------------- */
1428 calendar_realize_header (calendar);
1429 /* Day names window --------------------------------- */
1430 calendar_realize_day_names (calendar);
1431 /* Week number window -------------------------------- */
1432 calendar_realize_week_numbers (calendar);
1433 /* Main Window -------------------------------------- */
1434 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1435 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1436 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1438 attributes.x = priv->week_width + (widget->style->ythickness + INNER_BORDER);
1439 attributes.y = (priv->header_h + priv->day_name_h
1440 + (widget->style->ythickness + INNER_BORDER));
1441 attributes.width = (widget->allocation.width - attributes.x
1442 - (widget->style->xthickness + INNER_BORDER));
1443 attributes.height = priv->main_h;
1444 priv->main_win = gdk_window_new (widget->window,
1445 &attributes, attributes_mask);
1446 gdk_window_set_background (priv->main_win,
1447 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1448 gdk_window_show (priv->main_win);
1449 gdk_window_set_user_data (priv->main_win, widget);
1450 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1451 gdk_window_show (widget->window);
1452 gdk_window_set_user_data (widget->window, widget);
1456 gtk_calendar_unrealize (GtkWidget *widget)
1458 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1461 if (priv->header_win)
1463 for (i = 0; i < 4; i++)
1465 if (priv->arrow_win[i])
1467 gdk_window_set_user_data (priv->arrow_win[i], NULL);
1468 gdk_window_destroy (priv->arrow_win[i]);
1469 priv->arrow_win[i] = NULL;
1472 gdk_window_set_user_data (priv->header_win, NULL);
1473 gdk_window_destroy (priv->header_win);
1474 priv->header_win = NULL;
1479 gdk_window_set_user_data (priv->week_win, NULL);
1480 gdk_window_destroy (priv->week_win);
1481 priv->week_win = NULL;
1486 gdk_window_set_user_data (priv->main_win, NULL);
1487 gdk_window_destroy (priv->main_win);
1488 priv->main_win = NULL;
1490 if (priv->day_name_win)
1492 gdk_window_set_user_data (priv->day_name_win, NULL);
1493 gdk_window_destroy (priv->day_name_win);
1494 priv->day_name_win = NULL;
1497 if (GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize)
1498 (* GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize) (widget);
1502 /****************************************
1503 * Size Request and Allocate *
1504 ****************************************/
1507 gtk_calendar_size_request (GtkWidget *widget,
1508 GtkRequisition *requisition)
1510 GtkCalendar *calendar = GTK_CALENDAR (widget);
1511 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1512 PangoLayout *layout;
1513 PangoRectangle logical_rect;
1518 gint calendar_margin = CALENDAR_MARGIN;
1519 gint header_width, main_width;
1520 gint max_header_height = 0;
1524 gtk_widget_style_get (GTK_WIDGET (widget),
1525 "focus-line-width", &focus_width,
1526 "focus-padding", &focus_padding,
1529 layout = gtk_widget_create_pango_layout (widget, NULL);
1532 * Calculate the requisition width for the widget.
1537 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1539 priv->max_month_width = 0;
1540 for (i = 0; i < 12; i++)
1542 pango_layout_set_text (layout, default_monthname[i], -1);
1543 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1544 priv->max_month_width = MAX (priv->max_month_width,
1545 logical_rect.width + 8);
1546 max_header_height = MAX (max_header_height, logical_rect.height);
1549 priv->max_year_width = 0;
1550 /* Translators: This is a text measurement template.
1551 * Translate it to the widest year text.
1553 * Don't include the prefix "year measurement template|"
1554 * in the translation.
1556 * If you don't understand this, leave it as "2000"
1558 pango_layout_set_text (layout, Q_("year measurement template|2000"), -1);
1559 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1560 priv->max_year_width = MAX (priv->max_year_width,
1561 logical_rect.width + 8);
1562 max_header_height = MAX (max_header_height, logical_rect.height);
1566 priv->max_month_width = 0;
1567 priv->max_year_width = 0;
1570 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1571 header_width = (priv->max_month_width
1572 + priv->max_year_width
1575 header_width = (priv->max_month_width
1576 + priv->max_year_width
1577 + 4 * priv->arrow_width + 3 * 3);
1579 /* Mainwindow labels width */
1581 priv->max_day_char_width = 0;
1582 priv->min_day_width = 0;
1583 priv->max_label_char_ascent = 0;
1584 priv->max_label_char_descent = 0;
1586 for (i = 0; i < 9; i++)
1588 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1589 pango_layout_set_text (layout, buffer, -1);
1590 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1591 priv->min_day_width = MAX (priv->min_day_width,
1592 logical_rect.width);
1594 priv->max_day_char_ascent = MAX (priv->max_label_char_ascent,
1595 PANGO_ASCENT (logical_rect));
1596 priv->max_day_char_descent = MAX (priv->max_label_char_descent,
1597 PANGO_DESCENT (logical_rect));
1599 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1600 priv->max_day_char_width = priv->min_day_width / 2 + 1;
1602 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1603 for (i = 0; i < 7; i++)
1605 pango_layout_set_text (layout, default_abbreviated_dayname[i], -1);
1606 pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect);
1608 priv->min_day_width = MAX (priv->min_day_width, logical_rect.width);
1609 priv->max_label_char_ascent = MAX (priv->max_label_char_ascent,
1610 PANGO_ASCENT (logical_rect));
1611 priv->max_label_char_descent = MAX (priv->max_label_char_descent,
1612 PANGO_DESCENT (logical_rect));
1615 priv->max_week_char_width = 0;
1616 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1617 for (i = 0; i < 9; i++)
1619 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1620 pango_layout_set_text (layout, buffer, -1);
1621 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1622 priv->max_week_char_width = MAX (priv->max_week_char_width,
1623 logical_rect.width / 2);
1626 main_width = (7 * (priv->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1627 + (priv->max_week_char_width
1628 ? priv->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2
1632 requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2;
1635 * Calculate the requisition height for the widget.
1638 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1640 priv->header_h = (max_header_height + CALENDAR_YSEP * 2);
1647 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1649 priv->day_name_h = (priv->max_label_char_ascent
1650 + priv->max_label_char_descent
1651 + 2 * (focus_padding + focus_width) + calendar_margin);
1652 calendar_margin = CALENDAR_YSEP;
1656 priv->day_name_h = 0;
1659 priv->main_h = (CALENDAR_MARGIN + calendar_margin
1660 + 6 * (priv->max_day_char_ascent
1661 + priv->max_day_char_descent
1662 + 2 * (focus_padding + focus_width))
1665 height = (priv->header_h + priv->day_name_h
1668 requisition->height = height + (widget->style->ythickness + INNER_BORDER) * 2;
1670 g_object_unref (layout);
1674 gtk_calendar_size_allocate (GtkWidget *widget,
1675 GtkAllocation *allocation)
1677 GtkCalendar *calendar = GTK_CALENDAR (widget);
1678 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1679 gint xthickness = widget->style->xthickness;
1680 gint ythickness = widget->style->xthickness;
1684 widget->allocation = *allocation;
1686 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1687 year_left = priv->year_before;
1689 year_left = !priv->year_before;
1691 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1693 priv->day_width = (priv->min_day_width
1694 * ((allocation->width - (xthickness + INNER_BORDER) * 2
1695 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2))
1696 / (7 * priv->min_day_width + priv->max_week_char_width * 2));
1697 priv->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2
1698 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 )
1699 - priv->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1703 priv->day_width = (allocation->width
1704 - (xthickness + INNER_BORDER) * 2
1705 - (CALENDAR_MARGIN * 2)
1706 - (DAY_XSEP * 6))/7;
1707 priv->week_width = 0;
1710 if (GTK_WIDGET_REALIZED (widget))
1712 gdk_window_move_resize (widget->window,
1713 allocation->x, allocation->y,
1714 allocation->width, allocation->height);
1715 if (priv->header_win)
1716 gdk_window_move_resize (priv->header_win,
1717 xthickness, ythickness,
1718 allocation->width - 2 * xthickness, priv->header_h);
1720 for (i = 0 ; i < 4 ; i++)
1722 if (priv->arrow_win[i])
1725 calendar_arrow_rectangle (calendar, i, &rect);
1727 gdk_window_move_resize (priv->arrow_win[i],
1728 rect.x, rect.y, rect.width, rect.height);
1732 if (priv->day_name_win)
1733 gdk_window_move_resize (priv->day_name_win,
1734 xthickness + INNER_BORDER,
1735 priv->header_h + (widget->style->ythickness + INNER_BORDER),
1736 allocation->width - (xthickness + INNER_BORDER) * 2,
1738 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1741 gdk_window_move_resize (priv->week_win,
1742 (xthickness + INNER_BORDER),
1743 priv->header_h + priv->day_name_h
1744 + (widget->style->ythickness + INNER_BORDER),
1747 gdk_window_move_resize (priv->main_win,
1748 priv->week_width + (xthickness + INNER_BORDER),
1749 priv->header_h + priv->day_name_h
1750 + (widget->style->ythickness + INNER_BORDER),
1753 - (xthickness + INNER_BORDER) * 2,
1758 gdk_window_move_resize (priv->main_win,
1759 (xthickness + INNER_BORDER),
1760 priv->header_h + priv->day_name_h
1761 + (widget->style->ythickness + INNER_BORDER),
1764 - (xthickness + INNER_BORDER) * 2,
1767 gdk_window_move_resize (priv->week_win,
1770 - (xthickness + INNER_BORDER),
1771 priv->header_h + priv->day_name_h
1772 + (widget->style->ythickness + INNER_BORDER),
1780 /****************************************
1782 ****************************************/
1785 calendar_paint_header (GtkCalendar *calendar)
1787 GtkWidget *widget = GTK_WIDGET (calendar);
1788 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1792 gint header_width, cal_height;
1793 gint max_month_width;
1794 gint max_year_width;
1795 PangoLayout *layout;
1796 PangoRectangle logical_rect;
1802 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1803 year_left = priv->year_before;
1805 year_left = !priv->year_before;
1807 cr = gdk_cairo_create (priv->header_win);
1809 header_width = widget->allocation.width - 2 * widget->style->xthickness;
1810 cal_height = widget->allocation.height;
1812 max_month_width = priv->max_month_width;
1813 max_year_width = priv->max_year_width;
1815 gtk_paint_shadow (widget->style, priv->header_win,
1816 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1817 NULL, widget, "calendar",
1818 0, 0, header_width, priv->header_h);
1820 tmp_time = 1; /* Jan 1 1970, 00:00:01 UTC */
1821 tm = gmtime (&tmp_time);
1822 tm->tm_year = calendar->year - 1900;
1824 /* Translators: This dictates how the year is displayed in
1825 * gtkcalendar widget. See strftime() manual for the format.
1826 * Use only ASCII in the translation.
1828 * Also look for the msgid "year measurement template|2000".
1829 * Translate that entry to a year with the widest output of this
1832 * Don't include the prefix "calendar year format|" in the
1833 * translation. "%Y" is appropriate for most locales.
1835 strftime (buffer, sizeof (buffer), Q_("calendar year format|%Y"), tm);
1836 str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1837 layout = gtk_widget_create_pango_layout (widget, str);
1840 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1843 y = (priv->header_h - logical_rect.height) / 2;
1845 /* Draw year and its arrows */
1847 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1849 x = 3 + (max_year_width - logical_rect.width)/2;
1851 x = header_width - (3 + max_year_width
1852 - (max_year_width - logical_rect.width)/2);
1855 x = 3 + priv->arrow_width + (max_year_width - logical_rect.width)/2;
1857 x = header_width - (3 + priv->arrow_width + max_year_width
1858 - (max_year_width - logical_rect.width)/2);
1861 gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1862 cairo_move_to (cr, x, y);
1863 pango_cairo_show_layout (cr, layout);
1866 g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]);
1867 pango_layout_set_text (layout, buffer, -1);
1868 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1870 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1872 x = header_width - (3 + max_month_width
1873 - (max_month_width - logical_rect.width)/2);
1875 x = 3 + (max_month_width - logical_rect.width) / 2;
1878 x = header_width - (3 + priv->arrow_width + max_month_width
1879 - (max_month_width - logical_rect.width)/2);
1881 x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2;
1883 cairo_move_to (cr, x, y);
1884 pango_cairo_show_layout (cr, layout);
1886 g_object_unref (layout);
1891 calendar_paint_day_names (GtkCalendar *calendar)
1893 GtkWidget *widget = GTK_WIDGET (calendar);
1894 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1898 int day_width, cal_width;
1901 PangoLayout *layout;
1902 PangoRectangle logical_rect;
1906 cr = gdk_cairo_create (priv->day_name_win);
1908 gtk_widget_style_get (GTK_WIDGET (widget),
1909 "focus-line-width", &focus_width,
1910 "focus-padding", &focus_padding,
1913 day_width = priv->day_width;
1914 cal_width = widget->allocation.width;
1915 cal_height = widget->allocation.height;
1916 day_wid_sep = day_width + DAY_XSEP;
1919 * Draw rectangles as inverted background for the labels.
1922 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
1923 cairo_rectangle (cr,
1924 CALENDAR_MARGIN, CALENDAR_MARGIN,
1925 cal_width-CALENDAR_MARGIN * 2,
1926 priv->day_name_h - CALENDAR_MARGIN);
1929 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1931 cairo_rectangle (cr,
1933 priv->day_name_h - CALENDAR_YSEP,
1934 priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1943 layout = gtk_widget_create_pango_layout (widget, NULL);
1945 gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
1946 for (i = 0; i < 7; i++)
1948 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
1952 day = (day + priv->week_start) % 7;
1953 g_snprintf (buffer, sizeof (buffer), "%s", default_abbreviated_dayname[day]);
1955 pango_layout_set_text (layout, buffer, -1);
1956 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1960 + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
1961 (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
1964 + (day_width - logical_rect.width)/2),
1965 CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y);
1966 pango_cairo_show_layout (cr, layout);
1969 g_object_unref (layout);
1974 calendar_paint_week_numbers (GtkCalendar *calendar)
1976 GtkWidget *widget = GTK_WIDGET (calendar);
1977 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1979 gint row, week = 0, year;
1982 gint y_loc, day_height;
1983 PangoLayout *layout;
1984 PangoRectangle logical_rect;
1988 cr = gdk_cairo_create (priv->week_win);
1990 gtk_widget_style_get (GTK_WIDGET (widget),
1991 "focus-line-width", &focus_width,
1992 "focus-padding", &focus_padding,
1996 * Draw a rectangle as inverted background for the labels.
1999 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
2000 if (priv->day_name_win)
2001 cairo_rectangle (cr,
2004 priv->week_width - CALENDAR_MARGIN,
2005 priv->main_h - CALENDAR_MARGIN);
2007 cairo_rectangle (cr,
2010 priv->week_width - CALENDAR_MARGIN,
2011 priv->main_h - 2 * CALENDAR_MARGIN);
2018 layout = gtk_widget_create_pango_layout (widget, NULL);
2020 gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
2021 day_height = calendar_row_height (calendar);
2022 for (row = 0; row < 6; row++)
2026 year = calendar->year;
2027 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
2030 result = week_of_year (&week, &year,
2031 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
2032 + calendar->month) % 12 + 1, calendar->day[row][6]);
2033 g_return_if_fail (result);
2035 g_snprintf (buffer, sizeof (buffer), "%d", week);
2036 pango_layout_set_text (layout, buffer, -1);
2037 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2039 y_loc = calendar_top_y_for_row (calendar, row) + (day_height - logical_rect.height) / 2;
2041 x_loc = (priv->week_width
2042 - logical_rect.width
2043 - CALENDAR_XSEP - focus_padding - focus_width);
2045 cairo_move_to (cr, x_loc, y_loc);
2046 pango_cairo_show_layout (cr, layout);
2049 g_object_unref (layout);
2054 calendar_invalidate_day_num (GtkCalendar *calendar,
2057 gint r, c, row, col;
2061 for (r = 0; r < 6; r++)
2062 for (c = 0; c < 7; c++)
2063 if (calendar->day_month[r][c] == MONTH_CURRENT &&
2064 calendar->day[r][c] == day)
2070 g_return_if_fail (row != -1);
2071 g_return_if_fail (col != -1);
2073 calendar_invalidate_day (calendar, row, col);
2077 calendar_invalidate_day (GtkCalendar *calendar,
2081 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2085 GdkRectangle day_rect;
2087 calendar_day_rectangle (calendar, row, col, &day_rect);
2088 gdk_window_invalidate_rect (priv->main_win, &day_rect, FALSE);
2093 calendar_paint_day (GtkCalendar *calendar,
2097 GtkWidget *widget = GTK_WIDGET (calendar);
2098 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2100 GdkColor *text_color;
2104 GdkRectangle day_rect;
2106 PangoLayout *layout;
2107 PangoRectangle logical_rect;
2109 g_return_if_fail (row < 6);
2110 g_return_if_fail (col < 7);
2112 cr = gdk_cairo_create (priv->main_win);
2114 day = calendar->day[row][col];
2116 calendar_day_rectangle (calendar, row, col, &day_rect);
2118 if (calendar->day_month[row][col] == MONTH_PREV)
2120 text_color = PREV_MONTH_COLOR (widget);
2122 else if (calendar->day_month[row][col] == MONTH_NEXT)
2124 text_color = NEXT_MONTH_COLOR (widget);
2129 if (calendar->highlight_row == row && calendar->highlight_col == col)
2131 cairo_set_source_color (cr, HIGHLIGHT_BG_COLOR (widget));
2132 gdk_cairo_rectangle (cr, &day_rect);
2136 if (calendar->selected_day == day)
2138 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
2139 gdk_cairo_rectangle (cr, &day_rect);
2142 if (calendar->selected_day == day)
2143 text_color = SELECTED_FG_COLOR (widget);
2144 else if (calendar->marked_date[day-1])
2145 text_color = MARKED_COLOR (widget);
2147 text_color = NORMAL_DAY_COLOR (widget);
2150 g_snprintf (buffer, sizeof (buffer), "%d", day);
2151 layout = gtk_widget_create_pango_layout (widget, buffer);
2152 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2154 x_loc = day_rect.x + day_rect.width / 2 + priv->max_day_char_width;
2155 x_loc -= logical_rect.width;
2156 y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2;
2158 gdk_cairo_set_source_color (cr, text_color);
2159 cairo_move_to (cr, x_loc, y_loc);
2160 pango_cairo_show_layout (cr, layout);
2162 if (calendar->marked_date[day-1]
2163 && calendar->day_month[row][col] == MONTH_CURRENT)
2165 cairo_move_to (cr, x_loc - 1, y_loc);
2166 pango_cairo_show_layout (cr, layout);
2169 if (GTK_WIDGET_HAS_FOCUS (calendar)
2170 && calendar->focus_row == row && calendar->focus_col == col)
2174 if (calendar->selected_day == day)
2175 state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
2177 state = GTK_STATE_NORMAL;
2179 gtk_paint_focus (widget->style,
2183 (calendar->selected_day == day)
2184 ? GTK_STATE_SELECTED : GTK_STATE_NORMAL,
2186 NULL, widget, "calendar-day",
2187 day_rect.x, day_rect.y,
2188 day_rect.width, day_rect.height);
2191 g_object_unref (layout);
2196 calendar_paint_main (GtkCalendar *calendar)
2200 for (col = 0; col < 7; col++)
2201 for (row = 0; row < 6; row++)
2202 calendar_paint_day (calendar, row, col);
2206 calendar_invalidate_arrow (GtkCalendar *calendar,
2209 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2212 window = priv->arrow_win[arrow];
2214 gdk_window_invalidate_rect (window, NULL, FALSE);
2218 calendar_paint_arrow (GtkCalendar *calendar,
2221 GtkWidget *widget = GTK_WIDGET (calendar);
2222 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2225 window = priv->arrow_win[arrow];
2228 cairo_t *cr = gdk_cairo_create (window);
2232 state = priv->arrow_state[arrow];
2234 gdk_cairo_set_source_color (cr, &widget->style->bg[state]);
2238 gdk_drawable_get_size (window, &width, &height);
2239 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2240 gtk_paint_arrow (widget->style, window, state,
2241 GTK_SHADOW_OUT, NULL, widget, "calendar",
2242 GTK_ARROW_LEFT, TRUE,
2243 width/2 - 3, height/2 - 4, 8, 8);
2245 gtk_paint_arrow (widget->style, window, state,
2246 GTK_SHADOW_OUT, NULL, widget, "calendar",
2247 GTK_ARROW_RIGHT, TRUE,
2248 width/2 - 2, height/2 - 4, 8, 8);
2253 gtk_calendar_expose (GtkWidget *widget,
2254 GdkEventExpose *event)
2256 GtkCalendar *calendar = GTK_CALENDAR (widget);
2257 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2260 if (GTK_WIDGET_DRAWABLE (widget))
2262 if (event->window == priv->main_win)
2263 calendar_paint_main (calendar);
2265 if (event->window == priv->header_win)
2266 calendar_paint_header (calendar);
2268 for (i = 0; i < 4; i++)
2269 if (event->window == priv->arrow_win[i])
2270 calendar_paint_arrow (calendar, i);
2272 if (event->window == priv->day_name_win)
2273 calendar_paint_day_names (calendar);
2275 if (event->window == priv->week_win)
2276 calendar_paint_week_numbers (calendar);
2277 if (event->window == widget->window)
2279 gtk_paint_shadow (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2280 GTK_SHADOW_IN, NULL, widget, "calendar",
2281 0, 0, widget->allocation.width, widget->allocation.height);
2289 /****************************************
2291 ****************************************/
2293 #define CALENDAR_INITIAL_TIMER_DELAY 200
2294 #define CALENDAR_TIMER_DELAY 20
2297 calendar_arrow_action (GtkCalendar *calendar,
2302 case ARROW_YEAR_LEFT:
2303 calendar_set_year_prev (calendar);
2305 case ARROW_YEAR_RIGHT:
2306 calendar_set_year_next (calendar);
2308 case ARROW_MONTH_LEFT:
2309 calendar_set_month_prev (calendar);
2311 case ARROW_MONTH_RIGHT:
2312 calendar_set_month_next (calendar);
2320 calendar_timer (gpointer data)
2322 GtkCalendar *calendar = data;
2323 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2324 gboolean retval = FALSE;
2326 GDK_THREADS_ENTER ();
2330 calendar_arrow_action (calendar, priv->click_child);
2332 if (priv->need_timer)
2334 priv->need_timer = FALSE;
2335 priv->timer = g_timeout_add (CALENDAR_TIMER_DELAY,
2336 (GSourceFunc) calendar_timer,
2337 (gpointer) calendar);
2343 GDK_THREADS_LEAVE ();
2349 calendar_start_spinning (GtkCalendar *calendar,
2352 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2354 priv->click_child = click_child;
2358 priv->need_timer = TRUE;
2359 priv->timer = g_timeout_add (CALENDAR_INITIAL_TIMER_DELAY,
2366 calendar_stop_spinning (GtkCalendar *calendar)
2368 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2372 g_source_remove (priv->timer);
2374 priv->need_timer = FALSE;
2379 calendar_main_button_press (GtkCalendar *calendar,
2380 GdkEventButton *event)
2382 GtkWidget *widget = GTK_WIDGET (calendar);
2383 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2389 x = (gint) (event->x);
2390 y = (gint) (event->y);
2392 row = calendar_row_from_y (calendar, y);
2393 col = calendar_column_from_x (calendar, x);
2395 /* If row or column isn't found, just return. */
2396 if (row == -1 || col == -1)
2399 day_month = calendar->day_month[row][col];
2401 if (event->type == GDK_BUTTON_PRESS)
2403 day = calendar->day[row][col];
2405 if (day_month == MONTH_PREV)
2406 calendar_set_month_prev (calendar);
2407 else if (day_month == MONTH_NEXT)
2408 calendar_set_month_next (calendar);
2410 if (!GTK_WIDGET_HAS_FOCUS (widget))
2411 gtk_widget_grab_focus (widget);
2413 if (event->button == 1)
2416 priv->drag_start_x = x;
2417 priv->drag_start_y = y;
2420 calendar_select_and_focus_day (calendar, day);
2422 else if (event->type == GDK_2BUTTON_PRESS)
2425 if (day_month == MONTH_CURRENT)
2426 g_signal_emit (calendar,
2427 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL],
2433 gtk_calendar_button_press (GtkWidget *widget,
2434 GdkEventButton *event)
2436 GtkCalendar *calendar = GTK_CALENDAR (widget);
2437 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2440 if (event->window == priv->main_win)
2441 calendar_main_button_press (calendar, event);
2443 if (!GTK_WIDGET_HAS_FOCUS (widget))
2444 gtk_widget_grab_focus (widget);
2446 for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++)
2448 if (event->window == priv->arrow_win[arrow])
2451 /* only call the action on single click, not double */
2452 if (event->type == GDK_BUTTON_PRESS)
2454 if (event->button == 1)
2455 calendar_start_spinning (calendar, arrow);
2457 calendar_arrow_action (calendar, arrow);
2468 gtk_calendar_button_release (GtkWidget *widget,
2469 GdkEventButton *event)
2471 GtkCalendar *calendar = GTK_CALENDAR (widget);
2472 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2474 if (event->button == 1)
2476 calendar_stop_spinning (calendar);
2486 gtk_calendar_motion_notify (GtkWidget *widget,
2487 GdkEventMotion *event)
2489 GtkCalendar *calendar = GTK_CALENDAR (widget);
2490 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2491 gint event_x, event_y;
2493 gint old_row, old_col;
2495 event_x = (gint) (event->x);
2496 event_y = (gint) (event->y);
2498 if (event->window == priv->main_win)
2503 if (gtk_drag_check_threshold (widget,
2504 priv->drag_start_x, priv->drag_start_y,
2505 event->x, event->y))
2507 GdkDragContext *context;
2508 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
2509 gtk_target_list_add_text_targets (target_list, 0);
2510 context = gtk_drag_begin (widget, target_list, GDK_ACTION_COPY,
2511 1, (GdkEvent *)event);
2516 gtk_target_list_unref (target_list);
2517 gtk_drag_set_icon_default (context);
2522 row = calendar_row_from_y (calendar, event_y);
2523 col = calendar_column_from_x (calendar, event_x);
2525 if (row != calendar->highlight_row || calendar->highlight_col != col)
2527 old_row = calendar->highlight_row;
2528 old_col = calendar->highlight_col;
2529 if (old_row > -1 && old_col > -1)
2531 calendar->highlight_row = -1;
2532 calendar->highlight_col = -1;
2533 calendar_invalidate_day (calendar, old_row, old_col);
2536 calendar->highlight_row = row;
2537 calendar->highlight_col = col;
2539 if (row > -1 && col > -1)
2540 calendar_invalidate_day (calendar, row, col);
2548 gtk_calendar_enter_notify (GtkWidget *widget,
2549 GdkEventCrossing *event)
2551 GtkCalendar *calendar = GTK_CALENDAR (widget);
2552 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2554 if (event->window == priv->arrow_win[ARROW_MONTH_LEFT])
2556 priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2557 calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT);
2560 if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT])
2562 priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2563 calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT);
2566 if (event->window == priv->arrow_win[ARROW_YEAR_LEFT])
2568 priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2569 calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT);
2572 if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT])
2574 priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2575 calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT);
2582 gtk_calendar_leave_notify (GtkWidget *widget,
2583 GdkEventCrossing *event)
2585 GtkCalendar *calendar = GTK_CALENDAR (widget);
2586 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2590 if (event->window == priv->main_win)
2592 row = calendar->highlight_row;
2593 col = calendar->highlight_col;
2594 calendar->highlight_row = -1;
2595 calendar->highlight_col = -1;
2596 if (row > -1 && col > -1)
2597 calendar_invalidate_day (calendar, row, col);
2600 if (event->window == priv->arrow_win[ARROW_MONTH_LEFT])
2602 priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2603 calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT);
2606 if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT])
2608 priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2609 calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT);
2612 if (event->window == priv->arrow_win[ARROW_YEAR_LEFT])
2614 priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2615 calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT);
2618 if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT])
2620 priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2621 calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT);
2628 gtk_calendar_scroll (GtkWidget *widget,
2629 GdkEventScroll *event)
2631 GtkCalendar *calendar = GTK_CALENDAR (widget);
2633 if (event->direction == GDK_SCROLL_UP)
2635 if (!GTK_WIDGET_HAS_FOCUS (widget))
2636 gtk_widget_grab_focus (widget);
2637 calendar_set_month_prev (calendar);
2639 else if (event->direction == GDK_SCROLL_DOWN)
2641 if (!GTK_WIDGET_HAS_FOCUS (widget))
2642 gtk_widget_grab_focus (widget);
2643 calendar_set_month_next (calendar);
2652 /****************************************
2654 ****************************************/
2657 move_focus (GtkCalendar *calendar,
2660 GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar));
2662 if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) ||
2663 (text_dir == GTK_TEXT_DIR_RTL && direction == 1))
2665 if (calendar->focus_col > 0)
2666 calendar->focus_col--;
2667 else if (calendar->focus_row > 0)
2669 calendar->focus_col = 6;
2670 calendar->focus_row--;
2675 if (calendar->focus_col < 6)
2676 calendar->focus_col++;
2677 else if (calendar->focus_row < 5)
2679 calendar->focus_col = 0;
2680 calendar->focus_row++;
2686 gtk_calendar_key_press (GtkWidget *widget,
2689 GtkCalendar *calendar;
2695 calendar = GTK_CALENDAR (widget);
2698 old_focus_row = calendar->focus_row;
2699 old_focus_col = calendar->focus_col;
2701 switch (event->keyval)
2706 if (event->state & GDK_CONTROL_MASK)
2707 calendar_set_month_prev (calendar);
2710 move_focus (calendar, -1);
2711 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2712 calendar_invalidate_day (calendar, calendar->focus_row,
2713 calendar->focus_col);
2719 if (event->state & GDK_CONTROL_MASK)
2720 calendar_set_month_next (calendar);
2723 move_focus (calendar, 1);
2724 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2725 calendar_invalidate_day (calendar, calendar->focus_row,
2726 calendar->focus_col);
2732 if (event->state & GDK_CONTROL_MASK)
2733 calendar_set_year_prev (calendar);
2736 if (calendar->focus_row > 0)
2737 calendar->focus_row--;
2738 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2739 calendar_invalidate_day (calendar, calendar->focus_row,
2740 calendar->focus_col);
2746 if (event->state & GDK_CONTROL_MASK)
2747 calendar_set_year_next (calendar);
2750 if (calendar->focus_row < 5)
2751 calendar->focus_row++;
2752 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2753 calendar_invalidate_day (calendar, calendar->focus_row,
2754 calendar->focus_col);
2759 row = calendar->focus_row;
2760 col = calendar->focus_col;
2761 day = calendar->day[row][col];
2763 if (row > -1 && col > -1)
2767 if (calendar->day_month[row][col] == MONTH_PREV)
2768 calendar_set_month_prev (calendar);
2769 else if (calendar->day_month[row][col] == MONTH_NEXT)
2770 calendar_set_month_next (calendar);
2772 calendar_select_and_focus_day (calendar, day);
2780 /****************************************
2781 * Misc widget methods *
2782 ****************************************/
2785 calendar_set_background (GtkWidget *widget)
2787 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2790 if (GTK_WIDGET_REALIZED (widget))
2792 for (i = 0; i < 4; i++)
2794 if (priv->arrow_win[i])
2795 gdk_window_set_background (priv->arrow_win[i],
2796 HEADER_BG_COLOR (widget));
2798 if (priv->header_win)
2799 gdk_window_set_background (priv->header_win,
2800 HEADER_BG_COLOR (widget));
2801 if (priv->day_name_win)
2802 gdk_window_set_background (priv->day_name_win,
2803 BACKGROUND_COLOR (widget));
2805 gdk_window_set_background (priv->week_win,
2806 BACKGROUND_COLOR (widget));
2808 gdk_window_set_background (priv->main_win,
2809 BACKGROUND_COLOR (widget));
2811 gdk_window_set_background (widget->window,
2812 BACKGROUND_COLOR (widget));
2817 gtk_calendar_style_set (GtkWidget *widget,
2818 GtkStyle *previous_style)
2820 if (previous_style && GTK_WIDGET_REALIZED (widget))
2821 calendar_set_background (widget);
2825 gtk_calendar_state_changed (GtkWidget *widget,
2826 GtkStateType previous_state)
2828 GtkCalendar *calendar = GTK_CALENDAR (widget);
2829 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2832 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2835 calendar_stop_spinning (calendar);
2838 for (i = 0; i < 4; i++)
2839 if (GTK_WIDGET_IS_SENSITIVE (widget))
2840 priv->arrow_state[i] = GTK_STATE_NORMAL;
2842 priv->arrow_state[i] = GTK_STATE_INSENSITIVE;
2844 calendar_set_background (widget);
2848 gtk_calendar_grab_notify (GtkWidget *widget,
2849 gboolean was_grabbed)
2852 calendar_stop_spinning (GTK_CALENDAR (widget));
2856 gtk_calendar_focus_out (GtkWidget *widget,
2857 GdkEventFocus *event)
2859 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2861 calendar_stop_spinning (GTK_CALENDAR (widget));
2869 /****************************************
2871 ****************************************/
2874 gtk_calendar_drag_data_get (GtkWidget *widget,
2875 GdkDragContext *context,
2876 GtkSelectionData *selection_data,
2880 GtkCalendar *calendar = GTK_CALENDAR (widget);
2885 date = g_date_new_dmy (calendar->selected_day, calendar->month + 1, calendar->year);
2886 len = g_date_strftime (str, 127, "%x", date);
2887 gtk_selection_data_set_text (selection_data, str, len);
2892 /* Get/set whether drag_motion requested the drag data and
2893 * drag_data_received should thus not actually insert the data,
2894 * since the data doesn't result from a drop.
2897 set_status_pending (GdkDragContext *context,
2898 GdkDragAction suggested_action)
2900 g_object_set_data (G_OBJECT (context),
2901 I_("gtk-calendar-status-pending"),
2902 GINT_TO_POINTER (suggested_action));
2905 static GdkDragAction
2906 get_status_pending (GdkDragContext *context)
2908 return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
2909 "gtk-calendar-status-pending"));
2913 gtk_calendar_drag_leave (GtkWidget *widget,
2914 GdkDragContext *context,
2917 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2919 priv->drag_highlight = 0;
2920 gtk_drag_unhighlight (widget);
2925 gtk_calendar_drag_motion (GtkWidget *widget,
2926 GdkDragContext *context,
2931 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2934 if (!priv->drag_highlight)
2936 priv->drag_highlight = 1;
2937 gtk_drag_highlight (widget);
2940 target = gtk_drag_dest_find_target (widget, context, NULL);
2941 if (target == GDK_NONE)
2942 gdk_drag_status (context, 0, time);
2945 set_status_pending (context, context->suggested_action);
2946 gtk_drag_get_data (widget, context, target, time);
2953 gtk_calendar_drag_drop (GtkWidget *widget,
2954 GdkDragContext *context,
2961 target = gtk_drag_dest_find_target (widget, context, NULL);
2962 if (target != GDK_NONE)
2964 gtk_drag_get_data (widget, context,
2974 gtk_calendar_drag_data_received (GtkWidget *widget,
2975 GdkDragContext *context,
2978 GtkSelectionData *selection_data,
2982 GtkCalendar *calendar = GTK_CALENDAR (widget);
2983 guint day, month, year;
2986 GdkDragAction suggested_action;
2988 suggested_action = get_status_pending (context);
2990 if (suggested_action)
2992 set_status_pending (context, 0);
2994 /* We are getting this data due to a request in drag_motion,
2995 * rather than due to a request in drag_drop, so we are just
2996 * supposed to call drag_status, not actually paste in the
2999 str = gtk_selection_data_get_text (selection_data);
3002 date = g_date_new ();
3003 g_date_set_parse (date, str);
3004 if (!g_date_valid (date))
3005 suggested_action = 0;
3010 suggested_action = 0;
3012 gdk_drag_status (context, suggested_action, time);
3017 date = g_date_new ();
3018 str = gtk_selection_data_get_text (selection_data);
3021 g_date_set_parse (date, str);
3025 if (!g_date_valid (date))
3027 g_warning ("Received invalid date data\n");
3029 gtk_drag_finish (context, FALSE, FALSE, time);
3033 day = g_date_get_day (date);
3034 month = g_date_get_month (date);
3035 year = g_date_get_year (date);
3038 gtk_drag_finish (context, TRUE, FALSE, time);
3041 g_object_freeze_notify (G_OBJECT (calendar));
3042 if (!(calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
3043 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
3044 gtk_calendar_select_month (calendar, month - 1, year);
3045 gtk_calendar_select_day (calendar, day);
3046 g_object_thaw_notify (G_OBJECT (calendar));
3050 /****************************************
3052 ****************************************/
3057 * Creates a new calendar, with the current date being selected.
3059 * Return value: a newly #GtkCalendar widget
3062 gtk_calendar_new (void)
3064 return g_object_new (GTK_TYPE_CALENDAR, NULL);
3068 * gtk_calendar_display_options:
3069 * @calendar: a #GtkCalendar.
3070 * @flags: the display options to set.
3072 * Sets display options (whether to display the heading and the month headings).
3074 * Deprecated: Use gtk_calendar_set_display_options() instead
3077 gtk_calendar_display_options (GtkCalendar *calendar,
3078 GtkCalendarDisplayOptions flags)
3080 gtk_calendar_set_display_options (calendar, flags);
3084 * gtk_calendar_get_display_options:
3085 * @calendar: a #GtkCalendar
3087 * Returns the current display options of @calendar.
3089 * Return value: the display options.
3093 GtkCalendarDisplayOptions
3094 gtk_calendar_get_display_options (GtkCalendar *calendar)
3096 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), 0);
3098 return calendar->display_flags;
3102 * gtk_calendar_set_display_options:
3103 * @calendar: a #GtkCalendar
3104 * @flags: the display options to set
3106 * Sets display options (whether to display the heading and the month
3112 gtk_calendar_set_display_options (GtkCalendar *calendar,
3113 GtkCalendarDisplayOptions flags)
3115 GtkWidget *widget = GTK_WIDGET (calendar);
3116 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
3119 GtkCalendarDisplayOptions old_flags;
3121 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3123 old_flags = calendar->display_flags;
3125 if (GTK_WIDGET_REALIZED (widget))
3127 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
3130 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
3131 && (priv->header_win))
3133 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
3134 calendar_realize_arrows (calendar);
3138 for (i = 0; i < 4; i++)
3140 if (priv->arrow_win[i])
3142 gdk_window_set_user_data (priv->arrow_win[i],
3144 gdk_window_destroy (priv->arrow_win[i]);
3145 priv->arrow_win[i] = NULL;
3151 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
3155 if (flags & GTK_CALENDAR_SHOW_HEADING)
3157 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
3158 calendar_realize_header (calendar);
3162 for (i = 0; i < 4; i++)
3164 if (priv->arrow_win[i])
3166 gdk_window_set_user_data (priv->arrow_win[i],
3168 gdk_window_destroy (priv->arrow_win[i]);
3169 priv->arrow_win[i] = NULL;
3172 gdk_window_set_user_data (priv->header_win, NULL);
3173 gdk_window_destroy (priv->header_win);
3174 priv->header_win = NULL;
3179 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
3183 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
3185 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
3186 calendar_realize_day_names (calendar);
3190 gdk_window_set_user_data (priv->day_name_win, NULL);
3191 gdk_window_destroy (priv->day_name_win);
3192 priv->day_name_win = NULL;
3196 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3200 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3202 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
3203 calendar_realize_week_numbers (calendar);
3207 gdk_window_set_user_data (priv->week_win, NULL);
3208 gdk_window_destroy (priv->week_win);
3209 priv->week_win = NULL;
3213 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
3214 g_warning ("GTK_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale");
3216 calendar->display_flags = flags;
3218 gtk_widget_queue_resize (GTK_WIDGET (calendar));
3222 calendar->display_flags = flags;
3224 g_object_freeze_notify (G_OBJECT (calendar));
3225 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
3226 g_object_notify (G_OBJECT (calendar), "show-heading");
3227 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
3228 g_object_notify (G_OBJECT (calendar), "show-day-names");
3229 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
3230 g_object_notify (G_OBJECT (calendar), "no-month-change");
3231 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3232 g_object_notify (G_OBJECT (calendar), "show-week-numbers");
3233 g_object_thaw_notify (G_OBJECT (calendar));
3237 * gtk_calendar_select_month:
3238 * @calendar: a #GtkCalendar
3239 * @month: a month number between 0 and 11.
3240 * @year: the year the month is in.
3242 * Shifts the calendar to a different month.
3244 * Return value: %TRUE, always
3247 gtk_calendar_select_month (GtkCalendar *calendar,
3251 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3252 g_return_val_if_fail (month <= 11, FALSE);
3254 calendar->month = month;
3255 calendar->year = year;
3257 calendar_compute_days (calendar);
3259 gtk_widget_queue_draw (GTK_WIDGET (calendar));
3261 g_object_freeze_notify (G_OBJECT (calendar));
3262 g_object_notify (G_OBJECT (calendar), "month");
3263 g_object_notify (G_OBJECT (calendar), "year");
3264 g_object_thaw_notify (G_OBJECT (calendar));
3266 g_signal_emit (calendar,
3267 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
3273 * gtk_calendar_select_day:
3274 * @calendar: a #GtkCalendar.
3275 * @day: the day number between 1 and 31, or 0 to unselect
3276 * the currently selected day.
3278 * Selects a day from the current month.
3281 gtk_calendar_select_day (GtkCalendar *calendar,
3284 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3285 g_return_if_fail (day <= 31);
3287 /* Deselect the old day */
3288 if (calendar->selected_day > 0)
3292 selected_day = calendar->selected_day;
3293 calendar->selected_day = 0;
3294 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
3295 calendar_invalidate_day_num (calendar, selected_day);
3298 calendar->selected_day = day;
3300 /* Select the new day */
3303 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
3304 calendar_invalidate_day_num (calendar, day);
3307 g_object_notify (G_OBJECT (calendar), "day");
3309 g_signal_emit (calendar,
3310 gtk_calendar_signals[DAY_SELECTED_SIGNAL],
3315 * gtk_calendar_clear_marks:
3316 * @calendar: a #GtkCalendar
3318 * Remove all visual markers.
3321 gtk_calendar_clear_marks (GtkCalendar *calendar)
3325 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3327 for (day = 0; day < 31; day++)
3329 calendar->marked_date[day] = FALSE;
3332 calendar->num_marked_dates = 0;
3334 gtk_widget_queue_draw (GTK_WIDGET (calendar));
3338 * gtk_calendar_mark_day:
3339 * @calendar: a #GtkCalendar
3340 * @day: the day number to mark between 1 and 31.
3342 * Places a visual marker on a particular day.
3344 * Return value: %TRUE, always
3347 gtk_calendar_mark_day (GtkCalendar *calendar,
3350 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3352 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE)
3354 calendar->marked_date[day - 1] = TRUE;
3355 calendar->num_marked_dates++;
3356 calendar_invalidate_day_num (calendar, day);
3363 * gtk_calendar_unmark_day:
3364 * @calendar: a #GtkCalendar.
3365 * @day: the day number to unmark between 1 and 31.
3367 * Removes the visual marker from a particular day.
3369 * Return value: %TRUE, always
3372 gtk_calendar_unmark_day (GtkCalendar *calendar,
3375 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3377 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE)
3379 calendar->marked_date[day - 1] = FALSE;
3380 calendar->num_marked_dates--;
3381 calendar_invalidate_day_num (calendar, day);
3388 * gtk_calendar_get_date:
3389 * @calendar: a #GtkCalendar
3390 * @year: location to store the year number, or %NULL
3391 * @month: location to store the month number (between 0 and 11), or %NULL
3392 * @day: location to store the day number (between 1 and 31), or %NULL
3394 * Obtains the selected date from a #GtkCalendar.
3397 gtk_calendar_get_date (GtkCalendar *calendar,
3402 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3405 *year = calendar->year;
3408 *month = calendar->month;
3411 *day = calendar->selected_day;
3415 * gtk_calendar_freeze:
3416 * @calendar: a #GtkCalendar
3418 * Does nothing. Previously locked the display of the calendar until
3419 * it was thawed with gtk_calendar_thaw().
3422 gtk_calendar_freeze (GtkCalendar *calendar)
3424 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3428 * gtk_calendar_thaw:
3429 * @calendar: a #GtkCalendar
3431 * Does nothing. Previously defrosted a calendar; all the changes made
3432 * since the last gtk_calendar_freeze() were displayed.
3435 gtk_calendar_thaw (GtkCalendar *calendar)
3437 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3440 #define __GTK_CALENDAR_C__
3441 #include "gtkaliasdef.c"