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 Library 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 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library 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.
30 #include "gtkcalendar.h"
31 #include "gdk/gdkkeysyms.h"
33 /***************************************************************************/
34 /* The following date routines are taken from the lib_date package. Keep
35 * them seperate in case we want to update them if a newer lib_date comes
38 typedef unsigned int N_int;
39 typedef unsigned long N_long;
40 typedef signed long Z_long;
41 typedef enum { false = FALSE , true = TRUE } boolean;
43 #define and && /* logical (boolean) operators: lower case */
46 static N_int month_length[2][13] =
48 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
49 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
52 static N_int days_in_months[2][14] =
54 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
55 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
58 static Z_long calc_days(N_int year, N_int mm, N_int dd);
59 static N_int day_of_week(N_int year, N_int mm, N_int dd);
60 static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1,
61 N_int year2, N_int mm2, N_int dd2);
62 static N_int weeks_in_year(N_int year);
67 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
71 day_of_week(N_int year, N_int mm, N_int dd)
75 days = calc_days(year, mm, dd);
82 return( (N_int) days );
85 static N_int weeks_in_year(N_int year)
87 return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
91 check_date(N_int year, N_int mm, N_int dd)
93 if (year < 1) return(false);
94 if ((mm < 1) or (mm > 12)) return(false);
95 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
100 week_number(N_int year, N_int mm, N_int dd)
104 first = day_of_week(year,1,1) - 1;
105 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
110 year_to_days(N_int year)
112 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
117 calc_days(N_int year, N_int mm, N_int dd)
121 if (year < 1) return(0L);
122 if ((mm < 1) or (mm > 12)) return(0L);
123 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
124 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
128 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
130 if (check_date(*year,mm,dd))
132 *week = week_number(*year,mm,dd);
134 *week = weeks_in_year(--(*year));
135 else if (*week > weeks_in_year(*year))
146 dates_difference(N_int year1, N_int mm1, N_int dd1,
147 N_int year2, N_int mm2, N_int dd2)
149 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
152 /** END OF lib_date routines ************************************************/
154 #define CALENDAR_MARGIN 0
155 #define CALENDAR_YSEP 4
156 #define CALENDAR_XSEP 4
157 #define INNER_BORDER 4
161 #define DAY_XSEP 0 /* not really good for small calendar */
162 #define DAY_YSEP 0 /* not really good for small calendar */
165 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
166 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
167 #define DAY_NAME_COLOR(widget) (& (widget)->style->dark[GTK_WIDGET_STATE (widget)])
168 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
169 #define SELECTION_FOCUS_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
170 #define SELECTION_NO_FOCUS_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
171 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
172 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
173 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
174 #define FOREGROUND_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
175 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
176 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
178 #define HEADER_FONT(widget) ((widget)->style->font)
179 #define LABEL_FONT(widget) ((widget)->style->font)
180 #define DAY_FONT(widget) ((widget)->style->font)
196 MONTH_CHANGED_SIGNAL,
198 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
206 static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
208 static GtkWidgetClass *parent_class = NULL;
210 typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;
211 struct _GtkCalendarPrivateData
213 GdkWindow *header_win;
214 GdkWindow *day_name_win;
217 GdkWindow *arrow_win[4];
219 guint header_h, day_name_h, main_h;
221 guint arrow_state[4];
223 guint max_month_width;
224 guint max_year_width;
230 guint max_day_char_width;
231 guint max_day_char_ascent;
232 guint max_day_char_descent;
233 guint max_label_char_ascent;
234 guint max_label_char_descent;
235 guint max_week_char_width;
238 unsigned int dirty_header:1;
239 unsigned int dirty_day_names:1;
240 unsigned int dirty_main:1;
241 unsigned int dirty_week:1;
245 #define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))
247 typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);
249 static void gtk_calendar_class_init (GtkCalendarClass *class);
250 static void gtk_calendar_init (GtkCalendar *calendar);
251 static void gtk_calendar_realize (GtkWidget *widget);
252 static void gtk_calendar_unrealize (GtkWidget *widget);
253 static void gtk_calendar_draw_focus (GtkWidget *widget);
254 static void gtk_calendar_size_request (GtkWidget *widget,
255 GtkRequisition *requisition);
256 static void gtk_calendar_size_allocate (GtkWidget *widget,
257 GtkAllocation *allocation);
258 static gint gtk_calendar_expose (GtkWidget *widget,
259 GdkEventExpose *event);
260 static gint gtk_calendar_button_press (GtkWidget *widget,
261 GdkEventButton *event);
262 static void gtk_calendar_main_button (GtkWidget *widget,
263 GdkEventButton *event);
264 static gint gtk_calendar_motion_notify (GtkWidget *widget,
265 GdkEventMotion *event);
266 static gint gtk_calendar_enter_notify (GtkWidget *widget,
267 GdkEventCrossing *event);
268 static gint gtk_calendar_leave_notify (GtkWidget *widget,
269 GdkEventCrossing *event);
270 static gint gtk_calendar_key_press (GtkWidget *widget,
272 static gint gtk_calendar_focus_in (GtkWidget *widget,
273 GdkEventFocus *event);
274 static gint gtk_calendar_focus_out (GtkWidget *widget,
275 GdkEventFocus *event);
276 static void gtk_calendar_state_changed (GtkWidget *widget,
277 GtkStateType previous_state);
278 static void gtk_calendar_style_set (GtkWidget *widget,
279 GtkStyle *previous_style);
280 static void gtk_calendar_paint_header (GtkWidget *widget);
281 static void gtk_calendar_paint_day_names (GtkWidget *widget);
282 static void gtk_calendar_paint_week_numbers (GtkWidget *widget);
283 static void gtk_calendar_paint_main (GtkWidget *widget);
286 static void gtk_calendar_paint (GtkWidget *widget,
288 static void gtk_calendar_paint_arrow (GtkWidget *widget,
290 static void gtk_calendar_paint_day_num (GtkWidget *widget,
292 static void gtk_calendar_paint_day (GtkWidget *widget,
295 static void gtk_calendar_draw (GtkWidget *widget,
297 static void gtk_calendar_compute_days (GtkCalendar *calendar);
298 static gint left_x_for_column (GtkCalendar *calendar,
300 static gint top_y_for_row (GtkCalendar *calendar,
303 static char *default_abbreviated_dayname[7];
304 static char *default_monthname[12];
307 gtk_calendar_get_type (void)
309 static GtkType calendar_type = 0;
313 GtkTypeInfo calendar_info =
316 sizeof (GtkCalendar),
317 sizeof (GtkCalendarClass),
318 (GtkClassInitFunc) gtk_calendar_class_init,
319 (GtkObjectInitFunc) gtk_calendar_init,
320 (GtkArgSetFunc) NULL,
321 (GtkArgGetFunc) NULL,
324 calendar_type = gtk_type_unique (GTK_TYPE_WIDGET, &calendar_info);
327 return calendar_type;
331 gtk_calendar_class_init (GtkCalendarClass *class)
333 GtkObjectClass *object_class;
334 GtkWidgetClass *widget_class;
336 object_class = (GtkObjectClass*) class;
337 widget_class = (GtkWidgetClass*) class;
339 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
341 widget_class->realize = gtk_calendar_realize;
342 widget_class->unrealize = gtk_calendar_unrealize;
343 widget_class->expose_event = gtk_calendar_expose;
344 widget_class->draw = gtk_calendar_draw;
345 widget_class->draw_focus = gtk_calendar_draw_focus;
346 widget_class->size_request = gtk_calendar_size_request;
347 widget_class->size_allocate = gtk_calendar_size_allocate;
348 widget_class->button_press_event = gtk_calendar_button_press;
349 widget_class->motion_notify_event = gtk_calendar_motion_notify;
350 widget_class->enter_notify_event = gtk_calendar_enter_notify;
351 widget_class->leave_notify_event = gtk_calendar_leave_notify;
352 widget_class->key_press_event = gtk_calendar_key_press;
353 widget_class->focus_in_event = gtk_calendar_focus_in;
354 widget_class->focus_out_event = gtk_calendar_focus_out;
355 widget_class->style_set = gtk_calendar_style_set;
356 widget_class->state_changed = gtk_calendar_state_changed;
358 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
359 gtk_signal_new ("month_changed",
360 GTK_RUN_FIRST, object_class->type,
361 GTK_SIGNAL_OFFSET (GtkCalendarClass, month_changed),
362 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
363 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
364 gtk_signal_new ("day_selected",
365 GTK_RUN_FIRST, object_class->type,
366 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected),
367 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
368 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
369 gtk_signal_new ("day_selected_double_click",
370 GTK_RUN_FIRST, object_class->type,
371 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected_double_click),
372 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
373 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
374 gtk_signal_new ("prev_month",
375 GTK_RUN_FIRST, object_class->type,
376 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_month),
377 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
378 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
379 gtk_signal_new ("next_month",
380 GTK_RUN_FIRST, object_class->type,
381 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_month),
382 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
383 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
384 gtk_signal_new ("prev_year",
385 GTK_RUN_FIRST, object_class->type,
386 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_year),
387 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
388 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
389 gtk_signal_new ("next_year",
390 GTK_RUN_FIRST, object_class->type,
391 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_year),
392 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
394 gtk_object_class_add_signals (object_class, gtk_calendar_signals, LAST_SIGNAL);
396 class->month_changed = NULL;
397 class->day_selected = NULL;
398 class->day_selected_double_click = NULL;
399 class->prev_month = NULL;
400 class->next_month = NULL;
401 class->prev_year = NULL;
402 class->next_year = NULL;
406 gtk_calendar_init (GtkCalendar *calendar)
414 GtkCalendarPrivateData *private_data;
416 widget = GTK_WIDGET (calendar);
417 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
419 calendar->private_data = (gpointer) malloc (sizeof (GtkCalendarPrivateData));
420 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
422 if (!default_abbreviated_dayname[0])
425 tmp_time= (i+3)*86400;
426 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
427 default_abbreviated_dayname[i] = g_strdup (buffer);
430 if (!default_monthname[0])
434 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
435 default_monthname[i] = g_strdup (buffer);
440 tm = localtime (&secs);
441 calendar->month = tm->tm_mon;
442 calendar->year = 1900 + tm->tm_year;
445 calendar->marked_date[i] = FALSE;
446 calendar->selected_day = 1;
448 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
449 GTK_CALENDAR_SHOW_DAY_NAMES );
451 calendar->highlight_row = -1;
452 calendar->highlight_col = -1;
454 private_data->max_year_width = 0;
455 private_data->max_month_width = 0;
456 private_data->max_day_char_width = 0;
457 private_data->max_week_char_width = 0;
459 private_data->max_day_char_ascent = 0;
460 private_data->max_day_char_descent = 0;
461 private_data->max_label_char_ascent = 0;
462 private_data->max_label_char_descent = 0;
464 private_data->arrow_width = 10;
466 private_data->dirty_header = 0;
467 private_data->dirty_day_names = 0;
468 private_data->dirty_week = 0;
469 private_data->dirty_main = 0;
470 private_data->frozen = 0;
474 gtk_calendar_new (void)
476 return GTK_WIDGET (gtk_type_new (GTK_TYPE_CALENDAR));
479 /* column_from_x: returns the column 0-6 that the
480 * x pixel of the xwindow is in */
482 column_from_x (GtkCalendar *calendar,
486 gint x_left, x_right;
490 for (c = 0; c < 7; c++)
492 x_left = left_x_for_column (calendar, c);
493 x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
495 if (event_x > x_left && event_x < x_right)
506 row_height (GtkCalendar *calendar)
508 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN
509 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
510 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
514 /* row_from_y: returns the row 0-5 that the
515 * y pixel of the xwindow is in */
517 row_from_y (GtkCalendar *calendar,
522 gint y_top, y_bottom;
524 height = row_height (calendar);
527 for (r = 0; r < 6; r++)
529 y_top = top_y_for_row (calendar, r);
530 y_bottom = y_top + height;
532 if (event_y > y_top && event_y < y_bottom)
542 /* left_x_for_column: returns the x coordinate
543 * for the left of the column */
545 left_x_for_column (GtkCalendar *calendar,
551 width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
552 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
553 x_left = DAY_XSEP + (width + DAY_XSEP) * column;
555 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
560 /* top_y_for_row: returns the y coordinate
561 * for the top of the row */
563 top_y_for_row (GtkCalendar *calendar,
567 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h
568 - (CALENDAR_MARGIN + (6 - row)
569 * row_height (calendar)));
572 /* This function should be done by the toolkit, but we don't like the
573 * GTK arrows because they don't look good on this widget */
575 draw_arrow_right (GdkWindow *window,
583 for (i = 0; i <= size / 2; i++)
585 gdk_draw_line (window, gc,
593 /* This function should be done by the toolkit, but we don't like the
594 * GTK arrows because they don't look good on this widget */
596 draw_arrow_left (GdkWindow *window,
604 for (i = 0; i <= size / 2; i++)
606 gdk_draw_line (window, gc,
615 gtk_calendar_set_month_prev (GtkCalendar *calendar)
619 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
622 if (calendar->month == 0)
624 calendar->month = 11;
630 month_len = month_length[leap (calendar->year)][calendar->month + 1];
632 gtk_calendar_freeze (calendar);
633 gtk_calendar_compute_days (calendar);
635 gtk_signal_emit (GTK_OBJECT (calendar),
636 gtk_calendar_signals[PREV_MONTH_SIGNAL]);
637 gtk_signal_emit (GTK_OBJECT (calendar),
638 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
640 if (month_len < calendar->selected_day)
642 calendar->selected_day = 0;
643 gtk_calendar_select_day (calendar, month_len);
647 if (calendar->selected_day < 0)
648 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
650 gtk_calendar_select_day (calendar, calendar->selected_day);
653 gtk_calendar_select_day (calendar, calendar->selected_day);
654 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
655 gtk_calendar_thaw (calendar);
660 gtk_calendar_set_month_next (GtkCalendar *calendar)
664 g_return_if_fail (calendar != NULL);
665 g_return_if_fail (GTK_IS_WIDGET (calendar));
667 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
671 if (calendar->month == 11)
679 gtk_calendar_freeze (calendar);
680 gtk_calendar_compute_days (calendar);
681 gtk_signal_emit (GTK_OBJECT (calendar),
682 gtk_calendar_signals[NEXT_MONTH_SIGNAL]);
683 gtk_signal_emit (GTK_OBJECT (calendar),
684 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
686 month_len = month_length[leap (calendar->year)][calendar->month + 1];
688 if (month_len < calendar->selected_day)
690 calendar->selected_day = 0;
691 gtk_calendar_select_day (calendar, month_len);
694 gtk_calendar_select_day (calendar, calendar->selected_day);
696 gtk_calendar_paint (GTK_WIDGET(calendar), NULL);
697 gtk_calendar_thaw (calendar);
701 gtk_calendar_set_year_prev (GtkCalendar *calendar)
705 g_return_if_fail (calendar != NULL);
706 g_return_if_fail (GTK_IS_WIDGET (calendar));
709 gtk_calendar_freeze (calendar);
710 gtk_calendar_compute_days (calendar);
711 gtk_signal_emit (GTK_OBJECT (calendar),
712 gtk_calendar_signals[PREV_YEAR_SIGNAL]);
713 gtk_signal_emit (GTK_OBJECT (calendar),
714 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
716 month_len = month_length[leap (calendar->year)][calendar->month + 1];
718 if (month_len < calendar->selected_day)
720 calendar->selected_day = 0;
721 gtk_calendar_select_day (calendar, month_len);
724 gtk_calendar_select_day (calendar, calendar->selected_day);
726 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
727 gtk_calendar_thaw (calendar);
731 gtk_calendar_set_year_next (GtkCalendar *calendar)
736 g_return_if_fail (calendar != NULL);
737 g_return_if_fail (GTK_IS_WIDGET (calendar));
739 widget = GTK_WIDGET (calendar);
741 gtk_calendar_freeze (calendar);
744 gtk_calendar_compute_days (calendar);
745 gtk_signal_emit (GTK_OBJECT (calendar),
746 gtk_calendar_signals[NEXT_YEAR_SIGNAL]);
747 gtk_signal_emit (GTK_OBJECT (calendar),
748 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
750 month_len = month_length[leap (calendar->year)][calendar->month + 1];
752 if (month_len < calendar->selected_day)
754 calendar->selected_day = 0;
755 gtk_calendar_select_day (calendar, month_len);
758 gtk_calendar_select_day (calendar, calendar->selected_day);
760 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
761 gtk_calendar_thaw (calendar);
765 gtk_calendar_main_button (GtkWidget *widget,
766 GdkEventButton *event)
768 GtkCalendar *calendar;
773 calendar = GTK_CALENDAR (widget);
775 x = (gint) (event->x);
776 y = (gint) (event->y);
778 row = row_from_y (calendar, y);
779 col = column_from_x (calendar, x);
781 day_month = calendar->day_month[row][col];
783 if (day_month == MONTH_CURRENT)
785 if (event->type == GDK_2BUTTON_PRESS)
786 gtk_signal_emit (GTK_OBJECT (calendar),
787 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL]);
790 if (!GTK_WIDGET_HAS_FOCUS (widget))
791 gtk_widget_grab_focus (widget);
792 gtk_calendar_select_day (calendar, calendar->day[row][col]);
795 else if (day_month == MONTH_PREV)
796 gtk_calendar_set_month_prev (calendar);
797 else if (day_month == MONTH_NEXT)
798 gtk_calendar_set_month_next (calendar);
802 gtk_calendar_realize_arrows (GtkWidget *widget)
804 GtkCalendar *calendar;
805 GtkCalendarPrivateData *private_data;
806 GdkWindowAttr attributes;
807 gint attributes_mask;
810 g_return_if_fail (widget != NULL);
811 g_return_if_fail (GTK_IS_CALENDAR (widget));
813 calendar = GTK_CALENDAR (widget);
814 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
816 /* Arrow windows ------------------------------------- */
817 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
818 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
820 attributes.wclass = GDK_INPUT_OUTPUT;
821 attributes.window_type = GDK_WINDOW_CHILD;
822 attributes.visual = gtk_widget_get_visual (widget);
823 attributes.colormap = gtk_widget_get_colormap (widget);
824 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
825 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
826 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
827 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
829 attributes.width = private_data->arrow_width;
830 attributes.height = private_data->header_h - 7;
831 for (i = 0; i < 4; i++)
835 case ARROW_MONTH_LEFT:
838 case ARROW_MONTH_RIGHT:
839 attributes.x = (private_data->arrow_width
840 + private_data->max_month_width);
842 case ARROW_YEAR_LEFT:
843 attributes.x = (widget->allocation.width - 4
844 - (3 + 2*private_data->arrow_width
845 + private_data->max_year_width));
847 case ARROW_YEAR_RIGHT:
848 attributes.x = (widget->allocation.width - 4
849 - 3 - private_data->arrow_width);
852 private_data->arrow_win[i] = gdk_window_new (private_data->header_win,
855 private_data->arrow_state[i] = GTK_STATE_NORMAL;
856 gdk_window_set_background (private_data->arrow_win[i],
857 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
858 gdk_window_show (private_data->arrow_win[i]);
859 gdk_window_set_user_data (private_data->arrow_win[i], widget);
864 for (i = 0; i < 4; i++)
865 private_data->arrow_win[i] = NULL;
870 gtk_calendar_realize_header (GtkWidget *widget)
872 GtkCalendar *calendar;
873 GtkCalendarPrivateData *private_data;
874 GdkWindowAttr attributes;
875 gint attributes_mask;
877 g_return_if_fail (widget != NULL);
878 g_return_if_fail (GTK_IS_CALENDAR (widget));
880 calendar = GTK_CALENDAR (widget);
881 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
883 /* Header window ------------------------------------- */
884 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
886 attributes.wclass = GDK_INPUT_OUTPUT;
887 attributes.window_type = GDK_WINDOW_CHILD;
888 attributes.visual = gtk_widget_get_visual (widget);
889 attributes.colormap = gtk_widget_get_colormap (widget);
890 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
891 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
894 attributes.width = widget->allocation.width - 4;
895 attributes.height = private_data->header_h;
896 private_data->header_win = gdk_window_new (widget->window,
897 &attributes, attributes_mask);
899 gdk_window_set_background (private_data->header_win,
900 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
901 gdk_window_show (private_data->header_win);
902 gdk_window_set_user_data (private_data->header_win, widget);
907 private_data->header_win = NULL;
909 gtk_calendar_realize_arrows (widget);
913 gtk_calendar_realize_day_names (GtkWidget *widget)
915 GtkCalendar *calendar;
916 GtkCalendarPrivateData *private_data;
917 GdkWindowAttr attributes;
918 gint attributes_mask;
920 g_return_if_fail (widget != NULL);
921 g_return_if_fail (GTK_IS_CALENDAR (widget));
923 calendar = GTK_CALENDAR (widget);
924 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
926 /* Day names window --------------------------------- */
927 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
929 attributes.wclass = GDK_INPUT_OUTPUT;
930 attributes.window_type = GDK_WINDOW_CHILD;
931 attributes.visual = gtk_widget_get_visual (widget);
932 attributes.colormap = gtk_widget_get_colormap (widget);
933 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
934 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
935 attributes.x = (widget->style->klass->xthickness + INNER_BORDER);
936 attributes.y = private_data->header_h + (widget->style->klass->ythickness
938 attributes.width = (widget->allocation.width
939 - (widget->style->klass->xthickness + INNER_BORDER)
941 attributes.height = private_data->day_name_h;
942 private_data->day_name_win = gdk_window_new (widget->window,
945 gdk_window_set_background (private_data->day_name_win,
946 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
947 gdk_window_show (private_data->day_name_win);
948 gdk_window_set_user_data (private_data->day_name_win, widget);
952 private_data->day_name_win = NULL;
957 gtk_calendar_realize_week_numbers (GtkWidget *widget)
959 GtkCalendar *calendar;
960 GtkCalendarPrivateData *private_data;
961 GdkWindowAttr attributes;
962 gint attributes_mask;
964 g_return_if_fail (widget != NULL);
965 g_return_if_fail (GTK_IS_CALENDAR (widget));
967 calendar = GTK_CALENDAR (widget);
968 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
970 /* Week number window -------------------------------- */
971 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
973 attributes.wclass = GDK_INPUT_OUTPUT;
974 attributes.window_type = GDK_WINDOW_CHILD;
975 attributes.visual = gtk_widget_get_visual (widget);
976 attributes.colormap = gtk_widget_get_colormap (widget);
977 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
979 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
980 attributes.x = + (widget->style->klass->xthickness + INNER_BORDER);
981 attributes.y = (private_data->header_h + private_data->day_name_h
982 + (widget->style->klass->ythickness + INNER_BORDER));
983 attributes.width = private_data->week_width;
984 attributes.height = private_data->main_h;
985 private_data->week_win = gdk_window_new (widget->window,
986 &attributes, attributes_mask);
987 gdk_window_set_background (private_data->week_win,
988 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
989 gdk_window_show (private_data->week_win);
990 gdk_window_set_user_data (private_data->week_win, widget);
994 private_data->week_win = NULL;
999 gtk_calendar_realize (GtkWidget *widget)
1001 GtkCalendar *calendar;
1002 GtkCalendarPrivateData *private_data;
1003 GdkWindowAttr attributes;
1004 gint attributes_mask;
1006 g_return_if_fail (widget != NULL);
1007 g_return_if_fail (GTK_IS_CALENDAR (widget));
1009 calendar = GTK_CALENDAR (widget);
1010 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1012 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1013 gtk_calendar_compute_days (calendar);
1015 attributes.x = widget->allocation.x;
1016 attributes.y = widget->allocation.y;
1017 attributes.width = widget->allocation.width;
1018 attributes.height = widget->allocation.height;
1019 attributes.wclass = GDK_INPUT_OUTPUT;
1020 attributes.window_type = GDK_WINDOW_CHILD;
1021 attributes.event_mask = (gtk_widget_get_events (widget)
1022 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK);
1023 attributes.visual = gtk_widget_get_visual (widget);
1024 attributes.colormap = gtk_widget_get_colormap (widget);
1026 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1027 widget->window = gdk_window_new (widget->parent->window,
1028 &attributes, attributes_mask);
1030 widget->style = gtk_style_attach (widget->style, widget->window);
1032 /* Header window ------------------------------------- */
1033 gtk_calendar_realize_header (widget);
1034 /* Day names window --------------------------------- */
1035 gtk_calendar_realize_day_names (widget);
1036 /* Week number window -------------------------------- */
1037 gtk_calendar_realize_week_numbers (widget);
1038 /* Main Window -------------------------------------- */
1039 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1040 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1041 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1043 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1044 attributes.x = private_data->week_width;
1047 attributes.x += (widget->style->klass->xthickness + INNER_BORDER);
1048 attributes.y = (private_data->header_h + private_data->day_name_h
1049 + (widget->style->klass->ythickness + INNER_BORDER));
1050 attributes.width = (widget->allocation.width - attributes.x
1051 - (widget->style->klass->xthickness + INNER_BORDER));
1052 attributes.height = private_data->main_h;
1053 private_data->main_win = gdk_window_new (widget->window,
1054 &attributes, attributes_mask);
1055 gdk_window_set_background (private_data->main_win,
1056 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1057 gdk_window_show (private_data->main_win);
1058 gdk_window_set_user_data (private_data->main_win, widget);
1059 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1060 gdk_window_show (widget->window);
1061 gdk_window_set_user_data (widget->window, widget);
1063 /* Set widgets gc */
1064 calendar->gc = gdk_gc_new (widget->window);
1068 gtk_calendar_unrealize (GtkWidget *widget)
1070 GtkCalendar *calendar;
1071 GtkCalendarPrivateData *private_data;
1074 g_return_if_fail (widget != NULL);
1075 g_return_if_fail (GTK_IS_CALENDAR (widget));
1077 calendar = GTK_CALENDAR (widget);
1078 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1080 if (private_data->header_win)
1082 for (i = 0; i < 4; i++)
1084 if (private_data->arrow_win[i])
1086 gdk_window_set_user_data (private_data->arrow_win[i], NULL);
1087 gdk_window_destroy (private_data->arrow_win[i]);
1088 private_data->arrow_win[i] = NULL;
1091 gdk_window_set_user_data (private_data->header_win, NULL);
1092 gdk_window_destroy (private_data->header_win);
1093 private_data->header_win = NULL;
1096 if (private_data->week_win)
1098 gdk_window_set_user_data (private_data->week_win, NULL);
1099 gdk_window_destroy (private_data->week_win);
1100 private_data->week_win = NULL;
1103 if (private_data->main_win)
1105 gdk_window_set_user_data (private_data->main_win, NULL);
1106 gdk_window_destroy (private_data->main_win);
1107 private_data->main_win = NULL;
1110 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1111 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1115 gtk_calendar_size_request (GtkWidget *widget,
1116 GtkRequisition *requisition)
1118 GtkCalendar *calendar;
1119 GtkCalendarPrivateData *private_data;
1124 gint calendar_margin = CALENDAR_MARGIN;
1125 gint header_width, main_width;
1132 calendar = GTK_CALENDAR (widget);
1133 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1136 * Calculate the requisition width for the widget.
1141 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1143 private_data->max_month_width = 0;
1144 for (i = 0; i < 12; i++)
1146 private_data->max_month_width = MAX (private_data->max_month_width,
1147 gdk_string_measure (HEADER_FONT (widget),
1148 default_monthname[i]) + 8);
1150 private_data->max_year_width = 0;
1151 for (i=0; i<10; i++)
1153 sprintf (buffer, "%d%d%d%d", i,i,i,i);
1154 private_data->max_year_width = MAX (private_data->max_year_width,
1155 gdk_string_measure (HEADER_FONT (widget),
1161 private_data->max_month_width = 0;
1162 private_data->max_year_width = 0;
1165 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1166 header_width = (private_data->max_month_width
1167 + private_data->max_year_width
1170 header_width = (private_data->max_month_width
1171 + private_data->max_year_width
1172 + 4 * private_data->arrow_width + 3 * 3);
1174 /* Mainwindow labels width */
1176 private_data->max_day_char_width = 0;
1177 for (i = 0; i < 9; i++)
1179 sprintf (buffer, "%d%d", i, i);
1180 private_data->min_day_width = MAX (private_data->max_day_char_width,
1181 gdk_string_measure (DAY_FONT (widget),
1184 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1185 private_data->max_day_char_width = private_data->min_day_width / 2 +1;
1187 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1188 for (i = 0; i < 7; i++)
1190 gdk_text_extents (LABEL_FONT (widget),
1191 default_abbreviated_dayname[i],
1192 strlen(default_abbreviated_dayname[i]),
1198 private_data->min_day_width = MAX (private_data->min_day_width, width);
1199 private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent,
1201 private_data->max_label_char_descent = MAX (private_data->max_label_char_descent,
1205 private_data->max_week_char_width = 0;
1206 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1207 for (i = 0; i < 9; i++)
1209 sprintf (buffer, "%d%d", i, i);
1210 private_data->max_week_char_width = MAX (private_data->max_week_char_width,
1211 gdk_string_measure (LABEL_FONT (widget), buffer) / 2);
1214 main_width = (7 * (private_data->min_day_width + DAY_XPAD * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1215 + (private_data->max_week_char_width
1216 ? private_data->max_week_char_width * 2 + DAY_XPAD * 2 + CALENDAR_XSEP * 2
1220 requisition->width = MAX (header_width+4, main_width + (widget->style->klass->xthickness + INNER_BORDER) *2);
1223 * Calculate the requisition height for the widget.
1226 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1228 private_data->header_h = (HEADER_FONT (widget)->ascent
1229 + HEADER_FONT (widget)->descent
1230 + CALENDAR_YSEP * 2);
1234 private_data->header_h = 0;
1237 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1239 private_data->day_name_h = (private_data->max_label_char_ascent
1240 + private_data->max_label_char_descent
1241 + 2 * DAY_YPAD + calendar_margin);
1242 calendar_margin = CALENDAR_YSEP;
1246 private_data->day_name_h = 0;
1249 gdk_text_extents (DAY_FONT (widget),
1255 &private_data->max_day_char_ascent,
1256 &private_data->max_day_char_descent);
1258 private_data->main_h = (CALENDAR_MARGIN + calendar_margin
1259 + 6 * (private_data->max_day_char_ascent
1260 + private_data->max_day_char_descent
1265 * If we display weeknumbers we need some extra space
1268 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1270 private_data->main_h = MAX (private_data->main_h,
1271 (CALENDAR_MARGIN + calendar_margin
1272 + 6 * (private_data->max_day_char_ascent
1273 + private_data->max_day_char_descent
1278 height = (private_data->header_h + private_data->day_name_h
1279 + private_data->main_h);
1281 requisition->height = height + (widget->style->klass->ythickness + INNER_BORDER) * 2;
1285 gtk_calendar_size_allocate (GtkWidget *widget,
1286 GtkAllocation *allocation)
1288 GtkCalendar *calendar;
1289 GtkCalendarPrivateData *private_data;
1291 g_return_if_fail (widget != NULL);
1292 g_return_if_fail (GTK_IS_CALENDAR (widget));
1293 g_return_if_fail (allocation != NULL);
1295 widget->allocation = *allocation;
1297 calendar = GTK_CALENDAR (widget);
1298 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1300 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1302 private_data->day_width = (private_data->min_day_width
1303 * ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1304 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2))
1305 / (7 * private_data->min_day_width + private_data->max_week_char_width * 2));
1306 private_data->week_width = ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1307 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2 )
1308 - private_data->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1312 private_data->day_width = (allocation->width
1313 - (widget->style->klass->xthickness + INNER_BORDER) * 2
1314 - (CALENDAR_MARGIN * 2)
1315 - (DAY_XSEP * 7))/7;
1316 private_data->week_width = 0;
1319 if (GTK_WIDGET_REALIZED (widget))
1321 gdk_window_move_resize (widget->window,
1322 allocation->x, allocation->y,
1323 allocation->width, allocation->height);
1324 if (private_data->header_win)
1325 gdk_window_move_resize (private_data->header_win,
1327 allocation->width-4, private_data->header_h);
1328 if (private_data->arrow_win[ARROW_MONTH_LEFT])
1329 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
1331 private_data->arrow_width,
1332 private_data->header_h - 7);
1333 if (private_data->arrow_win[ARROW_MONTH_RIGHT])
1334 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
1335 (private_data->arrow_width
1336 + private_data->max_month_width),
1338 private_data->arrow_width,
1339 private_data->header_h - 7);
1340 if (private_data->arrow_win[ARROW_YEAR_LEFT])
1341 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
1342 (allocation->width - 4
1343 - (3 + 2*private_data->arrow_width
1344 + private_data->max_year_width)),
1346 private_data->arrow_width,
1347 private_data->header_h - 7);
1348 if (private_data->arrow_win[ARROW_YEAR_RIGHT])
1349 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
1350 (allocation->width - 4
1351 - 3 - private_data->arrow_width),
1353 private_data->arrow_width,
1354 private_data->header_h - 7);
1355 if (private_data->day_name_win)
1356 gdk_window_move_resize (private_data->day_name_win,
1357 widget->style->klass->xthickness + INNER_BORDER,
1358 private_data->header_h + (widget->style->klass->ythickness + INNER_BORDER),
1359 allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1360 private_data->day_name_h);
1361 if (private_data->week_win)
1362 gdk_window_move_resize (private_data->week_win,
1363 (widget->style->klass->xthickness + INNER_BORDER),
1364 private_data->header_h + private_data->day_name_h
1365 + (widget->style->klass->ythickness + INNER_BORDER),
1366 private_data->week_width,
1367 private_data->main_h);
1368 gdk_window_move_resize (private_data->main_win,
1369 (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1370 + (widget->style->klass->xthickness + INNER_BORDER),
1371 private_data->header_h + private_data->day_name_h
1372 + (widget->style->klass->ythickness + INNER_BORDER),
1374 - (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1375 - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1376 private_data->main_h);
1381 gtk_calendar_draw_focus (GtkWidget *widget)
1383 GtkCalendar *calendar;
1384 GtkCalendarPrivateData *private_data;
1388 g_return_if_fail (widget != NULL);
1389 g_return_if_fail (GTK_IS_CALENDAR (widget));
1391 calendar = GTK_CALENDAR (widget);
1392 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1394 if (GTK_WIDGET_DRAWABLE (widget))
1398 gdk_window_get_size (widget->window, &width, &height);
1399 gdk_window_clear (widget->window);
1401 gdk_draw_rectangle (widget->window,
1402 widget->style->base_gc[GTK_WIDGET_STATE (widget)],
1403 FALSE, x + 2, y + 2, width - 5, height - 5);
1405 gtk_draw_shadow (widget->style, widget->window,
1406 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1407 x, y, width, height);
1413 gtk_calendar_expose (GtkWidget *widget,
1414 GdkEventExpose *event)
1416 GtkCalendar *calendar;
1417 GtkCalendarPrivateData *private_data;
1419 g_return_val_if_fail (widget != NULL, FALSE);
1420 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
1421 g_return_val_if_fail (event != NULL, FALSE);
1423 calendar = GTK_CALENDAR (widget);
1424 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1426 if (GTK_WIDGET_DRAWABLE (widget))
1428 if (event->window == private_data->main_win)
1429 gtk_calendar_paint_main (widget);
1431 if (event->window == private_data->header_win)
1432 gtk_calendar_paint_header (widget);
1434 if (event->window == private_data->day_name_win)
1435 gtk_calendar_paint_day_names (widget);
1437 if (event->window == private_data->week_win)
1438 gtk_calendar_paint_week_numbers (widget);
1439 if (event->window == widget->window)
1440 gtk_widget_draw_focus (widget);
1447 gtk_calendar_draw (GtkWidget *widget,
1450 g_return_if_fail (widget != NULL);
1451 g_return_if_fail (GTK_IS_CALENDAR (widget));
1452 g_return_if_fail (area != NULL);
1454 if (GTK_WIDGET_DRAWABLE (widget))
1455 gtk_calendar_paint (widget, area);
1460 gtk_calendar_paint (GtkWidget *widget,
1463 GtkCalendar *calendar;
1464 GtkCalendarPrivateData *private_data;
1466 g_return_if_fail (widget != NULL);
1467 g_return_if_fail (widget->window != NULL);
1468 g_return_if_fail (GTK_IS_CALENDAR (widget));
1470 calendar = GTK_CALENDAR (widget);
1471 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1473 if (private_data->main_win != NULL)
1474 gtk_calendar_paint_main (widget);
1476 if (private_data->header_win != NULL)
1477 gtk_calendar_paint_header (widget);
1479 if (private_data->day_name_win != NULL)
1480 gtk_calendar_paint_day_names (widget);
1482 if (private_data->week_win != NULL)
1483 gtk_calendar_paint_week_numbers (widget);
1485 gtk_widget_draw_focus (widget);
1489 gtk_calendar_paint_header (GtkWidget *widget)
1491 GtkCalendar *calendar;
1495 gint header_width, cal_height;
1497 gint max_month_width;
1498 gint max_year_width;
1499 GtkCalendarPrivateData *private_data;
1501 calendar = GTK_CALENDAR (widget);
1502 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1504 if (private_data->frozen)
1506 private_data->dirty_header = 1;
1509 private_data->dirty_header = 0;
1513 gdk_window_clear (private_data->header_win);
1515 header_width = widget->allocation.width - 4;
1516 cal_height = widget->allocation.height;
1518 max_month_width = private_data->max_month_width;
1519 max_year_width = private_data->max_year_width;
1521 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1522 gtk_draw_shadow (widget->style, private_data->header_win,
1523 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1524 0, 0, header_width, private_data->header_h);
1528 y = private_data->header_h - (private_data->header_h
1529 - HEADER_FONT (widget)->ascent
1530 + HEADER_FONT (widget)->descent) / 2;
1531 y_arrow = (private_data->header_h - 9) / 2;
1533 /* Draw year and its arrows */
1534 sprintf (buffer, "%d", calendar->year);
1535 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1536 gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1537 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1538 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1539 header_width - (3 + max_year_width
1540 - (max_year_width - str_width)/2),
1543 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1544 header_width - (3 + private_data->arrow_width + max_year_width
1545 - (max_year_width - str_width)/2),
1549 sprintf (buffer, "%s", default_monthname[calendar->month]);
1550 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1551 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1552 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1553 3 + (max_month_width - str_width) / 2,
1556 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1557 3 + private_data->arrow_width + (max_month_width - str_width)/2,
1560 y += CALENDAR_YSEP + HEADER_FONT (widget)->descent;
1562 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1564 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
1565 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
1566 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
1567 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
1572 gtk_calendar_paint_day_names (GtkWidget *widget)
1574 GtkCalendar *calendar;
1578 int day_width, cal_width;
1582 GtkCalendarPrivateData *private_data;
1584 g_return_if_fail (widget != NULL);
1585 g_return_if_fail (GTK_IS_CALENDAR (widget));
1586 calendar = GTK_CALENDAR (widget);
1587 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1591 * Handle freeze/thaw functionality
1594 if (private_data->frozen)
1596 private_data->dirty_day_names = 1;
1599 private_data->dirty_day_names = 0;
1605 gdk_window_clear (private_data->day_name_win);
1607 day_width = private_data->day_width;
1608 cal_width = widget->allocation.width;
1609 cal_height = widget->allocation.height;
1610 day_wid_sep = day_width + DAY_XSEP;
1613 * Draw rectangles as inverted background for the labels.
1616 gdk_gc_set_foreground (gc, DAY_NAME_COLOR (GTK_WIDGET (calendar)));
1617 gdk_gc_set_background (gc, DAY_NAME_COLOR (GTK_WIDGET (calendar)));
1618 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1619 CALENDAR_MARGIN, CALENDAR_MARGIN,
1620 cal_width-CALENDAR_MARGIN * 2,
1621 private_data->day_name_h - CALENDAR_MARGIN);
1624 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1625 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1627 private_data->day_name_h - CALENDAR_YSEP,
1628 private_data->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1635 gdk_gc_set_foreground (gc, BACKGROUND_COLOR ( GTK_WIDGET (calendar)));
1636 for (i = 0; i < 7; i++)
1639 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1641 sprintf (buffer, "%s", default_abbreviated_dayname[day]);
1642 str_width = gdk_string_measure (LABEL_FONT (widget), buffer);
1643 gdk_draw_string (private_data->day_name_win, LABEL_FONT (widget),
1645 ((private_data->week_width ? CALENDAR_XSEP : CALENDAR_MARGIN)
1647 + private_data->week_width
1648 + (day_width - str_width)/2),
1649 CALENDAR_MARGIN + DAY_YPAD
1650 + private_data->max_label_char_ascent, buffer);
1655 gtk_calendar_paint_week_numbers (GtkWidget *widget)
1657 GtkCalendar *calendar;
1659 gint row, week, year;
1662 gint y_baseline, day_height;
1663 GtkCalendarPrivateData *private_data;
1665 g_return_if_fail (widget != NULL);
1666 g_return_if_fail (widget->window != NULL);
1667 g_return_if_fail (GTK_IS_CALENDAR (widget));
1668 calendar = GTK_CALENDAR (widget);
1669 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1673 * Handle freeze/thaw functionality
1676 if (private_data->frozen)
1678 private_data->dirty_week = 1;
1681 private_data->dirty_week = 0;
1687 gdk_window_clear (private_data->week_win);
1690 * Draw a rectangle as inverted background for the labels.
1693 gdk_gc_set_foreground (gc, DAY_NAME_COLOR (GTK_WIDGET (calendar)));
1694 gdk_gc_set_background (gc, DAY_NAME_COLOR (GTK_WIDGET (calendar)));
1695 if (private_data->day_name_win)
1696 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1699 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1700 private_data->main_h - CALENDAR_MARGIN);
1702 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1705 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1706 private_data->main_h - 2 * CALENDAR_MARGIN);
1712 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1713 day_height = row_height (calendar);
1714 for (row = 0; row < 6; row++)
1716 year = calendar->year;
1717 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
1719 y_baseline = (top_y_for_row (calendar, row)
1720 + (day_height + LABEL_FONT (widget)->ascent
1721 - LABEL_FONT (widget)->descent)/2);
1722 g_return_if_fail (week_of_year (&week, &year,
1723 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
1724 + calendar->month) % 12 + 1, calendar->day[row][6]));
1725 x_loc= (private_data->week_width - (private_data->week_width - CALENDAR_XSEP
1726 - DAY_XPAD * 2 - CALENDAR_MARGIN ) / 2
1727 - private_data->max_week_char_width
1728 - CALENDAR_XSEP - DAY_XPAD);
1732 sprintf (buffer, "%d", week/10);
1733 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1734 x_loc, y_baseline , buffer);
1737 sprintf (buffer, "%d", week%10);
1738 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1739 x_loc + private_data->max_week_char_width, y_baseline , buffer);
1744 gtk_calendar_paint_day_num (GtkWidget *widget,
1747 GtkCalendar *calendar;
1748 gint r, c, row, col;
1750 g_return_if_fail (widget != NULL);
1751 g_return_if_fail (GTK_IS_CALENDAR (widget));
1753 calendar = GTK_CALENDAR (widget);
1757 for (r = 0; r < 6; r++)
1758 for (c = 0; c < 7; c++)
1759 if (calendar->day_month[r][c] == MONTH_CURRENT &&
1760 calendar->day[r][c] == day)
1766 g_return_if_fail (row != -1);
1767 g_return_if_fail (col != -1);
1769 gtk_calendar_paint_day (widget, row, col);
1773 gtk_calendar_paint_day (GtkWidget *widget,
1777 GtkCalendar *calendar;
1787 GtkCalendarPrivateData *private_data;
1789 g_return_if_fail (widget != NULL);
1790 g_return_if_fail (GTK_IS_CALENDAR (widget));
1791 g_return_if_fail (row < 6);
1792 g_return_if_fail (col < 7);
1793 calendar = GTK_CALENDAR (widget);
1794 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1797 * Handle freeze/thaw functionality
1800 if (private_data->frozen)
1802 private_data->dirty_main = 1;
1806 day_height = row_height (calendar);
1808 day_xspace = private_data->day_width - private_data->max_day_char_width*2;
1810 day = calendar->day[row][col];
1812 x_left = left_x_for_column (calendar, col);
1813 x_loc = x_left + private_data->day_width / 2 + private_data->max_day_char_width;
1815 y_top = top_y_for_row (calendar, row);
1816 y_baseline = y_top + (day_height + private_data->max_day_char_ascent)/2;
1818 gdk_window_clear_area (private_data->main_win, x_left, y_top,
1819 private_data->day_width, day_height);
1823 if (calendar->day_month[row][col] == MONTH_PREV)
1825 gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
1827 else if (calendar->day_month[row][col] == MONTH_NEXT)
1829 gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
1833 if (calendar->highlight_row == row && calendar->highlight_col == col)
1835 gdk_gc_set_foreground (gc, HIGHLIGHT_BACK_COLOR (GTK_WIDGET (calendar)));
1836 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
1837 private_data->day_width, day_height);
1840 if (calendar->selected_day == day)
1842 if (GTK_WIDGET_HAS_FOCUS (widget))
1843 gdk_gc_set_foreground (gc, SELECTION_FOCUS_COLOR (GTK_WIDGET (calendar)));
1845 gdk_gc_set_foreground (gc, SELECTION_NO_FOCUS_COLOR (GTK_WIDGET (calendar)));
1846 gdk_draw_rectangle (private_data->main_win, gc, FALSE, x_left, y_top,
1847 private_data->day_width-1, day_height-1);
1850 if (calendar->marked_date[day-1])
1851 gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar)));
1853 gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
1856 sprintf (buffer, "%d", day);
1857 x_loc -= gdk_string_measure (DAY_FONT (widget), buffer);
1858 sprintf (buffer, "%d", day);
1859 gdk_draw_string (private_data->main_win,
1860 DAY_FONT (widget), gc,
1861 x_loc, y_baseline, buffer);
1862 if (calendar->marked_date[day-1])
1863 gdk_draw_string (private_data->main_win,
1864 DAY_FONT (widget), gc,
1865 x_loc-1, y_baseline, buffer);
1870 gtk_calendar_paint_main (GtkWidget *widget)
1872 GtkCalendar *calendar;
1873 GtkCalendarPrivateData *private_data;
1876 g_return_if_fail (widget != NULL);
1877 g_return_if_fail (widget->window != NULL);
1878 g_return_if_fail (GTK_IS_CALENDAR (widget));
1880 calendar = GTK_CALENDAR (widget);
1881 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1883 if (private_data->frozen)
1885 private_data->dirty_main = 1;
1888 private_data->dirty_main = 0;
1889 gdk_window_clear (private_data->main_win);
1891 /* gtk_calendar_compute_days (calendar); */ /* REMOVE later */
1893 for (col = 0; col < 7; col++)
1894 for (row = 0; row < 6; row++)
1895 gtk_calendar_paint_day (widget, row, col);
1899 gtk_calendar_compute_days (GtkCalendar *calendar)
1903 gint ndays_in_month;
1904 gint ndays_in_prev_month;
1910 g_return_if_fail (calendar != NULL);
1911 g_return_if_fail (GTK_IS_CALENDAR (calendar));
1913 year = calendar->year;
1914 month = calendar->month + 1;
1916 ndays_in_month = month_length[leap (year)][month];
1918 first_day = day_of_week (year, month, 1);
1920 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1926 /* Compute days of previous month */
1928 ndays_in_prev_month = month_length[leap (year)][month-1];
1930 ndays_in_prev_month = month_length[leap (year)][12];
1931 day = ndays_in_prev_month - first_day + 1;
1936 for (col = 0; col < first_day; col++)
1938 calendar->day[row][col] = day;
1939 calendar->day_month[row][col] = MONTH_PREV;
1944 /* Compute days of current month */
1946 for (day = 1; day <= ndays_in_month; day++)
1948 calendar->day[row][col] = day;
1949 calendar->day_month[row][col] = MONTH_CURRENT;
1959 /* Compute days of next month */
1961 for (; row <= 5; row++)
1963 for (; col <= 6; col++)
1965 calendar->day[row][col] = day;
1966 calendar->day_month[row][col] = MONTH_NEXT;
1973 /* ----------------------------------------------------------------------
1974 NAME: gtk_calendar_display_options
1975 DESCRIPTION: Set display options (whether to display the
1976 heading and the month headings)
1978 flags is can be an XOR of:
1979 GTK_CALENDAR_SHOW_HEADING
1980 GTK_CALENDAR_SHOW_DAY_NAMES
1981 GTK_CALENDAR_NO_MONTH_CHANGE
1982 GTK_CALENDAR_SHOW_WEEK_NUMBERS
1983 GTK_CALENDAR_WEEK_START_MONDAY
1984 ---------------------------------------------------------------------- */
1987 gtk_calendar_display_options (GtkCalendar *calendar,
1988 GtkCalendarDisplayOptions flags)
1990 GtkCalendarPrivateData *private_data;
1995 g_return_if_fail (calendar != NULL);
1996 g_return_if_fail (GTK_IS_CALENDAR (calendar));
1998 widget = GTK_WIDGET (calendar);
1999 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2001 if (GTK_WIDGET_REALIZED (widget))
2003 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
2006 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2007 && (private_data->header_win))
2009 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
2010 gtk_calendar_realize_arrows (widget);
2014 for (i = 0; i < 4; i++)
2016 if (private_data->arrow_win[i])
2018 gdk_window_set_user_data (private_data->arrow_win[i],
2020 gdk_window_destroy (private_data->arrow_win[i]);
2021 private_data->arrow_win[i] = NULL;
2027 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
2031 if (flags & GTK_CALENDAR_SHOW_HEADING)
2033 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
2034 gtk_calendar_realize_header (widget);
2038 for (i = 0; i < 4; i++)
2040 if (private_data->arrow_win[i])
2042 gdk_window_set_user_data (private_data->arrow_win[i],
2044 gdk_window_destroy (private_data->arrow_win[i]);
2045 private_data->arrow_win[i] = NULL;
2048 gdk_window_set_user_data (private_data->header_win, NULL);
2049 gdk_window_destroy (private_data->header_win);
2050 private_data->header_win = NULL;
2055 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
2059 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
2061 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
2062 gtk_calendar_realize_day_names (widget);
2066 gdk_window_set_user_data (private_data->day_name_win, NULL);
2067 gdk_window_destroy (private_data->day_name_win);
2068 private_data->day_name_win = NULL;
2072 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2076 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2078 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
2079 gtk_calendar_realize_week_numbers (widget);
2083 gdk_window_set_user_data (private_data->week_win, NULL);
2084 gdk_window_destroy (private_data->week_win);
2085 private_data->week_win = NULL;
2089 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
2091 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
2092 calendar->display_flags &= ~GTK_CALENDAR_WEEK_START_MONDAY;
2094 calendar->display_flags |= GTK_CALENDAR_WEEK_START_MONDAY;
2096 gtk_calendar_compute_days (calendar);
2097 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2098 if (private_data->day_name_win)
2099 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2102 calendar->display_flags = flags;
2104 gtk_widget_queue_resize (GTK_WIDGET (calendar));
2108 calendar->display_flags = flags;
2113 gtk_calendar_select_month (GtkCalendar *calendar,
2117 g_return_val_if_fail (calendar != NULL, FALSE);
2118 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2119 g_return_val_if_fail (month <= 11, FALSE);
2121 calendar->month = month;
2122 calendar->year = year;
2124 gtk_calendar_compute_days (calendar);
2126 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2127 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
2129 gtk_signal_emit (GTK_OBJECT (calendar),
2130 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
2135 gtk_calendar_select_day (GtkCalendar *calendar,
2138 g_return_if_fail (calendar != NULL);
2139 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2140 g_return_if_fail (day <= 31);
2142 /* gtk_calendar_compute_days (calendar); */
2144 /* Deselect the old day */
2145 if (calendar->selected_day > 0)
2149 selected_day = calendar->selected_day;
2150 calendar->selected_day = 0;
2151 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2152 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day);
2155 calendar->selected_day = day;
2157 /* Deselect the new day */
2160 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2161 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), day);
2164 gtk_signal_emit (GTK_OBJECT (calendar),
2165 gtk_calendar_signals[DAY_SELECTED_SIGNAL]);
2169 gtk_calendar_clear_marks (GtkCalendar *calendar)
2173 g_return_if_fail (calendar != NULL);
2174 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2176 for (day = 0; day < 31; day++)
2178 calendar->marked_date[day] = FALSE;
2181 if (GTK_WIDGET_DRAWABLE (calendar))
2183 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2188 gtk_calendar_mark_day (GtkCalendar *calendar,
2191 g_return_val_if_fail (calendar != NULL, FALSE);
2192 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2194 if (day >= 1 && day <= 31)
2195 calendar->marked_date[day - 1] = TRUE;
2197 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2199 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2206 gtk_calendar_unmark_day (GtkCalendar *calendar,
2209 g_return_val_if_fail (calendar != NULL, FALSE);
2210 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2212 if (day >= 1 && day <= 31)
2213 calendar->marked_date[day - 1] = FALSE;
2215 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2217 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2224 gtk_calendar_get_date (GtkCalendar *calendar,
2229 g_return_if_fail (calendar != NULL);
2230 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2233 *year = calendar->year;
2236 *month = calendar->month;
2239 *day = calendar->selected_day;
2243 gtk_calendar_button_press (GtkWidget *widget,
2244 GdkEventButton *event)
2246 GtkCalendar *calendar;
2247 GtkCalendarPrivateData *private_data;
2250 g_return_val_if_fail (widget != NULL, FALSE);
2251 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2252 g_return_val_if_fail (event != NULL, FALSE);
2254 calendar = GTK_CALENDAR (widget);
2255 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2257 x = (gint) (event->x);
2258 y = (gint) (event->y);
2260 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2261 gtk_calendar_set_month_prev (calendar);
2263 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2264 gtk_calendar_set_month_next (calendar);
2266 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2267 gtk_calendar_set_year_prev (calendar);
2269 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2270 gtk_calendar_set_year_next (calendar);
2272 if (event->window == private_data->main_win)
2273 gtk_calendar_main_button (widget, event);
2279 gtk_calendar_motion_notify (GtkWidget *widget,
2280 GdkEventMotion *event)
2282 GtkCalendar *calendar;
2283 GtkCalendarPrivateData *private_data;
2284 gint event_x, event_y;
2286 gint old_row, old_col;
2288 calendar = GTK_CALENDAR (widget);
2289 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2290 event_x = (gint) (event->x);
2291 event_y = (gint) (event->y);
2293 if (event->window == private_data->main_win)
2296 row = row_from_y (calendar, event_y);
2297 col = column_from_x (calendar, event_x);
2299 if (row != calendar->highlight_row || calendar->highlight_col != col)
2301 old_row = calendar->highlight_row;
2302 old_col = calendar->highlight_col;
2303 if (old_row > -1 && old_col > -1)
2305 calendar->highlight_row = -1;
2306 calendar->highlight_col = -1;
2307 gtk_calendar_paint_day (widget, old_row, old_col);
2310 calendar->highlight_row = row;
2311 calendar->highlight_col = col;
2313 if (row > -1 && col > -1)
2314 gtk_calendar_paint_day (widget, row, col);
2321 gtk_calendar_enter_notify (GtkWidget *widget,
2322 GdkEventCrossing *event)
2324 GtkCalendar *calendar;
2325 GtkCalendarPrivateData *private_data;
2327 g_return_val_if_fail (widget != NULL, FALSE);
2328 g_return_val_if_fail (event != NULL, FALSE);
2330 calendar = GTK_CALENDAR (widget);
2331 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2333 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2335 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2336 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2339 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2341 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2342 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2345 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2347 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2348 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2351 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2353 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2354 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2361 gtk_calendar_leave_notify (GtkWidget *widget,
2362 GdkEventCrossing *event)
2364 GtkCalendar *calendar;
2365 GtkCalendarPrivateData *private_data;
2369 g_return_val_if_fail (widget != NULL, FALSE);
2370 g_return_val_if_fail (event != NULL, FALSE);
2372 calendar = GTK_CALENDAR (widget);
2373 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2375 if (event->window == private_data->main_win)
2377 row = calendar->highlight_row;
2378 col = calendar->highlight_col;
2379 calendar->highlight_row = -1;
2380 calendar->highlight_col = -1;
2381 if (row > -1 && col > -1)
2382 gtk_calendar_paint_day (widget, row, col);
2385 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2387 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2388 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2391 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2393 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2394 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2397 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2399 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2400 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2403 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2405 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2406 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2413 gtk_calendar_paint_arrow (GtkWidget *widget,
2416 GtkCalendarPrivateData *private_data;
2419 GtkCalendar *calendar;
2423 g_return_if_fail (widget != NULL);
2425 calendar = GTK_CALENDAR (widget);
2426 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2428 if (private_data->frozen)
2430 private_data->dirty_header = 1;
2433 window = private_data->arrow_win[arrow];
2436 state = private_data->arrow_state[arrow];
2439 gdk_window_clear (window);
2440 gdk_window_set_background (window, &(widget)->style->bg[state]);
2441 gdk_window_get_size (window, &width, &height);
2442 gdk_window_clear_area (window,
2446 gdk_gc_set_foreground (gc, & (widget)->style->fg[state]);
2448 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2449 draw_arrow_left (window, gc, width/2 - 3, height/2 - 4, 8);
2451 draw_arrow_right (window, gc, width/2 - 2, height/2 - 4, 8);
2457 gtk_calendar_freeze (GtkCalendar *calendar)
2459 g_return_if_fail (calendar != NULL);
2460 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2462 GTK_CALENDAR_PRIVATE_DATA (calendar)->frozen++;
2466 gtk_calendar_thaw (GtkCalendar *calendar)
2468 GtkCalendarPrivateData *private_data;
2470 g_return_if_fail (calendar != NULL);
2471 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2473 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2475 if (private_data->frozen)
2477 private_data->frozen--;
2478 if (private_data->frozen)
2481 if (private_data->dirty_header)
2482 if (GTK_WIDGET_DRAWABLE (calendar))
2483 gtk_calendar_paint_header (GTK_WIDGET (calendar));
2485 if (private_data->dirty_day_names)
2486 if (GTK_WIDGET_DRAWABLE (calendar))
2487 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2489 if (private_data->dirty_week)
2490 if (GTK_WIDGET_DRAWABLE (calendar))
2491 gtk_calendar_paint_week_numbers (GTK_WIDGET (calendar));
2493 if (private_data->dirty_main)
2494 if (GTK_WIDGET_DRAWABLE (calendar))
2495 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2500 gtk_calendar_set_background (GtkWidget *widget)
2502 GtkCalendar *calendar;
2503 GtkCalendarPrivateData *private_data;
2506 g_return_if_fail (widget != NULL);
2507 g_return_if_fail (GTK_IS_CALENDAR (widget));
2509 calendar = GTK_CALENDAR (widget);
2510 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2512 if (GTK_WIDGET_REALIZED (widget))
2514 for (i = 0; i < 4; i++)
2516 if (private_data->arrow_win[i])
2517 gdk_window_set_background (private_data->arrow_win[i],
2518 HEADER_BG_COLOR (widget));
2520 if (private_data->header_win)
2521 gdk_window_set_background (private_data->header_win,
2522 HEADER_BG_COLOR (widget));
2523 if (private_data->day_name_win)
2524 gdk_window_set_background (private_data->day_name_win,
2525 BACKGROUND_COLOR (widget));
2526 if (private_data->week_win)
2527 gdk_window_set_background (private_data->week_win,
2528 BACKGROUND_COLOR (widget));
2529 if (private_data->main_win)
2530 gdk_window_set_background (private_data->main_win,
2531 BACKGROUND_COLOR (widget));
2533 gdk_window_set_background (widget->window,
2534 BACKGROUND_COLOR (widget));
2536 if (GTK_WIDGET_DRAWABLE (widget))
2537 gdk_window_clear (widget->window);
2541 gtk_calendar_style_set (GtkWidget *widget,
2542 GtkStyle *previous_style)
2544 g_return_if_fail (widget != NULL);
2545 g_return_if_fail (GTK_IS_CALENDAR (widget));
2547 if (previous_style && GTK_WIDGET_REALIZED (widget))
2548 gtk_calendar_set_background(widget);
2552 gtk_calendar_state_changed (GtkWidget *widget,
2553 GtkStateType previous_state)
2555 g_return_if_fail (widget != NULL);
2556 g_return_if_fail (GTK_IS_CALENDAR (widget));
2558 gtk_calendar_set_background (widget);
2562 gtk_calendar_focus_in (GtkWidget *widget,
2563 GdkEventFocus *event)
2565 GtkCalendar *calendar;
2567 g_return_val_if_fail (widget != NULL, FALSE);
2568 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2569 g_return_val_if_fail (event != NULL, FALSE);
2571 calendar = GTK_CALENDAR (widget);
2573 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2574 gtk_widget_draw_focus (widget);
2575 gtk_calendar_paint_day_num (widget, calendar->selected_day);
2581 gtk_calendar_focus_out (GtkWidget *widget,
2582 GdkEventFocus *event)
2584 GtkCalendar *calendar;
2586 g_return_val_if_fail (widget != NULL, FALSE);
2587 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2588 g_return_val_if_fail (event != NULL, FALSE);
2590 calendar = GTK_CALENDAR (widget);
2592 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2593 gtk_widget_draw_focus (widget);
2594 gtk_calendar_paint_day_num (widget, calendar->selected_day);
2600 gtk_calendar_key_press (GtkWidget *widget,
2603 GtkCalendar *calendar;
2606 g_return_val_if_fail (widget != NULL, FALSE);
2607 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2608 g_return_val_if_fail (event != NULL, FALSE);
2610 calendar = GTK_CALENDAR (widget);
2613 switch (event->keyval)
2617 if (event->state & GDK_CONTROL_MASK)
2618 gtk_calendar_set_month_prev (calendar);
2621 if (calendar->selected_day == 1)
2623 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2625 gtk_calendar_select_day (calendar, month_length[leap (calendar->year)][calendar->month + 1]);
2629 calendar->selected_day = -1;
2630 gtk_calendar_set_month_prev (calendar);
2634 gtk_calendar_select_day (calendar, calendar->selected_day - 1);
2639 if (event->state & GDK_CONTROL_MASK)
2640 gtk_calendar_set_month_next (calendar);
2643 if (calendar->selected_day == month_length[leap (calendar->year)][calendar->month + 1])
2645 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2647 gtk_calendar_select_day (calendar, 1);
2651 calendar->selected_day = 1;
2652 gtk_calendar_set_month_next (calendar);
2656 gtk_calendar_select_day (calendar, calendar->selected_day + 1);
2661 if (event->state & GDK_CONTROL_MASK)
2662 gtk_calendar_set_year_prev (calendar);
2666 overlap = calendar->selected_day - 7;
2669 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2672 month_len = month_length[leap (calendar->year)][calendar->month + 1];
2673 gtk_calendar_select_day (calendar, month_len - (month_len - (month_len / 7) * 7 - overlap)%7);
2677 calendar->selected_day = overlap - 1;
2678 gtk_calendar_set_month_prev (calendar);
2682 gtk_calendar_select_day (calendar, calendar->selected_day - 7);
2687 if (event->state & GDK_CONTROL_MASK)
2688 gtk_calendar_set_year_next (calendar);
2693 month_len = month_length[leap (calendar->year)][calendar->month + 1];
2694 overlap = (calendar->selected_day + 7 - month_len);
2697 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2699 gtk_calendar_select_day (calendar, (month_len - 1 - (month_len / 7) * 7
2700 + overlap) % 7 + 1);
2704 calendar->selected_day = overlap;
2705 gtk_calendar_set_month_next (calendar);
2709 gtk_calendar_select_day (calendar, calendar->selected_day + 7);