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)
47 typedef void (*GtkNotebookSignal) (GtkObject *object,
48 GtkNotebookPage *arg1,
52 static void gtk_notebook_class_init (GtkNotebookClass *klass);
53 static void gtk_notebook_init (GtkNotebook *notebook);
54 static void gtk_notebook_destroy (GtkObject *object);
55 static void gtk_notebook_map (GtkWidget *widget);
56 static void gtk_notebook_unmap (GtkWidget *widget);
57 static void gtk_notebook_realize (GtkWidget *widget);
58 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
59 static void gtk_notebook_size_request (GtkWidget *widget,
60 GtkRequisition *requisition);
61 static void gtk_notebook_size_allocate (GtkWidget *widget,
62 GtkAllocation *allocation);
63 static void gtk_notebook_paint (GtkWidget *widget,
65 static void gtk_notebook_draw (GtkWidget *widget,
67 static gint gtk_notebook_expose (GtkWidget *widget,
68 GdkEventExpose *event);
69 static gint gtk_notebook_button_press (GtkWidget *widget,
70 GdkEventButton *event);
71 static gint gtk_notebook_button_release (GtkWidget *widget,
72 GdkEventButton *event);
73 static gint gtk_notebook_enter_notify (GtkWidget *widget,
74 GdkEventCrossing *event);
75 static gint gtk_notebook_leave_notify (GtkWidget *widget,
76 GdkEventCrossing *event);
77 static gint gtk_notebook_motion_notify (GtkWidget *widget,
78 GdkEventMotion *event);
79 static gint gtk_notebook_key_press (GtkWidget *widget,
81 static void gtk_notebook_add (GtkContainer *container,
83 static void gtk_notebook_remove (GtkContainer *container,
85 static void gtk_notebook_real_remove (GtkNotebook *notebook,
88 static void gtk_notebook_foreach (GtkContainer *container,
90 gpointer callback_data);
91 static void gtk_notebook_switch_page (GtkNotebook *notebook,
92 GtkNotebookPage *page,
94 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
95 GtkNotebookPage *page,
97 static gint gtk_notebook_focus_in (GtkWidget *widget,
98 GdkEventFocus *event);
99 static gint gtk_notebook_focus_out (GtkWidget *widget,
100 GdkEventFocus *event);
101 static void gtk_notebook_draw_focus (GtkWidget *widget);
102 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
103 GtkNotebookPage *old_page);
104 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
105 GtkAllocation *allocation);
106 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
107 GtkNotebookPage *page,
108 GtkAllocation *allocation);
109 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
111 static gint gtk_notebook_timer (GtkNotebook *notebook);
112 static gint gtk_notebook_focus (GtkContainer *container,
113 GtkDirectionType direction);
114 static gint gtk_notebook_page_select (GtkNotebook *notebook);
115 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
120 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
121 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
123 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
124 GtkNotebookPage *page);
125 static void gtk_notebook_marshal_signal (GtkObject *object,
129 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
130 GtkNotebookPage *page);
131 static void gtk_notebook_update_labels (GtkNotebook *notebook,
134 static void gtk_notebook_menu_detacher (GtkWidget *widget,
136 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
138 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
139 GtkNotebookPage *page,
143 static GtkContainerClass *parent_class = NULL;
144 static guint notebook_signals[LAST_SIGNAL] = { 0 };
147 gtk_notebook_get_type ()
149 static guint notebook_type = 0;
153 GtkTypeInfo notebook_info =
156 sizeof (GtkNotebook),
157 sizeof (GtkNotebookClass),
158 (GtkClassInitFunc) gtk_notebook_class_init,
159 (GtkObjectInitFunc) gtk_notebook_init,
160 (GtkArgSetFunc) NULL,
161 (GtkArgGetFunc) NULL,
164 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
167 return notebook_type;
171 gtk_notebook_class_init (GtkNotebookClass *class)
173 GtkObjectClass *object_class;
174 GtkWidgetClass *widget_class;
175 GtkContainerClass *container_class;
177 object_class = (GtkObjectClass*) class;
178 widget_class = (GtkWidgetClass*) class;
179 container_class = (GtkContainerClass*) class;
181 parent_class = gtk_type_class (gtk_container_get_type ());
183 notebook_signals[SWITCH_PAGE] =
184 gtk_signal_new ("switch_page",
187 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
188 gtk_notebook_marshal_signal,
193 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
195 object_class->destroy = gtk_notebook_destroy;
197 widget_class->map = gtk_notebook_map;
198 widget_class->unmap = gtk_notebook_unmap;
199 widget_class->realize = gtk_notebook_realize;
200 widget_class->size_request = gtk_notebook_size_request;
201 widget_class->size_allocate = gtk_notebook_size_allocate;
202 widget_class->draw = gtk_notebook_draw;
203 widget_class->expose_event = gtk_notebook_expose;
204 widget_class->button_press_event = gtk_notebook_button_press;
205 widget_class->button_release_event = gtk_notebook_button_release;
206 widget_class->enter_notify_event = gtk_notebook_enter_notify;
207 widget_class->leave_notify_event = gtk_notebook_leave_notify;
208 widget_class->motion_notify_event = gtk_notebook_motion_notify;
209 widget_class->key_press_event = gtk_notebook_key_press;
210 widget_class->focus_in_event = gtk_notebook_focus_in;
211 widget_class->focus_out_event = gtk_notebook_focus_out;
212 widget_class->draw_focus = gtk_notebook_draw_focus;
214 container_class->add = gtk_notebook_add;
215 container_class->remove = gtk_notebook_remove;
216 container_class->foreach = gtk_notebook_foreach;
217 container_class->focus = gtk_notebook_focus;
219 class->switch_page = gtk_real_notebook_switch_page;
223 gtk_notebook_init (GtkNotebook *notebook)
225 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
227 notebook->cur_page = NULL;
228 notebook->children = NULL;
229 notebook->first_tab = NULL;
230 notebook->focus_tab = NULL;
231 notebook->panel = NULL;
232 notebook->menu = NULL;
234 notebook->tab_border = 3;
235 notebook->show_tabs = TRUE;
236 notebook->show_border = TRUE;
237 notebook->tab_pos = GTK_POS_TOP;
238 notebook->scrollable = FALSE;
239 notebook->in_child = 0;
240 notebook->click_child = 0;
241 notebook->button = 0;
242 notebook->need_timer = 0;
248 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
252 gtk_notebook_destroy (GtkObject *object)
254 GtkNotebook *notebook;
256 g_return_if_fail (object != NULL);
257 g_return_if_fail (GTK_IS_NOTEBOOK (object));
259 notebook = GTK_NOTEBOOK (object);
262 gtk_notebook_popup_disable (notebook);
264 GTK_OBJECT_CLASS (parent_class)->destroy (object);
268 gtk_notebook_append_page (GtkNotebook *notebook,
270 GtkWidget *tab_label)
272 g_return_if_fail (notebook != NULL);
273 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
274 g_return_if_fail (child != NULL);
276 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
280 gtk_notebook_append_page_menu (GtkNotebook *notebook,
282 GtkWidget *tab_label,
283 GtkWidget *menu_label)
285 g_return_if_fail (notebook != NULL);
286 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
287 g_return_if_fail (child != NULL);
289 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
293 gtk_notebook_prepend_page (GtkNotebook *notebook,
295 GtkWidget *tab_label)
297 g_return_if_fail (notebook != NULL);
298 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
299 g_return_if_fail (child != NULL);
301 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
305 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
307 GtkWidget *tab_label,
308 GtkWidget *menu_label)
310 g_return_if_fail (notebook != NULL);
311 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
312 g_return_if_fail (child != NULL);
314 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
318 gtk_notebook_insert_page (GtkNotebook *notebook,
320 GtkWidget *tab_label,
323 g_return_if_fail (notebook != NULL);
324 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
325 g_return_if_fail (child != NULL);
327 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
331 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
333 GtkWidget *tab_label,
334 GtkWidget *menu_label,
337 GtkNotebookPage *page;
340 g_return_if_fail (notebook != NULL);
341 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
342 g_return_if_fail (child != NULL);
344 page = g_new (GtkNotebookPage, 1);
346 page->requisition.width = 0;
347 page->requisition.height = 0;
348 page->allocation.x = 0;
349 page->allocation.y = 0;
350 page->allocation.width = 0;
351 page->allocation.height = 0;
352 page->default_menu = FALSE;
353 page->default_tab = FALSE;
355 nchildren = g_list_length (notebook->children);
356 if ((position < 0) || (position > nchildren))
357 position = nchildren;
359 notebook->children = g_list_insert (notebook->children, page, position);
363 page->default_tab = TRUE;
364 if (notebook->show_tabs)
365 tab_label = gtk_label_new ("");
367 page->tab_label = tab_label;
368 page->menu_label = menu_label;
371 page->default_menu = TRUE;
374 gtk_widget_ref (page->menu_label);
375 gtk_object_sink (GTK_OBJECT(page->menu_label));
379 gtk_notebook_menu_item_create (notebook, page, position);
381 gtk_notebook_update_labels
382 (notebook, g_list_nth (notebook->children, position), position + 1);
384 if (!notebook->first_tab)
385 notebook->first_tab = notebook->children;
387 if (!notebook->focus_tab)
388 notebook->focus_tab = notebook->children;
390 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
393 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
394 gtk_widget_show (tab_label);
397 if (!notebook->cur_page)
398 gtk_notebook_switch_page (notebook, page, 0);
400 if (GTK_WIDGET_VISIBLE (notebook))
402 if (GTK_WIDGET_REALIZED (notebook) &&
403 !GTK_WIDGET_REALIZED (child))
404 gtk_widget_realize (child);
406 if (GTK_WIDGET_MAPPED (notebook) &&
407 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
408 gtk_widget_map (child);
412 if (GTK_WIDGET_REALIZED (notebook) &&
413 !GTK_WIDGET_REALIZED (tab_label))
414 gtk_widget_realize (tab_label);
416 if (GTK_WIDGET_MAPPED (notebook) &&
417 !GTK_WIDGET_MAPPED (tab_label))
418 gtk_widget_map (tab_label);
422 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
423 gtk_widget_queue_resize (child);
427 gtk_notebook_remove_page (GtkNotebook *notebook,
432 g_return_if_fail (notebook != NULL);
433 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
435 if ((list = g_list_nth (notebook->children, page_num)))
436 gtk_notebook_real_remove (notebook, list, page_num);
440 gtk_notebook_add (GtkContainer *container,
443 g_return_if_fail (container != NULL);
444 g_return_if_fail (GTK_IS_NOTEBOOK (container));
445 g_return_if_fail (widget != NULL);
447 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
452 gtk_notebook_remove (GtkContainer *container,
455 GtkNotebook *notebook;
456 GtkNotebookPage *page;
460 g_return_if_fail (container != NULL);
461 g_return_if_fail (GTK_IS_NOTEBOOK (container));
462 g_return_if_fail (widget != NULL);
464 notebook = GTK_NOTEBOOK (container);
466 children = notebook->children;
470 page = children->data;
471 if (page->child == widget)
473 gtk_notebook_real_remove (notebook, children, page_num);
477 children = children->next;
482 gtk_notebook_real_remove (GtkNotebook *notebook,
486 GtkNotebookPage *page;
488 gint need_resize = FALSE;
492 next_list = list->prev;
497 next_list = list->next;
503 if (notebook->cur_page == list->data)
505 notebook->cur_page = NULL;
508 page = next_list->data;
509 gtk_notebook_switch_page (notebook, page, page_num);
513 if (list == notebook->first_tab)
514 notebook->first_tab = next_list;
515 if (list == notebook->focus_tab)
516 notebook->focus_tab = next_list;
520 if ((GTK_WIDGET_VISIBLE (page->child) ||
521 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
522 && GTK_WIDGET_VISIBLE (notebook))
525 gtk_widget_unparent (page->child);
528 gtk_widget_unparent (page->tab_label);
532 gtk_container_remove (GTK_CONTAINER (notebook->menu),
533 page->menu_label->parent);
534 gtk_widget_queue_resize (notebook->menu);
536 if (!page->default_menu)
537 gtk_widget_unref (page->menu_label);
539 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
541 notebook->children = g_list_remove_link (notebook->children, list);
546 gtk_widget_queue_resize (GTK_WIDGET (notebook));
551 gtk_notebook_current_page (GtkNotebook *notebook)
556 g_return_val_if_fail (notebook != NULL, -1);
557 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
559 if (notebook->cur_page)
562 children = notebook->children;
566 if (children->data == notebook->cur_page)
568 children = children->next;
584 gtk_notebook_set_page (GtkNotebook *notebook,
589 g_return_if_fail (notebook != NULL);
590 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
592 if ((list = g_list_nth (notebook->children, page_num)))
593 gtk_notebook_switch_page (notebook,
594 ((GtkNotebookPage *)(list->data)), page_num);
598 gtk_notebook_next_page (GtkNotebook *notebook)
600 GtkNotebookPage *page;
604 g_return_if_fail (notebook != NULL);
605 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
607 children = notebook->children;
611 if (notebook->cur_page == children->data)
613 children = children->next;
622 children = children->next;
627 children = notebook->children;
631 page = children->data;
632 gtk_notebook_switch_page (notebook, page, num);
636 gtk_notebook_prev_page (GtkNotebook *notebook)
638 GtkNotebookPage *page;
642 g_return_if_fail (notebook != NULL);
643 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
645 children = notebook->children;
649 if (notebook->cur_page == children->data)
651 children = children->next;
660 children = children->prev;
665 while (children->next)
667 children = children->next;
672 page = children->data;
673 gtk_notebook_switch_page (notebook, page, num);
677 gtk_notebook_foreach (GtkContainer *container,
678 GtkCallback callback,
679 gpointer callback_data)
681 GtkNotebook *notebook;
682 GtkNotebookPage *page;
685 g_return_if_fail (container != NULL);
686 g_return_if_fail (GTK_IS_NOTEBOOK (container));
687 g_return_if_fail (callback != NULL);
689 notebook = GTK_NOTEBOOK (container);
691 children = notebook->children;
694 page = children->data;
695 children = children->next;
696 (* callback) (page->child, callback_data);
701 gtk_notebook_expose_tabs (GtkNotebook *notebook)
704 GtkNotebookPage *page;
705 GdkEventExpose event;
708 widget = GTK_WIDGET (notebook);
709 border = GTK_CONTAINER (notebook)->border_width;
711 page = notebook->first_tab->data;
713 event.type = GDK_EXPOSE;
714 event.window = widget->window;
716 event.area.x = border;
717 event.area.y = border;
719 switch (notebook->tab_pos)
722 event.area.y = widget->allocation.height - border
723 - page->allocation.height - widget->style->klass->ythickness;
724 if (notebook->first_tab->data != notebook->cur_page)
725 event.area.y -= widget->style->klass->ythickness;
727 event.area.width = widget->allocation.width - 2 * border;
728 event.area.height = page->allocation.height
729 + widget->style->klass->ythickness;
730 if (notebook->first_tab->data != notebook->cur_page)
731 event.area.height += widget->style->klass->ythickness;
734 event.area.x = widget->allocation.width - border
735 - page->allocation.width - widget->style->klass->xthickness;
736 if (notebook->first_tab->data != notebook->cur_page)
737 event.area.x -= widget->style->klass->xthickness;
739 event.area.width = page->allocation.width
740 + widget->style->klass->xthickness;
741 event.area.height = widget->allocation.height - 2 * border;
742 if (notebook->first_tab->data != notebook->cur_page)
743 event.area.width += widget->style->klass->xthickness;
746 gtk_widget_event (widget, (GdkEvent *) &event);
750 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
753 g_return_if_fail (notebook != NULL);
754 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
756 if (notebook->tab_pos != pos)
758 notebook->tab_pos = pos;
760 if (GTK_WIDGET_VISIBLE (notebook))
762 gtk_widget_queue_resize (GTK_WIDGET (notebook));
764 gdk_window_clear (notebook->panel);
770 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
773 GtkNotebookPage *page;
776 g_return_if_fail (notebook != NULL);
777 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
779 if (notebook->show_tabs == show_tabs)
782 notebook->show_tabs = show_tabs;
783 children = notebook->children;
787 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
791 page = children->data;
792 children = children->next;
793 if (page->default_tab)
795 gtk_widget_destroy (page->tab_label);
796 page->tab_label = NULL;
799 gtk_widget_hide (page->tab_label);
803 gdk_window_hide (notebook->panel);
810 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
814 page = children->data;
815 children = children->next;
816 if (page->default_tab)
818 sprintf (string, "Page %d", i);
819 page->tab_label = gtk_label_new (string);
820 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
822 gtk_widget_show (page->tab_label);
826 gtk_widget_queue_resize (GTK_WIDGET (notebook));
830 gtk_notebook_set_show_border (GtkNotebook *notebook,
833 g_return_if_fail (notebook != NULL);
834 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
836 if (notebook->show_border != show_border)
838 notebook->show_border = show_border;
840 if (GTK_WIDGET_VISIBLE (notebook))
841 gtk_widget_queue_resize (GTK_WIDGET (notebook));
846 gtk_notebook_set_scrollable (GtkNotebook *notebook,
849 g_return_if_fail (notebook != NULL);
850 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
852 if (scrollable != notebook->scrollable)
854 if ( (notebook->scrollable = (scrollable != 0)) )
855 gtk_notebook_panel_realize (notebook);
856 else if (notebook->panel)
858 gdk_window_destroy (notebook->panel);
859 notebook->panel = NULL;
861 gtk_widget_queue_resize (GTK_WIDGET(notebook));
866 gtk_notebook_map (GtkWidget *widget)
868 GtkNotebook *notebook;
869 GtkNotebookPage *page;
872 g_return_if_fail (widget != NULL);
873 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
875 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
876 gdk_window_show (widget->window);
878 notebook = GTK_NOTEBOOK (widget);
880 if (notebook->cur_page &&
881 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
882 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
883 gtk_widget_map (notebook->cur_page->child);
885 if (notebook->scrollable)
886 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
889 children = notebook->children;
893 page = children->data;
894 children = children->next;
896 if (page->tab_label &&
897 GTK_WIDGET_VISIBLE (page->child) &&
898 !GTK_WIDGET_MAPPED (page->tab_label))
899 gtk_widget_map (page->tab_label);
905 gtk_notebook_unmap (GtkWidget *widget)
907 g_return_if_fail (widget != NULL);
908 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
910 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
911 gdk_window_hide (widget->window);
912 if (GTK_NOTEBOOK (widget)->panel)
913 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
917 gtk_notebook_realize (GtkWidget *widget)
919 GtkNotebook *notebook;
920 GdkWindowAttr attributes;
921 gint attributes_mask;
923 g_return_if_fail (widget != NULL);
924 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
926 notebook = GTK_NOTEBOOK (widget);
927 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
929 attributes.window_type = GDK_WINDOW_CHILD;
930 attributes.x = widget->allocation.x;
931 attributes.y = widget->allocation.y;
932 attributes.width = widget->allocation.width;
933 attributes.height = widget->allocation.height;
934 attributes.wclass = GDK_INPUT_OUTPUT;
935 attributes.visual = gtk_widget_get_visual (widget);
936 attributes.colormap = gtk_widget_get_colormap (widget);
937 attributes.event_mask = gtk_widget_get_events (widget);
938 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
939 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
941 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
943 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
944 gdk_window_set_user_data (widget->window, notebook);
946 widget->style = gtk_style_attach (widget->style, widget->window);
947 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
949 if (notebook->scrollable)
950 gtk_notebook_panel_realize (notebook);
954 gtk_notebook_panel_realize (GtkNotebook *notebook)
957 GdkWindowAttr attributes;
958 gint attributes_mask;
960 g_return_if_fail (notebook != NULL);
961 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
963 widget = GTK_WIDGET (notebook);
965 attributes.window_type = GDK_WINDOW_CHILD;
966 attributes.wclass = GDK_INPUT_OUTPUT;
967 attributes.visual = gtk_widget_get_visual (widget);
968 attributes.colormap = gtk_widget_get_colormap (widget);
969 attributes.event_mask = gtk_widget_get_events (widget);
970 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
971 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
972 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
974 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
976 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
977 attributes.height = ARROW_SIZE;
979 attributes.x = widget->allocation.width - attributes.width -
980 GTK_CONTAINER (notebook)->border_width;
981 attributes.y = widget->allocation.height - ARROW_SIZE -
982 GTK_CONTAINER (notebook)->border_width;
983 if (notebook->tab_pos == GTK_POS_TOP)
984 attributes.y = GTK_CONTAINER (notebook)->border_width;
985 else if (notebook->tab_pos == GTK_POS_LEFT)
986 attributes.x = widget->allocation.x
987 + GTK_CONTAINER (notebook)->border_width;
990 notebook->panel = gdk_window_new (widget->window, &attributes,
992 gtk_style_set_background (widget->style, notebook->panel,
994 gdk_window_set_user_data (notebook->panel, widget);
998 gtk_notebook_size_request (GtkWidget *widget,
999 GtkRequisition *requisition)
1001 GtkNotebook *notebook;
1002 GtkNotebookPage *page;
1005 g_return_if_fail (widget != NULL);
1006 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1007 g_return_if_fail (requisition != NULL);
1009 notebook = GTK_NOTEBOOK (widget);
1010 widget->requisition.width = 0;
1011 widget->requisition.height = 0;
1013 children = notebook->children;
1016 page = children->data;
1017 children = children->next;
1019 if (GTK_WIDGET_VISIBLE (page->child))
1021 gtk_widget_size_request (page->child, &page->child->requisition);
1023 widget->requisition.width = MAX (widget->requisition.width,
1024 page->child->requisition.width);
1025 widget->requisition.height = MAX (widget->requisition.height,
1026 page->child->requisition.height);
1030 if (notebook->show_border || notebook->show_tabs)
1032 widget->requisition.width += widget->style->klass->xthickness * 2;
1033 widget->requisition.height += widget->style->klass->ythickness * 2;
1035 if (notebook->show_tabs)
1038 gint tab_height = 0;
1041 children = notebook->children;
1044 page = children->data;
1045 children = children->next;
1047 if (GTK_WIDGET_VISIBLE (page->child))
1049 gtk_widget_size_request (page->tab_label,
1050 &page->tab_label->requisition);
1052 page->requisition.width =
1053 (page->tab_label->requisition.width +
1054 (widget->style->klass->xthickness + notebook->tab_border)
1056 page->requisition.height =
1057 (page->tab_label->requisition.height +
1058 (widget->style->klass->ythickness + notebook->tab_border)
1061 switch (notebook->tab_pos)
1064 case GTK_POS_BOTTOM:
1065 page->requisition.width -= TAB_OVERLAP;
1067 tab_width += page->requisition.width;
1068 tab_height = MAX (tab_height, page->requisition.height);
1069 tab_max = MAX (tab_max, page->requisition.width);
1073 page->requisition.height -= TAB_OVERLAP;
1075 tab_width = MAX (tab_width, page->requisition.width);
1076 tab_height += page->requisition.height;
1077 tab_max = MAX (tab_max, page->requisition.height);
1083 children = notebook->children;
1085 if (children && children->next && notebook->scrollable)
1087 if ((notebook->tab_pos == GTK_POS_TOP) ||
1088 (notebook->tab_pos == GTK_POS_BOTTOM))
1090 if (widget->requisition.width < tab_width)
1092 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1093 tab_height = MAX (tab_height, ARROW_SIZE);
1098 if (widget->requisition.height < tab_height)
1100 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1101 tab_width = MAX (tab_width,
1102 ARROW_SPACING + 2 * ARROW_SIZE);
1109 page = children->data;
1110 children = children->next;
1112 if (GTK_WIDGET_VISIBLE (page->child))
1114 if ((notebook->tab_pos == GTK_POS_TOP) ||
1115 (notebook->tab_pos == GTK_POS_BOTTOM))
1116 page->requisition.height = tab_height;
1118 page->requisition.width = tab_width;
1122 switch (notebook->tab_pos)
1125 case GTK_POS_BOTTOM:
1126 tab_width += widget->style->klass->xthickness;
1127 widget->requisition.width = MAX (widget->requisition.width,
1129 widget->requisition.height += tab_height;
1133 tab_height += widget->style->klass->ythickness;
1134 widget->requisition.width += tab_width;
1135 widget->requisition.height = MAX (widget->requisition.height,
1141 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1142 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1146 gtk_notebook_size_allocate (GtkWidget *widget,
1147 GtkAllocation *allocation)
1149 GtkNotebook *notebook;
1150 GtkNotebookPage *page;
1151 GtkAllocation child_allocation;
1154 g_return_if_fail (widget != NULL);
1155 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1156 g_return_if_fail (allocation != NULL);
1158 widget->allocation = *allocation;
1159 if (GTK_WIDGET_REALIZED (widget))
1160 gdk_window_move_resize (widget->window,
1161 allocation->x, allocation->y,
1162 allocation->width, allocation->height);
1164 notebook = GTK_NOTEBOOK (widget);
1165 if (notebook->children)
1167 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1168 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1169 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1170 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1172 if (notebook->show_tabs || notebook->show_border)
1174 child_allocation.x += widget->style->klass->xthickness;
1175 child_allocation.y += widget->style->klass->ythickness;
1176 child_allocation.width = MAX (1,
1177 child_allocation.width - widget->style->klass->xthickness * 2);
1178 child_allocation.height = MAX (1,
1179 child_allocation.height - widget->style->klass->ythickness * 2);
1181 if (notebook->show_tabs && notebook->children)
1183 switch (notebook->tab_pos)
1186 child_allocation.y += notebook->cur_page->requisition.height;
1187 case GTK_POS_BOTTOM:
1188 child_allocation.height = MAX (1,
1189 child_allocation.height - notebook->cur_page->requisition.height);
1192 child_allocation.x += notebook->cur_page->requisition.width;
1194 child_allocation.width = MAX (1,
1195 child_allocation.width - notebook->cur_page->requisition.width);
1201 children = notebook->children;
1204 page = children->data;
1205 children = children->next;
1207 if (GTK_WIDGET_VISIBLE (page->child))
1208 gtk_widget_size_allocate (page->child, &child_allocation);
1211 gtk_notebook_pages_allocate (notebook, allocation);
1216 gtk_notebook_paint (GtkWidget *widget,
1219 GtkNotebook *notebook;
1220 GtkNotebookPage *page;
1227 g_return_if_fail (widget != NULL);
1228 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1229 g_return_if_fail (area != NULL);
1231 if (GTK_WIDGET_DRAWABLE (widget))
1233 notebook = GTK_NOTEBOOK (widget);
1235 gdk_window_clear_area (widget->window,
1237 area->width, area->height);
1239 if (notebook->show_tabs || notebook->show_border)
1241 x = GTK_CONTAINER (widget)->border_width;
1242 y = GTK_CONTAINER (widget)->border_width;
1243 width = widget->allocation.width - x * 2;
1244 height = widget->allocation.height - y * 2;
1246 if (notebook->show_tabs && notebook->children)
1249 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1251 GtkNotebookPage *page;
1253 page = notebook->first_tab->data;
1255 switch (notebook->tab_pos)
1258 y += page->allocation.height +
1259 widget->style->klass->ythickness;
1260 case GTK_POS_BOTTOM:
1261 height -= page->allocation.height +
1262 widget->style->klass->ythickness;
1265 x += page->allocation.width +
1266 widget->style->klass->xthickness;
1268 width -= page->allocation.width +
1269 widget->style->klass->xthickness;
1272 gtk_draw_shadow (widget->style, widget->window,
1273 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1274 x, y, width, height);
1278 switch (notebook->tab_pos)
1281 y += notebook->cur_page->allocation.height;
1282 case GTK_POS_BOTTOM:
1283 height -= notebook->cur_page->allocation.height;
1286 x += notebook->cur_page->allocation.width;
1288 width -= notebook->cur_page->allocation.width;
1292 switch (notebook->tab_pos)
1295 points[0].x = notebook->cur_page->allocation.x;
1300 points[2].y = y + height - 1;
1301 points[3].x = x + width - 1;
1302 points[3].y = y + height - 1;
1303 points[4].x = x + width - 1;
1305 points[5].x = (notebook->cur_page->allocation.x +
1306 notebook->cur_page->allocation.width -
1307 widget->style->klass->xthickness);
1310 if (points[5].x == (x + width))
1313 case GTK_POS_BOTTOM:
1314 points[0].x = (notebook->cur_page->allocation.x +
1315 notebook->cur_page->allocation.width -
1316 widget->style->klass->xthickness);
1317 points[0].y = y + height - 1;
1318 points[1].x = x + width - 1;
1319 points[1].y = y + height - 1;
1320 points[2].x = x + width - 1;
1325 points[4].y = y + height - 1;
1326 points[5].x = notebook->cur_page->allocation.x;
1327 points[5].y = y + height - 1;
1329 if (points[0].x == (x + width))
1334 points[0].y = (notebook->cur_page->allocation.y +
1335 notebook->cur_page->allocation.height -
1336 widget->style->klass->ythickness);
1338 points[1].y = y + height - 1;
1339 points[2].x = x + width - 1;
1340 points[2].y = y + height - 1;
1341 points[3].x = x + width - 1;
1346 points[5].y = notebook->cur_page->allocation.y;
1348 if (points[0].y == (y + height))
1352 points[0].x = x + width - 1;
1353 points[0].y = notebook->cur_page->allocation.y;
1354 points[1].x = x + width - 1;
1359 points[3].y = y + height - 1;
1360 points[4].x = x + width - 1;
1361 points[4].y = y + height - 1;
1362 points[5].x = x + width - 1;
1363 points[5].y = (notebook->cur_page->allocation.y +
1364 notebook->cur_page->allocation.height -
1365 widget->style->klass->ythickness);
1367 if (points[5].y == (y + height))
1372 gtk_draw_polygon (widget->style, widget->window,
1373 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1376 children = g_list_last (notebook->children);
1381 page = children->data;
1382 children = children->prev;
1384 if (!GTK_WIDGET_MAPPED (page->tab_label))
1386 else if (notebook->cur_page != page)
1387 gtk_notebook_draw_tab (notebook, page, area);
1390 if (showarrow && notebook->scrollable && notebook->show_tabs)
1392 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1393 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1395 if (notebook->cur_page &&
1396 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1397 (notebook->cur_page))->tab_label))
1398 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1400 else if (notebook->show_border)
1402 gtk_draw_shadow (widget->style, widget->window,
1403 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1404 x, y, width, height);
1411 gtk_notebook_draw (GtkWidget *widget,
1414 GtkNotebook *notebook;
1415 GdkRectangle child_area;
1417 g_return_if_fail (widget != NULL);
1418 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1419 g_return_if_fail (area != NULL);
1421 if (GTK_WIDGET_DRAWABLE (widget))
1423 notebook = GTK_NOTEBOOK (widget);
1425 gtk_notebook_paint (widget, area);
1426 gtk_widget_draw_focus (widget);
1428 if (notebook->cur_page &&
1429 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1430 gtk_widget_draw (notebook->cur_page->child, &child_area);
1435 gtk_notebook_expose (GtkWidget *widget,
1436 GdkEventExpose *event)
1438 GtkNotebook *notebook;
1439 GdkEventExpose child_event;
1441 g_return_val_if_fail (widget != NULL, FALSE);
1442 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1443 g_return_val_if_fail (event != NULL, FALSE);
1445 if (GTK_WIDGET_DRAWABLE (widget))
1447 notebook = GTK_NOTEBOOK (widget);
1449 gtk_notebook_paint (widget, &event->area);
1450 gtk_widget_draw_focus (widget);
1452 child_event = *event;
1453 if (notebook->cur_page &&
1454 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1455 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1457 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1464 gtk_notebook_button_press (GtkWidget *widget,
1465 GdkEventButton *event)
1467 GtkNotebook *notebook;
1468 GtkNotebookPage *page;
1472 g_return_val_if_fail (widget != NULL, FALSE);
1473 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1474 g_return_val_if_fail (event != NULL, FALSE);
1476 notebook = GTK_NOTEBOOK (widget);
1478 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1479 || notebook->button)
1482 if (!GTK_WIDGET_HAS_FOCUS (widget) && !(GTK_CONTAINER (widget)->focus_child))
1483 gtk_widget_grab_focus (widget);
1485 if (event->window == notebook->panel)
1487 if (!GTK_WIDGET_HAS_FOCUS (widget))
1489 GTK_CONTAINER (widget)->focus_child = NULL;
1490 gtk_widget_grab_focus (widget);
1493 gtk_grab_add (widget);
1494 notebook->button = event->button;
1496 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1498 notebook->click_child = GTK_ARROW_LEFT;
1499 if (event->button == 1)
1501 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1502 if (!notebook->timer)
1504 notebook->timer = gtk_timeout_add
1505 (NOTEBOOK_INIT_SCROLL_DELAY,
1506 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1507 notebook->need_timer = TRUE;
1510 else if (event->button == 2)
1511 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1512 else if (event->button == 3)
1513 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1514 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1518 notebook->click_child = GTK_ARROW_RIGHT;
1519 if (event->button == 1)
1521 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1522 if (!notebook->timer)
1524 notebook->timer = gtk_timeout_add
1525 (NOTEBOOK_INIT_SCROLL_DELAY,
1526 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1527 notebook->need_timer = TRUE;
1530 else if (event->button == 2)
1531 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1532 else if (event->button == 3)
1533 gtk_notebook_switch_focus_tab (notebook,
1534 g_list_last (notebook->children));
1535 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1538 else if (event->window == widget->window)
1540 if (event->button == 3 && notebook->menu)
1542 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1543 NULL, NULL, 3, event->time);
1548 children = notebook->children;
1551 page = children->data;
1553 if (GTK_WIDGET_VISIBLE (page->child) &&
1554 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1555 (event->x >= page->allocation.x) &&
1556 (event->y >= page->allocation.y) &&
1557 (event->x <= (page->allocation.x + page->allocation.width)) &&
1558 (event->y <= (page->allocation.y + page->allocation.height)))
1560 GTK_CONTAINER (notebook)->focus_child = NULL;
1562 if (page == notebook->cur_page &&
1563 notebook->focus_tab != children &&
1564 GTK_WIDGET_HAS_FOCUS (notebook))
1566 GtkNotebookPage *old_page;
1568 old_page = (GtkNotebookPage *)
1569 (notebook->focus_tab->data);
1570 notebook->focus_tab = children;
1571 gtk_notebook_focus_changed (notebook, old_page);
1575 notebook->focus_tab = children;
1576 gtk_notebook_switch_page (notebook, page, num);
1577 gtk_widget_grab_focus (widget);
1581 children = children->next;
1589 gtk_notebook_button_release (GtkWidget *widget,
1590 GdkEventButton *event)
1592 GtkNotebook *notebook;
1594 g_return_val_if_fail (widget != NULL, FALSE);
1595 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1596 g_return_val_if_fail (event != NULL, FALSE);
1598 if (event->type != GDK_BUTTON_RELEASE)
1601 notebook = GTK_NOTEBOOK (widget);
1603 if (event->button == notebook->button)
1607 if (notebook->timer)
1609 gtk_timeout_remove (notebook->timer);
1610 notebook->timer = 0;
1611 notebook->need_timer = FALSE;
1613 gtk_grab_remove (widget);
1614 click_child = notebook->click_child;
1615 notebook->click_child = 0;
1616 notebook->button = 0;
1617 gtk_notebook_draw_arrow (notebook, click_child);
1624 gtk_notebook_enter_notify (GtkWidget *widget,
1625 GdkEventCrossing *event)
1627 GtkNotebook *notebook;
1629 g_return_val_if_fail (widget != NULL, FALSE);
1630 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1631 g_return_val_if_fail (event != NULL, FALSE);
1633 notebook = GTK_NOTEBOOK (widget);
1635 if (event->window == notebook->panel)
1640 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1642 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1644 notebook->in_child = GTK_ARROW_LEFT;
1646 if (notebook->click_child == 0)
1647 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1651 notebook->in_child = GTK_ARROW_RIGHT;
1653 if (notebook->click_child == 0)
1654 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1662 gtk_notebook_leave_notify (GtkWidget *widget,
1663 GdkEventCrossing *event)
1665 GtkNotebook *notebook;
1667 g_return_val_if_fail (widget != NULL, FALSE);
1668 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1669 g_return_val_if_fail (event != NULL, FALSE);
1671 notebook = GTK_NOTEBOOK (widget);
1673 if (event->window == notebook->panel && !notebook->click_child)
1675 if (notebook->in_child == GTK_ARROW_LEFT)
1677 notebook->in_child = 0;
1678 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1682 notebook->in_child = 0;
1683 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1690 gtk_notebook_motion_notify (GtkWidget *widget,
1691 GdkEventMotion *event)
1693 GtkNotebook *notebook;
1695 g_return_val_if_fail (widget != NULL, FALSE);
1696 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1697 g_return_val_if_fail (event != NULL, FALSE);
1699 notebook = GTK_NOTEBOOK (widget);
1701 if (notebook->button)
1704 if (event->window == notebook->panel)
1710 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1712 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
1713 notebook->in_child == GTK_ARROW_RIGHT)
1715 notebook->in_child = GTK_ARROW_LEFT;
1716 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1717 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1719 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
1720 notebook->in_child == GTK_ARROW_LEFT)
1722 notebook->in_child = GTK_ARROW_RIGHT;
1723 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1724 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1732 gtk_notebook_timer (GtkNotebook *notebook)
1734 g_return_val_if_fail (notebook != NULL, FALSE);
1735 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1737 if (notebook->timer)
1739 if (notebook->click_child == GTK_ARROW_LEFT)
1740 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1741 else if (notebook->click_child == GTK_ARROW_RIGHT)
1742 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1744 if (notebook->need_timer)
1746 notebook->need_timer = FALSE;
1747 notebook->timer = gtk_timeout_add
1748 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
1749 (gpointer) notebook);
1758 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
1760 GtkStateType state_type;
1761 GtkShadowType shadow_type;
1764 g_return_if_fail (notebook != NULL);
1765 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1767 widget = GTK_WIDGET(notebook);
1769 if (GTK_WIDGET_DRAWABLE (notebook))
1771 if (notebook->in_child == arrow)
1773 if (notebook->click_child == arrow)
1774 state_type = GTK_STATE_ACTIVE;
1776 state_type = GTK_STATE_PRELIGHT;
1779 state_type = GTK_STATE_NORMAL;
1781 if (notebook->click_child == arrow)
1782 shadow_type = GTK_SHADOW_IN;
1784 shadow_type = GTK_SHADOW_OUT;
1786 if (arrow == GTK_ARROW_LEFT)
1788 if (notebook->tab_pos == GTK_POS_LEFT ||
1789 notebook->tab_pos == GTK_POS_RIGHT)
1790 arrow = GTK_ARROW_UP;
1791 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1792 shadow_type, arrow, TRUE,
1793 0, 0, ARROW_SIZE, ARROW_SIZE);
1797 if (notebook->tab_pos == GTK_POS_LEFT ||
1798 notebook->tab_pos == GTK_POS_RIGHT)
1799 arrow = GTK_ARROW_DOWN;
1800 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1801 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
1802 0, ARROW_SIZE, ARROW_SIZE);
1808 gtk_real_notebook_switch_page (GtkNotebook *notebook,
1809 GtkNotebookPage *page)
1811 g_return_if_fail (notebook != NULL);
1812 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1813 g_return_if_fail (page != NULL);
1815 if (notebook->cur_page == page)
1818 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
1819 gtk_widget_unmap (notebook->cur_page->child);
1821 notebook->cur_page = page;
1823 if (notebook->focus_tab->data != (gpointer) notebook->cur_page)
1824 notebook->focus_tab =
1825 g_list_find (notebook->children, notebook->cur_page);
1827 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
1829 if (GTK_WIDGET_MAPPED (notebook))
1831 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
1832 gtk_widget_map (notebook->cur_page->child);
1835 gtk_widget_map (notebook->cur_page->child);
1836 gtk_widget_size_allocate (GTK_WIDGET (notebook),
1837 >K_WIDGET (notebook)->allocation);
1841 if (GTK_WIDGET_DRAWABLE (notebook))
1842 gtk_widget_queue_draw (GTK_WIDGET (notebook));
1846 gtk_notebook_draw_tab (GtkNotebook *notebook,
1847 GtkNotebookPage *page,
1850 GdkRectangle child_area;
1851 GdkRectangle page_area;
1852 GtkStateType state_type;
1856 g_return_if_fail (notebook != NULL);
1857 g_return_if_fail (page != NULL);
1858 g_return_if_fail (area != NULL);
1860 if (!GTK_WIDGET_MAPPED (page->tab_label))
1863 page_area.x = page->allocation.x;
1864 page_area.y = page->allocation.y;
1865 page_area.width = page->allocation.width;
1866 page_area.height = page->allocation.height;
1868 if (gdk_rectangle_intersect (&page_area, area, &child_area))
1872 switch (notebook->tab_pos)
1875 if (child_area.x + child_area.width >
1876 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1878 points[0].x = page->allocation.x + page->allocation.width - 1;
1879 points[0].y = page->allocation.y + page->allocation.height - 1;
1881 points[1].x = page->allocation.x + page->allocation.width - 1;
1882 points[1].y = page->allocation.y + TAB_CURVATURE;
1884 points[2].x = page->allocation.x + page->allocation.width
1885 - TAB_CURVATURE - 1;
1886 points[2].y = page->allocation.y;
1891 points[0].x = page->allocation.x + page->allocation.width
1893 points[0].y = page->allocation.y;
1897 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1898 (page == notebook->cur_page ||
1899 page == (GtkNotebookPage *)(notebook->children->data) ||
1900 (notebook->scrollable &&
1901 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1903 points[n].x = page->allocation.x + TAB_CURVATURE;
1904 points[n++].y = page->allocation.y;
1906 points[n].x = page->allocation.x;
1907 points[n++].y = page->allocation.y + TAB_CURVATURE;
1909 points[n].x = page->allocation.x;
1910 points[n++].y = page->allocation.y + page->allocation.height - 1;
1914 points[n].x = page->allocation.x + TAB_OVERLAP;
1915 points[n++].y = page->allocation.y;
1918 case GTK_POS_BOTTOM:
1919 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1920 (page == notebook->cur_page ||
1921 page == (GtkNotebookPage *)(notebook->children->data) ||
1922 (notebook->scrollable &&
1923 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1925 points[0].x = page->allocation.x;
1926 points[0].y = page->allocation.y;
1928 points[1].x = page->allocation.x;
1929 points[1].y = page->allocation.y + page->allocation.height
1930 - TAB_CURVATURE - 1;
1932 points[2].x = page->allocation.x + TAB_CURVATURE;
1933 points[2].y = page->allocation.y + page->allocation.height - 1;
1938 points[0].x = page->allocation.x + TAB_OVERLAP;
1939 points[0].y = page->allocation.y + page->allocation.height - 1;
1943 if (child_area.x + child_area.width >
1944 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1946 points[n].x = page->allocation.x + page->allocation.width
1947 - TAB_CURVATURE - 1;
1948 points[n++].y = page->allocation.y + page->allocation.height - 1;
1950 points[n].x = page->allocation.x + page->allocation.width - 1;
1951 points[n++].y = page->allocation.y + page->allocation.height
1952 - TAB_CURVATURE - 1;
1954 points[n].x = page->allocation.x + page->allocation.width - 1;
1955 points[n++].y = page->allocation.y;
1959 points[n].x = page->allocation.x + page->allocation.width
1961 points[n++].y = page->allocation.y + page->allocation.height - 1;
1965 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1966 (page == notebook->cur_page ||
1967 page == (GtkNotebookPage *)(notebook->children->data) ||
1968 (notebook->scrollable &&
1969 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1971 points[0].x = page->allocation.x + page->allocation.width - 1;
1972 points[0].y = page->allocation.y;
1974 points[1].x = page->allocation.x + TAB_CURVATURE;
1975 points[1].y = page->allocation.y;
1977 points[2].x = page->allocation.x;
1978 points[2].y = page->allocation.y + TAB_CURVATURE;
1983 points[0].x = page->allocation.x;
1984 points[0].y = page->allocation.y + TAB_OVERLAP;
1988 if (child_area.y + child_area.height >
1989 page->allocation.y + page->allocation.height - TAB_OVERLAP)
1991 points[n].x = page->allocation.x;
1992 points[n++].y = page->allocation.y + page->allocation.height
1993 - TAB_CURVATURE - 1;
1995 points[n].x = page->allocation.x + TAB_CURVATURE;
1996 points[n++].y = page->allocation.y + page->allocation.height - 1;
1998 points[n].x = page->allocation.x + page->allocation.width - 1;
1999 points[n++].y = page->allocation.y + page->allocation.height - 1;
2003 points[n].x = page->allocation.x;
2004 points[n++].y = page->allocation.y + page->allocation.height
2009 if (child_area.y + child_area.height >
2010 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2012 points[0].x = page->allocation.x;
2013 points[0].y = page->allocation.y + page->allocation.height - 1;
2015 points[1].x = page->allocation.x + page->allocation.width
2016 - TAB_CURVATURE - 1;
2017 points[1].y = page->allocation.y + page->allocation.height - 1;
2019 points[2].x = page->allocation.x + page->allocation.width - 1;
2020 points[2].y = page->allocation.y + page->allocation.height
2021 - TAB_CURVATURE - 1;
2026 points[0].x = page->allocation.x + page->allocation.width - 1;
2027 points[0].y = page->allocation.y + page->allocation.height
2032 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2033 (page == notebook->cur_page ||
2034 page == (GtkNotebookPage *)(notebook->children->data) ||
2035 (notebook->scrollable &&
2036 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2038 points[n].x = page->allocation.x + page->allocation.width - 1;
2039 points[n++].y = page->allocation.y + TAB_CURVATURE;
2041 points[n].x = page->allocation.x + page->allocation.width
2042 - TAB_CURVATURE - 1;
2043 points[n++].y = page->allocation.y;
2045 points[n].x = page->allocation.x;
2046 points[n++].y = page->allocation.y;
2050 points[n].x = page->allocation.x + page->allocation.width - 1;
2051 points[n++].y = page->allocation.y + TAB_OVERLAP;
2056 widget = GTK_WIDGET(notebook);
2058 if (notebook->cur_page == page)
2060 state_type = GTK_STATE_NORMAL;
2064 state_type = GTK_STATE_ACTIVE;
2065 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2066 TRUE, child_area.x, child_area.y,
2067 child_area.width, child_area.height);
2070 gtk_draw_polygon (widget->style, widget->window, state_type,
2071 GTK_SHADOW_OUT, points, n, FALSE);
2073 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2074 gtk_widget_draw (page->tab_label, &child_area);
2079 gtk_notebook_focus_in (GtkWidget *widget,
2080 GdkEventFocus *event)
2082 g_return_val_if_fail (widget != NULL, FALSE);
2083 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2084 g_return_val_if_fail (event != NULL, FALSE);
2086 if (GTK_CONTAINER (widget)->focus_child)
2088 if (gtk_notebook_page_select (GTK_NOTEBOOK (widget)))
2091 GTK_CONTAINER (widget)->focus_child = NULL;
2094 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2095 gtk_widget_draw_focus (widget);
2101 gtk_notebook_focus_out (GtkWidget *widget,
2102 GdkEventFocus *event)
2104 g_return_val_if_fail (widget != NULL, FALSE);
2105 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2106 g_return_val_if_fail (event != NULL, FALSE);
2108 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2109 gtk_widget_draw_focus (widget);
2115 gtk_notebook_draw_focus (GtkWidget *widget)
2117 GtkNotebook *notebook;
2119 g_return_if_fail (widget != NULL);
2120 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2122 notebook = GTK_NOTEBOOK (widget);
2124 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2125 notebook->focus_tab)
2127 GtkNotebookPage *page;
2130 page = notebook->focus_tab->data;
2132 if (GTK_WIDGET_HAS_FOCUS (widget))
2133 gc = widget->style->black_gc;
2134 else if (page == notebook->cur_page)
2135 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2137 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2139 gdk_draw_rectangle (widget->window,
2141 page->tab_label->allocation.x - 1,
2142 page->tab_label->allocation.y - 1,
2143 page->tab_label->allocation.width + 1,
2144 page->tab_label->allocation.height + 1);
2149 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2153 g_return_if_fail (notebook != NULL);
2154 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2155 g_return_if_fail (old_page != NULL);
2157 widget = GTK_WIDGET (notebook);
2159 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2160 notebook->focus_tab)
2162 GtkNotebookPage *page;
2165 page = notebook->focus_tab->data;
2167 if (GTK_WIDGET_HAS_FOCUS (widget))
2168 gc = widget->style->black_gc;
2169 else if (page == notebook->cur_page)
2170 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2172 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2174 gdk_draw_rectangle (widget->window,
2176 page->tab_label->allocation.x - 1,
2177 page->tab_label->allocation.y - 1,
2178 page->tab_label->allocation.width + 1,
2179 page->tab_label->allocation.height + 1);
2181 if (old_page == notebook->cur_page)
2182 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2184 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2186 gdk_draw_rectangle (widget->window,
2188 old_page->tab_label->allocation.x - 1,
2189 old_page->tab_label->allocation.y - 1,
2190 old_page->tab_label->allocation.width + 1,
2191 old_page->tab_label->allocation.height + 1);
2196 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2202 GtkNotebookPage *page = NULL;
2206 switch (notebook->tab_pos)
2209 case GTK_POS_BOTTOM:
2212 page = children->data;
2213 *tab_space -= page->requisition.width;
2214 if (*tab_space < 0 || children == *end)
2218 *tab_space = - (*tab_space + page->requisition.width);
2223 if (direction == STEP_NEXT)
2224 children = children->next;
2226 children = children->prev;
2233 page = children->data;
2234 *tab_space -= page->requisition.height;
2235 if (*tab_space < 0 || children == *end)
2239 *tab_space = - (*tab_space + page->requisition.height);
2244 if (direction == STEP_NEXT)
2245 children = children->next;
2247 children = children->prev;
2254 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2255 GtkAllocation *allocation)
2258 GtkContainer *container;
2259 GtkNotebookPage *page = NULL;
2260 GtkAllocation child_allocation;
2262 GList *last_child = NULL;
2263 gint showarrow = FALSE;
2272 if (!notebook->show_tabs || !notebook->children)
2275 widget = GTK_WIDGET (notebook);
2276 container = GTK_CONTAINER (notebook);
2278 child_allocation.x = container->border_width;
2279 child_allocation.y = container->border_width;
2281 switch (notebook->tab_pos)
2283 case GTK_POS_BOTTOM:
2284 child_allocation.y = (allocation->height -
2285 notebook->cur_page->requisition.height -
2286 container->border_width);
2288 child_allocation.height = notebook->cur_page->requisition.height;
2291 child_allocation.x = (allocation->width -
2292 notebook->cur_page->requisition.width -
2293 container->border_width);
2295 child_allocation.width = notebook->cur_page->requisition.width;
2299 if (notebook->scrollable)
2301 children = notebook->children;
2302 switch (notebook->tab_pos)
2305 case GTK_POS_BOTTOM:
2308 page = children->data;
2309 children = children->next;
2310 tab_space += page->requisition.width;
2312 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2315 page = notebook->focus_tab->data;
2317 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2318 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2319 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2321 page = notebook->children->data;
2322 if (notebook->tab_pos == GTK_POS_TOP)
2323 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2325 y = (allocation->height - container->border_width -
2326 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2333 page = children->data;
2334 children = children->next;
2335 tab_space += page->requisition.height;
2337 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2340 page = notebook->focus_tab->data;
2341 tab_space = (allocation->height -
2342 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2343 2 * container->border_width - page->requisition.height);
2344 y = allocation->height - container->border_width - ARROW_SIZE;
2346 page = notebook->children->data;
2347 if (notebook->tab_pos == GTK_POS_LEFT)
2348 x = (container->border_width +
2349 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2351 x = (allocation->width - container->border_width -
2352 (2 * ARROW_SIZE - ARROW_SPACING) -
2353 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2357 if (showarrow) /* first_tab <- focus_tab */
2359 children = notebook->focus_tab->prev;
2362 if (notebook->first_tab == children)
2364 children = children->prev;
2368 notebook->first_tab = notebook->focus_tab;
2370 gtk_notebook_calc_tabs (notebook, notebook->focus_tab->prev,
2371 &(notebook->first_tab), &tab_space,
2375 notebook->first_tab = notebook->first_tab->next;
2376 if (!notebook->first_tab)
2377 notebook->first_tab = notebook->focus_tab;
2378 last_child = notebook->focus_tab->next;
2380 else /* focus_tab -> end */
2382 if (!notebook->first_tab)
2383 notebook->first_tab = notebook->children;
2386 gtk_notebook_calc_tabs (notebook, notebook->focus_tab->next,
2387 &children, &tab_space, STEP_NEXT);
2390 last_child = children;
2391 else /* start <- first_tab */
2395 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2396 &children, &tab_space, STEP_PREV);
2398 notebook->first_tab = children->next;
2400 notebook->first_tab = notebook->children;
2404 if (GTK_WIDGET_REALIZED (notebook))
2406 gdk_window_move (notebook->panel, x, y);
2407 gdk_window_show (notebook->panel);
2412 tab_space = -tab_space;
2414 children = notebook->first_tab;
2415 while (children != last_child)
2417 children = children->next;
2424 children = notebook->children;
2425 while (children != notebook->first_tab)
2427 page = children->data;
2428 children = children->next;
2430 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2431 gtk_widget_unmap (page->tab_label);
2434 children = last_child;
2437 page = children->data;
2438 children = children->next;
2440 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2441 gtk_widget_unmap (page->tab_label);
2444 else /* !showarrow */
2446 notebook->first_tab = notebook->children;
2448 if (GTK_WIDGET_REALIZED (notebook))
2449 gdk_window_hide (notebook->panel);
2451 children = notebook->first_tab;
2454 children = notebook->children;
2457 while (children != last_child)
2459 page = children->data;
2460 children = children->next;
2462 if (GTK_WIDGET_VISIBLE (page->child))
2464 new_fill = (tab_space * i++) / n;
2465 switch (notebook->tab_pos)
2468 case GTK_POS_BOTTOM:
2469 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2473 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2476 old_fill = new_fill;
2477 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2479 switch (notebook->tab_pos)
2482 case GTK_POS_BOTTOM:
2483 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2487 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2491 if (GTK_WIDGET_REALIZED (notebook) &&
2492 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2493 gtk_widget_map (page->tab_label);
2499 gtk_notebook_page_allocate (GtkNotebook *notebook,
2500 GtkNotebookPage *page,
2501 GtkAllocation *allocation)
2503 GtkAllocation child_allocation;
2504 gint xthickness, ythickness;
2506 g_return_if_fail (notebook != NULL);
2507 g_return_if_fail (page != NULL);
2508 g_return_if_fail (allocation != NULL);
2510 page->allocation = *allocation;
2512 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2513 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2515 if (notebook->cur_page != page)
2517 switch (notebook->tab_pos)
2520 page->allocation.y += ythickness;
2521 case GTK_POS_BOTTOM:
2522 page->allocation.height -= ythickness;
2525 page->allocation.x += xthickness;
2527 page->allocation.width -= xthickness;
2532 switch (notebook->tab_pos)
2535 child_allocation.x = xthickness + notebook->tab_border;
2536 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2537 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2538 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2539 child_allocation.x += page->allocation.x;
2541 case GTK_POS_BOTTOM:
2542 child_allocation.x = xthickness + notebook->tab_border;
2543 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2544 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2545 child_allocation.x += page->allocation.x;
2546 child_allocation.y = page->allocation.y + notebook->tab_border;
2549 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
2550 child_allocation.y = ythickness + notebook->tab_border;
2551 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2552 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2553 child_allocation.y += page->allocation.y;
2556 child_allocation.y = ythickness + notebook->tab_border;
2557 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2558 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2559 child_allocation.x = page->allocation.x + notebook->tab_border;
2560 child_allocation.y += page->allocation.y;
2564 if (page->tab_label)
2565 gtk_widget_size_allocate (page->tab_label, &child_allocation);
2569 gtk_notebook_menu_switch_page (GtkWidget *widget,
2570 GtkNotebookPage *page)
2572 GtkNotebook *notebook;
2576 g_return_if_fail (widget != NULL);
2577 g_return_if_fail (page != NULL);
2579 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
2580 (GTK_MENU (widget->parent)));
2582 if (notebook->cur_page == page)
2586 children = notebook->children;
2587 while (children && children->data != page)
2589 children = children->next;
2593 gtk_signal_emit (GTK_OBJECT (notebook),
2594 notebook_signals[SWITCH_PAGE],
2600 gtk_notebook_switch_page (GtkNotebook *notebook,
2601 GtkNotebookPage *page,
2604 g_return_if_fail (notebook != NULL);
2605 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2606 g_return_if_fail (page != NULL);
2608 if (notebook->cur_page == page)
2611 gtk_signal_emit (GTK_OBJECT (notebook),
2612 notebook_signals[SWITCH_PAGE],
2618 gtk_notebook_marshal_signal (GtkObject *object,
2623 GtkNotebookSignal rfunc;
2625 rfunc = (GtkNotebookSignal) func;
2627 (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
2632 gtk_notebook_focus (GtkContainer *container,
2633 GtkDirectionType direction)
2635 GtkNotebook *notebook;
2636 GtkWidget *focus_child;
2637 GtkNotebookPage *page = NULL;
2638 GtkNotebookPage *old_page;
2641 g_return_val_if_fail (container != NULL, FALSE);
2642 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
2644 notebook = GTK_NOTEBOOK (container);
2646 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
2649 focus_child = container->focus_child;
2650 container->focus_child = NULL;
2652 if (!notebook->show_tabs)
2654 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2656 if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
2660 gtk_widget_grab_focus (notebook->cur_page->child);
2664 else if (GTK_IS_CONTAINER (notebook->cur_page->child))
2666 if (gtk_container_focus
2667 (GTK_CONTAINER (notebook->cur_page->child), direction))
2674 old_page = notebook->focus_tab->data;
2677 if (!GTK_WIDGET_HAS_FOCUS (container) && !focus_child)
2679 gtk_widget_grab_focus (GTK_WIDGET (container));
2683 if (focus_child && focus_child == old_page->child)
2685 if (GTK_WIDGET_VISIBLE (old_page->child))
2687 if (GTK_IS_CONTAINER (old_page->child) &&
2688 !GTK_WIDGET_HAS_FOCUS (old_page->child))
2690 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
2694 gtk_widget_grab_focus (GTK_WIDGET(notebook));
2702 case GTK_DIR_TAB_FORWARD:
2705 if (!notebook->focus_tab->next)
2708 notebook->focus_tab = notebook->focus_tab->next;
2709 page = notebook->focus_tab->data;
2712 case GTK_DIR_TAB_BACKWARD:
2715 if (!notebook->focus_tab->prev)
2718 notebook->focus_tab = notebook->focus_tab->prev;
2719 page = notebook->focus_tab->data;
2726 if (GTK_WIDGET_MAPPED (page->tab_label))
2727 gtk_notebook_focus_changed (notebook, old_page);
2730 gtk_notebook_pages_allocate (notebook,
2731 &(GTK_WIDGET (notebook)->allocation));
2732 gtk_notebook_expose_tabs (notebook);
2740 gtk_notebook_page_select (GtkNotebook *notebook)
2742 g_return_val_if_fail (notebook != NULL, FALSE);
2743 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2745 if (notebook->focus_tab)
2747 GtkNotebookPage *page;
2751 page = notebook->focus_tab->data;
2753 children = notebook->children;
2755 while (children != notebook->focus_tab)
2757 children = children->next;
2761 gtk_notebook_switch_page (notebook, page, num);
2763 if (GTK_WIDGET_VISIBLE (page->child))
2765 if (GTK_WIDGET_CAN_FOCUS (page->child))
2767 gtk_widget_grab_focus (page->child);
2770 else if (GTK_IS_CONTAINER (page->child))
2772 if (gtk_container_focus (GTK_CONTAINER (page->child),
2773 GTK_DIR_TAB_FORWARD))
2782 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
2785 GtkNotebookPage *old_page;
2786 GtkNotebookPage *page;
2788 g_return_if_fail (notebook != NULL);
2789 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2791 if (notebook->focus_tab != new_child)
2793 old_page = notebook->focus_tab->data;
2794 notebook->focus_tab = new_child;
2795 page = notebook->focus_tab->data;
2796 if (GTK_WIDGET_MAPPED (page->tab_label))
2797 gtk_notebook_focus_changed (notebook, old_page);
2800 gtk_notebook_pages_allocate (notebook,
2801 &(GTK_WIDGET (notebook)->allocation));
2802 gtk_notebook_expose_tabs (notebook);
2808 gtk_notebook_key_press (GtkWidget *widget,
2811 GtkNotebook *notebook;
2812 GtkDirectionType direction = 0;
2815 g_return_val_if_fail (widget != NULL, FALSE);
2816 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2817 g_return_val_if_fail (event != NULL, FALSE);
2819 notebook = GTK_NOTEBOOK (widget);
2822 if (!notebook->children || !notebook->show_tabs)
2825 switch (event->keyval)
2828 direction = GTK_DIR_UP;
2831 direction = GTK_DIR_LEFT;
2834 direction = GTK_DIR_DOWN;
2837 direction = GTK_DIR_RIGHT;
2840 if (event->state & GDK_SHIFT_MASK)
2841 direction = GTK_DIR_TAB_BACKWARD;
2843 direction = GTK_DIR_TAB_FORWARD;
2846 gtk_notebook_switch_focus_tab (notebook, notebook->children);
2849 gtk_notebook_switch_focus_tab (notebook,
2850 g_list_last (notebook->children));
2854 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
2860 return gtk_container_focus (GTK_CONTAINER (widget), direction);
2865 gtk_notebook_set_tab_border (GtkNotebook *notebook,
2868 g_return_if_fail (notebook != NULL);
2869 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2871 if (notebook->tab_border != tab_border && tab_border > 0)
2873 notebook->tab_border = tab_border;
2875 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
2876 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2881 gtk_notebook_update_labels (GtkNotebook *notebook,
2885 GtkNotebookPage *page;
2892 sprintf (string, "Page %d", page_num);
2893 if (notebook->show_tabs && page->default_tab)
2894 gtk_label_set (GTK_LABEL (page->tab_label), string);
2895 if (notebook->menu && page->default_menu)
2897 if (GTK_IS_LABEL (page->tab_label))
2898 gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
2900 gtk_label_set (GTK_LABEL (page->menu_label), string);
2907 gtk_notebook_menu_item_create (GtkNotebook *notebook,
2908 GtkNotebookPage *page,
2911 GtkWidget *menu_item;
2913 if (page->default_menu)
2915 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2916 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
2918 page->menu_label = gtk_label_new ("");
2920 gtk_widget_show (page->menu_label);
2921 menu_item = gtk_menu_item_new ();
2922 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
2923 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
2924 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
2925 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page),
2927 gtk_widget_show (menu_item);
2931 gtk_notebook_popup_enable (GtkNotebook *notebook)
2933 GtkNotebookPage *page;
2936 g_return_if_fail (notebook != NULL);
2937 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2942 notebook->menu = gtk_menu_new ();
2944 children = notebook->children;
2947 page = children->data;
2948 children = children->next;
2949 gtk_notebook_menu_item_create (notebook, page, -1);
2951 gtk_notebook_update_labels (notebook, notebook->children,1);
2953 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
2954 gtk_notebook_menu_detacher);
2958 gtk_notebook_menu_label_unparent (GtkWidget *widget,
2961 gtk_widget_unparent (GTK_BIN(widget)->child);
2962 GTK_BIN(widget)->child = NULL;
2966 gtk_notebook_popup_disable (GtkNotebook *notebook)
2968 g_return_if_fail (notebook != NULL);
2969 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2971 if (!notebook->menu)
2974 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
2975 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
2976 gtk_widget_destroy (notebook->menu);
2980 gtk_notebook_menu_detacher (GtkWidget *widget,
2983 GtkNotebook *notebook;
2985 g_return_if_fail (widget != NULL);
2986 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2988 notebook = GTK_NOTEBOOK (widget);
2989 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
2991 notebook->menu = NULL;