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
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 #include "gtknotebook.h"
20 #include "gtksignal.h"
23 #include "gtkmenuitem.h"
25 #include <gdk/gdkkeysyms.h>
30 #define TAB_CURVATURE 1
32 #define ARROW_SPACING 3
33 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
34 #define NOTEBOOK_SCROLL_DELAY (100)
65 typedef void (*GtkNotebookSignal) (GtkObject *object,
66 GtkNotebookPage *arg1,
70 static void gtk_notebook_class_init (GtkNotebookClass *klass);
71 static void gtk_notebook_init (GtkNotebook *notebook);
72 static void gtk_notebook_set_arg (GtkObject *object,
75 static void gtk_notebook_get_arg (GtkObject *object,
78 static void gtk_notebook_set_child_arg (GtkContainer *container,
82 static void gtk_notebook_get_child_arg (GtkContainer *container,
86 static void gtk_notebook_destroy (GtkObject *object);
87 static void gtk_notebook_map (GtkWidget *widget);
88 static void gtk_notebook_unmap (GtkWidget *widget);
89 static void gtk_notebook_realize (GtkWidget *widget);
90 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
91 static void gtk_notebook_size_request (GtkWidget *widget,
92 GtkRequisition *requisition);
93 static void gtk_notebook_size_allocate (GtkWidget *widget,
94 GtkAllocation *allocation);
95 static void gtk_notebook_paint (GtkWidget *widget,
97 static void gtk_notebook_draw (GtkWidget *widget,
99 static gint gtk_notebook_expose (GtkWidget *widget,
100 GdkEventExpose *event);
101 static gint gtk_notebook_button_press (GtkWidget *widget,
102 GdkEventButton *event);
103 static gint gtk_notebook_button_release (GtkWidget *widget,
104 GdkEventButton *event);
105 static gint gtk_notebook_enter_notify (GtkWidget *widget,
106 GdkEventCrossing *event);
107 static gint gtk_notebook_leave_notify (GtkWidget *widget,
108 GdkEventCrossing *event);
109 static gint gtk_notebook_motion_notify (GtkWidget *widget,
110 GdkEventMotion *event);
111 static gint gtk_notebook_key_press (GtkWidget *widget,
113 static void gtk_notebook_add (GtkContainer *container,
115 static void gtk_notebook_remove (GtkContainer *container,
117 static void gtk_notebook_real_remove (GtkNotebook *notebook,
120 static void gtk_notebook_foreach (GtkContainer *container,
121 GtkCallback callback,
122 gpointer callback_data);
123 static void gtk_notebook_switch_page (GtkNotebook *notebook,
124 GtkNotebookPage *page,
126 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
127 GtkNotebookPage *page,
129 static void gtk_notebook_set_focus_child (GtkContainer *container,
131 static gint gtk_notebook_focus_in (GtkWidget *widget,
132 GdkEventFocus *event);
133 static gint gtk_notebook_focus_out (GtkWidget *widget,
134 GdkEventFocus *event);
135 static void gtk_notebook_draw_focus (GtkWidget *widget);
136 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
137 GtkNotebookPage *old_page);
138 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
139 GtkAllocation *allocation);
140 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
141 GtkNotebookPage *page,
142 GtkAllocation *allocation);
143 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
145 static gint gtk_notebook_timer (GtkNotebook *notebook);
146 static gint gtk_notebook_focus (GtkContainer *container,
147 GtkDirectionType direction);
148 static gint gtk_notebook_page_select (GtkNotebook *notebook);
149 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
154 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
155 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
157 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
158 GtkNotebookPage *page,
160 static void gtk_notebook_marshal_signal (GtkObject *object,
164 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
165 GtkNotebookPage *page);
166 static void gtk_notebook_update_labels (GtkNotebook *notebook,
169 static void gtk_notebook_menu_detacher (GtkWidget *widget,
171 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
173 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
174 GtkNotebookPage *page,
176 static GtkType gtk_notebook_child_type (GtkContainer *container);
179 static GtkContainerClass *parent_class = NULL;
180 static guint notebook_signals[LAST_SIGNAL] = { 0 };
183 gtk_notebook_get_type (void)
185 static GtkType notebook_type = 0;
189 GtkTypeInfo notebook_info =
192 sizeof (GtkNotebook),
193 sizeof (GtkNotebookClass),
194 (GtkClassInitFunc) gtk_notebook_class_init,
195 (GtkObjectInitFunc) gtk_notebook_init,
196 /* reserved_1 */ NULL,
197 /* reserved_2 */ NULL,
198 (GtkClassInitFunc) NULL,
201 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
204 return notebook_type;
208 gtk_notebook_class_init (GtkNotebookClass *class)
210 GtkObjectClass *object_class;
211 GtkWidgetClass *widget_class;
212 GtkContainerClass *container_class;
214 object_class = (GtkObjectClass*) class;
215 widget_class = (GtkWidgetClass*) class;
216 container_class = (GtkContainerClass*) class;
217 parent_class = gtk_type_class (gtk_container_get_type ());
219 gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
220 gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
221 gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_BORDER);
222 gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
223 gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
224 gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
225 gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
227 gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
229 * gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
230 * gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
233 notebook_signals[SWITCH_PAGE] =
234 gtk_signal_new ("switch_page",
237 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
238 gtk_notebook_marshal_signal,
243 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
245 object_class->set_arg = gtk_notebook_set_arg;
246 object_class->get_arg = gtk_notebook_get_arg;
247 object_class->destroy = gtk_notebook_destroy;
249 widget_class->map = gtk_notebook_map;
250 widget_class->unmap = gtk_notebook_unmap;
251 widget_class->realize = gtk_notebook_realize;
252 widget_class->size_request = gtk_notebook_size_request;
253 widget_class->size_allocate = gtk_notebook_size_allocate;
254 widget_class->draw = gtk_notebook_draw;
255 widget_class->expose_event = gtk_notebook_expose;
256 widget_class->button_press_event = gtk_notebook_button_press;
257 widget_class->button_release_event = gtk_notebook_button_release;
258 widget_class->enter_notify_event = gtk_notebook_enter_notify;
259 widget_class->leave_notify_event = gtk_notebook_leave_notify;
260 widget_class->motion_notify_event = gtk_notebook_motion_notify;
261 widget_class->key_press_event = gtk_notebook_key_press;
262 widget_class->focus_in_event = gtk_notebook_focus_in;
263 widget_class->focus_out_event = gtk_notebook_focus_out;
264 widget_class->draw_focus = gtk_notebook_draw_focus;
266 container_class->add = gtk_notebook_add;
267 container_class->remove = gtk_notebook_remove;
268 container_class->foreach = gtk_notebook_foreach;
269 container_class->focus = gtk_notebook_focus;
270 container_class->set_focus_child = gtk_notebook_set_focus_child;
271 container_class->get_child_arg = gtk_notebook_get_child_arg;
272 container_class->set_child_arg = gtk_notebook_set_child_arg;
273 container_class->child_type = gtk_notebook_child_type;
275 class->switch_page = gtk_real_notebook_switch_page;
279 gtk_notebook_set_arg (GtkObject *object,
283 GtkNotebook *notebook;
285 notebook = GTK_NOTEBOOK (object);
290 gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
292 case ARG_SHOW_BORDER:
293 gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
296 gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
298 case ARG_ENABLE_POPUP:
299 if (GTK_VALUE_BOOL (*arg))
300 gtk_notebook_popup_enable (notebook);
302 gtk_notebook_popup_disable (notebook);
305 gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
308 gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
311 gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
319 gtk_notebook_get_arg (GtkObject *object,
323 GtkNotebook *notebook;
325 notebook = GTK_NOTEBOOK (object);
330 GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
332 case ARG_SHOW_BORDER:
333 GTK_VALUE_BOOL (*arg) = notebook->show_border;
336 GTK_VALUE_BOOL (*arg) = notebook->scrollable;
338 case ARG_ENABLE_POPUP:
339 GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
342 GTK_VALUE_INT (*arg) = gtk_notebook_current_page (notebook);
345 GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
348 GTK_VALUE_UINT (*arg) = notebook->tab_border;
351 arg->type = GTK_TYPE_INVALID;
357 gtk_notebook_set_child_arg (GtkContainer *container,
362 GtkNotebook *notebook;
363 GtkNotebookPage *page = NULL;
366 notebook = GTK_NOTEBOOK (container);
368 for (list = notebook->children; list; list = list->next)
371 if (page->child == child)
379 case CHILD_ARG_TAB_LABEL:
380 /* a NULL pointer indicates a default_tab setting, otherwise
381 * we need to set the associated label
383 if (GTK_VALUE_STRING (*arg))
385 page->default_tab = FALSE;
387 gtk_widget_unparent (page->tab_label);
388 page->tab_label = gtk_label_new (GTK_VALUE_STRING (*arg));
389 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
390 if (notebook->show_tabs)
391 gtk_widget_show (page->tab_label);
395 page->default_tab = TRUE;
397 gtk_widget_unparent (page->tab_label);
398 if (!notebook->show_tabs)
399 page->tab_label = NULL;
404 sprintf (string, "Page %u", g_list_index (notebook->children, page) + 1);
405 page->tab_label = gtk_label_new (string);
406 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
407 gtk_widget_show (page->tab_label);
411 case CHILD_ARG_MENU_LABEL:
413 case CHILD_ARG_POSITION:
421 gtk_notebook_get_child_arg (GtkContainer *container,
426 GtkNotebook *notebook;
427 GtkNotebookPage *page = NULL;
430 notebook = GTK_NOTEBOOK (container);
432 for (list = notebook->children; list; list = list->next)
435 if (page->child == child)
440 arg->type = GTK_TYPE_INVALID;
446 case CHILD_ARG_TAB_LABEL:
447 if (page->default_tab)
448 GTK_VALUE_STRING (*arg) = NULL;
451 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
452 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->tab_label)->label);
454 GTK_VALUE_STRING (*arg) = NULL;
457 case CHILD_ARG_MENU_LABEL:
459 case CHILD_ARG_POSITION:
462 arg->type = GTK_TYPE_INVALID;
468 gtk_notebook_child_type (GtkContainer *container)
470 return GTK_TYPE_WIDGET;
474 gtk_notebook_init (GtkNotebook *notebook)
476 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
478 notebook->cur_page = NULL;
479 notebook->children = NULL;
480 notebook->first_tab = NULL;
481 notebook->focus_tab = NULL;
482 notebook->panel = NULL;
483 notebook->menu = NULL;
485 notebook->tab_border = 3;
486 notebook->show_tabs = TRUE;
487 notebook->show_border = TRUE;
488 notebook->tab_pos = GTK_POS_TOP;
489 notebook->scrollable = FALSE;
490 notebook->in_child = 0;
491 notebook->click_child = 0;
492 notebook->button = 0;
493 notebook->need_timer = 0;
494 notebook->child_has_focus = FALSE;
498 gtk_notebook_new (void)
500 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
504 gtk_notebook_destroy (GtkObject *object)
506 GtkNotebook *notebook;
508 g_return_if_fail (object != NULL);
509 g_return_if_fail (GTK_IS_NOTEBOOK (object));
511 notebook = GTK_NOTEBOOK (object);
514 gtk_notebook_popup_disable (notebook);
516 GTK_OBJECT_CLASS (parent_class)->destroy (object);
520 gtk_notebook_append_page (GtkNotebook *notebook,
522 GtkWidget *tab_label)
524 g_return_if_fail (notebook != NULL);
525 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
526 g_return_if_fail (child != NULL);
528 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
532 gtk_notebook_append_page_menu (GtkNotebook *notebook,
534 GtkWidget *tab_label,
535 GtkWidget *menu_label)
537 g_return_if_fail (notebook != NULL);
538 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
539 g_return_if_fail (child != NULL);
541 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
545 gtk_notebook_prepend_page (GtkNotebook *notebook,
547 GtkWidget *tab_label)
549 g_return_if_fail (notebook != NULL);
550 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
551 g_return_if_fail (child != NULL);
553 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
557 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
559 GtkWidget *tab_label,
560 GtkWidget *menu_label)
562 g_return_if_fail (notebook != NULL);
563 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
564 g_return_if_fail (child != NULL);
566 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
570 gtk_notebook_insert_page (GtkNotebook *notebook,
572 GtkWidget *tab_label,
575 g_return_if_fail (notebook != NULL);
576 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
577 g_return_if_fail (child != NULL);
579 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
583 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
585 GtkWidget *tab_label,
586 GtkWidget *menu_label,
589 GtkNotebookPage *page;
592 g_return_if_fail (notebook != NULL);
593 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
594 g_return_if_fail (child != NULL);
596 page = g_new (GtkNotebookPage, 1);
598 page->requisition.width = 0;
599 page->requisition.height = 0;
600 page->allocation.x = 0;
601 page->allocation.y = 0;
602 page->allocation.width = 0;
603 page->allocation.height = 0;
604 page->default_menu = FALSE;
605 page->default_tab = FALSE;
607 nchildren = g_list_length (notebook->children);
608 if ((position < 0) || (position > nchildren))
609 position = nchildren;
611 notebook->children = g_list_insert (notebook->children, page, position);
615 page->default_tab = TRUE;
616 if (notebook->show_tabs)
617 tab_label = gtk_label_new ("");
619 page->tab_label = tab_label;
620 page->menu_label = menu_label;
623 page->default_menu = TRUE;
626 gtk_widget_ref (page->menu_label);
627 gtk_object_sink (GTK_OBJECT(page->menu_label));
631 gtk_notebook_menu_item_create (notebook, page, position);
633 gtk_notebook_update_labels
634 (notebook, g_list_nth (notebook->children, position), position + 1);
636 if (!notebook->first_tab)
637 notebook->first_tab = notebook->children;
639 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
642 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
643 gtk_widget_show (tab_label);
646 if (!notebook->cur_page)
648 gtk_notebook_switch_page (notebook, page, 0);
649 notebook->focus_tab = NULL;
652 if (GTK_WIDGET_VISIBLE (notebook))
654 if (GTK_WIDGET_REALIZED (notebook) &&
655 !GTK_WIDGET_REALIZED (child))
656 gtk_widget_realize (child);
658 if (GTK_WIDGET_MAPPED (notebook) &&
659 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
660 gtk_widget_map (child);
664 if (GTK_WIDGET_REALIZED (notebook) &&
665 !GTK_WIDGET_REALIZED (tab_label))
666 gtk_widget_realize (tab_label);
668 if (GTK_WIDGET_MAPPED (notebook) &&
669 !GTK_WIDGET_MAPPED (tab_label))
670 gtk_widget_map (tab_label);
674 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
675 gtk_widget_queue_resize (child);
679 gtk_notebook_remove_page (GtkNotebook *notebook,
684 g_return_if_fail (notebook != NULL);
685 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
689 list = g_list_nth (notebook->children, page_num);
691 gtk_notebook_real_remove (notebook, list, page_num);
695 list = g_list_last (notebook->children);
697 gtk_notebook_real_remove (notebook, list,
698 g_list_index (notebook->children, list->data));
703 gtk_notebook_add (GtkContainer *container,
706 g_return_if_fail (container != NULL);
707 g_return_if_fail (GTK_IS_NOTEBOOK (container));
708 g_return_if_fail (widget != NULL);
710 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
715 gtk_notebook_remove (GtkContainer *container,
718 GtkNotebook *notebook;
719 GtkNotebookPage *page;
723 g_return_if_fail (container != NULL);
724 g_return_if_fail (GTK_IS_NOTEBOOK (container));
725 g_return_if_fail (widget != NULL);
727 notebook = GTK_NOTEBOOK (container);
729 children = notebook->children;
733 page = children->data;
734 if (page->child == widget)
736 gtk_notebook_real_remove (notebook, children, page_num);
740 children = children->next;
745 gtk_notebook_real_remove (GtkNotebook *notebook,
749 GtkNotebookPage *page;
751 gint need_resize = FALSE;
755 next_list = list->prev;
760 next_list = list->next;
766 if (notebook->cur_page == list->data)
768 notebook->cur_page = NULL;
771 page = next_list->data;
772 gtk_notebook_switch_page (notebook, page, page_num);
776 if (list == notebook->first_tab)
777 notebook->first_tab = next_list;
778 if (list == notebook->focus_tab)
779 notebook->focus_tab = next_list;
783 if ((GTK_WIDGET_VISIBLE (page->child) ||
784 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
785 && GTK_WIDGET_VISIBLE (notebook))
788 gtk_widget_unparent (page->child);
791 gtk_widget_unparent (page->tab_label);
795 gtk_container_remove (GTK_CONTAINER (notebook->menu),
796 page->menu_label->parent);
797 gtk_widget_queue_resize (notebook->menu);
799 if (!page->default_menu)
800 gtk_widget_unref (page->menu_label);
802 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
804 notebook->children = g_list_remove_link (notebook->children, list);
809 gtk_widget_queue_resize (GTK_WIDGET (notebook));
814 gtk_notebook_current_page (GtkNotebook *notebook)
819 g_return_val_if_fail (notebook != NULL, -1);
820 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
822 if (notebook->cur_page)
825 children = notebook->children;
829 if (children->data == notebook->cur_page)
831 children = children->next;
847 gtk_notebook_set_page (GtkNotebook *notebook,
852 g_return_if_fail (notebook != NULL);
853 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
857 list = g_list_nth (notebook->children, page_num);
859 gtk_notebook_switch_page (notebook, list->data, page_num);
863 list = g_list_last (notebook->children);
865 gtk_notebook_switch_page (notebook, list->data,
866 g_list_index (notebook->children, list->data));
871 gtk_notebook_next_page (GtkNotebook *notebook)
873 GtkNotebookPage *page;
877 g_return_if_fail (notebook != NULL);
878 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
880 children = notebook->children;
884 if (notebook->cur_page == children->data)
886 children = children->next;
895 children = children->next;
900 children = notebook->children;
904 page = children->data;
905 gtk_notebook_switch_page (notebook, page, num);
909 gtk_notebook_prev_page (GtkNotebook *notebook)
911 GtkNotebookPage *page;
915 g_return_if_fail (notebook != NULL);
916 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
918 children = notebook->children;
922 if (notebook->cur_page == children->data)
924 children = children->next;
933 children = children->prev;
938 while (children->next)
940 children = children->next;
945 page = children->data;
946 gtk_notebook_switch_page (notebook, page, num);
950 gtk_notebook_foreach (GtkContainer *container,
951 GtkCallback callback,
952 gpointer callback_data)
954 GtkNotebook *notebook;
955 GtkNotebookPage *page;
958 g_return_if_fail (container != NULL);
959 g_return_if_fail (GTK_IS_NOTEBOOK (container));
960 g_return_if_fail (callback != NULL);
962 notebook = GTK_NOTEBOOK (container);
964 children = notebook->children;
967 page = children->data;
968 children = children->next;
969 (* callback) (page->child, callback_data);
974 gtk_notebook_expose_tabs (GtkNotebook *notebook)
977 GtkNotebookPage *page;
978 GdkEventExpose event;
981 widget = GTK_WIDGET (notebook);
982 border = GTK_CONTAINER (notebook)->border_width;
984 page = notebook->first_tab->data;
986 event.type = GDK_EXPOSE;
987 event.window = widget->window;
989 event.area.x = border;
990 event.area.y = border;
992 switch (notebook->tab_pos)
995 event.area.y = widget->allocation.height - border
996 - page->allocation.height - widget->style->klass->ythickness;
997 if (notebook->first_tab->data != notebook->cur_page)
998 event.area.y -= widget->style->klass->ythickness;
1000 event.area.width = widget->allocation.width - 2 * border;
1001 event.area.height = page->allocation.height
1002 + widget->style->klass->ythickness;
1003 if (notebook->first_tab->data != notebook->cur_page)
1004 event.area.height += widget->style->klass->ythickness;
1007 event.area.x = widget->allocation.width - border
1008 - page->allocation.width - widget->style->klass->xthickness;
1009 if (notebook->first_tab->data != notebook->cur_page)
1010 event.area.x -= widget->style->klass->xthickness;
1012 event.area.width = page->allocation.width
1013 + widget->style->klass->xthickness;
1014 event.area.height = widget->allocation.height - 2 * border;
1015 if (notebook->first_tab->data != notebook->cur_page)
1016 event.area.width += widget->style->klass->xthickness;
1019 gtk_widget_event (widget, (GdkEvent *) &event);
1023 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
1024 GtkPositionType pos)
1026 g_return_if_fail (notebook != NULL);
1027 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1029 if (notebook->tab_pos != pos)
1031 notebook->tab_pos = pos;
1033 if (GTK_WIDGET_VISIBLE (notebook))
1035 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1036 if (notebook->panel)
1037 gdk_window_clear (notebook->panel);
1043 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
1046 GtkNotebookPage *page;
1049 g_return_if_fail (notebook != NULL);
1050 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1052 if (notebook->show_tabs == show_tabs)
1055 notebook->show_tabs = show_tabs;
1056 children = notebook->children;
1060 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
1064 page = children->data;
1065 children = children->next;
1066 if (page->default_tab)
1068 gtk_widget_destroy (page->tab_label);
1069 page->tab_label = NULL;
1072 gtk_widget_hide (page->tab_label);
1075 if (notebook->panel)
1076 gdk_window_hide (notebook->panel);
1083 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
1087 page = children->data;
1088 children = children->next;
1089 if (page->default_tab)
1091 sprintf (string, "Page %d", i);
1092 page->tab_label = gtk_label_new (string);
1093 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
1095 gtk_widget_show (page->tab_label);
1099 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1103 gtk_notebook_set_show_border (GtkNotebook *notebook,
1106 g_return_if_fail (notebook != NULL);
1107 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1109 if (notebook->show_border != show_border)
1111 notebook->show_border = show_border;
1113 if (GTK_WIDGET_VISIBLE (notebook))
1114 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1119 gtk_notebook_set_scrollable (GtkNotebook *notebook,
1122 g_return_if_fail (notebook != NULL);
1123 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1125 if (scrollable != notebook->scrollable)
1127 if ( (notebook->scrollable = (scrollable != 0)) )
1128 gtk_notebook_panel_realize (notebook);
1129 else if (notebook->panel)
1131 gdk_window_destroy (notebook->panel);
1132 notebook->panel = NULL;
1134 gtk_widget_queue_resize (GTK_WIDGET(notebook));
1139 gtk_notebook_map (GtkWidget *widget)
1141 GtkNotebook *notebook;
1142 GtkNotebookPage *page;
1145 g_return_if_fail (widget != NULL);
1146 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1148 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1149 gdk_window_show (widget->window);
1151 notebook = GTK_NOTEBOOK (widget);
1153 if (notebook->cur_page &&
1154 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1155 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1156 gtk_widget_map (notebook->cur_page->child);
1158 if (notebook->scrollable)
1159 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
1162 children = notebook->children;
1166 page = children->data;
1167 children = children->next;
1169 if (page->tab_label &&
1170 GTK_WIDGET_VISIBLE (page->child) &&
1171 !GTK_WIDGET_MAPPED (page->tab_label))
1172 gtk_widget_map (page->tab_label);
1178 gtk_notebook_unmap (GtkWidget *widget)
1180 g_return_if_fail (widget != NULL);
1181 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1183 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1184 gdk_window_hide (widget->window);
1185 if (GTK_NOTEBOOK (widget)->panel)
1186 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
1190 gtk_notebook_realize (GtkWidget *widget)
1192 GtkNotebook *notebook;
1193 GdkWindowAttr attributes;
1194 gint attributes_mask;
1196 g_return_if_fail (widget != NULL);
1197 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1199 notebook = GTK_NOTEBOOK (widget);
1200 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1202 attributes.window_type = GDK_WINDOW_CHILD;
1203 attributes.x = widget->allocation.x;
1204 attributes.y = widget->allocation.y;
1205 attributes.width = widget->allocation.width;
1206 attributes.height = widget->allocation.height;
1207 attributes.wclass = GDK_INPUT_OUTPUT;
1208 attributes.visual = gtk_widget_get_visual (widget);
1209 attributes.colormap = gtk_widget_get_colormap (widget);
1210 attributes.event_mask = gtk_widget_get_events (widget);
1211 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1212 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
1214 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1216 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1217 gdk_window_set_user_data (widget->window, notebook);
1219 widget->style = gtk_style_attach (widget->style, widget->window);
1220 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1222 if (notebook->scrollable)
1223 gtk_notebook_panel_realize (notebook);
1227 gtk_notebook_panel_realize (GtkNotebook *notebook)
1230 GdkWindowAttr attributes;
1231 gint attributes_mask;
1233 g_return_if_fail (notebook != NULL);
1234 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1236 widget = GTK_WIDGET (notebook);
1238 attributes.window_type = GDK_WINDOW_CHILD;
1239 attributes.wclass = GDK_INPUT_OUTPUT;
1240 attributes.visual = gtk_widget_get_visual (widget);
1241 attributes.colormap = gtk_widget_get_colormap (widget);
1242 attributes.event_mask = gtk_widget_get_events (widget);
1243 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1244 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1245 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1247 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1249 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1250 attributes.height = ARROW_SIZE;
1252 attributes.x = widget->allocation.width - attributes.width -
1253 GTK_CONTAINER (notebook)->border_width;
1254 attributes.y = widget->allocation.height - ARROW_SIZE -
1255 GTK_CONTAINER (notebook)->border_width;
1256 if (notebook->tab_pos == GTK_POS_TOP)
1257 attributes.y = GTK_CONTAINER (notebook)->border_width;
1258 else if (notebook->tab_pos == GTK_POS_LEFT)
1259 attributes.x = widget->allocation.x
1260 + GTK_CONTAINER (notebook)->border_width;
1263 notebook->panel = gdk_window_new (widget->window, &attributes,
1265 gtk_style_set_background (widget->style, notebook->panel,
1267 gdk_window_set_user_data (notebook->panel, widget);
1271 gtk_notebook_size_request (GtkWidget *widget,
1272 GtkRequisition *requisition)
1274 GtkNotebook *notebook;
1275 GtkNotebookPage *page;
1278 g_return_if_fail (widget != NULL);
1279 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1280 g_return_if_fail (requisition != NULL);
1282 notebook = GTK_NOTEBOOK (widget);
1283 widget->requisition.width = 0;
1284 widget->requisition.height = 0;
1286 children = notebook->children;
1289 page = children->data;
1290 children = children->next;
1292 if (GTK_WIDGET_VISIBLE (page->child))
1294 gtk_widget_size_request (page->child, &page->child->requisition);
1296 widget->requisition.width = MAX (widget->requisition.width,
1297 page->child->requisition.width);
1298 widget->requisition.height = MAX (widget->requisition.height,
1299 page->child->requisition.height);
1303 if (notebook->show_border || notebook->show_tabs)
1305 widget->requisition.width += widget->style->klass->xthickness * 2;
1306 widget->requisition.height += widget->style->klass->ythickness * 2;
1308 if (notebook->show_tabs)
1311 gint tab_height = 0;
1314 children = notebook->children;
1317 page = children->data;
1318 children = children->next;
1320 if (GTK_WIDGET_VISIBLE (page->child))
1322 gtk_widget_size_request (page->tab_label,
1323 &page->tab_label->requisition);
1325 page->requisition.width =
1326 (page->tab_label->requisition.width +
1327 (widget->style->klass->xthickness + notebook->tab_border)
1329 page->requisition.height =
1330 (page->tab_label->requisition.height +
1331 (widget->style->klass->ythickness + notebook->tab_border)
1334 switch (notebook->tab_pos)
1337 case GTK_POS_BOTTOM:
1338 page->requisition.width -= TAB_OVERLAP;
1340 tab_width += page->requisition.width;
1341 tab_height = MAX (tab_height, page->requisition.height);
1342 tab_max = MAX (tab_max, page->requisition.width);
1346 page->requisition.height -= TAB_OVERLAP;
1348 tab_width = MAX (tab_width, page->requisition.width);
1349 tab_height += page->requisition.height;
1350 tab_max = MAX (tab_max, page->requisition.height);
1356 children = notebook->children;
1358 if (children && children->next && notebook->scrollable)
1360 if ((notebook->tab_pos == GTK_POS_TOP) ||
1361 (notebook->tab_pos == GTK_POS_BOTTOM))
1363 if (widget->requisition.width < tab_width)
1365 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1366 tab_height = MAX (tab_height, ARROW_SIZE);
1371 if (widget->requisition.height < tab_height)
1373 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1374 tab_width = MAX (tab_width,
1375 ARROW_SPACING + 2 * ARROW_SIZE);
1382 page = children->data;
1383 children = children->next;
1385 if (GTK_WIDGET_VISIBLE (page->child))
1387 if ((notebook->tab_pos == GTK_POS_TOP) ||
1388 (notebook->tab_pos == GTK_POS_BOTTOM))
1389 page->requisition.height = tab_height;
1391 page->requisition.width = tab_width;
1395 switch (notebook->tab_pos)
1398 case GTK_POS_BOTTOM:
1399 tab_width += widget->style->klass->xthickness;
1400 widget->requisition.width = MAX (widget->requisition.width,
1402 widget->requisition.height += tab_height;
1406 tab_height += widget->style->klass->ythickness;
1407 widget->requisition.width += tab_width;
1408 widget->requisition.height = MAX (widget->requisition.height,
1414 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1415 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1419 gtk_notebook_size_allocate (GtkWidget *widget,
1420 GtkAllocation *allocation)
1422 GtkNotebook *notebook;
1423 GtkNotebookPage *page;
1424 GtkAllocation child_allocation;
1427 g_return_if_fail (widget != NULL);
1428 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1429 g_return_if_fail (allocation != NULL);
1431 widget->allocation = *allocation;
1432 if (GTK_WIDGET_REALIZED (widget))
1433 gdk_window_move_resize (widget->window,
1434 allocation->x, allocation->y,
1435 allocation->width, allocation->height);
1437 notebook = GTK_NOTEBOOK (widget);
1438 if (notebook->children)
1440 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1441 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1442 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1443 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1445 if (notebook->show_tabs || notebook->show_border)
1447 child_allocation.x += widget->style->klass->xthickness;
1448 child_allocation.y += widget->style->klass->ythickness;
1449 child_allocation.width = MAX (1,
1450 child_allocation.width - widget->style->klass->xthickness * 2);
1451 child_allocation.height = MAX (1,
1452 child_allocation.height - widget->style->klass->ythickness * 2);
1454 if (notebook->show_tabs && notebook->children)
1456 switch (notebook->tab_pos)
1459 child_allocation.y += notebook->cur_page->requisition.height;
1460 case GTK_POS_BOTTOM:
1461 child_allocation.height = MAX (1,
1462 child_allocation.height - notebook->cur_page->requisition.height);
1465 child_allocation.x += notebook->cur_page->requisition.width;
1467 child_allocation.width = MAX (1,
1468 child_allocation.width - notebook->cur_page->requisition.width);
1474 children = notebook->children;
1477 page = children->data;
1478 children = children->next;
1480 if (GTK_WIDGET_VISIBLE (page->child))
1481 gtk_widget_size_allocate (page->child, &child_allocation);
1484 gtk_notebook_pages_allocate (notebook, allocation);
1489 gtk_notebook_paint (GtkWidget *widget,
1492 GtkNotebook *notebook;
1493 GtkNotebookPage *page;
1500 g_return_if_fail (widget != NULL);
1501 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1502 g_return_if_fail (area != NULL);
1504 if (GTK_WIDGET_DRAWABLE (widget))
1506 notebook = GTK_NOTEBOOK (widget);
1508 gdk_window_clear_area (widget->window,
1510 area->width, area->height);
1512 if (notebook->show_tabs || notebook->show_border)
1514 x = GTK_CONTAINER (widget)->border_width;
1515 y = GTK_CONTAINER (widget)->border_width;
1516 width = widget->allocation.width - x * 2;
1517 height = widget->allocation.height - y * 2;
1519 if (notebook->show_tabs && notebook->children)
1522 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1524 GtkNotebookPage *page;
1526 page = notebook->first_tab->data;
1528 switch (notebook->tab_pos)
1531 y += page->allocation.height +
1532 widget->style->klass->ythickness;
1533 case GTK_POS_BOTTOM:
1534 height -= page->allocation.height +
1535 widget->style->klass->ythickness;
1538 x += page->allocation.width +
1539 widget->style->klass->xthickness;
1541 width -= page->allocation.width +
1542 widget->style->klass->xthickness;
1545 gtk_draw_shadow (widget->style, widget->window,
1546 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1547 x, y, width, height);
1551 switch (notebook->tab_pos)
1554 y += notebook->cur_page->allocation.height;
1555 case GTK_POS_BOTTOM:
1556 height -= notebook->cur_page->allocation.height;
1559 x += notebook->cur_page->allocation.width;
1561 width -= notebook->cur_page->allocation.width;
1565 switch (notebook->tab_pos)
1568 points[0].x = notebook->cur_page->allocation.x;
1573 points[2].y = y + height - 1;
1574 points[3].x = x + width - 1;
1575 points[3].y = y + height - 1;
1576 points[4].x = x + width - 1;
1578 points[5].x = (notebook->cur_page->allocation.x +
1579 notebook->cur_page->allocation.width -
1580 widget->style->klass->xthickness);
1583 if (points[5].x == (x + width))
1586 case GTK_POS_BOTTOM:
1587 points[0].x = (notebook->cur_page->allocation.x +
1588 notebook->cur_page->allocation.width -
1589 widget->style->klass->xthickness);
1590 points[0].y = y + height - 1;
1591 points[1].x = x + width - 1;
1592 points[1].y = y + height - 1;
1593 points[2].x = x + width - 1;
1598 points[4].y = y + height - 1;
1599 points[5].x = notebook->cur_page->allocation.x;
1600 points[5].y = y + height - 1;
1602 if (points[0].x == (x + width))
1607 points[0].y = (notebook->cur_page->allocation.y +
1608 notebook->cur_page->allocation.height -
1609 widget->style->klass->ythickness);
1611 points[1].y = y + height - 1;
1612 points[2].x = x + width - 1;
1613 points[2].y = y + height - 1;
1614 points[3].x = x + width - 1;
1619 points[5].y = notebook->cur_page->allocation.y;
1621 if (points[0].y == (y + height))
1625 points[0].x = x + width - 1;
1626 points[0].y = notebook->cur_page->allocation.y;
1627 points[1].x = x + width - 1;
1632 points[3].y = y + height - 1;
1633 points[4].x = x + width - 1;
1634 points[4].y = y + height - 1;
1635 points[5].x = x + width - 1;
1636 points[5].y = (notebook->cur_page->allocation.y +
1637 notebook->cur_page->allocation.height -
1638 widget->style->klass->ythickness);
1640 if (points[5].y == (y + height))
1645 gtk_draw_polygon (widget->style, widget->window,
1646 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1649 children = g_list_last (notebook->children);
1654 page = children->data;
1655 children = children->prev;
1657 if (!GTK_WIDGET_MAPPED (page->tab_label))
1659 else if (notebook->cur_page != page)
1660 gtk_notebook_draw_tab (notebook, page, area);
1663 if (showarrow && notebook->scrollable && notebook->show_tabs)
1665 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1666 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1668 if (notebook->cur_page &&
1669 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1670 (notebook->cur_page))->tab_label))
1671 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1673 else if (notebook->show_border)
1675 gtk_draw_shadow (widget->style, widget->window,
1676 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1677 x, y, width, height);
1684 gtk_notebook_draw (GtkWidget *widget,
1687 GtkNotebook *notebook;
1688 GdkRectangle child_area;
1690 g_return_if_fail (widget != NULL);
1691 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1692 g_return_if_fail (area != NULL);
1694 if (GTK_WIDGET_DRAWABLE (widget))
1696 notebook = GTK_NOTEBOOK (widget);
1698 gtk_notebook_paint (widget, area);
1699 gtk_widget_draw_focus (widget);
1701 if (notebook->cur_page &&
1702 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1703 gtk_widget_draw (notebook->cur_page->child, &child_area);
1708 gtk_notebook_expose (GtkWidget *widget,
1709 GdkEventExpose *event)
1711 GtkNotebook *notebook;
1712 GdkEventExpose child_event;
1714 g_return_val_if_fail (widget != NULL, FALSE);
1715 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1716 g_return_val_if_fail (event != NULL, FALSE);
1718 if (GTK_WIDGET_DRAWABLE (widget))
1720 notebook = GTK_NOTEBOOK (widget);
1722 gtk_notebook_paint (widget, &event->area);
1723 gtk_widget_draw_focus (widget);
1725 child_event = *event;
1726 if (notebook->cur_page &&
1727 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1728 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1730 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1737 gtk_notebook_button_press (GtkWidget *widget,
1738 GdkEventButton *event)
1740 GtkNotebook *notebook;
1741 GtkNotebookPage *page;
1745 g_return_val_if_fail (widget != NULL, FALSE);
1746 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1747 g_return_val_if_fail (event != NULL, FALSE);
1749 notebook = GTK_NOTEBOOK (widget);
1751 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1752 || notebook->button)
1755 if (event->window == notebook->panel)
1757 if (!GTK_WIDGET_HAS_FOCUS (widget))
1758 gtk_widget_grab_focus (widget);
1760 gtk_grab_add (widget);
1761 notebook->button = event->button;
1763 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1765 notebook->click_child = GTK_ARROW_LEFT;
1766 if (event->button == 1)
1768 if (!notebook->focus_tab || notebook->focus_tab->prev)
1769 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1771 if (!notebook->timer)
1773 notebook->timer = gtk_timeout_add
1774 (NOTEBOOK_INIT_SCROLL_DELAY,
1775 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1776 notebook->need_timer = TRUE;
1779 else if (event->button == 2)
1780 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1781 else if (event->button == 3)
1782 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1783 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1787 notebook->click_child = GTK_ARROW_RIGHT;
1788 if (event->button == 1)
1790 if (!notebook->focus_tab || notebook->focus_tab->next)
1791 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1792 if (!notebook->timer)
1794 notebook->timer = gtk_timeout_add
1795 (NOTEBOOK_INIT_SCROLL_DELAY,
1796 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1797 notebook->need_timer = TRUE;
1800 else if (event->button == 2)
1801 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1802 else if (event->button == 3)
1803 gtk_notebook_switch_focus_tab (notebook,
1804 g_list_last (notebook->children));
1805 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1808 else if (event->window == widget->window)
1810 if (event->button == 3 && notebook->menu)
1812 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1813 NULL, NULL, 3, event->time);
1818 children = notebook->children;
1821 page = children->data;
1823 if (GTK_WIDGET_VISIBLE (page->child) &&
1824 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1825 (event->x >= page->allocation.x) &&
1826 (event->y >= page->allocation.y) &&
1827 (event->x <= (page->allocation.x + page->allocation.width)) &&
1828 (event->y <= (page->allocation.y + page->allocation.height)))
1830 if (page == notebook->cur_page && notebook->focus_tab &&
1831 notebook->focus_tab != children &&
1832 GTK_WIDGET_HAS_FOCUS (notebook))
1834 GtkNotebookPage *old_page;
1836 notebook->child_has_focus = FALSE;
1837 old_page = (GtkNotebookPage *)
1838 (notebook->focus_tab->data);
1839 notebook->focus_tab = children;
1840 gtk_notebook_focus_changed (notebook, old_page);
1844 notebook->focus_tab = children;
1845 gtk_notebook_switch_page (notebook, page, num);
1846 gtk_widget_grab_focus (widget);
1850 children = children->next;
1853 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1854 gtk_widget_grab_focus (widget);
1860 gtk_notebook_button_release (GtkWidget *widget,
1861 GdkEventButton *event)
1863 GtkNotebook *notebook;
1865 g_return_val_if_fail (widget != NULL, FALSE);
1866 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1867 g_return_val_if_fail (event != NULL, FALSE);
1869 if (event->type != GDK_BUTTON_RELEASE)
1872 notebook = GTK_NOTEBOOK (widget);
1874 if (event->button == notebook->button)
1878 if (notebook->timer)
1880 gtk_timeout_remove (notebook->timer);
1881 notebook->timer = 0;
1882 notebook->need_timer = FALSE;
1884 gtk_grab_remove (widget);
1885 click_child = notebook->click_child;
1886 notebook->click_child = 0;
1887 notebook->button = 0;
1888 gtk_notebook_draw_arrow (notebook, click_child);
1895 gtk_notebook_enter_notify (GtkWidget *widget,
1896 GdkEventCrossing *event)
1898 GtkNotebook *notebook;
1900 g_return_val_if_fail (widget != NULL, FALSE);
1901 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1902 g_return_val_if_fail (event != NULL, FALSE);
1904 notebook = GTK_NOTEBOOK (widget);
1906 if (event->window == notebook->panel)
1911 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1913 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1915 notebook->in_child = GTK_ARROW_LEFT;
1917 if (notebook->click_child == 0)
1918 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1922 notebook->in_child = GTK_ARROW_RIGHT;
1924 if (notebook->click_child == 0)
1925 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1933 gtk_notebook_leave_notify (GtkWidget *widget,
1934 GdkEventCrossing *event)
1936 GtkNotebook *notebook;
1938 g_return_val_if_fail (widget != NULL, FALSE);
1939 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1940 g_return_val_if_fail (event != NULL, FALSE);
1942 notebook = GTK_NOTEBOOK (widget);
1944 if (event->window == notebook->panel && !notebook->click_child)
1946 if (notebook->in_child == GTK_ARROW_LEFT)
1948 notebook->in_child = 0;
1949 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1953 notebook->in_child = 0;
1954 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1961 gtk_notebook_motion_notify (GtkWidget *widget,
1962 GdkEventMotion *event)
1964 GtkNotebook *notebook;
1966 g_return_val_if_fail (widget != NULL, FALSE);
1967 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1968 g_return_val_if_fail (event != NULL, FALSE);
1970 notebook = GTK_NOTEBOOK (widget);
1972 if (notebook->button)
1975 if (event->window == notebook->panel)
1981 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1983 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
1984 notebook->in_child == GTK_ARROW_RIGHT)
1986 notebook->in_child = GTK_ARROW_LEFT;
1987 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1988 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1990 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
1991 notebook->in_child == GTK_ARROW_LEFT)
1993 notebook->in_child = GTK_ARROW_RIGHT;
1994 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1995 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2003 gtk_notebook_timer (GtkNotebook *notebook)
2005 g_return_val_if_fail (notebook != NULL, FALSE);
2006 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2008 if (notebook->timer)
2010 if (notebook->click_child == GTK_ARROW_LEFT)
2012 if (!notebook->focus_tab || notebook->focus_tab->prev)
2013 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
2015 else if (notebook->click_child == GTK_ARROW_RIGHT)
2017 if (!notebook->focus_tab || notebook->focus_tab->next)
2018 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
2021 if (notebook->need_timer)
2023 notebook->need_timer = FALSE;
2024 notebook->timer = gtk_timeout_add
2025 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
2026 (gpointer) notebook);
2035 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
2037 GtkStateType state_type;
2038 GtkShadowType shadow_type;
2041 g_return_if_fail (notebook != NULL);
2042 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2044 widget = GTK_WIDGET(notebook);
2046 if (GTK_WIDGET_DRAWABLE (notebook))
2048 if (notebook->in_child == arrow)
2050 if (notebook->click_child == arrow)
2051 state_type = GTK_STATE_ACTIVE;
2053 state_type = GTK_STATE_PRELIGHT;
2056 state_type = GTK_STATE_NORMAL;
2058 if (notebook->click_child == arrow)
2059 shadow_type = GTK_SHADOW_IN;
2061 shadow_type = GTK_SHADOW_OUT;
2063 if (arrow == GTK_ARROW_LEFT)
2065 if (notebook->tab_pos == GTK_POS_LEFT ||
2066 notebook->tab_pos == GTK_POS_RIGHT)
2067 arrow = GTK_ARROW_UP;
2068 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2069 shadow_type, arrow, TRUE,
2070 0, 0, ARROW_SIZE, ARROW_SIZE);
2074 if (notebook->tab_pos == GTK_POS_LEFT ||
2075 notebook->tab_pos == GTK_POS_RIGHT)
2076 arrow = GTK_ARROW_DOWN;
2077 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2078 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2079 0, ARROW_SIZE, ARROW_SIZE);
2085 gtk_real_notebook_switch_page (GtkNotebook *notebook,
2086 GtkNotebookPage *page,
2089 g_return_if_fail (notebook != NULL);
2090 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2091 g_return_if_fail (page != NULL);
2093 if (notebook->cur_page == page)
2096 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
2097 gtk_widget_unmap (notebook->cur_page->child);
2099 notebook->cur_page = page;
2101 if (!notebook->focus_tab ||
2102 notebook->focus_tab->data != (gpointer) notebook->cur_page)
2103 notebook->focus_tab =
2104 g_list_find (notebook->children, notebook->cur_page);
2106 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
2108 if (GTK_WIDGET_MAPPED (notebook))
2110 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
2111 gtk_widget_map (notebook->cur_page->child);
2114 gtk_widget_map (notebook->cur_page->child);
2115 gtk_widget_size_allocate (GTK_WIDGET (notebook),
2116 >K_WIDGET (notebook)->allocation);
2120 if (GTK_WIDGET_DRAWABLE (notebook))
2121 gtk_widget_queue_draw (GTK_WIDGET (notebook));
2125 gtk_notebook_draw_tab (GtkNotebook *notebook,
2126 GtkNotebookPage *page,
2129 GdkRectangle child_area;
2130 GdkRectangle page_area;
2131 GtkStateType state_type;
2135 g_return_if_fail (notebook != NULL);
2136 g_return_if_fail (page != NULL);
2137 g_return_if_fail (area != NULL);
2139 if (!GTK_WIDGET_MAPPED (page->tab_label))
2142 page_area.x = page->allocation.x;
2143 page_area.y = page->allocation.y;
2144 page_area.width = page->allocation.width;
2145 page_area.height = page->allocation.height;
2147 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2151 switch (notebook->tab_pos)
2154 if (child_area.x + child_area.width >
2155 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2157 points[0].x = page->allocation.x + page->allocation.width - 1;
2158 points[0].y = page->allocation.y + page->allocation.height - 1;
2160 points[1].x = page->allocation.x + page->allocation.width - 1;
2161 points[1].y = page->allocation.y + TAB_CURVATURE;
2163 points[2].x = page->allocation.x + page->allocation.width
2164 - TAB_CURVATURE - 1;
2165 points[2].y = page->allocation.y;
2170 points[0].x = page->allocation.x + page->allocation.width
2172 points[0].y = page->allocation.y;
2176 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2177 (page == notebook->cur_page ||
2178 page == (GtkNotebookPage *)(notebook->children->data) ||
2179 (notebook->scrollable &&
2180 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2182 points[n].x = page->allocation.x + TAB_CURVATURE;
2183 points[n++].y = page->allocation.y;
2185 points[n].x = page->allocation.x;
2186 points[n++].y = page->allocation.y + TAB_CURVATURE;
2188 points[n].x = page->allocation.x;
2189 points[n++].y = page->allocation.y + page->allocation.height - 1;
2193 points[n].x = page->allocation.x + TAB_OVERLAP;
2194 points[n++].y = page->allocation.y;
2197 case GTK_POS_BOTTOM:
2198 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2199 (page == notebook->cur_page ||
2200 page == (GtkNotebookPage *)(notebook->children->data) ||
2201 (notebook->scrollable &&
2202 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2204 points[0].x = page->allocation.x;
2205 points[0].y = page->allocation.y;
2207 points[1].x = page->allocation.x;
2208 points[1].y = page->allocation.y + page->allocation.height
2209 - TAB_CURVATURE - 1;
2211 points[2].x = page->allocation.x + TAB_CURVATURE;
2212 points[2].y = page->allocation.y + page->allocation.height - 1;
2217 points[0].x = page->allocation.x + TAB_OVERLAP;
2218 points[0].y = page->allocation.y + page->allocation.height - 1;
2222 if (child_area.x + child_area.width >
2223 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2225 points[n].x = page->allocation.x + page->allocation.width
2226 - TAB_CURVATURE - 1;
2227 points[n++].y = page->allocation.y + page->allocation.height - 1;
2229 points[n].x = page->allocation.x + page->allocation.width - 1;
2230 points[n++].y = page->allocation.y + page->allocation.height
2231 - TAB_CURVATURE - 1;
2233 points[n].x = page->allocation.x + page->allocation.width - 1;
2234 points[n++].y = page->allocation.y;
2238 points[n].x = page->allocation.x + page->allocation.width
2240 points[n++].y = page->allocation.y + page->allocation.height - 1;
2244 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2245 (page == notebook->cur_page ||
2246 page == (GtkNotebookPage *)(notebook->children->data) ||
2247 (notebook->scrollable &&
2248 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2250 points[0].x = page->allocation.x + page->allocation.width - 1;
2251 points[0].y = page->allocation.y;
2253 points[1].x = page->allocation.x + TAB_CURVATURE;
2254 points[1].y = page->allocation.y;
2256 points[2].x = page->allocation.x;
2257 points[2].y = page->allocation.y + TAB_CURVATURE;
2262 points[0].x = page->allocation.x;
2263 points[0].y = page->allocation.y + TAB_OVERLAP;
2267 if (child_area.y + child_area.height >
2268 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2270 points[n].x = page->allocation.x;
2271 points[n++].y = page->allocation.y + page->allocation.height
2272 - TAB_CURVATURE - 1;
2274 points[n].x = page->allocation.x + TAB_CURVATURE;
2275 points[n++].y = page->allocation.y + page->allocation.height - 1;
2277 points[n].x = page->allocation.x + page->allocation.width - 1;
2278 points[n++].y = page->allocation.y + page->allocation.height - 1;
2282 points[n].x = page->allocation.x;
2283 points[n++].y = page->allocation.y + page->allocation.height
2288 if (child_area.y + child_area.height >
2289 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2291 points[0].x = page->allocation.x;
2292 points[0].y = page->allocation.y + page->allocation.height - 1;
2294 points[1].x = page->allocation.x + page->allocation.width
2295 - TAB_CURVATURE - 1;
2296 points[1].y = page->allocation.y + page->allocation.height - 1;
2298 points[2].x = page->allocation.x + page->allocation.width - 1;
2299 points[2].y = page->allocation.y + page->allocation.height
2300 - TAB_CURVATURE - 1;
2305 points[0].x = page->allocation.x + page->allocation.width - 1;
2306 points[0].y = page->allocation.y + page->allocation.height
2311 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2312 (page == notebook->cur_page ||
2313 page == (GtkNotebookPage *)(notebook->children->data) ||
2314 (notebook->scrollable &&
2315 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2317 points[n].x = page->allocation.x + page->allocation.width - 1;
2318 points[n++].y = page->allocation.y + TAB_CURVATURE;
2320 points[n].x = page->allocation.x + page->allocation.width
2321 - TAB_CURVATURE - 1;
2322 points[n++].y = page->allocation.y;
2324 points[n].x = page->allocation.x;
2325 points[n++].y = page->allocation.y;
2329 points[n].x = page->allocation.x + page->allocation.width - 1;
2330 points[n++].y = page->allocation.y + TAB_OVERLAP;
2335 widget = GTK_WIDGET(notebook);
2337 if (notebook->cur_page == page)
2339 state_type = GTK_STATE_NORMAL;
2343 state_type = GTK_STATE_ACTIVE;
2344 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2345 TRUE, child_area.x, child_area.y,
2346 child_area.width, child_area.height);
2349 gtk_draw_polygon (widget->style, widget->window, state_type,
2350 GTK_SHADOW_OUT, points, n, FALSE);
2352 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2353 gtk_widget_draw (page->tab_label, &child_area);
2358 gtk_notebook_set_focus_child (GtkContainer *container,
2361 GtkNotebook *notebook;
2363 g_return_if_fail (container != NULL);
2364 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2368 g_return_if_fail (GTK_IS_WIDGET (child));
2370 notebook = GTK_NOTEBOOK (container);
2372 notebook->child_has_focus = TRUE;
2373 if (!notebook->focus_tab)
2376 GtkNotebookPage *page;
2378 children = notebook->children;
2381 page = children->data;
2382 if (page->child == child || page->tab_label == child)
2383 notebook->focus_tab = children;
2384 children = children->next;
2388 parent_class->set_focus_child (container, child);
2392 gtk_notebook_focus_in (GtkWidget *widget,
2393 GdkEventFocus *event)
2395 g_return_val_if_fail (widget != NULL, FALSE);
2396 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2397 g_return_val_if_fail (event != NULL, FALSE);
2399 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2400 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2401 gtk_widget_draw_focus (widget);
2407 gtk_notebook_focus_out (GtkWidget *widget,
2408 GdkEventFocus *event)
2410 g_return_val_if_fail (widget != NULL, FALSE);
2411 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2412 g_return_val_if_fail (event != NULL, FALSE);
2414 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2415 gtk_widget_draw_focus (widget);
2421 gtk_notebook_draw_focus (GtkWidget *widget)
2423 GtkNotebook *notebook;
2425 g_return_if_fail (widget != NULL);
2426 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2428 notebook = GTK_NOTEBOOK (widget);
2430 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2431 notebook->focus_tab)
2433 GtkNotebookPage *page;
2436 page = notebook->focus_tab->data;
2438 if (GTK_WIDGET_HAS_FOCUS (widget))
2439 gc = widget->style->black_gc;
2440 else if (page == notebook->cur_page)
2441 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2443 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2445 gdk_draw_rectangle (widget->window,
2447 page->tab_label->allocation.x - 1,
2448 page->tab_label->allocation.y - 1,
2449 page->tab_label->allocation.width + 1,
2450 page->tab_label->allocation.height + 1);
2455 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2459 g_return_if_fail (notebook != NULL);
2460 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2462 widget = GTK_WIDGET (notebook);
2464 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs)
2468 if (notebook->focus_tab)
2470 GtkNotebookPage *page;
2472 page = notebook->focus_tab->data;
2474 if (GTK_WIDGET_HAS_FOCUS (widget))
2475 gc = widget->style->black_gc;
2476 else if (page == notebook->cur_page)
2477 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2479 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2481 gdk_draw_rectangle (widget->window,
2483 page->tab_label->allocation.x - 1,
2484 page->tab_label->allocation.y - 1,
2485 page->tab_label->allocation.width + 1,
2486 page->tab_label->allocation.height + 1);
2491 if (old_page == notebook->cur_page)
2492 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2494 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2496 gdk_draw_rectangle (widget->window,
2498 old_page->tab_label->allocation.x - 1,
2499 old_page->tab_label->allocation.y - 1,
2500 old_page->tab_label->allocation.width + 1,
2501 old_page->tab_label->allocation.height + 1);
2507 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2513 GtkNotebookPage *page = NULL;
2517 switch (notebook->tab_pos)
2520 case GTK_POS_BOTTOM:
2523 page = children->data;
2524 *tab_space -= page->requisition.width;
2525 if (*tab_space < 0 || children == *end)
2529 *tab_space = - (*tab_space + page->requisition.width);
2534 if (direction == STEP_NEXT)
2535 children = children->next;
2537 children = children->prev;
2544 page = children->data;
2545 *tab_space -= page->requisition.height;
2546 if (*tab_space < 0 || children == *end)
2550 *tab_space = - (*tab_space + page->requisition.height);
2555 if (direction == STEP_NEXT)
2556 children = children->next;
2558 children = children->prev;
2565 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2566 GtkAllocation *allocation)
2569 GtkContainer *container;
2570 GtkNotebookPage *page = NULL;
2571 GtkAllocation child_allocation;
2573 GList *last_child = NULL;
2574 gint showarrow = FALSE;
2583 if (!notebook->show_tabs || !notebook->children)
2586 widget = GTK_WIDGET (notebook);
2587 container = GTK_CONTAINER (notebook);
2589 child_allocation.x = container->border_width;
2590 child_allocation.y = container->border_width;
2592 switch (notebook->tab_pos)
2594 case GTK_POS_BOTTOM:
2595 child_allocation.y = (allocation->height -
2596 notebook->cur_page->requisition.height -
2597 container->border_width);
2599 child_allocation.height = notebook->cur_page->requisition.height;
2602 child_allocation.x = (allocation->width -
2603 notebook->cur_page->requisition.width -
2604 container->border_width);
2606 child_allocation.width = notebook->cur_page->requisition.width;
2610 if (notebook->scrollable)
2614 children = notebook->children;
2616 if (notebook->focus_tab)
2617 focus_tab = notebook->focus_tab;
2618 else if (notebook->first_tab)
2619 focus_tab = notebook->first_tab;
2621 focus_tab = notebook->children;
2623 switch (notebook->tab_pos)
2626 case GTK_POS_BOTTOM:
2629 page = children->data;
2630 children = children->next;
2631 tab_space += page->requisition.width;
2633 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2636 page = focus_tab->data;
2638 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2639 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2640 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2642 page = notebook->children->data;
2643 if (notebook->tab_pos == GTK_POS_TOP)
2644 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2646 y = (allocation->height - container->border_width -
2647 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2654 page = children->data;
2655 children = children->next;
2656 tab_space += page->requisition.height;
2658 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2661 page = focus_tab->data;
2662 tab_space = (allocation->height -
2663 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2664 2 * container->border_width - page->requisition.height);
2665 y = allocation->height - container->border_width - ARROW_SIZE;
2667 page = notebook->children->data;
2668 if (notebook->tab_pos == GTK_POS_LEFT)
2669 x = (container->border_width +
2670 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2672 x = (allocation->width - container->border_width -
2673 (2 * ARROW_SIZE - ARROW_SPACING) -
2674 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2678 if (showarrow) /* first_tab <- focus_tab */
2680 children = focus_tab->prev;
2683 if (notebook->first_tab == children)
2685 children = children->prev;
2689 notebook->first_tab = focus_tab;
2691 gtk_notebook_calc_tabs (notebook, focus_tab->prev,
2692 &(notebook->first_tab), &tab_space,
2696 notebook->first_tab = notebook->first_tab->next;
2697 if (!notebook->first_tab)
2698 notebook->first_tab = focus_tab;
2699 last_child = focus_tab->next;
2701 else /* focus_tab -> end */
2703 if (!notebook->first_tab)
2704 notebook->first_tab = notebook->children;
2707 gtk_notebook_calc_tabs (notebook, focus_tab->next,
2708 &children, &tab_space, STEP_NEXT);
2711 last_child = children;
2712 else /* start <- first_tab */
2716 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2717 &children, &tab_space, STEP_PREV);
2719 notebook->first_tab = children->next;
2721 notebook->first_tab = notebook->children;
2725 if (GTK_WIDGET_REALIZED (notebook))
2727 gdk_window_move (notebook->panel, x, y);
2728 gdk_window_show (notebook->panel);
2733 tab_space = -tab_space;
2735 children = notebook->first_tab;
2736 while (children != last_child)
2738 children = children->next;
2745 children = notebook->children;
2746 while (children != notebook->first_tab)
2748 page = children->data;
2749 children = children->next;
2751 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2752 gtk_widget_unmap (page->tab_label);
2755 children = last_child;
2758 page = children->data;
2759 children = children->next;
2761 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2762 gtk_widget_unmap (page->tab_label);
2765 else /* !showarrow */
2767 notebook->first_tab = notebook->children;
2769 if (GTK_WIDGET_REALIZED (notebook))
2770 gdk_window_hide (notebook->panel);
2772 children = notebook->first_tab;
2775 children = notebook->children;
2778 while (children != last_child)
2780 page = children->data;
2781 children = children->next;
2783 if (GTK_WIDGET_VISIBLE (page->child))
2785 new_fill = (tab_space * i++) / n;
2786 switch (notebook->tab_pos)
2789 case GTK_POS_BOTTOM:
2790 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2794 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2797 old_fill = new_fill;
2798 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2800 switch (notebook->tab_pos)
2803 case GTK_POS_BOTTOM:
2804 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2808 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2812 if (GTK_WIDGET_REALIZED (notebook) &&
2813 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2814 gtk_widget_map (page->tab_label);
2820 gtk_notebook_page_allocate (GtkNotebook *notebook,
2821 GtkNotebookPage *page,
2822 GtkAllocation *allocation)
2824 GtkAllocation child_allocation;
2825 gint xthickness, ythickness;
2827 g_return_if_fail (notebook != NULL);
2828 g_return_if_fail (page != NULL);
2829 g_return_if_fail (allocation != NULL);
2831 page->allocation = *allocation;
2833 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2834 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2836 if (notebook->cur_page != page)
2838 switch (notebook->tab_pos)
2841 page->allocation.y += ythickness;
2842 case GTK_POS_BOTTOM:
2843 page->allocation.height -= ythickness;
2846 page->allocation.x += xthickness;
2848 page->allocation.width -= xthickness;
2853 switch (notebook->tab_pos)
2856 child_allocation.x = xthickness + notebook->tab_border;
2857 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2858 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2859 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2860 child_allocation.x += page->allocation.x;
2862 case GTK_POS_BOTTOM:
2863 child_allocation.x = xthickness + notebook->tab_border;
2864 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2865 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2866 child_allocation.x += page->allocation.x;
2867 child_allocation.y = page->allocation.y + notebook->tab_border;
2870 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
2871 child_allocation.y = ythickness + notebook->tab_border;
2872 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2873 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2874 child_allocation.y += page->allocation.y;
2877 child_allocation.y = ythickness + notebook->tab_border;
2878 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2879 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2880 child_allocation.x = page->allocation.x + notebook->tab_border;
2881 child_allocation.y += page->allocation.y;
2885 if (page->tab_label)
2886 gtk_widget_size_allocate (page->tab_label, &child_allocation);
2890 gtk_notebook_menu_switch_page (GtkWidget *widget,
2891 GtkNotebookPage *page)
2893 GtkNotebook *notebook;
2897 g_return_if_fail (widget != NULL);
2898 g_return_if_fail (page != NULL);
2900 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
2901 (GTK_MENU (widget->parent)));
2903 if (notebook->cur_page == page)
2907 children = notebook->children;
2908 while (children && children->data != page)
2910 children = children->next;
2914 gtk_signal_emit (GTK_OBJECT (notebook),
2915 notebook_signals[SWITCH_PAGE],
2921 gtk_notebook_switch_page (GtkNotebook *notebook,
2922 GtkNotebookPage *page,
2925 g_return_if_fail (notebook != NULL);
2926 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2927 g_return_if_fail (page != NULL);
2929 if (notebook->cur_page == page)
2932 gtk_signal_emit (GTK_OBJECT (notebook),
2933 notebook_signals[SWITCH_PAGE],
2939 gtk_notebook_marshal_signal (GtkObject *object,
2944 GtkNotebookSignal rfunc;
2946 rfunc = (GtkNotebookSignal) func;
2948 (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
2953 gtk_notebook_focus (GtkContainer *container,
2954 GtkDirectionType direction)
2956 GtkNotebook *notebook;
2957 GtkWidget *focus_child;
2958 GtkNotebookPage *page = NULL;
2959 GtkNotebookPage *old_page = NULL;
2962 g_return_val_if_fail (container != NULL, FALSE);
2963 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
2965 notebook = GTK_NOTEBOOK (container);
2967 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
2970 focus_child = container->focus_child;
2971 gtk_container_set_focus_child (container, NULL);
2973 if (!notebook->show_tabs)
2975 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2977 if (GTK_IS_CONTAINER (notebook->cur_page->child))
2979 if (gtk_container_focus
2980 (GTK_CONTAINER (notebook->cur_page->child), direction))
2983 else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
2987 gtk_widget_grab_focus (notebook->cur_page->child);
2995 if (notebook->focus_tab)
2996 old_page = notebook->focus_tab->data;
3000 if (focus_child && old_page && focus_child == old_page->child &&
3001 notebook->child_has_focus)
3003 if (GTK_WIDGET_VISIBLE (old_page->child))
3005 if (GTK_IS_CONTAINER (old_page->child) &&
3006 !GTK_WIDGET_HAS_FOCUS (old_page->child))
3008 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
3012 gtk_widget_grab_focus (GTK_WIDGET(notebook));
3020 case GTK_DIR_TAB_FORWARD:
3023 if (!notebook->focus_tab)
3024 notebook->focus_tab = notebook->children;
3026 notebook->focus_tab = notebook->focus_tab->next;
3028 if (!notebook->focus_tab)
3030 gtk_notebook_focus_changed (notebook, old_page);
3034 page = notebook->focus_tab->data;
3037 case GTK_DIR_TAB_BACKWARD:
3040 if (!notebook->focus_tab)
3041 notebook->focus_tab = g_list_last (notebook->children);
3043 notebook->focus_tab = notebook->focus_tab->prev;
3045 if (!notebook->focus_tab)
3047 gtk_notebook_focus_changed (notebook, old_page);
3051 page = notebook->focus_tab->data;
3058 if (!GTK_WIDGET_HAS_FOCUS (container) )
3059 gtk_widget_grab_focus (GTK_WIDGET (container));
3061 if (GTK_WIDGET_MAPPED (page->tab_label))
3062 gtk_notebook_focus_changed (notebook, old_page);
3065 gtk_notebook_pages_allocate (notebook,
3066 &(GTK_WIDGET (notebook)->allocation));
3067 gtk_notebook_expose_tabs (notebook);
3075 gtk_notebook_page_select (GtkNotebook *notebook)
3077 g_return_val_if_fail (notebook != NULL, FALSE);
3078 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3080 if (notebook->focus_tab)
3082 GtkNotebookPage *page;
3086 page = notebook->focus_tab->data;
3088 children = notebook->children;
3090 while (children != notebook->focus_tab)
3092 children = children->next;
3096 gtk_notebook_switch_page (notebook, page, num);
3098 if (GTK_WIDGET_VISIBLE (page->child))
3100 if (GTK_IS_CONTAINER (page->child))
3102 if (gtk_container_focus (GTK_CONTAINER (page->child),
3103 GTK_DIR_TAB_FORWARD))
3106 else if (GTK_WIDGET_CAN_FOCUS (page->child))
3108 gtk_widget_grab_focus (page->child);
3117 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3120 GtkNotebookPage *old_page = NULL;
3121 GtkNotebookPage *page;
3123 g_return_if_fail (notebook != NULL);
3124 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3126 if (notebook->focus_tab != new_child)
3128 if (notebook->focus_tab)
3129 old_page = notebook->focus_tab->data;
3131 notebook->focus_tab = new_child;
3132 page = notebook->focus_tab->data;
3133 if (GTK_WIDGET_MAPPED (page->tab_label))
3134 gtk_notebook_focus_changed (notebook, old_page);
3137 gtk_notebook_pages_allocate (notebook,
3138 &(GTK_WIDGET (notebook)->allocation));
3139 gtk_notebook_expose_tabs (notebook);
3145 gtk_notebook_key_press (GtkWidget *widget,
3148 GtkNotebook *notebook;
3149 GtkDirectionType direction = 0;
3152 g_return_val_if_fail (widget != NULL, FALSE);
3153 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3154 g_return_val_if_fail (event != NULL, FALSE);
3156 notebook = GTK_NOTEBOOK (widget);
3159 if (!notebook->children || !notebook->show_tabs)
3162 switch (event->keyval)
3165 direction = GTK_DIR_UP;
3168 direction = GTK_DIR_LEFT;
3171 direction = GTK_DIR_DOWN;
3174 direction = GTK_DIR_RIGHT;
3177 case GDK_ISO_Left_Tab:
3178 if (event->state & GDK_SHIFT_MASK)
3179 direction = GTK_DIR_TAB_BACKWARD;
3181 direction = GTK_DIR_TAB_FORWARD;
3184 gtk_notebook_switch_focus_tab (notebook, notebook->children);
3187 gtk_notebook_switch_focus_tab (notebook,
3188 g_list_last (notebook->children));
3192 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
3198 return gtk_container_focus (GTK_CONTAINER (widget), direction);
3203 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3206 g_return_if_fail (notebook != NULL);
3207 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3209 if (notebook->tab_border != tab_border)
3211 notebook->tab_border = tab_border;
3213 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3214 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3219 gtk_notebook_update_labels (GtkNotebook *notebook,
3223 GtkNotebookPage *page;
3230 sprintf (string, "Page %u", page_num);
3231 if (notebook->show_tabs && page->default_tab)
3232 gtk_label_set (GTK_LABEL (page->tab_label), string);
3233 if (notebook->menu && page->default_menu)
3235 if (GTK_IS_LABEL (page->tab_label))
3236 gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
3238 gtk_label_set (GTK_LABEL (page->menu_label), string);
3245 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3246 GtkNotebookPage *page,
3249 GtkWidget *menu_item;
3251 if (page->default_menu)
3253 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3254 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3256 page->menu_label = gtk_label_new ("");
3257 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3259 gtk_widget_show (page->menu_label);
3260 menu_item = gtk_menu_item_new ();
3261 gtk_widget_freeze_accelerators (menu_item);
3262 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3263 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
3264 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3265 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page),
3267 gtk_widget_show (menu_item);
3271 gtk_notebook_popup_enable (GtkNotebook *notebook)
3273 GtkNotebookPage *page;
3276 g_return_if_fail (notebook != NULL);
3277 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3282 notebook->menu = gtk_menu_new ();
3284 children = notebook->children;
3287 page = children->data;
3288 children = children->next;
3289 gtk_notebook_menu_item_create (notebook, page, -1);
3291 gtk_notebook_update_labels (notebook, notebook->children,1);
3293 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
3294 gtk_notebook_menu_detacher);
3298 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3301 gtk_widget_unparent (GTK_BIN(widget)->child);
3302 GTK_BIN(widget)->child = NULL;
3306 gtk_notebook_popup_disable (GtkNotebook *notebook)
3308 g_return_if_fail (notebook != NULL);
3309 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3311 if (!notebook->menu)
3314 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
3315 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
3316 gtk_widget_destroy (notebook->menu);
3320 gtk_notebook_menu_detacher (GtkWidget *widget,
3323 GtkNotebook *notebook;
3325 g_return_if_fail (widget != NULL);
3326 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3328 notebook = GTK_NOTEBOOK (widget);
3329 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3331 notebook->menu = NULL;