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 static void gtk_notebook_class_init (GtkNotebookClass *klass);
66 static void gtk_notebook_init (GtkNotebook *notebook);
67 static void gtk_notebook_set_arg (GtkObject *object,
70 static void gtk_notebook_get_arg (GtkObject *object,
73 static void gtk_notebook_set_child_arg (GtkContainer *container,
77 static void gtk_notebook_get_child_arg (GtkContainer *container,
81 static void gtk_notebook_destroy (GtkObject *object);
82 static void gtk_notebook_map (GtkWidget *widget);
83 static void gtk_notebook_unmap (GtkWidget *widget);
84 static void gtk_notebook_realize (GtkWidget *widget);
85 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
86 static void gtk_notebook_size_request (GtkWidget *widget,
87 GtkRequisition *requisition);
88 static void gtk_notebook_size_allocate (GtkWidget *widget,
89 GtkAllocation *allocation);
90 static void gtk_notebook_paint (GtkWidget *widget,
92 static void gtk_notebook_draw (GtkWidget *widget,
94 static gint gtk_notebook_expose (GtkWidget *widget,
95 GdkEventExpose *event);
96 static gint gtk_notebook_button_press (GtkWidget *widget,
97 GdkEventButton *event);
98 static gint gtk_notebook_button_release (GtkWidget *widget,
99 GdkEventButton *event);
100 static gint gtk_notebook_enter_notify (GtkWidget *widget,
101 GdkEventCrossing *event);
102 static gint gtk_notebook_leave_notify (GtkWidget *widget,
103 GdkEventCrossing *event);
104 static gint gtk_notebook_motion_notify (GtkWidget *widget,
105 GdkEventMotion *event);
106 static gint gtk_notebook_key_press (GtkWidget *widget,
108 static void gtk_notebook_add (GtkContainer *container,
110 static void gtk_notebook_remove (GtkContainer *container,
112 static void gtk_notebook_real_remove (GtkNotebook *notebook,
115 static void gtk_notebook_foreach (GtkContainer *container,
116 GtkCallback callback,
117 gpointer callback_data);
118 static void gtk_notebook_switch_page (GtkNotebook *notebook,
119 GtkNotebookPage *page,
121 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
122 GtkNotebookPage *page,
124 static void gtk_notebook_set_focus_child (GtkContainer *container,
126 static gint gtk_notebook_focus_in (GtkWidget *widget,
127 GdkEventFocus *event);
128 static gint gtk_notebook_focus_out (GtkWidget *widget,
129 GdkEventFocus *event);
130 static void gtk_notebook_draw_focus (GtkWidget *widget);
131 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
132 GtkNotebookPage *old_page);
133 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
134 GtkAllocation *allocation);
135 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
136 GtkNotebookPage *page,
137 GtkAllocation *allocation);
138 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
140 static gint gtk_notebook_timer (GtkNotebook *notebook);
141 static gint gtk_notebook_focus (GtkContainer *container,
142 GtkDirectionType direction);
143 static gint gtk_notebook_page_select (GtkNotebook *notebook);
144 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
149 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
150 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
152 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
153 GtkNotebookPage *page,
155 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
156 GtkNotebookPage *page);
157 static void gtk_notebook_update_labels (GtkNotebook *notebook,
160 static void gtk_notebook_menu_detacher (GtkWidget *widget,
162 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
164 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
165 GtkNotebookPage *page,
167 static GtkType gtk_notebook_child_type (GtkContainer *container);
168 static gint gtk_notebook_find_page (gconstpointer a,
172 static GtkContainerClass *parent_class = NULL;
173 static guint notebook_signals[LAST_SIGNAL] = { 0 };
176 gtk_notebook_get_type (void)
178 static GtkType notebook_type = 0;
182 GtkTypeInfo notebook_info =
185 sizeof (GtkNotebook),
186 sizeof (GtkNotebookClass),
187 (GtkClassInitFunc) gtk_notebook_class_init,
188 (GtkObjectInitFunc) gtk_notebook_init,
189 /* reserved_1 */ NULL,
190 /* reserved_2 */ NULL,
191 (GtkClassInitFunc) NULL,
194 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
197 return notebook_type;
201 gtk_notebook_class_init (GtkNotebookClass *class)
203 GtkObjectClass *object_class;
204 GtkWidgetClass *widget_class;
205 GtkContainerClass *container_class;
207 object_class = (GtkObjectClass*) class;
208 widget_class = (GtkWidgetClass*) class;
209 container_class = (GtkContainerClass*) class;
210 parent_class = gtk_type_class (gtk_container_get_type ());
212 gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
213 gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
214 gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_BORDER);
215 gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
216 gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
217 gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
218 gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
220 gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
221 gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
222 gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
224 notebook_signals[SWITCH_PAGE] =
225 gtk_signal_new ("switch_page",
228 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
229 gtk_marshal_NONE__POINTER_UINT,
234 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
236 object_class->set_arg = gtk_notebook_set_arg;
237 object_class->get_arg = gtk_notebook_get_arg;
238 object_class->destroy = gtk_notebook_destroy;
240 widget_class->map = gtk_notebook_map;
241 widget_class->unmap = gtk_notebook_unmap;
242 widget_class->realize = gtk_notebook_realize;
243 widget_class->size_request = gtk_notebook_size_request;
244 widget_class->size_allocate = gtk_notebook_size_allocate;
245 widget_class->draw = gtk_notebook_draw;
246 widget_class->expose_event = gtk_notebook_expose;
247 widget_class->button_press_event = gtk_notebook_button_press;
248 widget_class->button_release_event = gtk_notebook_button_release;
249 widget_class->enter_notify_event = gtk_notebook_enter_notify;
250 widget_class->leave_notify_event = gtk_notebook_leave_notify;
251 widget_class->motion_notify_event = gtk_notebook_motion_notify;
252 widget_class->key_press_event = gtk_notebook_key_press;
253 widget_class->focus_in_event = gtk_notebook_focus_in;
254 widget_class->focus_out_event = gtk_notebook_focus_out;
255 widget_class->draw_focus = gtk_notebook_draw_focus;
257 container_class->add = gtk_notebook_add;
258 container_class->remove = gtk_notebook_remove;
259 container_class->foreach = gtk_notebook_foreach;
260 container_class->focus = gtk_notebook_focus;
261 container_class->set_focus_child = gtk_notebook_set_focus_child;
262 container_class->get_child_arg = gtk_notebook_get_child_arg;
263 container_class->set_child_arg = gtk_notebook_set_child_arg;
264 container_class->child_type = gtk_notebook_child_type;
266 class->switch_page = gtk_real_notebook_switch_page;
270 gtk_notebook_set_arg (GtkObject *object,
274 GtkNotebook *notebook;
276 notebook = GTK_NOTEBOOK (object);
281 gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
283 case ARG_SHOW_BORDER:
284 gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
287 gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
289 case ARG_ENABLE_POPUP:
290 if (GTK_VALUE_BOOL (*arg))
291 gtk_notebook_popup_enable (notebook);
293 gtk_notebook_popup_disable (notebook);
296 gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
299 gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
302 gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
310 gtk_notebook_get_arg (GtkObject *object,
314 GtkNotebook *notebook;
316 notebook = GTK_NOTEBOOK (object);
321 GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
323 case ARG_SHOW_BORDER:
324 GTK_VALUE_BOOL (*arg) = notebook->show_border;
327 GTK_VALUE_BOOL (*arg) = notebook->scrollable;
329 case ARG_ENABLE_POPUP:
330 GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
333 GTK_VALUE_INT (*arg) = gtk_notebook_current_page (notebook);
336 GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
339 GTK_VALUE_UINT (*arg) = notebook->tab_border;
342 arg->type = GTK_TYPE_INVALID;
348 gtk_notebook_set_child_arg (GtkContainer *container,
353 GtkNotebook *notebook;
354 GtkNotebookPage *page = NULL;
358 notebook = GTK_NOTEBOOK (container);
362 case CHILD_ARG_TAB_LABEL:
363 /* a NULL pointer indicates a default_tab setting, otherwise
364 * we need to set the associated label
367 if (!(list = g_list_find_custom (notebook->children, child,
368 gtk_notebook_find_page)))
373 if (GTK_VALUE_STRING (*arg))
375 page->default_tab = FALSE;
377 gtk_widget_unparent (page->tab_label);
378 page->tab_label = gtk_label_new (GTK_VALUE_STRING (*arg));
379 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
380 if (notebook->show_tabs)
382 gtk_widget_show (page->tab_label);
383 gtk_notebook_pages_allocate
384 (notebook, &(GTK_WIDGET (notebook)->allocation));
385 gtk_notebook_expose_tabs (notebook);
390 page->default_tab = TRUE;
392 gtk_widget_unparent (page->tab_label);
393 if (!notebook->show_tabs)
394 page->tab_label = NULL;
399 sprintf (string, "Page %u", g_list_index (notebook->children, page) + 1);
400 page->tab_label = gtk_label_new (string);
401 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
402 gtk_widget_show (page->tab_label);
403 gtk_notebook_pages_allocate
404 (notebook, &(GTK_WIDGET (notebook)->allocation));
405 gtk_notebook_expose_tabs (notebook);
409 case CHILD_ARG_MENU_LABEL:
411 for (position = 0, list = notebook->children; list;
412 list = list->next, position++)
415 if (page->child == child)
419 if (page->menu_label)
423 gtk_container_remove (GTK_CONTAINER (notebook->menu),
424 page->menu_label->parent);
425 gtk_widget_queue_resize (notebook->menu);
427 if (!page->default_menu)
428 gtk_widget_unref (page->menu_label);
430 if (GTK_VALUE_STRING (*arg))
432 page->menu_label = gtk_label_new (GTK_VALUE_STRING (*arg));
433 gtk_widget_ref (page->menu_label);
434 gtk_object_sink (GTK_OBJECT(page->menu_label));
435 page->default_menu = FALSE;
438 page->default_menu = TRUE;
441 gtk_notebook_menu_item_create (notebook, page, position);
444 case CHILD_ARG_POSITION:
445 gtk_notebook_reorder_child (notebook, child, GTK_VALUE_INT (*arg));
453 gtk_notebook_get_child_arg (GtkContainer *container,
458 GtkNotebook *notebook;
459 GtkNotebookPage *page = NULL;
462 notebook = GTK_NOTEBOOK (container);
464 if (!(list = g_list_find_custom (notebook->children, child,
465 gtk_notebook_find_page)))
467 arg->type = GTK_TYPE_INVALID;
475 case CHILD_ARG_TAB_LABEL:
476 if (page->default_tab)
477 GTK_VALUE_STRING (*arg) = NULL;
480 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
481 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->tab_label)->label);
483 GTK_VALUE_STRING (*arg) = NULL;
486 case CHILD_ARG_MENU_LABEL:
487 if (page->default_menu)
488 GTK_VALUE_STRING (*arg) = NULL;
491 if (page->menu_label && GTK_IS_LABEL (page->menu_label))
492 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->menu_label)->label);
494 GTK_VALUE_STRING (*arg) = NULL;
497 case CHILD_ARG_POSITION:
498 GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
501 arg->type = GTK_TYPE_INVALID;
507 gtk_notebook_child_type (GtkContainer *container)
509 return GTK_TYPE_WIDGET;
513 gtk_notebook_init (GtkNotebook *notebook)
515 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
517 notebook->cur_page = NULL;
518 notebook->children = NULL;
519 notebook->first_tab = NULL;
520 notebook->focus_tab = NULL;
521 notebook->panel = NULL;
522 notebook->menu = NULL;
524 notebook->tab_border = 3;
525 notebook->show_tabs = TRUE;
526 notebook->show_border = TRUE;
527 notebook->tab_pos = GTK_POS_TOP;
528 notebook->scrollable = FALSE;
529 notebook->in_child = 0;
530 notebook->click_child = 0;
531 notebook->button = 0;
532 notebook->need_timer = 0;
533 notebook->child_has_focus = FALSE;
537 gtk_notebook_new (void)
539 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
543 gtk_notebook_destroy (GtkObject *object)
545 GtkNotebook *notebook;
547 g_return_if_fail (object != NULL);
548 g_return_if_fail (GTK_IS_NOTEBOOK (object));
550 notebook = GTK_NOTEBOOK (object);
553 gtk_notebook_popup_disable (notebook);
555 GTK_OBJECT_CLASS (parent_class)->destroy (object);
559 gtk_notebook_append_page (GtkNotebook *notebook,
561 GtkWidget *tab_label)
563 g_return_if_fail (notebook != NULL);
564 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
565 g_return_if_fail (child != NULL);
567 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
571 gtk_notebook_append_page_menu (GtkNotebook *notebook,
573 GtkWidget *tab_label,
574 GtkWidget *menu_label)
576 g_return_if_fail (notebook != NULL);
577 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
578 g_return_if_fail (child != NULL);
580 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
584 gtk_notebook_prepend_page (GtkNotebook *notebook,
586 GtkWidget *tab_label)
588 g_return_if_fail (notebook != NULL);
589 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
590 g_return_if_fail (child != NULL);
592 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
596 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
598 GtkWidget *tab_label,
599 GtkWidget *menu_label)
601 g_return_if_fail (notebook != NULL);
602 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
603 g_return_if_fail (child != NULL);
605 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
609 gtk_notebook_insert_page (GtkNotebook *notebook,
611 GtkWidget *tab_label,
614 g_return_if_fail (notebook != NULL);
615 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
616 g_return_if_fail (child != NULL);
618 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
622 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
624 GtkWidget *tab_label,
625 GtkWidget *menu_label,
628 GtkNotebookPage *page;
631 g_return_if_fail (notebook != NULL);
632 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
633 g_return_if_fail (child != NULL);
635 page = g_new (GtkNotebookPage, 1);
637 page->requisition.width = 0;
638 page->requisition.height = 0;
639 page->allocation.x = 0;
640 page->allocation.y = 0;
641 page->allocation.width = 0;
642 page->allocation.height = 0;
643 page->default_menu = FALSE;
644 page->default_tab = FALSE;
646 nchildren = g_list_length (notebook->children);
647 if ((position < 0) || (position > nchildren))
648 position = nchildren;
650 notebook->children = g_list_insert (notebook->children, page, position);
654 page->default_tab = TRUE;
655 if (notebook->show_tabs)
656 tab_label = gtk_label_new ("");
658 page->tab_label = tab_label;
659 page->menu_label = menu_label;
662 page->default_menu = TRUE;
665 gtk_widget_ref (page->menu_label);
666 gtk_object_sink (GTK_OBJECT(page->menu_label));
670 gtk_notebook_menu_item_create (notebook, page, position);
672 gtk_notebook_update_labels
673 (notebook, g_list_nth (notebook->children, position), position + 1);
675 if (!notebook->first_tab)
676 notebook->first_tab = notebook->children;
678 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
681 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
682 gtk_widget_show (tab_label);
685 if (!notebook->cur_page)
687 gtk_notebook_switch_page (notebook, page, 0);
688 gtk_notebook_switch_focus_tab (notebook, NULL);
691 if (GTK_WIDGET_VISIBLE (notebook))
693 if (GTK_WIDGET_REALIZED (notebook) &&
694 !GTK_WIDGET_REALIZED (child))
695 gtk_widget_realize (child);
697 if (GTK_WIDGET_MAPPED (notebook) &&
698 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
699 gtk_widget_map (child);
703 if (GTK_WIDGET_REALIZED (notebook) &&
704 !GTK_WIDGET_REALIZED (tab_label))
705 gtk_widget_realize (tab_label);
707 if (GTK_WIDGET_MAPPED (notebook) &&
708 !GTK_WIDGET_MAPPED (tab_label))
709 gtk_widget_map (tab_label);
713 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
714 gtk_widget_queue_resize (child);
718 gtk_notebook_remove_page (GtkNotebook *notebook,
723 g_return_if_fail (notebook != NULL);
724 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
728 list = g_list_nth (notebook->children, page_num);
730 gtk_notebook_real_remove (notebook, list, page_num);
734 list = g_list_last (notebook->children);
736 gtk_notebook_real_remove
737 (notebook, list, g_list_index (notebook->children, list->data));
742 gtk_notebook_add (GtkContainer *container,
745 g_return_if_fail (container != NULL);
746 g_return_if_fail (GTK_IS_NOTEBOOK (container));
747 g_return_if_fail (widget != NULL);
749 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
754 gtk_notebook_remove (GtkContainer *container,
757 GtkNotebook *notebook;
758 GtkNotebookPage *page;
762 g_return_if_fail (container != NULL);
763 g_return_if_fail (GTK_IS_NOTEBOOK (container));
764 g_return_if_fail (widget != NULL);
766 notebook = GTK_NOTEBOOK (container);
768 children = notebook->children;
772 page = children->data;
773 if (page->child == widget)
775 gtk_notebook_real_remove (notebook, children, page_num);
779 children = children->next;
784 gtk_notebook_real_remove (GtkNotebook *notebook,
788 GtkNotebookPage *page;
790 gint need_resize = FALSE;
794 next_list = list->prev;
799 next_list = list->next;
805 if (notebook->cur_page == list->data)
807 notebook->cur_page = NULL;
810 page = next_list->data;
811 gtk_notebook_switch_page (notebook, page, page_num);
815 if (list == notebook->first_tab)
816 notebook->first_tab = next_list;
817 if (list == notebook->focus_tab)
818 gtk_notebook_switch_focus_tab (notebook, next_list);
822 if ((GTK_WIDGET_VISIBLE (page->child) ||
823 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
824 && GTK_WIDGET_VISIBLE (notebook))
827 gtk_widget_unparent (page->child);
830 gtk_widget_unparent (page->tab_label);
834 gtk_container_remove (GTK_CONTAINER (notebook->menu),
835 page->menu_label->parent);
836 gtk_widget_queue_resize (notebook->menu);
838 if (!page->default_menu)
839 gtk_widget_unref (page->menu_label);
841 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
843 notebook->children = g_list_remove_link (notebook->children, list);
848 gtk_widget_queue_resize (GTK_WIDGET (notebook));
853 gtk_notebook_current_page (GtkNotebook *notebook)
858 g_return_val_if_fail (notebook != NULL, -1);
859 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
861 if (notebook->cur_page)
864 children = notebook->children;
868 if (children->data == notebook->cur_page)
870 children = children->next;
886 gtk_notebook_set_page (GtkNotebook *notebook,
891 g_return_if_fail (notebook != NULL);
892 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
896 list = g_list_nth (notebook->children, page_num);
898 gtk_notebook_switch_page (notebook, list->data, page_num);
902 list = g_list_last (notebook->children);
904 gtk_notebook_switch_page (notebook, list->data,
905 g_list_index (notebook->children, list->data));
910 gtk_notebook_next_page (GtkNotebook *notebook)
912 GtkNotebookPage *page;
916 g_return_if_fail (notebook != NULL);
917 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
919 children = notebook->children;
923 if (notebook->cur_page == children->data)
925 children = children->next;
934 children = children->next;
939 children = notebook->children;
943 page = children->data;
944 gtk_notebook_switch_page (notebook, page, num);
948 gtk_notebook_prev_page (GtkNotebook *notebook)
950 GtkNotebookPage *page;
954 g_return_if_fail (notebook != NULL);
955 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
957 children = notebook->children;
961 if (notebook->cur_page == children->data)
963 children = children->next;
972 children = children->prev;
977 while (children->next)
979 children = children->next;
984 page = children->data;
985 gtk_notebook_switch_page (notebook, page, num);
989 gtk_notebook_reorder_child (GtkNotebook *notebook,
994 GtkNotebookPage *page;
997 g_return_if_fail (notebook != NULL);
998 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
999 g_return_if_fail (child != NULL);
1000 g_return_if_fail (GTK_IS_WIDGET (child));
1002 for (old_pos = 0, list = notebook->children; list;
1003 list = list->next, old_pos++)
1006 if (page->child == child)
1010 if (!list || old_pos == position)
1013 notebook->children = g_list_remove_link (notebook->children, list);
1015 if (position <= 0 || !notebook->children)
1017 list->next = notebook->children;
1019 list->next->prev = list;
1020 notebook->children = list;
1026 if ((work = g_list_nth (notebook->children, position)))
1028 list->prev = work->prev;
1030 list->prev->next = list;
1036 work = g_list_last (notebook->children);
1044 GtkWidget *menu_item;
1046 menu_item = page->menu_label->parent;
1047 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
1048 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
1049 gtk_notebook_menu_item_create (notebook, page, position);
1050 gtk_widget_queue_resize (notebook->menu);
1053 gtk_notebook_update_labels (notebook, notebook->children, 1);
1055 if (notebook->show_tabs)
1057 gtk_notebook_pages_allocate (notebook,
1058 &(GTK_WIDGET (notebook)->allocation));
1059 gtk_notebook_expose_tabs (notebook);
1064 gtk_notebook_foreach (GtkContainer *container,
1065 GtkCallback callback,
1066 gpointer callback_data)
1068 GtkNotebook *notebook;
1069 GtkNotebookPage *page;
1072 g_return_if_fail (container != NULL);
1073 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1074 g_return_if_fail (callback != NULL);
1076 notebook = GTK_NOTEBOOK (container);
1078 children = notebook->children;
1081 page = children->data;
1082 children = children->next;
1083 (* callback) (page->child, callback_data);
1088 gtk_notebook_expose_tabs (GtkNotebook *notebook)
1091 GtkNotebookPage *page;
1092 GdkEventExpose event;
1095 widget = GTK_WIDGET (notebook);
1096 border = GTK_CONTAINER (notebook)->border_width;
1098 page = notebook->first_tab->data;
1100 event.type = GDK_EXPOSE;
1101 event.window = widget->window;
1103 event.area.x = border;
1104 event.area.y = border;
1106 switch (notebook->tab_pos)
1108 case GTK_POS_BOTTOM:
1109 event.area.y = widget->allocation.height - border
1110 - page->allocation.height - widget->style->klass->ythickness;
1111 if (notebook->first_tab->data != notebook->cur_page)
1112 event.area.y -= widget->style->klass->ythickness;
1114 event.area.width = widget->allocation.width - 2 * border;
1115 event.area.height = page->allocation.height
1116 + widget->style->klass->ythickness;
1117 if (notebook->first_tab->data != notebook->cur_page)
1118 event.area.height += widget->style->klass->ythickness;
1121 event.area.x = widget->allocation.width - border
1122 - page->allocation.width - widget->style->klass->xthickness;
1123 if (notebook->first_tab->data != notebook->cur_page)
1124 event.area.x -= widget->style->klass->xthickness;
1126 event.area.width = page->allocation.width
1127 + widget->style->klass->xthickness;
1128 event.area.height = widget->allocation.height - 2 * border;
1129 if (notebook->first_tab->data != notebook->cur_page)
1130 event.area.width += widget->style->klass->xthickness;
1133 gtk_widget_event (widget, (GdkEvent *) &event);
1137 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
1138 GtkPositionType pos)
1140 g_return_if_fail (notebook != NULL);
1141 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1143 if (notebook->tab_pos != pos)
1145 notebook->tab_pos = pos;
1147 if (GTK_WIDGET_VISIBLE (notebook))
1149 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1150 if (notebook->panel)
1151 gdk_window_clear (notebook->panel);
1157 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
1160 GtkNotebookPage *page;
1163 g_return_if_fail (notebook != NULL);
1164 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1166 if (notebook->show_tabs == show_tabs)
1169 notebook->show_tabs = show_tabs;
1170 children = notebook->children;
1174 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
1178 page = children->data;
1179 children = children->next;
1180 if (page->default_tab)
1182 gtk_widget_destroy (page->tab_label);
1183 page->tab_label = NULL;
1186 gtk_widget_hide (page->tab_label);
1189 if (notebook->panel)
1190 gdk_window_hide (notebook->panel);
1197 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
1201 page = children->data;
1202 children = children->next;
1203 if (page->default_tab)
1205 sprintf (string, "Page %d", i);
1206 page->tab_label = gtk_label_new (string);
1207 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
1209 gtk_widget_show (page->tab_label);
1213 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1217 gtk_notebook_set_show_border (GtkNotebook *notebook,
1220 g_return_if_fail (notebook != NULL);
1221 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1223 if (notebook->show_border != show_border)
1225 notebook->show_border = show_border;
1227 if (GTK_WIDGET_VISIBLE (notebook))
1228 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1233 gtk_notebook_set_scrollable (GtkNotebook *notebook,
1236 g_return_if_fail (notebook != NULL);
1237 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1239 if (scrollable != notebook->scrollable)
1241 if ( (notebook->scrollable = (scrollable != 0)) )
1242 gtk_notebook_panel_realize (notebook);
1243 else if (notebook->panel)
1245 gdk_window_destroy (notebook->panel);
1246 notebook->panel = NULL;
1248 gtk_widget_queue_resize (GTK_WIDGET(notebook));
1253 gtk_notebook_map (GtkWidget *widget)
1255 GtkNotebook *notebook;
1256 GtkNotebookPage *page;
1259 g_return_if_fail (widget != NULL);
1260 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1262 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1263 gdk_window_show (widget->window);
1265 notebook = GTK_NOTEBOOK (widget);
1267 if (notebook->cur_page &&
1268 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1269 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1270 gtk_widget_map (notebook->cur_page->child);
1272 if (notebook->scrollable)
1273 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
1276 children = notebook->children;
1280 page = children->data;
1281 children = children->next;
1283 if (page->tab_label &&
1284 GTK_WIDGET_VISIBLE (page->child) &&
1285 !GTK_WIDGET_MAPPED (page->tab_label))
1286 gtk_widget_map (page->tab_label);
1292 gtk_notebook_unmap (GtkWidget *widget)
1294 g_return_if_fail (widget != NULL);
1295 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1297 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1298 gdk_window_hide (widget->window);
1299 if (GTK_NOTEBOOK (widget)->panel)
1300 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
1304 gtk_notebook_realize (GtkWidget *widget)
1306 GtkNotebook *notebook;
1307 GdkWindowAttr attributes;
1308 gint attributes_mask;
1310 g_return_if_fail (widget != NULL);
1311 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1313 notebook = GTK_NOTEBOOK (widget);
1314 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1316 attributes.window_type = GDK_WINDOW_CHILD;
1317 attributes.x = widget->allocation.x;
1318 attributes.y = widget->allocation.y;
1319 attributes.width = widget->allocation.width;
1320 attributes.height = widget->allocation.height;
1321 attributes.wclass = GDK_INPUT_OUTPUT;
1322 attributes.visual = gtk_widget_get_visual (widget);
1323 attributes.colormap = gtk_widget_get_colormap (widget);
1324 attributes.event_mask = gtk_widget_get_events (widget);
1325 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1326 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
1328 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1330 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1331 gdk_window_set_user_data (widget->window, notebook);
1333 widget->style = gtk_style_attach (widget->style, widget->window);
1334 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1336 if (notebook->scrollable)
1337 gtk_notebook_panel_realize (notebook);
1341 gtk_notebook_panel_realize (GtkNotebook *notebook)
1344 GdkWindowAttr attributes;
1345 gint attributes_mask;
1347 g_return_if_fail (notebook != NULL);
1348 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1350 widget = GTK_WIDGET (notebook);
1352 attributes.window_type = GDK_WINDOW_CHILD;
1353 attributes.wclass = GDK_INPUT_OUTPUT;
1354 attributes.visual = gtk_widget_get_visual (widget);
1355 attributes.colormap = gtk_widget_get_colormap (widget);
1356 attributes.event_mask = gtk_widget_get_events (widget);
1357 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1358 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1359 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1361 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1363 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1364 attributes.height = ARROW_SIZE;
1366 attributes.x = widget->allocation.width - attributes.width -
1367 GTK_CONTAINER (notebook)->border_width;
1368 attributes.y = widget->allocation.height - ARROW_SIZE -
1369 GTK_CONTAINER (notebook)->border_width;
1370 if (notebook->tab_pos == GTK_POS_TOP)
1371 attributes.y = GTK_CONTAINER (notebook)->border_width;
1372 else if (notebook->tab_pos == GTK_POS_LEFT)
1373 attributes.x = widget->allocation.x
1374 + GTK_CONTAINER (notebook)->border_width;
1377 notebook->panel = gdk_window_new (widget->window, &attributes,
1379 gtk_style_set_background (widget->style, notebook->panel,
1381 gdk_window_set_user_data (notebook->panel, widget);
1385 gtk_notebook_size_request (GtkWidget *widget,
1386 GtkRequisition *requisition)
1388 GtkNotebook *notebook;
1389 GtkNotebookPage *page;
1392 g_return_if_fail (widget != NULL);
1393 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1394 g_return_if_fail (requisition != NULL);
1396 notebook = GTK_NOTEBOOK (widget);
1397 widget->requisition.width = 0;
1398 widget->requisition.height = 0;
1400 children = notebook->children;
1403 page = children->data;
1404 children = children->next;
1406 if (GTK_WIDGET_VISIBLE (page->child))
1408 gtk_widget_size_request (page->child, &page->child->requisition);
1410 widget->requisition.width = MAX (widget->requisition.width,
1411 page->child->requisition.width);
1412 widget->requisition.height = MAX (widget->requisition.height,
1413 page->child->requisition.height);
1417 if (notebook->show_border || notebook->show_tabs)
1419 widget->requisition.width += widget->style->klass->xthickness * 2;
1420 widget->requisition.height += widget->style->klass->ythickness * 2;
1422 if (notebook->show_tabs)
1425 gint tab_height = 0;
1428 children = notebook->children;
1431 page = children->data;
1432 children = children->next;
1434 if (GTK_WIDGET_VISIBLE (page->child))
1436 gtk_widget_size_request (page->tab_label,
1437 &page->tab_label->requisition);
1439 page->requisition.width =
1440 (page->tab_label->requisition.width +
1441 (widget->style->klass->xthickness + notebook->tab_border)
1443 page->requisition.height =
1444 (page->tab_label->requisition.height +
1445 (widget->style->klass->ythickness + notebook->tab_border)
1448 switch (notebook->tab_pos)
1451 case GTK_POS_BOTTOM:
1452 page->requisition.width -= TAB_OVERLAP;
1454 tab_width += page->requisition.width;
1455 tab_height = MAX (tab_height, page->requisition.height);
1456 tab_max = MAX (tab_max, page->requisition.width);
1460 page->requisition.height -= TAB_OVERLAP;
1462 tab_width = MAX (tab_width, page->requisition.width);
1463 tab_height += page->requisition.height;
1464 tab_max = MAX (tab_max, page->requisition.height);
1470 children = notebook->children;
1472 if (children && children->next && notebook->scrollable)
1474 if ((notebook->tab_pos == GTK_POS_TOP) ||
1475 (notebook->tab_pos == GTK_POS_BOTTOM))
1477 if (widget->requisition.width < tab_width)
1479 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1480 tab_height = MAX (tab_height, ARROW_SIZE);
1485 if (widget->requisition.height < tab_height)
1487 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1488 tab_width = MAX (tab_width,
1489 ARROW_SPACING + 2 * ARROW_SIZE);
1496 page = children->data;
1497 children = children->next;
1499 if (GTK_WIDGET_VISIBLE (page->child))
1501 if ((notebook->tab_pos == GTK_POS_TOP) ||
1502 (notebook->tab_pos == GTK_POS_BOTTOM))
1503 page->requisition.height = tab_height;
1505 page->requisition.width = tab_width;
1509 switch (notebook->tab_pos)
1512 case GTK_POS_BOTTOM:
1513 tab_width += widget->style->klass->xthickness;
1514 widget->requisition.width = MAX (widget->requisition.width,
1516 widget->requisition.height += tab_height;
1520 tab_height += widget->style->klass->ythickness;
1521 widget->requisition.width += tab_width;
1522 widget->requisition.height = MAX (widget->requisition.height,
1528 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1529 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1533 gtk_notebook_size_allocate (GtkWidget *widget,
1534 GtkAllocation *allocation)
1536 GtkNotebook *notebook;
1537 GtkNotebookPage *page;
1538 GtkAllocation child_allocation;
1541 g_return_if_fail (widget != NULL);
1542 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1543 g_return_if_fail (allocation != NULL);
1545 widget->allocation = *allocation;
1546 if (GTK_WIDGET_REALIZED (widget))
1547 gdk_window_move_resize (widget->window,
1548 allocation->x, allocation->y,
1549 allocation->width, allocation->height);
1551 notebook = GTK_NOTEBOOK (widget);
1552 if (notebook->children)
1554 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1555 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1556 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1557 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1559 if (notebook->show_tabs || notebook->show_border)
1561 child_allocation.x += widget->style->klass->xthickness;
1562 child_allocation.y += widget->style->klass->ythickness;
1563 child_allocation.width = MAX (1,
1564 child_allocation.width - widget->style->klass->xthickness * 2);
1565 child_allocation.height = MAX (1,
1566 child_allocation.height - widget->style->klass->ythickness * 2);
1568 if (notebook->show_tabs && notebook->children)
1570 switch (notebook->tab_pos)
1573 child_allocation.y += notebook->cur_page->requisition.height;
1574 case GTK_POS_BOTTOM:
1575 child_allocation.height = MAX (1,
1576 child_allocation.height - notebook->cur_page->requisition.height);
1579 child_allocation.x += notebook->cur_page->requisition.width;
1581 child_allocation.width = MAX (1,
1582 child_allocation.width - notebook->cur_page->requisition.width);
1588 children = notebook->children;
1591 page = children->data;
1592 children = children->next;
1594 if (GTK_WIDGET_VISIBLE (page->child))
1595 gtk_widget_size_allocate (page->child, &child_allocation);
1598 gtk_notebook_pages_allocate (notebook, allocation);
1603 gtk_notebook_paint (GtkWidget *widget,
1606 GtkNotebook *notebook;
1607 GtkNotebookPage *page;
1614 g_return_if_fail (widget != NULL);
1615 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1616 g_return_if_fail (area != NULL);
1618 if (GTK_WIDGET_DRAWABLE (widget))
1620 notebook = GTK_NOTEBOOK (widget);
1622 gdk_window_clear_area (widget->window,
1624 area->width, area->height);
1626 if (notebook->show_tabs || notebook->show_border)
1628 x = GTK_CONTAINER (widget)->border_width;
1629 y = GTK_CONTAINER (widget)->border_width;
1630 width = widget->allocation.width - x * 2;
1631 height = widget->allocation.height - y * 2;
1633 if (notebook->show_tabs && notebook->children)
1636 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1638 GtkNotebookPage *page;
1640 page = notebook->first_tab->data;
1642 switch (notebook->tab_pos)
1645 y += page->allocation.height +
1646 widget->style->klass->ythickness;
1647 case GTK_POS_BOTTOM:
1648 height -= page->allocation.height +
1649 widget->style->klass->ythickness;
1652 x += page->allocation.width +
1653 widget->style->klass->xthickness;
1655 width -= page->allocation.width +
1656 widget->style->klass->xthickness;
1659 gtk_draw_shadow (widget->style, widget->window,
1660 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1661 x, y, width, height);
1667 switch (notebook->tab_pos)
1670 y += notebook->cur_page->allocation.height;
1671 case GTK_POS_BOTTOM:
1672 height -= notebook->cur_page->allocation.height;
1675 x += notebook->cur_page->allocation.width;
1677 width -= notebook->cur_page->allocation.width;
1681 switch (notebook->tab_pos)
1684 if (x != notebook->cur_page->allocation.x)
1686 points[i].x = notebook->cur_page->allocation.x;
1693 points[i++].y = y + height - 1;
1694 points[i].x = x + width - 1;
1695 points[i++].y = y + height - 1;
1696 points[i].x = x + width - 1;
1699 if ((notebook->cur_page->allocation.x +
1700 notebook->cur_page->allocation.width -
1701 widget->style->klass->xthickness) <
1702 x + width - widget->style->klass->xthickness)
1704 points[i].x = (notebook->cur_page->allocation.x +
1705 notebook->cur_page->allocation.width -
1706 widget->style->klass->xthickness);
1708 if (points[i].x == (x + width))
1715 case GTK_POS_BOTTOM:
1716 if ((notebook->cur_page->allocation.x +
1717 notebook->cur_page->allocation.width -
1718 widget->style->klass->xthickness) <
1719 x + width - widget->style->klass->xthickness)
1721 points[i].x = (notebook->cur_page->allocation.x +
1722 notebook->cur_page->allocation.width -
1723 widget->style->klass->xthickness);
1725 if (points[i].x == (x + width))
1728 points[i++].y = y + height - 1;
1731 points[i].x = x + width - 1;
1732 points[i++].y = y + height - 1;
1733 points[i].x = x + width - 1;
1738 points[i++].y = y + height - 1;
1740 if (notebook->cur_page->allocation.x != x)
1742 points[i].x = notebook->cur_page->allocation.x;
1743 points[i++].y = y + height - 1;
1748 if ((notebook->cur_page->allocation.y +
1749 notebook->cur_page->allocation.height -
1750 widget->style->klass->ythickness) <
1751 y + height - widget->style->klass->ythickness)
1754 points[i++].y = notebook->cur_page->allocation.y +
1755 notebook->cur_page->allocation.height -
1756 widget->style->klass->ythickness;
1758 if (points[0].y == (y + height))
1763 points[i++].y = y + height - 1;
1764 points[i].x = x + width - 1;
1765 points[i++].y = y + height - 1;
1766 points[i].x = x + width - 1;
1771 if (notebook->cur_page->allocation.y != y)
1774 points[i++].y = notebook->cur_page->allocation.y;
1779 if (notebook->cur_page->allocation.y != y)
1781 points[i].x = x + width - 1;
1782 points[i++].y = notebook->cur_page->allocation.y;
1785 points[i].x = x + width - 1;
1790 points[i++].y = y + height - 1;
1791 points[i].x = x + width - 1;
1792 points[i++].y = y + height - 1;
1794 if ((notebook->cur_page->allocation.y +
1795 notebook->cur_page->allocation.height -
1796 widget->style->klass->ythickness) <
1797 y + height - widget->style->klass->ythickness)
1799 points[i].x = x + width - 1;
1800 points[i++].y = notebook->cur_page->allocation.y +
1801 notebook->cur_page->allocation.height -
1802 widget->style->klass->ythickness;
1804 if (points[i - 1].y == (y + height))
1805 points[i - 1].y -= 1;
1811 gtk_draw_polygon (widget->style, widget->window,
1812 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1816 children = g_list_last (notebook->children);
1821 page = children->data;
1822 children = children->prev;
1824 if (!GTK_WIDGET_MAPPED (page->tab_label))
1826 else if (notebook->cur_page != page)
1827 gtk_notebook_draw_tab (notebook, page, area);
1830 if (showarrow && notebook->scrollable && notebook->show_tabs)
1832 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1833 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1835 if (notebook->cur_page &&
1836 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1837 (notebook->cur_page))->tab_label))
1838 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1840 else if (notebook->show_border)
1842 gtk_draw_shadow (widget->style, widget->window,
1843 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1844 x, y, width, height);
1851 gtk_notebook_draw (GtkWidget *widget,
1854 GtkNotebook *notebook;
1855 GdkRectangle child_area;
1857 g_return_if_fail (widget != NULL);
1858 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1859 g_return_if_fail (area != NULL);
1861 if (GTK_WIDGET_DRAWABLE (widget))
1863 notebook = GTK_NOTEBOOK (widget);
1865 gtk_notebook_paint (widget, area);
1866 gtk_widget_draw_focus (widget);
1868 if (notebook->cur_page &&
1869 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1870 gtk_widget_draw (notebook->cur_page->child, &child_area);
1875 gtk_notebook_expose (GtkWidget *widget,
1876 GdkEventExpose *event)
1878 GtkNotebook *notebook;
1879 GdkEventExpose child_event;
1881 g_return_val_if_fail (widget != NULL, FALSE);
1882 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1883 g_return_val_if_fail (event != NULL, FALSE);
1885 if (GTK_WIDGET_DRAWABLE (widget))
1887 notebook = GTK_NOTEBOOK (widget);
1889 gtk_notebook_paint (widget, &event->area);
1890 gtk_widget_draw_focus (widget);
1892 child_event = *event;
1893 if (notebook->cur_page &&
1894 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1895 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1897 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1904 gtk_notebook_button_press (GtkWidget *widget,
1905 GdkEventButton *event)
1907 GtkNotebook *notebook;
1908 GtkNotebookPage *page;
1912 g_return_val_if_fail (widget != NULL, FALSE);
1913 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1914 g_return_val_if_fail (event != NULL, FALSE);
1916 notebook = GTK_NOTEBOOK (widget);
1918 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1919 || notebook->button)
1922 if (event->window == notebook->panel)
1924 if (!GTK_WIDGET_HAS_FOCUS (widget))
1925 gtk_widget_grab_focus (widget);
1927 gtk_grab_add (widget);
1928 notebook->button = event->button;
1930 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1932 notebook->click_child = GTK_ARROW_LEFT;
1933 if (event->button == 1)
1935 if (!notebook->focus_tab || notebook->focus_tab->prev)
1936 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1938 if (!notebook->timer)
1940 notebook->timer = gtk_timeout_add
1941 (NOTEBOOK_INIT_SCROLL_DELAY,
1942 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1943 notebook->need_timer = TRUE;
1946 else if (event->button == 2)
1947 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1948 else if (event->button == 3)
1949 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1950 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1954 notebook->click_child = GTK_ARROW_RIGHT;
1955 if (event->button == 1)
1957 if (!notebook->focus_tab || notebook->focus_tab->next)
1958 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1959 if (!notebook->timer)
1961 notebook->timer = gtk_timeout_add
1962 (NOTEBOOK_INIT_SCROLL_DELAY,
1963 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1964 notebook->need_timer = TRUE;
1967 else if (event->button == 2)
1968 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1969 else if (event->button == 3)
1970 gtk_notebook_switch_focus_tab (notebook,
1971 g_list_last (notebook->children));
1972 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1975 else if (event->window == widget->window)
1977 if (event->button == 3 && notebook->menu)
1979 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1980 NULL, NULL, 3, event->time);
1985 children = notebook->children;
1988 page = children->data;
1990 if (GTK_WIDGET_VISIBLE (page->child) &&
1991 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1992 (event->x >= page->allocation.x) &&
1993 (event->y >= page->allocation.y) &&
1994 (event->x <= (page->allocation.x + page->allocation.width)) &&
1995 (event->y <= (page->allocation.y + page->allocation.height)))
1997 if (page == notebook->cur_page && notebook->focus_tab &&
1998 notebook->focus_tab != children &&
1999 GTK_WIDGET_HAS_FOCUS (notebook))
2001 GtkNotebookPage *old_page;
2003 notebook->child_has_focus = FALSE;
2004 old_page = (GtkNotebookPage *)
2005 (notebook->focus_tab->data);
2006 gtk_notebook_switch_focus_tab (notebook, children);
2007 gtk_notebook_focus_changed (notebook, old_page);
2011 gtk_notebook_switch_focus_tab (notebook, children);
2012 gtk_notebook_switch_page (notebook, page, num);
2013 gtk_widget_grab_focus (widget);
2017 children = children->next;
2020 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
2021 gtk_widget_grab_focus (widget);
2027 gtk_notebook_button_release (GtkWidget *widget,
2028 GdkEventButton *event)
2030 GtkNotebook *notebook;
2032 g_return_val_if_fail (widget != NULL, FALSE);
2033 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2034 g_return_val_if_fail (event != NULL, FALSE);
2036 if (event->type != GDK_BUTTON_RELEASE)
2039 notebook = GTK_NOTEBOOK (widget);
2041 if (event->button == notebook->button)
2045 if (notebook->timer)
2047 gtk_timeout_remove (notebook->timer);
2048 notebook->timer = 0;
2049 notebook->need_timer = FALSE;
2051 gtk_grab_remove (widget);
2052 click_child = notebook->click_child;
2053 notebook->click_child = 0;
2054 notebook->button = 0;
2055 gtk_notebook_draw_arrow (notebook, click_child);
2062 gtk_notebook_enter_notify (GtkWidget *widget,
2063 GdkEventCrossing *event)
2065 GtkNotebook *notebook;
2067 g_return_val_if_fail (widget != NULL, FALSE);
2068 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2069 g_return_val_if_fail (event != NULL, FALSE);
2071 notebook = GTK_NOTEBOOK (widget);
2073 if (event->window == notebook->panel)
2078 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
2080 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
2082 notebook->in_child = GTK_ARROW_LEFT;
2084 if (notebook->click_child == 0)
2085 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2089 notebook->in_child = GTK_ARROW_RIGHT;
2091 if (notebook->click_child == 0)
2092 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2100 gtk_notebook_leave_notify (GtkWidget *widget,
2101 GdkEventCrossing *event)
2103 GtkNotebook *notebook;
2105 g_return_val_if_fail (widget != NULL, FALSE);
2106 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2107 g_return_val_if_fail (event != NULL, FALSE);
2109 notebook = GTK_NOTEBOOK (widget);
2111 if (event->window == notebook->panel && !notebook->click_child)
2113 if (notebook->in_child == GTK_ARROW_LEFT)
2115 notebook->in_child = 0;
2116 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
2120 notebook->in_child = 0;
2121 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
2128 gtk_notebook_motion_notify (GtkWidget *widget,
2129 GdkEventMotion *event)
2131 GtkNotebook *notebook;
2133 g_return_val_if_fail (widget != NULL, FALSE);
2134 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2135 g_return_val_if_fail (event != NULL, FALSE);
2137 notebook = GTK_NOTEBOOK (widget);
2139 if (notebook->button)
2142 if (event->window == notebook->panel)
2148 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
2150 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
2151 notebook->in_child == GTK_ARROW_RIGHT)
2153 notebook->in_child = GTK_ARROW_LEFT;
2154 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2155 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2157 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
2158 notebook->in_child == GTK_ARROW_LEFT)
2160 notebook->in_child = GTK_ARROW_RIGHT;
2161 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2162 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2170 gtk_notebook_timer (GtkNotebook *notebook)
2172 g_return_val_if_fail (notebook != NULL, FALSE);
2173 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2175 if (notebook->timer)
2177 if (notebook->click_child == GTK_ARROW_LEFT)
2179 if (!notebook->focus_tab || notebook->focus_tab->prev)
2180 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
2182 else if (notebook->click_child == GTK_ARROW_RIGHT)
2184 if (!notebook->focus_tab || notebook->focus_tab->next)
2185 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
2188 if (notebook->need_timer)
2190 notebook->need_timer = FALSE;
2191 notebook->timer = gtk_timeout_add
2192 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
2193 (gpointer) notebook);
2202 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
2204 GtkStateType state_type;
2205 GtkShadowType shadow_type;
2208 g_return_if_fail (notebook != NULL);
2209 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2211 widget = GTK_WIDGET(notebook);
2213 if (GTK_WIDGET_DRAWABLE (notebook))
2215 if (notebook->in_child == arrow)
2217 if (notebook->click_child == arrow)
2218 state_type = GTK_STATE_ACTIVE;
2220 state_type = GTK_STATE_PRELIGHT;
2223 state_type = GTK_STATE_NORMAL;
2225 if (notebook->click_child == arrow)
2226 shadow_type = GTK_SHADOW_IN;
2228 shadow_type = GTK_SHADOW_OUT;
2230 if (arrow == GTK_ARROW_LEFT)
2232 if (notebook->focus_tab && !notebook->focus_tab->prev)
2234 shadow_type = GTK_SHADOW_ETCHED_IN;
2235 state_type = GTK_STATE_NORMAL;
2238 if (notebook->tab_pos == GTK_POS_LEFT ||
2239 notebook->tab_pos == GTK_POS_RIGHT)
2240 arrow = GTK_ARROW_UP;
2241 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2242 shadow_type, arrow, TRUE,
2243 0, 0, ARROW_SIZE, ARROW_SIZE);
2247 if (notebook->focus_tab && !notebook->focus_tab->next)
2249 shadow_type = GTK_SHADOW_ETCHED_IN;
2250 state_type = GTK_STATE_NORMAL;
2253 if (notebook->tab_pos == GTK_POS_LEFT ||
2254 notebook->tab_pos == GTK_POS_RIGHT)
2255 arrow = GTK_ARROW_DOWN;
2256 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2257 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2258 0, ARROW_SIZE, ARROW_SIZE);
2264 gtk_real_notebook_switch_page (GtkNotebook *notebook,
2265 GtkNotebookPage *page,
2268 g_return_if_fail (notebook != NULL);
2269 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2270 g_return_if_fail (page != NULL);
2272 if (notebook->cur_page == page)
2275 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
2276 gtk_widget_unmap (notebook->cur_page->child);
2278 notebook->cur_page = page;
2280 if (!notebook->focus_tab ||
2281 notebook->focus_tab->data != (gpointer) notebook->cur_page)
2282 notebook->focus_tab =
2283 g_list_find (notebook->children, notebook->cur_page);
2285 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
2287 if (GTK_WIDGET_MAPPED (notebook))
2289 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
2290 gtk_widget_map (notebook->cur_page->child);
2293 gtk_widget_map (notebook->cur_page->child);
2294 gtk_widget_size_allocate (GTK_WIDGET (notebook),
2295 >K_WIDGET (notebook)->allocation);
2299 if (GTK_WIDGET_DRAWABLE (notebook))
2300 gtk_widget_queue_draw (GTK_WIDGET (notebook));
2304 gtk_notebook_draw_tab (GtkNotebook *notebook,
2305 GtkNotebookPage *page,
2308 GdkRectangle child_area;
2309 GdkRectangle page_area;
2310 GtkStateType state_type;
2314 g_return_if_fail (notebook != NULL);
2315 g_return_if_fail (page != NULL);
2316 g_return_if_fail (area != NULL);
2318 if (!GTK_WIDGET_MAPPED (page->tab_label))
2321 page_area.x = page->allocation.x;
2322 page_area.y = page->allocation.y;
2323 page_area.width = page->allocation.width;
2324 page_area.height = page->allocation.height;
2326 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2330 switch (notebook->tab_pos)
2333 if (child_area.x + child_area.width >
2334 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2336 points[0].x = page->allocation.x + page->allocation.width - 1;
2337 points[0].y = page->allocation.y + page->allocation.height - 1;
2339 points[1].x = page->allocation.x + page->allocation.width - 1;
2340 points[1].y = page->allocation.y + TAB_CURVATURE;
2342 points[2].x = page->allocation.x + page->allocation.width
2343 - TAB_CURVATURE - 1;
2344 points[2].y = page->allocation.y;
2349 points[0].x = page->allocation.x + page->allocation.width
2351 points[0].y = page->allocation.y;
2355 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2356 (page == notebook->cur_page ||
2357 page == (GtkNotebookPage *)(notebook->children->data) ||
2358 (notebook->scrollable &&
2359 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2361 points[n].x = page->allocation.x + TAB_CURVATURE;
2362 points[n++].y = page->allocation.y;
2364 points[n].x = page->allocation.x;
2365 points[n++].y = page->allocation.y + TAB_CURVATURE;
2367 points[n].x = page->allocation.x;
2368 points[n++].y = page->allocation.y + page->allocation.height - 1;
2372 points[n].x = page->allocation.x + TAB_OVERLAP;
2373 points[n++].y = page->allocation.y;
2376 case GTK_POS_BOTTOM:
2377 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2378 (page == notebook->cur_page ||
2379 page == (GtkNotebookPage *)(notebook->children->data) ||
2380 (notebook->scrollable &&
2381 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2383 points[0].x = page->allocation.x;
2384 points[0].y = page->allocation.y;
2386 points[1].x = page->allocation.x;
2387 points[1].y = page->allocation.y + page->allocation.height
2388 - TAB_CURVATURE - 1;
2390 points[2].x = page->allocation.x + TAB_CURVATURE;
2391 points[2].y = page->allocation.y + page->allocation.height - 1;
2396 points[0].x = page->allocation.x + TAB_OVERLAP;
2397 points[0].y = page->allocation.y + page->allocation.height - 1;
2401 if (child_area.x + child_area.width >
2402 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2404 points[n].x = page->allocation.x + page->allocation.width
2405 - TAB_CURVATURE - 1;
2406 points[n++].y = page->allocation.y + page->allocation.height - 1;
2408 points[n].x = page->allocation.x + page->allocation.width - 1;
2409 points[n++].y = page->allocation.y + page->allocation.height
2410 - TAB_CURVATURE - 1;
2412 points[n].x = page->allocation.x + page->allocation.width - 1;
2413 points[n++].y = page->allocation.y;
2417 points[n].x = page->allocation.x + page->allocation.width
2419 points[n++].y = page->allocation.y + page->allocation.height - 1;
2423 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2424 (page == notebook->cur_page ||
2425 page == (GtkNotebookPage *)(notebook->children->data) ||
2426 (notebook->scrollable &&
2427 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2429 points[0].x = page->allocation.x + page->allocation.width - 1;
2430 points[0].y = page->allocation.y;
2432 points[1].x = page->allocation.x + TAB_CURVATURE;
2433 points[1].y = page->allocation.y;
2435 points[2].x = page->allocation.x;
2436 points[2].y = page->allocation.y + TAB_CURVATURE;
2441 points[0].x = page->allocation.x;
2442 points[0].y = page->allocation.y + TAB_OVERLAP;
2446 if (child_area.y + child_area.height >
2447 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2449 points[n].x = page->allocation.x;
2450 points[n++].y = page->allocation.y + page->allocation.height
2451 - TAB_CURVATURE - 1;
2453 points[n].x = page->allocation.x + TAB_CURVATURE;
2454 points[n++].y = page->allocation.y + page->allocation.height - 1;
2456 points[n].x = page->allocation.x + page->allocation.width - 1;
2457 points[n++].y = page->allocation.y + page->allocation.height - 1;
2461 points[n].x = page->allocation.x;
2462 points[n++].y = page->allocation.y + page->allocation.height
2467 if (child_area.y + child_area.height >
2468 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2470 points[0].x = page->allocation.x;
2471 points[0].y = page->allocation.y + page->allocation.height - 1;
2473 points[1].x = page->allocation.x + page->allocation.width
2474 - TAB_CURVATURE - 1;
2475 points[1].y = page->allocation.y + page->allocation.height - 1;
2477 points[2].x = page->allocation.x + page->allocation.width - 1;
2478 points[2].y = page->allocation.y + page->allocation.height
2479 - TAB_CURVATURE - 1;
2484 points[0].x = page->allocation.x + page->allocation.width - 1;
2485 points[0].y = page->allocation.y + page->allocation.height
2490 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2491 (page == notebook->cur_page ||
2492 page == (GtkNotebookPage *)(notebook->children->data) ||
2493 (notebook->scrollable &&
2494 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2496 points[n].x = page->allocation.x + page->allocation.width - 1;
2497 points[n++].y = page->allocation.y + TAB_CURVATURE;
2499 points[n].x = page->allocation.x + page->allocation.width
2500 - TAB_CURVATURE - 1;
2501 points[n++].y = page->allocation.y;
2503 points[n].x = page->allocation.x;
2504 points[n++].y = page->allocation.y;
2508 points[n].x = page->allocation.x + page->allocation.width - 1;
2509 points[n++].y = page->allocation.y + TAB_OVERLAP;
2514 widget = GTK_WIDGET(notebook);
2516 if (notebook->cur_page == page)
2518 state_type = GTK_STATE_NORMAL;
2522 state_type = GTK_STATE_ACTIVE;
2523 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2524 TRUE, child_area.x, child_area.y,
2525 child_area.width, child_area.height);
2528 gtk_draw_polygon (widget->style, widget->window, state_type,
2529 GTK_SHADOW_OUT, points, n, FALSE);
2531 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2532 gtk_widget_draw (page->tab_label, &child_area);
2537 gtk_notebook_set_focus_child (GtkContainer *container,
2540 GtkNotebook *notebook;
2542 g_return_if_fail (container != NULL);
2543 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2547 g_return_if_fail (GTK_IS_WIDGET (child));
2549 notebook = GTK_NOTEBOOK (container);
2551 notebook->child_has_focus = TRUE;
2552 if (!notebook->focus_tab)
2555 GtkNotebookPage *page;
2557 children = notebook->children;
2560 page = children->data;
2561 if (page->child == child || page->tab_label == child)
2562 gtk_notebook_switch_focus_tab (notebook, children);
2563 children = children->next;
2567 parent_class->set_focus_child (container, child);
2571 gtk_notebook_focus_in (GtkWidget *widget,
2572 GdkEventFocus *event)
2574 g_return_val_if_fail (widget != NULL, FALSE);
2575 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2576 g_return_val_if_fail (event != NULL, FALSE);
2578 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2579 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2580 gtk_widget_draw_focus (widget);
2586 gtk_notebook_focus_out (GtkWidget *widget,
2587 GdkEventFocus *event)
2589 g_return_val_if_fail (widget != NULL, FALSE);
2590 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2591 g_return_val_if_fail (event != NULL, FALSE);
2593 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2594 gtk_widget_draw_focus (widget);
2600 gtk_notebook_draw_focus (GtkWidget *widget)
2602 GtkNotebook *notebook;
2604 g_return_if_fail (widget != NULL);
2605 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2607 notebook = GTK_NOTEBOOK (widget);
2609 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2610 notebook->focus_tab)
2612 GtkNotebookPage *page;
2615 page = notebook->focus_tab->data;
2617 if (GTK_WIDGET_HAS_FOCUS (widget))
2618 gc = widget->style->black_gc;
2619 else if (page == notebook->cur_page)
2620 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2622 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2624 gdk_draw_rectangle (widget->window,
2626 page->tab_label->allocation.x - 1,
2627 page->tab_label->allocation.y - 1,
2628 page->tab_label->allocation.width + 1,
2629 page->tab_label->allocation.height + 1);
2634 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2638 g_return_if_fail (notebook != NULL);
2639 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2641 widget = GTK_WIDGET (notebook);
2643 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs)
2647 if (notebook->focus_tab)
2649 GtkNotebookPage *page;
2651 page = notebook->focus_tab->data;
2653 if (GTK_WIDGET_HAS_FOCUS (widget))
2654 gc = widget->style->black_gc;
2655 else if (page == notebook->cur_page)
2656 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2658 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2660 gdk_draw_rectangle (widget->window,
2662 page->tab_label->allocation.x - 1,
2663 page->tab_label->allocation.y - 1,
2664 page->tab_label->allocation.width + 1,
2665 page->tab_label->allocation.height + 1);
2670 if (old_page == notebook->cur_page)
2671 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2673 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2675 gdk_draw_rectangle (widget->window,
2677 old_page->tab_label->allocation.x - 1,
2678 old_page->tab_label->allocation.y - 1,
2679 old_page->tab_label->allocation.width + 1,
2680 old_page->tab_label->allocation.height + 1);
2686 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2692 GtkNotebookPage *page = NULL;
2696 switch (notebook->tab_pos)
2699 case GTK_POS_BOTTOM:
2702 page = children->data;
2703 *tab_space -= page->requisition.width;
2704 if (*tab_space < 0 || children == *end)
2708 *tab_space = - (*tab_space + page->requisition.width);
2713 if (direction == STEP_NEXT)
2714 children = children->next;
2716 children = children->prev;
2723 page = children->data;
2724 *tab_space -= page->requisition.height;
2725 if (*tab_space < 0 || children == *end)
2729 *tab_space = - (*tab_space + page->requisition.height);
2734 if (direction == STEP_NEXT)
2735 children = children->next;
2737 children = children->prev;
2744 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2745 GtkAllocation *allocation)
2748 GtkContainer *container;
2749 GtkNotebookPage *page = NULL;
2750 GtkAllocation child_allocation;
2752 GList *last_child = NULL;
2753 gint showarrow = FALSE;
2762 if (!notebook->show_tabs || !notebook->children)
2765 widget = GTK_WIDGET (notebook);
2766 container = GTK_CONTAINER (notebook);
2768 child_allocation.x = container->border_width;
2769 child_allocation.y = container->border_width;
2771 switch (notebook->tab_pos)
2773 case GTK_POS_BOTTOM:
2774 child_allocation.y = (allocation->height -
2775 notebook->cur_page->requisition.height -
2776 container->border_width);
2778 child_allocation.height = notebook->cur_page->requisition.height;
2781 child_allocation.x = (allocation->width -
2782 notebook->cur_page->requisition.width -
2783 container->border_width);
2785 child_allocation.width = notebook->cur_page->requisition.width;
2789 if (notebook->scrollable)
2793 children = notebook->children;
2795 if (notebook->focus_tab)
2796 focus_tab = notebook->focus_tab;
2797 else if (notebook->first_tab)
2798 focus_tab = notebook->first_tab;
2800 focus_tab = notebook->children;
2802 switch (notebook->tab_pos)
2805 case GTK_POS_BOTTOM:
2808 page = children->data;
2809 children = children->next;
2810 tab_space += page->requisition.width;
2812 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2815 page = focus_tab->data;
2817 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2818 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2819 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2821 page = notebook->children->data;
2822 if (notebook->tab_pos == GTK_POS_TOP)
2823 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2825 y = (allocation->height - container->border_width -
2826 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2833 page = children->data;
2834 children = children->next;
2835 tab_space += page->requisition.height;
2837 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2840 page = focus_tab->data;
2841 tab_space = (allocation->height -
2842 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2843 2 * container->border_width - page->requisition.height);
2844 y = allocation->height - container->border_width - ARROW_SIZE;
2846 page = notebook->children->data;
2847 if (notebook->tab_pos == GTK_POS_LEFT)
2848 x = (container->border_width +
2849 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2851 x = (allocation->width - container->border_width -
2852 (2 * ARROW_SIZE - ARROW_SPACING) -
2853 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2857 if (showarrow) /* first_tab <- focus_tab */
2859 children = focus_tab->prev;
2862 if (notebook->first_tab == children)
2864 children = children->prev;
2868 notebook->first_tab = focus_tab;
2870 gtk_notebook_calc_tabs (notebook, focus_tab->prev,
2871 &(notebook->first_tab), &tab_space,
2875 notebook->first_tab = notebook->first_tab->next;
2876 if (!notebook->first_tab)
2877 notebook->first_tab = focus_tab;
2878 last_child = focus_tab->next;
2880 else /* focus_tab -> end */
2882 if (!notebook->first_tab)
2883 notebook->first_tab = notebook->children;
2886 gtk_notebook_calc_tabs (notebook, focus_tab->next,
2887 &children, &tab_space, STEP_NEXT);
2890 last_child = children;
2891 else /* start <- first_tab */
2895 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2896 &children, &tab_space, STEP_PREV);
2898 notebook->first_tab = children->next;
2900 notebook->first_tab = notebook->children;
2904 if (GTK_WIDGET_REALIZED (notebook))
2906 gdk_window_move (notebook->panel, x, y);
2907 gdk_window_show (notebook->panel);
2912 tab_space = -tab_space;
2914 children = notebook->first_tab;
2915 while (children != last_child)
2917 children = children->next;
2924 children = notebook->children;
2925 while (children != notebook->first_tab)
2927 page = children->data;
2928 children = children->next;
2930 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2931 gtk_widget_unmap (page->tab_label);
2934 children = last_child;
2937 page = children->data;
2938 children = children->next;
2940 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2941 gtk_widget_unmap (page->tab_label);
2944 else /* !showarrow */
2946 notebook->first_tab = notebook->children;
2948 if (GTK_WIDGET_REALIZED (notebook))
2949 gdk_window_hide (notebook->panel);
2951 children = notebook->first_tab;
2954 children = notebook->children;
2957 while (children != last_child)
2959 page = children->data;
2960 children = children->next;
2962 if (GTK_WIDGET_VISIBLE (page->child))
2964 new_fill = (tab_space * i++) / n;
2965 switch (notebook->tab_pos)
2968 case GTK_POS_BOTTOM:
2969 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2973 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2976 old_fill = new_fill;
2977 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2979 switch (notebook->tab_pos)
2982 case GTK_POS_BOTTOM:
2983 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2987 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2991 if (GTK_WIDGET_REALIZED (notebook) &&
2992 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2993 gtk_widget_map (page->tab_label);
2999 gtk_notebook_page_allocate (GtkNotebook *notebook,
3000 GtkNotebookPage *page,
3001 GtkAllocation *allocation)
3003 GtkAllocation child_allocation;
3004 gint xthickness, ythickness;
3006 g_return_if_fail (notebook != NULL);
3007 g_return_if_fail (page != NULL);
3008 g_return_if_fail (allocation != NULL);
3010 page->allocation = *allocation;
3012 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
3013 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
3015 if (notebook->cur_page != page)
3017 switch (notebook->tab_pos)
3020 page->allocation.y += ythickness;
3021 case GTK_POS_BOTTOM:
3022 page->allocation.height -= ythickness;
3025 page->allocation.x += xthickness;
3027 page->allocation.width -= xthickness;
3032 switch (notebook->tab_pos)
3035 child_allocation.x = xthickness + notebook->tab_border;
3036 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
3037 child_allocation.width = page->allocation.width - child_allocation.x * 2;
3038 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
3039 child_allocation.x += page->allocation.x;
3041 case GTK_POS_BOTTOM:
3042 child_allocation.x = xthickness + notebook->tab_border;
3043 child_allocation.width = page->allocation.width - child_allocation.x * 2;
3044 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
3045 child_allocation.x += page->allocation.x;
3046 child_allocation.y = page->allocation.y + notebook->tab_border;
3049 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
3050 child_allocation.y = ythickness + notebook->tab_border;
3051 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3052 child_allocation.height = page->allocation.height - child_allocation.y * 2;
3053 child_allocation.y += page->allocation.y;
3056 child_allocation.y = ythickness + notebook->tab_border;
3057 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3058 child_allocation.height = page->allocation.height - child_allocation.y * 2;
3059 child_allocation.x = page->allocation.x + notebook->tab_border;
3060 child_allocation.y += page->allocation.y;
3064 if (page->tab_label)
3065 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3069 gtk_notebook_menu_switch_page (GtkWidget *widget,
3070 GtkNotebookPage *page)
3072 GtkNotebook *notebook;
3076 g_return_if_fail (widget != NULL);
3077 g_return_if_fail (page != NULL);
3079 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3080 (GTK_MENU (widget->parent)));
3082 if (notebook->cur_page == page)
3086 children = notebook->children;
3087 while (children && children->data != page)
3089 children = children->next;
3093 gtk_signal_emit (GTK_OBJECT (notebook),
3094 notebook_signals[SWITCH_PAGE],
3100 gtk_notebook_switch_page (GtkNotebook *notebook,
3101 GtkNotebookPage *page,
3104 g_return_if_fail (notebook != NULL);
3105 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3106 g_return_if_fail (page != NULL);
3108 if (notebook->cur_page == page)
3111 gtk_signal_emit (GTK_OBJECT (notebook),
3112 notebook_signals[SWITCH_PAGE],
3118 gtk_notebook_focus (GtkContainer *container,
3119 GtkDirectionType direction)
3121 GtkNotebook *notebook;
3122 GtkWidget *focus_child;
3123 GtkNotebookPage *page = NULL;
3124 GtkNotebookPage *old_page = NULL;
3127 g_return_val_if_fail (container != NULL, FALSE);
3128 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
3130 notebook = GTK_NOTEBOOK (container);
3132 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
3135 focus_child = container->focus_child;
3136 gtk_container_set_focus_child (container, NULL);
3138 if (!notebook->show_tabs)
3140 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
3142 if (GTK_IS_CONTAINER (notebook->cur_page->child))
3144 if (gtk_container_focus
3145 (GTK_CONTAINER (notebook->cur_page->child), direction))
3148 else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
3152 gtk_widget_grab_focus (notebook->cur_page->child);
3160 if (notebook->focus_tab)
3161 old_page = notebook->focus_tab->data;
3165 if (focus_child && old_page && focus_child == old_page->child &&
3166 notebook->child_has_focus)
3168 if (GTK_WIDGET_VISIBLE (old_page->child))
3170 if (GTK_IS_CONTAINER (old_page->child) &&
3171 !GTK_WIDGET_HAS_FOCUS (old_page->child))
3173 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
3177 gtk_widget_grab_focus (GTK_WIDGET(notebook));
3185 case GTK_DIR_TAB_FORWARD:
3188 if (!notebook->focus_tab)
3189 gtk_notebook_switch_focus_tab (notebook, notebook->children);
3191 gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->next);
3193 if (!notebook->focus_tab)
3195 gtk_notebook_focus_changed (notebook, old_page);
3199 page = notebook->focus_tab->data;
3203 case GTK_DIR_TAB_BACKWARD:
3206 if (!notebook->focus_tab)
3207 gtk_notebook_switch_focus_tab
3208 (notebook, g_list_last (notebook->children));
3210 gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->prev);
3212 if (!notebook->focus_tab)
3214 gtk_notebook_focus_changed (notebook, old_page);
3218 page = notebook->focus_tab->data;
3225 if (!GTK_WIDGET_HAS_FOCUS (container) )
3226 gtk_widget_grab_focus (GTK_WIDGET (container));
3228 if (GTK_WIDGET_MAPPED (page->tab_label))
3229 gtk_notebook_focus_changed (notebook, old_page);
3232 gtk_notebook_pages_allocate (notebook,
3233 &(GTK_WIDGET (notebook)->allocation));
3234 gtk_notebook_expose_tabs (notebook);
3242 gtk_notebook_page_select (GtkNotebook *notebook)
3244 g_return_val_if_fail (notebook != NULL, FALSE);
3245 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3247 if (notebook->focus_tab)
3249 GtkNotebookPage *page;
3253 page = notebook->focus_tab->data;
3255 children = notebook->children;
3257 while (children != notebook->focus_tab)
3259 children = children->next;
3263 gtk_notebook_switch_page (notebook, page, num);
3265 if (GTK_WIDGET_VISIBLE (page->child))
3267 if (GTK_IS_CONTAINER (page->child))
3269 if (gtk_container_focus (GTK_CONTAINER (page->child),
3270 GTK_DIR_TAB_FORWARD))
3273 else if (GTK_WIDGET_CAN_FOCUS (page->child))
3275 gtk_widget_grab_focus (page->child);
3284 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3288 GtkNotebookPage *old_page = NULL;
3289 GtkNotebookPage *page;
3291 g_return_if_fail (notebook != NULL);
3292 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3294 if (notebook->focus_tab == new_child)
3297 old_tab = notebook->focus_tab;
3298 notebook->focus_tab = new_child;
3300 if (notebook->scrollable)
3302 if ((new_child == NULL) != (old_tab == NULL))
3304 gdk_window_clear (notebook->panel);
3305 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3306 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3311 if ((old_tab->prev == NULL) != (new_child->prev == NULL))
3313 gdk_window_clear_area (notebook->panel, 0, 0,
3314 ARROW_SIZE, ARROW_SIZE);
3315 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3317 if ((old_tab->next == NULL) != (new_child->next == NULL))
3319 gdk_window_clear_area (notebook->panel,
3320 ARROW_SIZE + ARROW_SPACING, 0,
3321 ARROW_SIZE, ARROW_SIZE);
3322 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3327 if (!notebook->focus_tab)
3331 old_page = old_tab->data;
3333 page = notebook->focus_tab->data;
3334 if (GTK_WIDGET_MAPPED (page->tab_label))
3335 gtk_notebook_focus_changed (notebook, old_page);
3338 gtk_notebook_pages_allocate (notebook,
3339 &(GTK_WIDGET (notebook)->allocation));
3340 gtk_notebook_expose_tabs (notebook);
3345 gtk_notebook_key_press (GtkWidget *widget,
3348 GtkNotebook *notebook;
3349 GtkDirectionType direction = 0;
3352 g_return_val_if_fail (widget != NULL, FALSE);
3353 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3354 g_return_val_if_fail (event != NULL, FALSE);
3356 notebook = GTK_NOTEBOOK (widget);
3359 if (!notebook->children || !notebook->show_tabs)
3362 switch (event->keyval)
3365 direction = GTK_DIR_UP;
3368 direction = GTK_DIR_LEFT;
3371 direction = GTK_DIR_DOWN;
3374 direction = GTK_DIR_RIGHT;
3377 case GDK_ISO_Left_Tab:
3378 if (event->state & GDK_SHIFT_MASK)
3379 direction = GTK_DIR_TAB_BACKWARD;
3381 direction = GTK_DIR_TAB_FORWARD;
3384 gtk_notebook_switch_focus_tab (notebook, notebook->children);
3387 gtk_notebook_switch_focus_tab (notebook,
3388 g_list_last (notebook->children));
3392 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
3398 return gtk_container_focus (GTK_CONTAINER (widget), direction);
3403 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3406 g_return_if_fail (notebook != NULL);
3407 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3409 if (notebook->tab_border != tab_border)
3411 notebook->tab_border = tab_border;
3413 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3414 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3419 gtk_notebook_update_labels (GtkNotebook *notebook,
3423 GtkNotebookPage *page;
3430 sprintf (string, "Page %u", page_num);
3431 if (notebook->show_tabs && page->default_tab)
3432 gtk_label_set (GTK_LABEL (page->tab_label), string);
3433 if (notebook->menu && page->default_menu)
3435 if (GTK_IS_LABEL (page->tab_label))
3436 gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
3438 gtk_label_set (GTK_LABEL (page->menu_label), string);
3445 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3446 GtkNotebookPage *page,
3449 GtkWidget *menu_item;
3451 if (page->default_menu)
3453 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3454 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3456 page->menu_label = gtk_label_new ("");
3457 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3460 gtk_widget_show (page->menu_label);
3461 menu_item = gtk_menu_item_new ();
3462 gtk_widget_freeze_accelerators (menu_item);
3463 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3464 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
3465 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3466 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3467 gtk_widget_show (menu_item);
3471 gtk_notebook_popup_enable (GtkNotebook *notebook)
3473 GtkNotebookPage *page;
3476 g_return_if_fail (notebook != NULL);
3477 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3482 notebook->menu = gtk_menu_new ();
3484 children = notebook->children;
3487 page = children->data;
3488 children = children->next;
3489 gtk_notebook_menu_item_create (notebook, page, -1);
3491 gtk_notebook_update_labels (notebook, notebook->children,1);
3493 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
3494 gtk_notebook_menu_detacher);
3498 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3501 gtk_widget_unparent (GTK_BIN(widget)->child);
3502 GTK_BIN(widget)->child = NULL;
3506 gtk_notebook_popup_disable (GtkNotebook *notebook)
3508 g_return_if_fail (notebook != NULL);
3509 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3511 if (!notebook->menu)
3514 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
3515 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
3516 gtk_widget_destroy (notebook->menu);
3520 gtk_notebook_menu_detacher (GtkWidget *widget,
3523 GtkNotebook *notebook;
3525 g_return_if_fail (widget != NULL);
3526 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3528 notebook = GTK_NOTEBOOK (widget);
3529 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3531 notebook->menu = NULL;
3535 gtk_notebook_find_page (gconstpointer a,
3538 return (((GtkNotebookPage *) a)->child != b);