1 /* example-start calendar calendar.c */
3 * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Grönlund
4 * Copyright (C) 2000 Tony Gale
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #define DEF_PAD_SMALL 6
28 #define TM_YEAR_BASE 1900
30 typedef struct _CalendarData
32 GtkWidget *calendar_widget;
33 GtkWidget *flag_checkboxes[6];
35 GtkWidget *font_dialog;
42 GHashTable *details_table;
43 GtkTextBuffer *details_buffer;
44 gulong details_changed;
51 calendar_month_change,
61 calendar_date_to_string (CalendarData *data,
66 guint year, month, day;
68 gtk_calendar_get_date (GTK_CALENDAR(data->window),
70 date = g_date_new_dmy (day, month + 1, year);
71 g_date_strftime (buffer, buff_len-1, "%x", date);
77 calendar_set_detail (CalendarData *data,
83 gchar *key = g_strdup_printf ("%04d-%02d-%02d", year, month + 1, day);
84 g_hash_table_replace (data->details_table, key, detail);
88 calendar_get_detail (CalendarData *data,
96 key = g_strdup_printf ("%04d-%02d-%02d", year, month + 1, day);
97 detail = g_hash_table_lookup (data->details_table, key);
100 return (detail ? g_strdup (detail) : NULL);
104 calendar_update_details (CalendarData *data)
106 guint year, month, day;
109 gtk_calendar_get_date (GTK_CALENDAR (data->calendar_widget), &year, &month, &day);
110 detail = calendar_get_detail (data, year, month, day);
112 g_signal_handler_block (data->details_buffer, data->details_changed);
113 gtk_text_buffer_set_text (data->details_buffer, detail ? detail : "", -1);
114 g_signal_handler_unblock (data->details_buffer, data->details_changed);
120 calendar_set_signal_strings (char *sig_str,
123 const gchar *prev_sig;
125 prev_sig = gtk_label_get_text (GTK_LABEL (data->prev_sig));
126 gtk_label_set_text (GTK_LABEL (data->prev2_sig), prev_sig);
128 prev_sig = gtk_label_get_text (GTK_LABEL (data->last_sig));
129 gtk_label_set_text (GTK_LABEL (data->prev_sig), prev_sig);
130 gtk_label_set_text (GTK_LABEL (data->last_sig), sig_str);
134 calendar_month_changed (GtkWidget *widget,
137 char buffer[256] = "month_changed: ";
139 calendar_date_to_string (data, buffer+15, 256-15);
140 calendar_set_signal_strings (buffer, data);
144 calendar_day_selected (GtkWidget *widget,
147 char buffer[256] = "day_selected: ";
149 calendar_date_to_string (data, buffer+14, 256-14);
150 calendar_set_signal_strings (buffer, data);
152 calendar_update_details (data);
156 calendar_day_selected_double_click (GtkWidget *widget,
159 char buffer[256] = "day_selected_double_click: ";
162 calendar_date_to_string (data, buffer+27, 256-27);
163 calendar_set_signal_strings (buffer, data);
164 gtk_calendar_get_date (GTK_CALENDAR (data->window),
167 if (gtk_calendar_get_day_is_marked (GTK_CALENDAR (data->window), day))
168 gtk_calendar_unmark_day (GTK_CALENDAR (data->window), day);
170 gtk_calendar_mark_day (GTK_CALENDAR (data->window), day);
174 calendar_prev_month (GtkWidget *widget,
177 char buffer[256] = "prev_month: ";
179 calendar_date_to_string (data, buffer+12, 256-12);
180 calendar_set_signal_strings (buffer, data);
184 calendar_next_month (GtkWidget *widget,
187 char buffer[256] = "next_month: ";
189 calendar_date_to_string (data, buffer+12, 256-12);
190 calendar_set_signal_strings (buffer, data);
194 calendar_prev_year (GtkWidget *widget,
197 char buffer[256] = "prev_year: ";
199 calendar_date_to_string (data, buffer+11, 256-11);
200 calendar_set_signal_strings (buffer, data);
204 calendar_next_year (GtkWidget *widget,
207 char buffer[256] = "next_year: ";
209 calendar_date_to_string (data, buffer+11, 256-11);
210 calendar_set_signal_strings (buffer, data);
215 calendar_set_flags (CalendarData *calendar)
219 for (i = 0; i < G_N_ELEMENTS (calendar->settings); i++)
220 if (calendar->settings[i])
221 options=options + (1 << i);
223 if (calendar->window)
224 gtk_calendar_set_display_options (GTK_CALENDAR (calendar->window), options);
228 calendar_toggle_flag (GtkWidget *toggle,
229 CalendarData *calendar)
233 for (i = 0; i < G_N_ELEMENTS (calendar->flag_checkboxes); i++)
234 if (calendar->flag_checkboxes[i] == toggle)
235 calendar->settings[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
237 calendar_set_flags(calendar);
241 void calendar_select_font (GtkWidget *button,
242 CalendarData *calendar)
244 const char *font = NULL;
245 PangoFontDescription *font_desc;
247 if (calendar->window)
249 font = gtk_font_button_get_font_name (GTK_FONT_BUTTON (button));
250 font_desc = pango_font_description_from_string (font);
251 gtk_widget_override_font (calendar->window, font_desc);
252 pango_font_description_free (font_desc);
257 calendar_detail_cb (GtkCalendar *calendar,
263 return calendar_get_detail (data, year, month, day);
267 calendar_details_changed (GtkTextBuffer *buffer,
270 GtkTextIter start, end;
271 guint year, month, day;
274 gtk_text_buffer_get_start_iter(buffer, &start);
275 gtk_text_buffer_get_end_iter(buffer, &end);
277 gtk_calendar_get_date (GTK_CALENDAR (data->calendar_widget), &year, &month, &day);
278 detail = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
286 calendar_set_detail (data, year, month, day, detail);
287 gtk_widget_queue_resize (data->calendar_widget);
291 demonstrate_details (CalendarData *data)
293 static char *rainbow[] = { "#900", "#980", "#390", "#095", "#059", "#309", "#908" };
294 GtkCalendar *calendar = GTK_CALENDAR (data->calendar_widget);
295 guint year, month, day;
298 gtk_calendar_get_date (calendar,
299 &year, &month, &day);
301 for (day = 0; day < 29; ++day)
303 detail = g_strdup_printf ("<span color='%s'>yadda\n"
304 "(%04d-%02d-%02d)</span>",
305 rainbow[(day - 1) % 7], year, month, day);
306 calendar_set_detail (data, year, month, day, detail);
309 gtk_widget_queue_resize (data->calendar_widget);
310 calendar_update_details (data);
314 reset_details (CalendarData *data)
316 g_hash_table_remove_all (data->details_table);
317 gtk_widget_queue_resize (data->calendar_widget);
318 calendar_update_details (data);
322 calendar_toggle_details (GtkWidget *widget,
325 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
326 gtk_calendar_set_detail_func (GTK_CALENDAR (data->calendar_widget),
327 calendar_detail_cb, data, NULL);
329 gtk_calendar_set_detail_func (GTK_CALENDAR (data->calendar_widget),
334 create_expander (const char *caption,
339 GtkWidget *expander = gtk_expander_new ("");
340 GtkWidget *label = gtk_expander_get_label_widget (GTK_EXPANDER (expander));
341 GtkWidget *align = gtk_alignment_new (0, 0, xscale, yscale);
343 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 18, 0);
344 gtk_label_set_markup (GTK_LABEL (label), caption);
346 gtk_container_add (GTK_CONTAINER (expander), align);
347 gtk_container_add (GTK_CONTAINER (align), child);
353 create_frame (const char *caption,
358 GtkWidget *frame = gtk_frame_new ("");
359 GtkWidget *label = gtk_frame_get_label_widget (GTK_FRAME (frame));
360 GtkWidget *align = gtk_alignment_new (0, 0, xscale, yscale);
362 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
363 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 6, 0, 18, 0);
364 gtk_label_set_markup (GTK_LABEL (label), caption);
366 gtk_container_add (GTK_CONTAINER (frame), align);
367 gtk_container_add (GTK_CONTAINER (align), child);
373 detail_width_changed (GtkSpinButton *button,
376 gint value = (gint) gtk_spin_button_get_value (button);
377 gtk_calendar_set_detail_width_chars (GTK_CALENDAR (data->calendar_widget), value);
381 detail_height_changed (GtkSpinButton *button,
384 gint value = (gint) gtk_spin_button_get_value (button);
385 gtk_calendar_set_detail_height_rows (GTK_CALENDAR (data->calendar_widget), value);
389 create_calendar(void)
391 static CalendarData calendar_data;
393 GtkWidget *window, *hpaned, *vbox, *rpane, *hbox;
394 GtkWidget *calendar, *toggle, *scroller, *button;
395 GtkWidget *frame, *label, *bbox, *align, *details;
398 GtkStyleContext *context;
399 const PangoFontDescription *font_desc;
408 { TRUE, "Show _Heading" },
409 { TRUE, "Show Day _Names" },
410 { FALSE, "No Month _Change" },
411 { TRUE, "Show _Week Numbers" },
412 { FALSE, "Week Start _Monday" },
413 { TRUE, "Show De_tails" },
416 calendar_data.window = NULL;
417 calendar_data.font_dialog = NULL;
418 calendar_data.details_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
420 for (i = 0; i < G_N_ELEMENTS (calendar_data.settings); i++)
421 calendar_data.settings[i] = 0;
423 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
424 gtk_window_set_title (GTK_WINDOW (window), "GtkCalendar Example");
425 gtk_container_set_border_width (GTK_CONTAINER (window), 12);
426 g_signal_connect (window, "destroy",
427 G_CALLBACK (gtk_main_quit),
429 g_signal_connect (window, "delete-event",
430 G_CALLBACK (gtk_false),
433 hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
435 /* Calendar widget */
437 calendar = gtk_calendar_new ();
438 calendar_data.calendar_widget = calendar;
439 frame = create_frame ("<b>Calendar</b>", calendar, 0, 0);
440 gtk_paned_pack1 (GTK_PANED (hpaned), frame, TRUE, FALSE);
442 calendar_data.window = calendar;
443 calendar_set_flags(&calendar_data);
444 gtk_calendar_mark_day (GTK_CALENDAR (calendar), 19);
446 g_signal_connect (calendar, "month_changed",
447 G_CALLBACK (calendar_month_changed),
449 g_signal_connect (calendar, "day_selected",
450 G_CALLBACK (calendar_day_selected),
452 g_signal_connect (calendar, "day_selected_double_click",
453 G_CALLBACK (calendar_day_selected_double_click),
455 g_signal_connect (calendar, "prev_month",
456 G_CALLBACK (calendar_prev_month),
458 g_signal_connect (calendar, "next_month",
459 G_CALLBACK (calendar_next_month),
461 g_signal_connect (calendar, "prev_year",
462 G_CALLBACK (calendar_prev_year),
464 g_signal_connect (calendar, "next_year",
465 G_CALLBACK (calendar_next_year),
468 rpane = gtk_box_new (GTK_ORIENTATION_VERTICAL, DEF_PAD_SMALL);
469 gtk_paned_pack2 (GTK_PANED (hpaned), rpane, FALSE, FALSE);
471 /* Build the right font-button */
473 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, DEF_PAD_SMALL);
474 frame = create_frame ("<b>Options</b>", vbox, 1, 0);
475 gtk_box_pack_start (GTK_BOX (rpane), frame, FALSE, TRUE, 0);
476 size = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
478 context = gtk_widget_get_style_context (calendar);
479 font_desc = gtk_style_context_get_font (context, GTK_STATE_FLAG_NORMAL);
480 font = pango_font_description_to_string (font_desc);
481 button = gtk_font_button_new_with_font (font);
484 g_signal_connect (button, "font-set",
485 G_CALLBACK(calendar_select_font),
488 label = gtk_label_new_with_mnemonic ("_Font:");
489 gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
490 gtk_widget_set_halign (label, GTK_ALIGN_START);
491 gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
492 gtk_size_group_add_widget (size, label);
494 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, DEF_PAD_SMALL);
495 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
496 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
497 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
499 /* Build the width entry */
501 button = gtk_spin_button_new_with_range (0, 127, 1);
502 gtk_spin_button_set_value (GTK_SPIN_BUTTON (button),
503 gtk_calendar_get_detail_width_chars (GTK_CALENDAR (calendar)));
505 g_signal_connect (button, "value-changed",
506 G_CALLBACK (detail_width_changed),
509 label = gtk_label_new_with_mnemonic ("Details W_idth:");
510 gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
511 gtk_widget_set_halign (label, GTK_ALIGN_START);
512 gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
513 gtk_size_group_add_widget (size, label);
515 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, DEF_PAD_SMALL);
516 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
517 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
518 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
520 /* Build the height entry */
522 button = gtk_spin_button_new_with_range (0, 127, 1);
523 gtk_spin_button_set_value (GTK_SPIN_BUTTON (button),
524 gtk_calendar_get_detail_height_rows (GTK_CALENDAR (calendar)));
526 g_signal_connect (button, "value-changed",
527 G_CALLBACK (detail_height_changed),
530 label = gtk_label_new_with_mnemonic ("Details H_eight:");
531 gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
532 gtk_widget_set_halign (label, GTK_ALIGN_START);
533 gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
534 gtk_size_group_add_widget (size, label);
536 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, DEF_PAD_SMALL);
537 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
538 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
539 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
541 /* Build the right details frame */
543 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, DEF_PAD_SMALL);
544 frame = create_frame ("<b>Details</b>", vbox, 1, 1);
545 gtk_box_pack_start (GTK_BOX (rpane), frame, FALSE, TRUE, 0);
547 details = gtk_text_view_new();
548 calendar_data.details_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (details));
550 calendar_data.details_changed = g_signal_connect (calendar_data.details_buffer, "changed",
551 G_CALLBACK (calendar_details_changed),
554 scroller = gtk_scrolled_window_new (NULL, NULL);
555 gtk_container_add (GTK_CONTAINER (scroller), details);
557 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroller),
559 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroller),
560 GTK_POLICY_AUTOMATIC,
561 GTK_POLICY_AUTOMATIC);
563 gtk_box_pack_start (GTK_BOX (vbox), scroller, FALSE, TRUE, 0);
565 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, DEF_PAD_SMALL);
566 align = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
567 gtk_container_add (GTK_CONTAINER (align), hbox);
568 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, TRUE, 0);
570 button = gtk_button_new_with_mnemonic ("Demonstrate _Details");
572 g_signal_connect_swapped (button,
574 G_CALLBACK (demonstrate_details),
577 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
579 button = gtk_button_new_with_mnemonic ("_Reset Details");
581 g_signal_connect_swapped (button,
583 G_CALLBACK (reset_details),
586 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
588 toggle = gtk_check_button_new_with_mnemonic ("_Use Details");
589 g_signal_connect (toggle, "toggled",
590 G_CALLBACK(calendar_toggle_details),
592 gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, TRUE, 0);
594 /* Build the Right frame with the flags in */
596 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
597 frame = create_expander ("<b>Flags</b>", vbox, 1, 0);
598 gtk_box_pack_start (GTK_BOX (rpane), frame, TRUE, TRUE, 0);
600 for (i = 0; i < G_N_ELEMENTS (calendar_data.settings); i++)
602 toggle = gtk_check_button_new_with_mnemonic(flags[i].label);
603 gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, TRUE, 0);
604 calendar_data.flag_checkboxes[i] = toggle;
606 g_signal_connect (toggle, "toggled",
607 G_CALLBACK (calendar_toggle_flag),
610 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), flags[i].init);
614 * Build the Signal-event part.
617 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, DEF_PAD_SMALL);
618 gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
619 frame = create_frame ("<b>Signal Events</b>", vbox, 1, 0);
621 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
622 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
623 label = gtk_label_new ("Signal:");
624 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
625 calendar_data.last_sig = gtk_label_new ("");
626 gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
628 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
629 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
630 label = gtk_label_new ("Previous signal:");
631 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
632 calendar_data.prev_sig = gtk_label_new ("");
633 gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
635 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
636 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
637 label = gtk_label_new ("Second previous signal:");
638 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
639 calendar_data.prev2_sig = gtk_label_new ("");
640 gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
643 * Glue everything together
646 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
647 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
649 button = gtk_button_new_with_label ("Close");
650 g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
651 gtk_container_add (GTK_CONTAINER (bbox), button);
653 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, DEF_PAD_SMALL);
655 gtk_box_pack_start (GTK_BOX (vbox), hpaned,
657 gtk_box_pack_start (GTK_BOX (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL),
659 gtk_box_pack_start (GTK_BOX (vbox), frame,
661 gtk_box_pack_start (GTK_BOX (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL),
663 gtk_box_pack_start (GTK_BOX (vbox), bbox,
666 gtk_container_add (GTK_CONTAINER (window), vbox);
668 gtk_widget_set_can_default (button, TRUE);
669 gtk_widget_grab_default (button);
671 gtk_window_set_default_size (GTK_WINDOW (window), 600, 0);
672 gtk_widget_show_all (window);
679 gtk_init (&argc, &argv);
681 if (g_getenv ("GTK_RTL"))
682 gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);