1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "gtknotebook.h"
19 #include "gtksignal.h"
22 #define CHILD_SPACING 2
24 #define TAB_CURVATURE 1
32 typedef void (*GtkNotebookSignal) (GtkObject *object,
36 static void gtk_notebook_class_init (GtkNotebookClass *klass);
37 static void gtk_notebook_init (GtkNotebook *notebook);
38 static void gtk_notebook_destroy (GtkObject *object);
39 static void gtk_notebook_map (GtkWidget *widget);
40 static void gtk_notebook_unmap (GtkWidget *widget);
41 static void gtk_notebook_realize (GtkWidget *widget);
42 static void gtk_notebook_unrealize (GtkWidget *widget);
43 static void gtk_notebook_size_request (GtkWidget *widget,
44 GtkRequisition *requisition);
45 static void gtk_notebook_size_allocate (GtkWidget *widget,
46 GtkAllocation *allocation);
47 static void gtk_notebook_paint (GtkWidget *widget,
49 static void gtk_notebook_draw (GtkWidget *widget,
51 static gint gtk_notebook_expose (GtkWidget *widget,
52 GdkEventExpose *event);
53 static gint gtk_notebook_button_press (GtkWidget *widget,
54 GdkEventButton *event);
55 static void gtk_notebook_add (GtkContainer *container,
57 static void gtk_notebook_remove (GtkContainer *container,
59 static void gtk_notebook_foreach (GtkContainer *container,
61 gpointer callback_data);
62 static void gtk_notebook_switch_page (GtkNotebook *notebook,
63 GtkNotebookPage *page);
64 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
65 GtkNotebookPage *page,
67 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
68 GtkAllocation *allocation);
69 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
70 GtkNotebookPage *page,
71 GtkAllocation *allocation);
73 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
74 GtkNotebookPage *page);
76 static void gtk_notebook_marshal_signal (GtkObject *object,
81 static GtkContainerClass *parent_class = NULL;
82 static gint notebook_signals[LAST_SIGNAL] = { 0 };
85 gtk_notebook_get_type ()
87 static guint notebook_type = 0;
91 GtkTypeInfo notebook_info =
95 sizeof (GtkNotebookClass),
96 (GtkClassInitFunc) gtk_notebook_class_init,
97 (GtkObjectInitFunc) gtk_notebook_init,
102 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
105 return notebook_type;
109 gtk_notebook_class_init (GtkNotebookClass *class)
111 GtkObjectClass *object_class;
112 GtkWidgetClass *widget_class;
113 GtkContainerClass *container_class;
115 object_class = (GtkObjectClass*) class;
116 widget_class = (GtkWidgetClass*) class;
117 container_class = (GtkContainerClass*) class;
119 parent_class = gtk_type_class (gtk_container_get_type ());
121 notebook_signals[SWITCH_PAGE] =
122 gtk_signal_new ("switch_page",
125 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
126 gtk_notebook_marshal_signal,
130 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
132 object_class->destroy = gtk_notebook_destroy;
134 widget_class->map = gtk_notebook_map;
135 widget_class->unmap = gtk_notebook_unmap;
136 widget_class->realize = gtk_notebook_realize;
137 widget_class->unrealize = gtk_notebook_unrealize;
138 widget_class->size_request = gtk_notebook_size_request;
139 widget_class->size_allocate = gtk_notebook_size_allocate;
140 widget_class->draw = gtk_notebook_draw;
141 widget_class->expose_event = gtk_notebook_expose;
142 widget_class->button_press_event = gtk_notebook_button_press;
144 container_class->add = gtk_notebook_add;
145 container_class->remove = gtk_notebook_remove;
146 container_class->foreach = gtk_notebook_foreach;
148 class->switch_page = gtk_real_notebook_switch_page;
152 gtk_notebook_init (GtkNotebook *notebook)
154 notebook->cur_page = NULL;
155 notebook->children = NULL;
156 notebook->show_tabs = TRUE;
157 notebook->show_border = TRUE;
158 notebook->tab_pos = GTK_POS_TOP;
164 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
168 gtk_notebook_append_page (GtkNotebook *notebook,
170 GtkWidget *tab_label)
172 g_return_if_fail (notebook != NULL);
173 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
174 g_return_if_fail (child != NULL);
175 g_return_if_fail (tab_label != NULL);
177 gtk_notebook_insert_page (notebook, child, tab_label, -1);
181 gtk_notebook_prepend_page (GtkNotebook *notebook,
183 GtkWidget *tab_label)
185 g_return_if_fail (notebook != NULL);
186 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
187 g_return_if_fail (child != NULL);
188 g_return_if_fail (tab_label != NULL);
190 gtk_notebook_insert_page (notebook, child, tab_label, 0);
194 gtk_notebook_insert_page (GtkNotebook *notebook,
196 GtkWidget *tab_label,
199 GtkNotebookPage *page;
202 g_return_if_fail (notebook != NULL);
203 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
204 g_return_if_fail (child != NULL);
205 g_return_if_fail (tab_label != NULL);
207 page = g_new (GtkNotebookPage, 1);
209 page->tab_label = tab_label;
210 page->requisition.width = 0;
211 page->requisition.height = 0;
212 page->allocation.x = 0;
213 page->allocation.y = 0;
214 page->allocation.width = 0;
215 page->allocation.height = 0;
217 nchildren = g_list_length (notebook->children);
218 if ((position < 0) || (position > nchildren))
219 position = nchildren;
221 notebook->children = g_list_insert (notebook->children, page, position);
223 if (!notebook->cur_page)
224 notebook->cur_page = page;
226 gtk_widget_show (tab_label);
227 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
228 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
230 if (GTK_WIDGET_VISIBLE (notebook))
232 if (GTK_WIDGET_REALIZED (notebook) &&
233 !GTK_WIDGET_REALIZED (child))
234 gtk_widget_realize (child);
237 if (GTK_WIDGET_MAPPED (notebook) &&
238 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
239 gtk_widget_map (child);
241 if (GTK_WIDGET_REALIZED (notebook) &&
242 !GTK_WIDGET_REALIZED (tab_label))
243 gtk_widget_realize (tab_label);
245 if (GTK_WIDGET_MAPPED (notebook) &&
246 !GTK_WIDGET_MAPPED (tab_label))
247 gtk_widget_map (tab_label);
250 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
251 gtk_widget_queue_resize (child);
255 gtk_notebook_remove_page (GtkNotebook *notebook,
258 GtkNotebookPage *page;
261 g_return_if_fail (notebook != NULL);
262 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
264 tmp_list = g_list_nth (notebook->children, page_num);
267 page = tmp_list->data;
269 if (notebook->cur_page == page)
270 gtk_notebook_prev_page (notebook);
271 if (notebook->cur_page == page)
272 notebook->cur_page = NULL;
274 notebook->children = g_list_remove_link (notebook->children, tmp_list);
275 g_list_free (tmp_list);
281 gtk_notebook_current_page (GtkNotebook *notebook)
286 g_return_val_if_fail (notebook != NULL, -1);
287 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
289 if (notebook->cur_page)
292 children = notebook->children;
296 if (children->data == notebook->cur_page)
298 children = children->next;
314 gtk_notebook_set_page (GtkNotebook *notebook,
317 GtkNotebookPage *page;
320 g_return_if_fail (notebook != NULL);
321 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
323 tmp_list = g_list_nth (notebook->children, page_num);
326 page = tmp_list->data;
327 gtk_notebook_switch_page (notebook, page);
332 gtk_notebook_next_page (GtkNotebook *notebook)
334 GtkNotebookPage *page;
337 g_return_if_fail (notebook != NULL);
338 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
340 children = notebook->children;
343 page = children->data;
345 if (notebook->cur_page == page)
347 children = children->next;
349 children = notebook->children;
350 page = children->data;
352 gtk_notebook_switch_page (notebook, page);
355 children = children->next;
360 gtk_notebook_prev_page (GtkNotebook *notebook)
362 GtkNotebookPage *page;
365 g_return_if_fail (notebook != NULL);
366 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
368 children = notebook->children;
371 page = children->data;
373 if (notebook->cur_page == page)
375 children = children->prev;
377 children = g_list_last (notebook->children);
378 page = children->data;
380 gtk_notebook_switch_page (notebook, page);
383 children = children->next;
388 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
391 g_return_if_fail (notebook != NULL);
392 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
394 if (notebook->tab_pos != pos)
396 notebook->tab_pos = pos;
398 if (GTK_WIDGET_VISIBLE (notebook))
399 gtk_widget_queue_resize (GTK_WIDGET (notebook));
404 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
407 g_return_if_fail (notebook != NULL);
408 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
410 if (notebook->show_tabs != show_tabs)
412 notebook->show_tabs = show_tabs;
414 if (GTK_WIDGET_VISIBLE (notebook))
415 gtk_widget_queue_resize (GTK_WIDGET (notebook));
420 gtk_notebook_set_show_border (GtkNotebook *notebook,
423 g_return_if_fail (notebook != NULL);
424 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
426 if (notebook->show_border != show_border)
428 notebook->show_border = show_border;
430 if (GTK_WIDGET_VISIBLE (notebook))
431 gtk_widget_queue_resize (GTK_WIDGET (notebook));
436 gtk_notebook_destroy (GtkObject *object)
438 GtkNotebook *notebook;
439 GtkNotebookPage *page;
442 g_return_if_fail (object != NULL);
443 g_return_if_fail (GTK_IS_NOTEBOOK (object));
445 notebook = GTK_NOTEBOOK (object);
447 children = notebook->children;
450 page = children->data;
451 children = children->next;
453 page->child->parent = NULL;
454 page->tab_label->parent = NULL;
456 gtk_object_unref (GTK_OBJECT (page->child));
457 gtk_object_unref (GTK_OBJECT (page->tab_label));
459 gtk_widget_destroy (page->child);
460 gtk_widget_destroy (page->tab_label);
465 g_list_free (notebook->children);
467 if (GTK_OBJECT_CLASS (parent_class)->destroy)
468 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
472 gtk_notebook_map (GtkWidget *widget)
474 GtkNotebook *notebook;
475 GtkNotebookPage *page;
478 g_return_if_fail (widget != NULL);
479 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
481 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
482 gdk_window_show (widget->window);
484 notebook = GTK_NOTEBOOK (widget);
486 if (notebook->cur_page &&
487 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
488 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
489 gtk_widget_map (notebook->cur_page->child);
491 children = notebook->children;
494 page = children->data;
495 children = children->next;
497 if (GTK_WIDGET_VISIBLE (page->child) &&
498 !GTK_WIDGET_MAPPED (page->tab_label))
499 gtk_widget_map (page->tab_label);
504 gtk_notebook_unmap (GtkWidget *widget)
506 g_return_if_fail (widget != NULL);
507 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
509 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
510 gdk_window_hide (widget->window);
514 gtk_notebook_realize (GtkWidget *widget)
516 GtkNotebook *notebook;
517 GdkWindowAttr attributes;
518 gint attributes_mask;
520 g_return_if_fail (widget != NULL);
521 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
523 notebook = GTK_NOTEBOOK (widget);
524 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
526 attributes.window_type = GDK_WINDOW_CHILD;
527 attributes.x = widget->allocation.x;
528 attributes.y = widget->allocation.y;
529 attributes.width = widget->allocation.width;
530 attributes.height = widget->allocation.height;
531 attributes.wclass = GDK_INPUT_OUTPUT;
532 attributes.visual = gtk_widget_get_visual (widget);
533 attributes.colormap = gtk_widget_get_colormap (widget);
534 attributes.event_mask = gtk_widget_get_events (widget);
535 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
537 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
539 widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
540 gdk_window_set_user_data (widget->window, notebook);
542 widget->style = gtk_style_attach (widget->style, widget->window);
543 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
547 gtk_notebook_unrealize (GtkWidget *widget)
549 g_return_if_fail (widget != NULL);
550 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
552 GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
554 gtk_style_detach (widget->style);
555 gdk_window_destroy (widget->window);
556 widget->window = NULL;
560 gtk_notebook_size_request (GtkWidget *widget,
561 GtkRequisition *requisition)
563 GtkNotebook *notebook;
564 GtkNotebookPage *page;
569 g_return_if_fail (widget != NULL);
570 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
571 g_return_if_fail (requisition != NULL);
573 notebook = GTK_NOTEBOOK (widget);
574 widget->requisition.width = 0;
575 widget->requisition.height = 0;
577 children = notebook->children;
580 page = children->data;
581 children = children->next;
583 if (GTK_WIDGET_VISIBLE (page->child))
585 gtk_widget_size_request (page->child, &page->child->requisition);
587 widget->requisition.width = MAX (widget->requisition.width,
588 page->child->requisition.width);
589 widget->requisition.height = MAX (widget->requisition.height,
590 page->child->requisition.height);
594 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
595 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
597 if (notebook->show_tabs)
599 widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
600 widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
605 children = notebook->children;
608 page = children->data;
609 children = children->next;
611 if (GTK_WIDGET_VISIBLE (page->child))
613 gtk_widget_size_request (page->tab_label, &page->tab_label->requisition);
615 page->requisition.width = (page->tab_label->requisition.width +
616 (GTK_WIDGET (widget)->style->klass->xthickness +
618 page->requisition.height = (page->tab_label->requisition.height +
619 (GTK_WIDGET (widget)->style->klass->ythickness +
622 switch (notebook->tab_pos)
626 page->requisition.width -= TAB_OVERLAP;
627 page->requisition.height -= GTK_WIDGET (widget)->style->klass->ythickness;
629 tab_width += page->requisition.width;
630 tab_height = MAX (tab_height, page->requisition.height);
634 page->requisition.width -= GTK_WIDGET (widget)->style->klass->xthickness;
635 page->requisition.height -= TAB_OVERLAP;
637 tab_width = MAX (tab_width, page->requisition.width);
638 tab_height += page->requisition.height;
644 children = notebook->children;
647 page = children->data;
648 children = children->next;
650 if (GTK_WIDGET_VISIBLE (page->child))
652 if ((notebook->tab_pos == GTK_POS_TOP) ||
653 (notebook->tab_pos == GTK_POS_BOTTOM))
654 page->requisition.height = tab_height;
656 page->requisition.width = tab_width;
660 switch (notebook->tab_pos)
664 tab_width += GTK_WIDGET (widget)->style->klass->xthickness;
665 widget->requisition.width = MAX (widget->requisition.width, tab_width);
666 widget->requisition.height += tab_height;
670 tab_height += GTK_WIDGET (widget)->style->klass->ythickness;
671 widget->requisition.width += tab_width;
672 widget->requisition.height = MAX (widget->requisition.height, tab_height);
676 else if (notebook->show_border)
678 widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
679 widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
684 gtk_notebook_size_allocate (GtkWidget *widget,
685 GtkAllocation *allocation)
687 GtkNotebook *notebook;
688 GtkNotebookPage *page;
689 GtkAllocation child_allocation;
692 g_return_if_fail (widget != NULL);
693 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
694 g_return_if_fail (allocation != NULL);
696 widget->allocation = *allocation;
697 if (GTK_WIDGET_REALIZED (widget))
698 gdk_window_move_resize (widget->window,
699 allocation->x, allocation->y,
700 allocation->width, allocation->height);
702 notebook = GTK_NOTEBOOK (widget);
703 if (notebook->children)
705 child_allocation.x = GTK_CONTAINER (widget)->border_width;
706 child_allocation.y = GTK_CONTAINER (widget)->border_width;
707 child_allocation.width = allocation->width - child_allocation.x * 2;
708 child_allocation.height = allocation->height - child_allocation.y * 2;
710 if (notebook->show_tabs || notebook->show_border)
712 child_allocation.x += GTK_WIDGET (widget)->style->klass->xthickness;
713 child_allocation.y += GTK_WIDGET (widget)->style->klass->ythickness;
714 child_allocation.width -= GTK_WIDGET (widget)->style->klass->xthickness * 2;
715 child_allocation.height -= GTK_WIDGET (widget)->style->klass->ythickness * 2;
717 if (notebook->show_tabs && notebook->children)
719 switch (notebook->tab_pos)
722 child_allocation.y += notebook->cur_page->requisition.height;
724 child_allocation.height -= notebook->cur_page->requisition.height;
727 child_allocation.x += notebook->cur_page->requisition.width;
729 child_allocation.width -= notebook->cur_page->requisition.width;
735 children = notebook->children;
738 page = children->data;
739 children = children->next;
741 if (GTK_WIDGET_VISIBLE (page->child))
742 gtk_widget_size_allocate (page->child, &child_allocation);
745 if (notebook->show_tabs && notebook->children)
746 gtk_notebook_pages_allocate (notebook, allocation);
751 gtk_notebook_paint (GtkWidget *widget,
754 GtkNotebook *notebook;
755 GtkNotebookPage *page;
761 g_return_if_fail (widget != NULL);
762 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
763 g_return_if_fail (area != NULL);
765 if (GTK_WIDGET_DRAWABLE (widget))
767 notebook = GTK_NOTEBOOK (widget);
769 gdk_window_clear_area (widget->window,
771 area->width, area->height);
773 if (notebook->show_tabs || notebook->show_border)
775 x = GTK_CONTAINER (widget)->border_width;
776 y = GTK_CONTAINER (widget)->border_width;
777 width = widget->allocation.width - x * 2;
778 height = widget->allocation.height - y * 2;
780 if (notebook->show_tabs && notebook->children)
782 switch (notebook->tab_pos)
785 y += notebook->cur_page->allocation.height;
787 height -= notebook->cur_page->allocation.height;
790 x += notebook->cur_page->allocation.width;
792 width -= notebook->cur_page->allocation.width;
796 switch (notebook->tab_pos)
799 points[0].x = notebook->cur_page->allocation.x;
804 points[2].y = y + height - 1;
805 points[3].x = x + width - 1;
806 points[3].y = y + height - 1;
807 points[4].x = x + width - 1;
809 points[5].x = (notebook->cur_page->allocation.x +
810 notebook->cur_page->allocation.width -
811 GTK_WIDGET (notebook)->style->klass->xthickness);
814 if (points[5].x == (x + width))
818 points[0].x = (notebook->cur_page->allocation.x +
819 notebook->cur_page->allocation.width -
820 GTK_WIDGET (notebook)->style->klass->xthickness);
821 points[0].y = y + height - 1;
822 points[1].x = x + width - 1;
823 points[1].y = y + height - 1;
824 points[2].x = x + width - 1;
829 points[4].y = y + height - 1;
830 points[5].x = notebook->cur_page->allocation.x;
831 points[5].y = y + height - 1;
833 if (points[0].x == (x + width))
838 points[0].y = (notebook->cur_page->allocation.y +
839 notebook->cur_page->allocation.height -
840 GTK_WIDGET (notebook)->style->klass->ythickness);
842 points[1].y = y + height - 1;
843 points[2].x = x + width - 1;
844 points[2].y = y + height - 1;
845 points[3].x = x + width - 1;
850 points[5].y = notebook->cur_page->allocation.y;
852 if (points[0].y == (y + height))
856 points[0].x = x + width - 1;
857 points[0].y = notebook->cur_page->allocation.y;
858 points[1].x = x + width - 1;
863 points[3].y = y + height - 1;
864 points[4].x = x + width - 1;
865 points[4].y = y + height - 1;
866 points[5].x = x + width - 1;
867 points[5].y = (notebook->cur_page->allocation.y +
868 notebook->cur_page->allocation.height -
869 GTK_WIDGET (notebook)->style->klass->ythickness);
871 if (points[5].y == (y + height))
876 gtk_draw_polygon (widget->style, widget->window,
877 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
880 children = g_list_last (notebook->children);
883 page = children->data;
884 children = children->prev;
886 if (notebook->cur_page != page)
887 gtk_notebook_draw_tab (notebook, page, area);
890 if (notebook->cur_page)
891 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
893 else if (notebook->show_border)
895 gtk_draw_shadow (widget->style, widget->window,
896 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
897 x, y, width, height);
904 gtk_notebook_draw (GtkWidget *widget,
907 GtkNotebook *notebook;
908 GdkRectangle child_area;
910 g_return_if_fail (widget != NULL);
911 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
912 g_return_if_fail (area != NULL);
914 if (GTK_WIDGET_DRAWABLE (widget))
916 notebook = GTK_NOTEBOOK (widget);
918 gtk_notebook_paint (widget, area);
920 if (notebook->cur_page &&
921 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
922 gtk_widget_draw (notebook->cur_page->child, &child_area);
927 gtk_notebook_expose (GtkWidget *widget,
928 GdkEventExpose *event)
930 GtkNotebook *notebook;
931 GdkEventExpose child_event;
933 g_return_val_if_fail (widget != NULL, FALSE);
934 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
935 g_return_val_if_fail (event != NULL, FALSE);
937 if (GTK_WIDGET_DRAWABLE (widget))
939 notebook = GTK_NOTEBOOK (widget);
941 gtk_notebook_paint (widget, &event->area);
943 child_event = *event;
944 if (notebook->cur_page && GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
945 gtk_widget_intersect (notebook->cur_page->child, &event->area, &child_event.area))
946 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
953 gtk_notebook_button_press (GtkWidget *widget,
954 GdkEventButton *event)
956 GtkNotebook *notebook;
957 GtkNotebookPage *page;
960 g_return_val_if_fail (widget != NULL, FALSE);
961 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
962 g_return_val_if_fail (event != NULL, FALSE);
964 if ((event->type != GDK_BUTTON_PRESS) ||
965 (event->window != widget->window))
968 notebook = GTK_NOTEBOOK (widget);
970 children = notebook->children;
973 page = children->data;
975 if (GTK_WIDGET_VISIBLE (page->child) &&
976 (event->x >= page->allocation.x) &&
977 (event->y >= page->allocation.y) &&
978 (event->x <= (page->allocation.x + page->allocation.width)) &&
979 (event->y <= (page->allocation.y + page->allocation.height)))
981 gtk_notebook_switch_page (notebook, page);
984 children = children->next;
991 gtk_notebook_add (GtkContainer *container,
994 g_warning ("gtk_notebook_add: use gtk_notebook_{append,prepend}_page instead\n");
998 gtk_notebook_remove (GtkContainer *container,
1001 GtkNotebook *notebook;
1002 GtkNotebookPage *page;
1005 g_return_if_fail (container != NULL);
1006 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1007 g_return_if_fail (widget != NULL);
1009 notebook = GTK_NOTEBOOK (container);
1011 children = notebook->children;
1014 page = children->data;
1016 if (page->child == widget)
1018 gtk_widget_unparent (page->child);
1019 gtk_widget_unparent (page->tab_label);
1021 notebook->children = g_list_remove_link (notebook->children, children);
1022 g_list_free (children);
1025 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
1026 gtk_widget_queue_resize (GTK_WIDGET (container));
1031 children = children->next;
1036 gtk_notebook_foreach (GtkContainer *container,
1037 GtkCallback callback,
1038 gpointer callback_data)
1040 GtkNotebook *notebook;
1041 GtkNotebookPage *page;
1044 g_return_if_fail (container != NULL);
1045 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1046 g_return_if_fail (callback != NULL);
1048 notebook = GTK_NOTEBOOK (container);
1050 children = notebook->children;
1053 page = children->data;
1054 children = children->next;
1056 (* callback) (page->child, callback_data);
1061 gtk_real_notebook_switch_page (GtkNotebook *notebook,
1062 GtkNotebookPage *page)
1064 g_return_if_fail (notebook != NULL);
1065 g_return_if_fail (page != NULL);
1067 if (notebook->cur_page != page)
1069 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
1070 gtk_widget_unmap (notebook->cur_page->child);
1072 notebook->cur_page = page;
1073 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
1075 if (GTK_WIDGET_MAPPED (notebook))
1077 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
1079 gtk_widget_map (notebook->cur_page->child);
1083 gtk_widget_map (notebook->cur_page->child);
1084 gtk_widget_size_allocate (GTK_WIDGET (notebook),
1085 >K_WIDGET (notebook)->allocation);
1089 if (GTK_WIDGET_DRAWABLE (notebook))
1090 gtk_widget_queue_draw (GTK_WIDGET (notebook));
1096 gtk_notebook_draw_tab (GtkNotebook *notebook,
1097 GtkNotebookPage *page,
1100 GdkRectangle child_area;
1101 GdkRectangle page_area;
1102 GtkStateType state_type;
1106 g_return_if_fail (notebook != NULL);
1107 g_return_if_fail (page != NULL);
1108 g_return_if_fail (area != NULL);
1110 page_area.x = page->allocation.x;
1111 page_area.y = page->allocation.y;
1112 page_area.width = page->allocation.width;
1113 page_area.height = page->allocation.height;
1115 if (gdk_rectangle_intersect (&page_area, area, &child_area))
1119 switch (notebook->tab_pos)
1122 if( child_area.x + child_area.width >
1123 page->allocation.x + page->allocation.width - TAB_OVERLAP )
1125 points[0].x = page->allocation.x + page->allocation.width - 1;
1126 points[0].y = page->allocation.y + page->allocation.height - 1;
1128 points[1].x = page->allocation.x + page->allocation.width - 1;
1129 points[1].y = page->allocation.y + TAB_CURVATURE;
1131 points[2].x = page->allocation.x + page->allocation.width
1132 - TAB_CURVATURE - 1;
1133 points[2].y = page->allocation.y;
1138 points[0].x = page->allocation.x + page->allocation.width
1140 points[0].y = page->allocation.y;
1144 if( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1145 (page == notebook->cur_page ||
1146 page == (GtkNotebookPage *)(notebook->children->data)) )
1148 points[n].x = page->allocation.x + TAB_CURVATURE;
1149 points[n++].y = page->allocation.y;
1151 points[n].x = page->allocation.x;
1152 points[n++].y = page->allocation.y + TAB_CURVATURE;
1154 points[n].x = page->allocation.x;
1155 points[n++].y = page->allocation.y + page->allocation.height - 1;
1159 points[n].x = page->allocation.x + TAB_OVERLAP;
1160 points[n++].y = page->allocation.y;
1163 case GTK_POS_BOTTOM:
1164 if( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1165 (page == notebook->cur_page ||
1166 page == (GtkNotebookPage *)(notebook->children->data)) )
1168 points[0].x = page->allocation.x;
1169 points[0].y = page->allocation.y;
1171 points[1].x = page->allocation.x;
1172 points[1].y = page->allocation.y + page->allocation.height
1173 - TAB_CURVATURE - 1;
1175 points[2].x = page->allocation.x + TAB_CURVATURE;
1176 points[2].y = page->allocation.y + page->allocation.height - 1;
1181 points[0].x = page->allocation.x + TAB_OVERLAP;
1182 points[0].y = page->allocation.y + page->allocation.height - 1;
1186 if( child_area.x + child_area.width >
1187 page->allocation.x + page->allocation.width - TAB_OVERLAP )
1189 points[n].x = page->allocation.x + page->allocation.width
1190 - TAB_CURVATURE - 1;
1191 points[n++].y = page->allocation.y + page->allocation.height - 1;
1193 points[n].x = page->allocation.x + page->allocation.width - 1;
1194 points[n++].y = page->allocation.y + page->allocation.height
1195 - TAB_CURVATURE - 1;
1197 points[n].x = page->allocation.x + page->allocation.width - 1;
1198 points[n++].y = page->allocation.y;
1202 points[n].x = page->allocation.x + page->allocation.width
1204 points[n++].y = page->allocation.y + page->allocation.height - 1;
1208 if( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1209 (page == notebook->cur_page ||
1210 page == (GtkNotebookPage *)(notebook->children->data)) )
1212 points[0].x = page->allocation.x + page->allocation.width - 1;
1213 points[0].y = page->allocation.y;
1215 points[1].x = page->allocation.x + TAB_CURVATURE;
1216 points[1].y = page->allocation.y;
1218 points[2].x = page->allocation.x;
1219 points[2].y = page->allocation.y + TAB_CURVATURE;
1224 points[0].x = page->allocation.x;
1225 points[0].y = page->allocation.y + TAB_OVERLAP;
1229 if( child_area.y + child_area.height >
1230 page->allocation.y + page->allocation.height - TAB_OVERLAP )
1232 points[n].x = page->allocation.x;
1233 points[n++].y = page->allocation.y + page->allocation.height
1234 - TAB_CURVATURE - 1;
1236 points[n].x = page->allocation.x + TAB_CURVATURE;
1237 points[n++].y = page->allocation.y + page->allocation.height - 1;
1239 points[n].x = page->allocation.x + page->allocation.width - 1;
1240 points[n++].y = page->allocation.y + page->allocation.height - 1;
1244 points[n].x = page->allocation.x;
1245 points[n++].y = page->allocation.y + page->allocation.height
1250 if( child_area.y + child_area.height >
1251 page->allocation.y + page->allocation.height - TAB_OVERLAP )
1253 points[0].x = page->allocation.x;
1254 points[0].y = page->allocation.y + page->allocation.height - 1;
1256 points[1].x = page->allocation.x + page->allocation.width
1257 - TAB_CURVATURE - 1;
1258 points[1].y = page->allocation.y + page->allocation.height - 1;
1260 points[2].x = page->allocation.x + page->allocation.width - 1;
1261 points[2].y = page->allocation.y + page->allocation.height
1262 - TAB_CURVATURE - 1;
1267 points[0].x = page->allocation.x + page->allocation.width - 1;
1268 points[0].y = page->allocation.y + page->allocation.height
1273 if( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1274 (page == notebook->cur_page ||
1275 page == (GtkNotebookPage *)(notebook->children->data)) )
1277 points[n].x = page->allocation.x + page->allocation.width - 1;
1278 points[n++].y = page->allocation.y + TAB_CURVATURE;
1280 points[n].x = page->allocation.x + page->allocation.width
1281 - TAB_CURVATURE - 1;
1282 points[n++].y = page->allocation.y;
1284 points[n].x = page->allocation.x;
1285 points[n++].y = page->allocation.y;
1289 points[n].x = page->allocation.x + page->allocation.width - 1;
1290 points[n++].y = page->allocation.y + TAB_OVERLAP;
1295 widget = GTK_WIDGET(notebook);
1297 if (notebook->cur_page == page)
1298 state_type = GTK_STATE_NORMAL;
1301 state_type = GTK_STATE_ACTIVE;
1303 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
1304 TRUE, child_area.x, child_area.y,
1305 child_area.width, child_area.height);
1308 gtk_draw_polygon (widget->style, widget->window, state_type,
1309 GTK_SHADOW_OUT, points, n, FALSE);
1311 if (gtk_widget_intersect (page->tab_label, area, &child_area))
1312 gtk_widget_draw (page->tab_label, &child_area);
1318 gtk_notebook_pages_allocate (GtkNotebook *notebook,
1319 GtkAllocation *allocation)
1321 GtkNotebookPage *page;
1322 GtkAllocation child_allocation;
1325 if (notebook->show_tabs && notebook->children)
1327 child_allocation.x = GTK_CONTAINER (notebook)->border_width;
1328 child_allocation.y = GTK_CONTAINER (notebook)->border_width;
1330 switch (notebook->tab_pos)
1332 case GTK_POS_BOTTOM:
1333 child_allocation.y = allocation->height - notebook->cur_page->requisition.height;
1335 child_allocation.height = notebook->cur_page->requisition.height;
1338 child_allocation.x = allocation->width - notebook->cur_page->requisition.width;
1340 child_allocation.width = notebook->cur_page->requisition.width;
1344 children = notebook->children;
1347 page = children->data;
1348 children = children->next;
1350 if (GTK_WIDGET_VISIBLE (page->child))
1352 switch (notebook->tab_pos)
1355 case GTK_POS_BOTTOM:
1356 child_allocation.width = page->requisition.width + TAB_OVERLAP;
1360 child_allocation.height = page->requisition.height + TAB_OVERLAP;
1364 gtk_notebook_page_allocate (notebook, page, &child_allocation);
1366 switch (notebook->tab_pos)
1369 case GTK_POS_BOTTOM:
1370 child_allocation.x += child_allocation.width - TAB_OVERLAP;
1374 child_allocation.y += child_allocation.height - TAB_OVERLAP;
1383 gtk_notebook_page_allocate (GtkNotebook *notebook,
1384 GtkNotebookPage *page,
1385 GtkAllocation *allocation)
1387 GtkAllocation child_allocation;
1388 gint xthickness, ythickness;
1390 g_return_if_fail (notebook != NULL);
1391 g_return_if_fail (page != NULL);
1392 g_return_if_fail (allocation != NULL);
1394 page->allocation = *allocation;
1396 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
1397 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
1399 if (notebook->cur_page != page)
1401 switch (notebook->tab_pos)
1404 page->allocation.y += ythickness;
1405 case GTK_POS_BOTTOM:
1406 page->allocation.height -= ythickness;
1409 page->allocation.x += xthickness;
1411 page->allocation.width -= xthickness;
1416 switch (notebook->tab_pos)
1419 child_allocation.x = xthickness + CHILD_SPACING;
1420 child_allocation.y = ythickness + CHILD_SPACING;
1421 child_allocation.width = page->allocation.width - child_allocation.x * 2;
1422 child_allocation.height = page->allocation.height - child_allocation.y;
1423 child_allocation.x += page->allocation.x;
1424 child_allocation.y += page->allocation.y;
1426 case GTK_POS_BOTTOM:
1427 child_allocation.x = xthickness + CHILD_SPACING;
1428 child_allocation.y = ythickness + CHILD_SPACING;
1429 child_allocation.width = page->allocation.width - child_allocation.x * 2;
1430 child_allocation.height = page->allocation.height - child_allocation.y;
1431 child_allocation.x += page->allocation.x;
1432 child_allocation.y = page->allocation.y;
1435 child_allocation.x = xthickness + CHILD_SPACING;
1436 child_allocation.y = ythickness + CHILD_SPACING;
1437 child_allocation.width = page->allocation.width - child_allocation.x;
1438 child_allocation.height = page->allocation.height - child_allocation.y * 2;
1439 child_allocation.x += page->allocation.x;
1440 child_allocation.y += page->allocation.y;
1443 child_allocation.x = xthickness + CHILD_SPACING;
1444 child_allocation.y = ythickness + CHILD_SPACING;
1445 child_allocation.width = page->allocation.width - child_allocation.x;
1446 child_allocation.height = page->allocation.height - child_allocation.y * 2;
1447 child_allocation.x = page->allocation.x;
1448 child_allocation.y += page->allocation.y;
1452 gtk_widget_size_allocate (page->tab_label, &child_allocation);
1456 gtk_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page)
1458 gtk_signal_emit (GTK_OBJECT (notebook), notebook_signals[SWITCH_PAGE], page);
1462 gtk_notebook_marshal_signal (GtkObject *object,
1467 GtkNotebookSignal rfunc;
1469 rfunc = (GtkNotebookSignal) func;
1471 (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);