1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 #include "gtknotebook.h"
19 #include "gtksignal.h"
22 #include "gtkmenuitem.h"
24 #include <gdk/gdkkeysyms.h>
29 #define TAB_CURVATURE 1
31 #define ARROW_SPACING 3
32 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
33 #define NOTEBOOK_SCROLL_DELAY (100)
46 typedef void (*GtkNotebookSignal) (GtkObject *object,
47 GtkNotebookPage *arg1,
51 static void gtk_notebook_class_init (GtkNotebookClass *klass);
52 static void gtk_notebook_init (GtkNotebook *notebook);
53 static void gtk_notebook_destroy (GtkObject *object);
54 static void gtk_notebook_map (GtkWidget *widget);
55 static void gtk_notebook_unmap (GtkWidget *widget);
56 static void gtk_notebook_realize (GtkWidget *widget);
57 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
58 static void gtk_notebook_size_request (GtkWidget *widget,
59 GtkRequisition *requisition);
60 static void gtk_notebook_size_allocate (GtkWidget *widget,
61 GtkAllocation *allocation);
62 static void gtk_notebook_paint (GtkWidget *widget,
64 static void gtk_notebook_draw (GtkWidget *widget,
66 static gint gtk_notebook_expose (GtkWidget *widget,
67 GdkEventExpose *event);
68 static gint gtk_notebook_button_press (GtkWidget *widget,
69 GdkEventButton *event);
70 static gint gtk_notebook_button_release (GtkWidget *widget,
71 GdkEventButton *event);
72 static gint gtk_notebook_enter_notify (GtkWidget *widget,
73 GdkEventCrossing *event);
74 static gint gtk_notebook_leave_notify (GtkWidget *widget,
75 GdkEventCrossing *event);
76 static gint gtk_notebook_motion_notify (GtkWidget *widget,
77 GdkEventMotion *event);
78 static gint gtk_notebook_key_press (GtkWidget *widget,
80 static void gtk_notebook_add (GtkContainer *container,
82 static void gtk_notebook_remove (GtkContainer *container,
84 static void gtk_notebook_real_remove (GtkNotebook *notebook,
87 static void gtk_notebook_foreach (GtkContainer *container,
89 gpointer callback_data);
90 static void gtk_notebook_switch_page (GtkNotebook *notebook,
91 GtkNotebookPage *page,
93 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
94 GtkNotebookPage *page,
96 static gint gtk_notebook_focus_in (GtkWidget *widget,
97 GdkEventFocus *event);
98 static gint gtk_notebook_focus_out (GtkWidget *widget,
99 GdkEventFocus *event);
100 static void gtk_notebook_draw_focus (GtkWidget *widget);
101 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
102 GtkNotebookPage *old_page);
103 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
104 GtkAllocation *allocation);
105 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
106 GtkNotebookPage *page,
107 GtkAllocation *allocation);
108 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
110 static gint gtk_notebook_timer (GtkNotebook *notebook);
111 static gint gtk_notebook_focus (GtkContainer *container,
112 GtkDirectionType direction);
113 static gint gtk_notebook_page_select (GtkNotebook *notebook);
114 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
119 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
120 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
122 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
123 GtkNotebookPage *page);
124 static void gtk_notebook_marshal_signal (GtkObject *object,
128 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
129 GtkNotebookPage *page);
130 static void gtk_notebook_update_labels (GtkNotebook *notebook,
133 static void gtk_notebook_menu_detacher (GtkWidget *widget,
135 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
137 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
138 GtkNotebookPage *page,
142 static GtkContainerClass *parent_class = NULL;
143 static guint notebook_signals[LAST_SIGNAL] = { 0 };
146 gtk_notebook_get_type ()
148 static guint notebook_type = 0;
152 GtkTypeInfo notebook_info =
155 sizeof (GtkNotebook),
156 sizeof (GtkNotebookClass),
157 (GtkClassInitFunc) gtk_notebook_class_init,
158 (GtkObjectInitFunc) gtk_notebook_init,
159 (GtkArgSetFunc) NULL,
160 (GtkArgGetFunc) NULL,
163 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
166 return notebook_type;
170 gtk_notebook_class_init (GtkNotebookClass *class)
172 GtkObjectClass *object_class;
173 GtkWidgetClass *widget_class;
174 GtkContainerClass *container_class;
176 object_class = (GtkObjectClass*) class;
177 widget_class = (GtkWidgetClass*) class;
178 container_class = (GtkContainerClass*) class;
180 parent_class = gtk_type_class (gtk_container_get_type ());
182 notebook_signals[SWITCH_PAGE] =
183 gtk_signal_new ("switch_page",
186 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
187 gtk_notebook_marshal_signal,
192 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
194 object_class->destroy = gtk_notebook_destroy;
196 widget_class->map = gtk_notebook_map;
197 widget_class->unmap = gtk_notebook_unmap;
198 widget_class->realize = gtk_notebook_realize;
199 widget_class->size_request = gtk_notebook_size_request;
200 widget_class->size_allocate = gtk_notebook_size_allocate;
201 widget_class->draw = gtk_notebook_draw;
202 widget_class->expose_event = gtk_notebook_expose;
203 widget_class->button_press_event = gtk_notebook_button_press;
204 widget_class->button_release_event = gtk_notebook_button_release;
205 widget_class->enter_notify_event = gtk_notebook_enter_notify;
206 widget_class->leave_notify_event = gtk_notebook_leave_notify;
207 widget_class->motion_notify_event = gtk_notebook_motion_notify;
208 widget_class->key_press_event = gtk_notebook_key_press;
209 widget_class->focus_in_event = gtk_notebook_focus_in;
210 widget_class->focus_out_event = gtk_notebook_focus_out;
211 widget_class->draw_focus = gtk_notebook_draw_focus;
213 container_class->add = gtk_notebook_add;
214 container_class->remove = gtk_notebook_remove;
215 container_class->foreach = gtk_notebook_foreach;
216 container_class->focus = gtk_notebook_focus;
218 class->switch_page = gtk_real_notebook_switch_page;
222 gtk_notebook_init (GtkNotebook *notebook)
224 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
226 notebook->cur_page = NULL;
227 notebook->children = NULL;
228 notebook->first_tab = NULL;
229 notebook->focus_tab = NULL;
230 notebook->panel = NULL;
231 notebook->menu = NULL;
233 notebook->tab_border = 3;
234 notebook->show_tabs = TRUE;
235 notebook->show_border = TRUE;
236 notebook->tab_pos = GTK_POS_TOP;
237 notebook->scrollable = FALSE;
238 notebook->in_child = 0;
239 notebook->click_child = 0;
240 notebook->button = 0;
241 notebook->need_timer = 0;
247 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
251 gtk_notebook_destroy (GtkObject *object)
253 GtkNotebook *notebook;
255 g_return_if_fail (object != NULL);
256 g_return_if_fail (GTK_IS_NOTEBOOK (object));
258 notebook = GTK_NOTEBOOK (object);
261 gtk_notebook_popup_disable (notebook);
263 GTK_OBJECT_CLASS (parent_class)->destroy (object);
267 gtk_notebook_append_page (GtkNotebook *notebook,
269 GtkWidget *tab_label)
271 g_return_if_fail (notebook != NULL);
272 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
273 g_return_if_fail (child != NULL);
275 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
279 gtk_notebook_append_page_menu (GtkNotebook *notebook,
281 GtkWidget *tab_label,
282 GtkWidget *menu_label)
284 g_return_if_fail (notebook != NULL);
285 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
286 g_return_if_fail (child != NULL);
288 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
292 gtk_notebook_prepend_page (GtkNotebook *notebook,
294 GtkWidget *tab_label)
296 g_return_if_fail (notebook != NULL);
297 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
298 g_return_if_fail (child != NULL);
300 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
304 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
306 GtkWidget *tab_label,
307 GtkWidget *menu_label)
309 g_return_if_fail (notebook != NULL);
310 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
311 g_return_if_fail (child != NULL);
313 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
317 gtk_notebook_insert_page (GtkNotebook *notebook,
319 GtkWidget *tab_label,
322 g_return_if_fail (notebook != NULL);
323 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
324 g_return_if_fail (child != NULL);
326 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
330 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
332 GtkWidget *tab_label,
333 GtkWidget *menu_label,
336 GtkNotebookPage *page;
339 g_return_if_fail (notebook != NULL);
340 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
341 g_return_if_fail (child != NULL);
343 page = g_new (GtkNotebookPage, 1);
345 page->requisition.width = 0;
346 page->requisition.height = 0;
347 page->allocation.x = 0;
348 page->allocation.y = 0;
349 page->allocation.width = 0;
350 page->allocation.height = 0;
351 page->default_menu = FALSE;
352 page->default_tab = FALSE;
354 nchildren = g_list_length (notebook->children);
355 if ((position < 0) || (position > nchildren))
356 position = nchildren;
358 notebook->children = g_list_insert (notebook->children, page, position);
362 page->default_tab = TRUE;
363 if (notebook->show_tabs)
364 tab_label = gtk_label_new ("");
366 page->tab_label = tab_label;
367 page->menu_label = menu_label;
370 page->default_menu = TRUE;
373 gtk_widget_ref (page->menu_label);
374 gtk_object_sink (GTK_OBJECT(page->menu_label));
378 gtk_notebook_menu_item_create (notebook, page, position);
380 gtk_notebook_update_labels
381 (notebook, g_list_nth (notebook->children, position), position + 1);
383 if (!notebook->first_tab)
384 notebook->first_tab = notebook->children;
386 if (!notebook->focus_tab)
387 notebook->focus_tab = notebook->children;
389 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
392 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
393 gtk_widget_show (tab_label);
396 if (!notebook->cur_page)
397 gtk_notebook_switch_page (notebook, page, 0);
399 if (GTK_WIDGET_VISIBLE (notebook))
401 if (GTK_WIDGET_REALIZED (notebook) &&
402 !GTK_WIDGET_REALIZED (child))
403 gtk_widget_realize (child);
405 if (GTK_WIDGET_MAPPED (notebook) &&
406 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
407 gtk_widget_map (child);
411 if (GTK_WIDGET_REALIZED (notebook) &&
412 !GTK_WIDGET_REALIZED (tab_label))
413 gtk_widget_realize (tab_label);
415 if (GTK_WIDGET_MAPPED (notebook) &&
416 !GTK_WIDGET_MAPPED (tab_label))
417 gtk_widget_map (tab_label);
421 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
422 gtk_widget_queue_resize (child);
426 gtk_notebook_remove_page (GtkNotebook *notebook,
431 g_return_if_fail (notebook != NULL);
432 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
434 if ((list = g_list_nth (notebook->children, page_num)))
435 gtk_notebook_real_remove (notebook, list, page_num);
439 gtk_notebook_add (GtkContainer *container,
442 g_return_if_fail (container != NULL);
443 g_return_if_fail (GTK_IS_NOTEBOOK (container));
444 g_return_if_fail (widget != NULL);
446 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
451 gtk_notebook_remove (GtkContainer *container,
454 GtkNotebook *notebook;
455 GtkNotebookPage *page;
459 g_return_if_fail (container != NULL);
460 g_return_if_fail (GTK_IS_NOTEBOOK (container));
461 g_return_if_fail (widget != NULL);
463 notebook = GTK_NOTEBOOK (container);
465 children = notebook->children;
469 page = children->data;
470 if (page->child == widget)
472 gtk_notebook_real_remove (notebook, children, page_num);
476 children = children->next;
481 gtk_notebook_real_remove (GtkNotebook *notebook,
485 GtkNotebookPage *page;
487 gint need_resize = FALSE;
491 next_list = list->prev;
496 next_list = list->next;
502 if (notebook->cur_page == list->data)
504 notebook->cur_page = NULL;
507 page = next_list->data;
508 gtk_notebook_switch_page (notebook, page, page_num);
512 if (list == notebook->first_tab)
513 notebook->first_tab = next_list;
514 if (list == notebook->focus_tab)
515 notebook->focus_tab = next_list;
519 if ((GTK_WIDGET_VISIBLE (page->child) ||
520 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
521 && GTK_WIDGET_VISIBLE (notebook))
524 gtk_widget_unparent (page->child);
527 gtk_widget_unparent (page->tab_label);
531 gtk_container_remove (GTK_CONTAINER (notebook->menu),
532 page->menu_label->parent);
533 gtk_widget_queue_resize (notebook->menu);
535 if (!page->default_menu)
536 gtk_widget_unref (page->menu_label);
538 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
540 notebook->children = g_list_remove_link (notebook->children, list);
545 gtk_widget_queue_resize (GTK_WIDGET (notebook));
550 gtk_notebook_current_page (GtkNotebook *notebook)
555 g_return_val_if_fail (notebook != NULL, -1);
556 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
558 if (notebook->cur_page)
561 children = notebook->children;
565 if (children->data == notebook->cur_page)
567 children = children->next;
583 gtk_notebook_set_page (GtkNotebook *notebook,
588 g_return_if_fail (notebook != NULL);
589 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
591 if ((list = g_list_nth (notebook->children, page_num)))
592 gtk_notebook_switch_page (notebook,
593 ((GtkNotebookPage *)(list->data)), page_num);
597 gtk_notebook_next_page (GtkNotebook *notebook)
599 GtkNotebookPage *page;
603 g_return_if_fail (notebook != NULL);
604 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
606 children = notebook->children;
610 if (notebook->cur_page == children->data)
612 children = children->next;
621 children = children->next;
626 children = notebook->children;
630 page = children->data;
631 gtk_notebook_switch_page (notebook, page, num);
635 gtk_notebook_prev_page (GtkNotebook *notebook)
637 GtkNotebookPage *page;
641 g_return_if_fail (notebook != NULL);
642 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
644 children = notebook->children;
648 if (notebook->cur_page == children->data)
650 children = children->next;
659 children = children->prev;
664 while (children->next)
666 children = children->next;
671 page = children->data;
672 gtk_notebook_switch_page (notebook, page, num);
676 gtk_notebook_foreach (GtkContainer *container,
677 GtkCallback callback,
678 gpointer callback_data)
680 GtkNotebook *notebook;
681 GtkNotebookPage *page;
684 g_return_if_fail (container != NULL);
685 g_return_if_fail (GTK_IS_NOTEBOOK (container));
686 g_return_if_fail (callback != NULL);
688 notebook = GTK_NOTEBOOK (container);
690 children = notebook->children;
693 page = children->data;
694 children = children->next;
695 (* callback) (page->child, callback_data);
700 gtk_notebook_expose_tabs (GtkNotebook *notebook)
703 GtkNotebookPage *page;
704 GdkEventExpose event;
707 widget = GTK_WIDGET (notebook);
708 border = GTK_CONTAINER (notebook)->border_width;
710 page = notebook->first_tab->data;
712 event.type = GDK_EXPOSE;
713 event.window = widget->window;
715 event.area.x = border;
716 event.area.y = border;
718 switch (notebook->tab_pos)
721 event.area.y = widget->allocation.height - border
722 - page->allocation.height - widget->style->klass->ythickness;
723 if (notebook->first_tab->data != notebook->cur_page)
724 event.area.y -= widget->style->klass->ythickness;
726 event.area.width = widget->allocation.width - 2 * border;
727 event.area.height = page->allocation.height
728 + widget->style->klass->ythickness;
729 if (notebook->first_tab->data != notebook->cur_page)
730 event.area.height += widget->style->klass->ythickness;
733 event.area.x = widget->allocation.width - border
734 - page->allocation.width - widget->style->klass->xthickness;
735 if (notebook->first_tab->data != notebook->cur_page)
736 event.area.x -= widget->style->klass->xthickness;
738 event.area.width = page->allocation.width
739 + widget->style->klass->xthickness;
740 event.area.height = widget->allocation.height - 2 * border;
741 if (notebook->first_tab->data != notebook->cur_page)
742 event.area.width += widget->style->klass->xthickness;
745 gtk_widget_event (widget, (GdkEvent *) &event);
749 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
752 g_return_if_fail (notebook != NULL);
753 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
755 if (notebook->tab_pos != pos)
757 notebook->tab_pos = pos;
759 if (GTK_WIDGET_VISIBLE (notebook))
761 gtk_widget_queue_resize (GTK_WIDGET (notebook));
763 gdk_window_clear (notebook->panel);
769 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
772 GtkNotebookPage *page;
775 g_return_if_fail (notebook != NULL);
776 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
778 if (notebook->show_tabs == show_tabs)
781 notebook->show_tabs = show_tabs;
782 children = notebook->children;
786 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
790 page = children->data;
791 children = children->next;
792 if (page->default_tab)
793 gtk_widget_destroy (page->tab_label);
795 gtk_widget_hide (page->tab_label);
799 gdk_window_hide (notebook->panel);
806 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
810 page = children->data;
811 children = children->next;
812 if (page->default_tab)
814 sprintf (string, "Page %d", i);
815 page->tab_label = gtk_label_new (string);
816 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
818 gtk_widget_show (page->tab_label);
822 gtk_widget_queue_resize (GTK_WIDGET (notebook));
826 gtk_notebook_set_show_border (GtkNotebook *notebook,
829 g_return_if_fail (notebook != NULL);
830 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
832 if (notebook->show_border != show_border)
834 notebook->show_border = show_border;
836 if (GTK_WIDGET_VISIBLE (notebook))
837 gtk_widget_queue_resize (GTK_WIDGET (notebook));
842 gtk_notebook_set_scrollable (GtkNotebook *notebook,
845 g_return_if_fail (notebook != NULL);
846 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
848 if (scrollable != notebook->scrollable)
850 if ( (notebook->scrollable = (scrollable != 0)) )
851 gtk_notebook_panel_realize (notebook);
852 else if (notebook->panel)
854 gdk_window_destroy (notebook->panel);
855 notebook->panel = NULL;
857 gtk_widget_queue_resize (GTK_WIDGET(notebook));
862 gtk_notebook_map (GtkWidget *widget)
864 GtkNotebook *notebook;
865 GtkNotebookPage *page;
868 g_return_if_fail (widget != NULL);
869 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
871 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
872 gdk_window_show (widget->window);
874 notebook = GTK_NOTEBOOK (widget);
876 if (notebook->cur_page &&
877 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
878 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
879 gtk_widget_map (notebook->cur_page->child);
881 if (notebook->scrollable)
882 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
885 children = notebook->children;
889 page = children->data;
890 children = children->next;
892 if (page->tab_label &&
893 GTK_WIDGET_VISIBLE (page->child) &&
894 !GTK_WIDGET_MAPPED (page->tab_label))
895 gtk_widget_map (page->tab_label);
901 gtk_notebook_unmap (GtkWidget *widget)
903 g_return_if_fail (widget != NULL);
904 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
906 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
907 gdk_window_hide (widget->window);
908 if (GTK_NOTEBOOK (widget)->panel)
909 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
913 gtk_notebook_realize (GtkWidget *widget)
915 GtkNotebook *notebook;
916 GdkWindowAttr attributes;
917 gint attributes_mask;
919 g_return_if_fail (widget != NULL);
920 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
922 notebook = GTK_NOTEBOOK (widget);
923 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
925 attributes.window_type = GDK_WINDOW_CHILD;
926 attributes.x = widget->allocation.x;
927 attributes.y = widget->allocation.y;
928 attributes.width = widget->allocation.width;
929 attributes.height = widget->allocation.height;
930 attributes.wclass = GDK_INPUT_OUTPUT;
931 attributes.visual = gtk_widget_get_visual (widget);
932 attributes.colormap = gtk_widget_get_colormap (widget);
933 attributes.event_mask = gtk_widget_get_events (widget);
934 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
935 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
937 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
939 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
940 gdk_window_set_user_data (widget->window, notebook);
942 widget->style = gtk_style_attach (widget->style, widget->window);
943 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
945 if (notebook->scrollable)
946 gtk_notebook_panel_realize (notebook);
950 gtk_notebook_panel_realize (GtkNotebook *notebook)
953 GdkWindowAttr attributes;
954 gint attributes_mask;
956 g_return_if_fail (notebook != NULL);
957 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
959 widget = GTK_WIDGET (notebook);
961 attributes.window_type = GDK_WINDOW_CHILD;
962 attributes.wclass = GDK_INPUT_OUTPUT;
963 attributes.visual = gtk_widget_get_visual (widget);
964 attributes.colormap = gtk_widget_get_colormap (widget);
965 attributes.event_mask = gtk_widget_get_events (widget);
966 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
967 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
968 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
970 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
972 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
973 attributes.height = ARROW_SIZE;
975 attributes.x = widget->allocation.width - attributes.width -
976 GTK_CONTAINER (notebook)->border_width;
977 attributes.y = widget->allocation.height - ARROW_SIZE -
978 GTK_CONTAINER (notebook)->border_width;
979 if (notebook->tab_pos == GTK_POS_TOP)
980 attributes.y = GTK_CONTAINER (notebook)->border_width;
981 else if (notebook->tab_pos == GTK_POS_LEFT)
982 attributes.x = widget->allocation.x
983 + GTK_CONTAINER (notebook)->border_width;
986 notebook->panel = gdk_window_new (widget->window, &attributes,
988 gtk_style_set_background (widget->style, notebook->panel,
990 gdk_window_set_user_data (notebook->panel, widget);
994 gtk_notebook_size_request (GtkWidget *widget,
995 GtkRequisition *requisition)
997 GtkNotebook *notebook;
998 GtkNotebookPage *page;
1001 g_return_if_fail (widget != NULL);
1002 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1003 g_return_if_fail (requisition != NULL);
1005 notebook = GTK_NOTEBOOK (widget);
1006 widget->requisition.width = 0;
1007 widget->requisition.height = 0;
1009 children = notebook->children;
1012 page = children->data;
1013 children = children->next;
1015 if (GTK_WIDGET_VISIBLE (page->child))
1017 gtk_widget_size_request (page->child, &page->child->requisition);
1019 widget->requisition.width = MAX (widget->requisition.width,
1020 page->child->requisition.width);
1021 widget->requisition.height = MAX (widget->requisition.height,
1022 page->child->requisition.height);
1026 if (notebook->show_border || notebook->show_tabs)
1028 widget->requisition.width += widget->style->klass->xthickness * 2;
1029 widget->requisition.height += widget->style->klass->ythickness * 2;
1031 if (notebook->show_tabs)
1034 gint tab_height = 0;
1037 children = notebook->children;
1040 page = children->data;
1041 children = children->next;
1043 if (GTK_WIDGET_VISIBLE (page->child))
1045 gtk_widget_size_request (page->tab_label,
1046 &page->tab_label->requisition);
1048 page->requisition.width =
1049 (page->tab_label->requisition.width +
1050 (widget->style->klass->xthickness + notebook->tab_border)
1052 page->requisition.height =
1053 (page->tab_label->requisition.height +
1054 (widget->style->klass->ythickness + notebook->tab_border)
1057 switch (notebook->tab_pos)
1060 case GTK_POS_BOTTOM:
1061 page->requisition.width -= TAB_OVERLAP;
1063 tab_width += page->requisition.width;
1064 tab_height = MAX (tab_height, page->requisition.height);
1065 tab_max = MAX (tab_max, page->requisition.width);
1069 page->requisition.height -= TAB_OVERLAP;
1071 tab_width = MAX (tab_width, page->requisition.width);
1072 tab_height += page->requisition.height;
1073 tab_max = MAX (tab_max, page->requisition.height);
1079 children = notebook->children;
1081 if (children && children->next && notebook->scrollable)
1083 if ((notebook->tab_pos == GTK_POS_TOP) ||
1084 (notebook->tab_pos == GTK_POS_BOTTOM))
1086 if (widget->requisition.width < tab_width)
1088 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1089 tab_height = MAX (tab_height, ARROW_SIZE);
1094 if (widget->requisition.height < tab_height)
1096 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1097 tab_width = MAX (tab_width,
1098 ARROW_SPACING + 2 * ARROW_SIZE);
1105 page = children->data;
1106 children = children->next;
1108 if (GTK_WIDGET_VISIBLE (page->child))
1110 if ((notebook->tab_pos == GTK_POS_TOP) ||
1111 (notebook->tab_pos == GTK_POS_BOTTOM))
1112 page->requisition.height = tab_height;
1114 page->requisition.width = tab_width;
1118 switch (notebook->tab_pos)
1121 case GTK_POS_BOTTOM:
1122 tab_width += widget->style->klass->xthickness;
1123 widget->requisition.width = MAX (widget->requisition.width,
1125 widget->requisition.height += tab_height;
1129 tab_height += widget->style->klass->ythickness;
1130 widget->requisition.width += tab_width;
1131 widget->requisition.height = MAX (widget->requisition.height,
1137 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1138 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1142 gtk_notebook_size_allocate (GtkWidget *widget,
1143 GtkAllocation *allocation)
1145 GtkNotebook *notebook;
1146 GtkNotebookPage *page;
1147 GtkAllocation child_allocation;
1150 g_return_if_fail (widget != NULL);
1151 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1152 g_return_if_fail (allocation != NULL);
1154 widget->allocation = *allocation;
1155 if (GTK_WIDGET_REALIZED (widget))
1156 gdk_window_move_resize (widget->window,
1157 allocation->x, allocation->y,
1158 allocation->width, allocation->height);
1160 notebook = GTK_NOTEBOOK (widget);
1161 if (notebook->children)
1163 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1164 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1165 child_allocation.width = allocation->width - child_allocation.x * 2;
1166 child_allocation.height = allocation->height - child_allocation.y * 2;
1168 if (notebook->show_tabs || notebook->show_border)
1170 child_allocation.x += widget->style->klass->xthickness;
1171 child_allocation.y += widget->style->klass->ythickness;
1172 child_allocation.width -= widget->style->klass->xthickness * 2;
1173 child_allocation.height -= widget->style->klass->ythickness * 2;
1175 if (notebook->show_tabs && notebook->children)
1177 switch (notebook->tab_pos)
1180 child_allocation.y += notebook->cur_page->requisition.height;
1181 case GTK_POS_BOTTOM:
1182 child_allocation.height -= notebook->cur_page->requisition.height;
1185 child_allocation.x += notebook->cur_page->requisition.width;
1187 child_allocation.width -= notebook->cur_page->requisition.width;
1193 children = notebook->children;
1196 page = children->data;
1197 children = children->next;
1199 if (GTK_WIDGET_VISIBLE (page->child))
1200 gtk_widget_size_allocate (page->child, &child_allocation);
1203 gtk_notebook_pages_allocate (notebook, allocation);
1208 gtk_notebook_paint (GtkWidget *widget,
1211 GtkNotebook *notebook;
1212 GtkNotebookPage *page;
1219 g_return_if_fail (widget != NULL);
1220 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1221 g_return_if_fail (area != NULL);
1223 if (GTK_WIDGET_DRAWABLE (widget))
1225 notebook = GTK_NOTEBOOK (widget);
1227 gdk_window_clear_area (widget->window,
1229 area->width, area->height);
1231 if (notebook->show_tabs || notebook->show_border)
1233 x = GTK_CONTAINER (widget)->border_width;
1234 y = GTK_CONTAINER (widget)->border_width;
1235 width = widget->allocation.width - x * 2;
1236 height = widget->allocation.height - y * 2;
1238 if (notebook->show_tabs && notebook->children)
1241 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1243 GtkNotebookPage *page;
1245 page = notebook->first_tab->data;
1247 switch (notebook->tab_pos)
1250 y += page->allocation.height +
1251 widget->style->klass->ythickness;
1252 case GTK_POS_BOTTOM:
1253 height -= page->allocation.height +
1254 widget->style->klass->ythickness;
1257 x += page->allocation.width +
1258 widget->style->klass->xthickness;
1260 width -= page->allocation.width +
1261 widget->style->klass->xthickness;
1264 gtk_draw_shadow (widget->style, widget->window,
1265 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1266 x, y, width, height);
1270 switch (notebook->tab_pos)
1273 y += notebook->cur_page->allocation.height;
1274 case GTK_POS_BOTTOM:
1275 height -= notebook->cur_page->allocation.height;
1278 x += notebook->cur_page->allocation.width;
1280 width -= notebook->cur_page->allocation.width;
1284 switch (notebook->tab_pos)
1287 points[0].x = notebook->cur_page->allocation.x;
1292 points[2].y = y + height - 1;
1293 points[3].x = x + width - 1;
1294 points[3].y = y + height - 1;
1295 points[4].x = x + width - 1;
1297 points[5].x = (notebook->cur_page->allocation.x +
1298 notebook->cur_page->allocation.width -
1299 widget->style->klass->xthickness);
1302 if (points[5].x == (x + width))
1305 case GTK_POS_BOTTOM:
1306 points[0].x = (notebook->cur_page->allocation.x +
1307 notebook->cur_page->allocation.width -
1308 widget->style->klass->xthickness);
1309 points[0].y = y + height - 1;
1310 points[1].x = x + width - 1;
1311 points[1].y = y + height - 1;
1312 points[2].x = x + width - 1;
1317 points[4].y = y + height - 1;
1318 points[5].x = notebook->cur_page->allocation.x;
1319 points[5].y = y + height - 1;
1321 if (points[0].x == (x + width))
1326 points[0].y = (notebook->cur_page->allocation.y +
1327 notebook->cur_page->allocation.height -
1328 widget->style->klass->ythickness);
1330 points[1].y = y + height - 1;
1331 points[2].x = x + width - 1;
1332 points[2].y = y + height - 1;
1333 points[3].x = x + width - 1;
1338 points[5].y = notebook->cur_page->allocation.y;
1340 if (points[0].y == (y + height))
1344 points[0].x = x + width - 1;
1345 points[0].y = notebook->cur_page->allocation.y;
1346 points[1].x = x + width - 1;
1351 points[3].y = y + height - 1;
1352 points[4].x = x + width - 1;
1353 points[4].y = y + height - 1;
1354 points[5].x = x + width - 1;
1355 points[5].y = (notebook->cur_page->allocation.y +
1356 notebook->cur_page->allocation.height -
1357 widget->style->klass->ythickness);
1359 if (points[5].y == (y + height))
1364 gtk_draw_polygon (widget->style, widget->window,
1365 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1368 children = g_list_last (notebook->children);
1373 page = children->data;
1374 children = children->prev;
1376 if (!GTK_WIDGET_MAPPED (page->tab_label))
1378 else if (notebook->cur_page != page)
1379 gtk_notebook_draw_tab (notebook, page, area);
1382 if (showarrow && notebook->scrollable && notebook->show_tabs)
1384 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1385 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1387 if (notebook->cur_page &&
1388 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1389 (notebook->cur_page))->tab_label))
1390 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1392 else if (notebook->show_border)
1394 gtk_draw_shadow (widget->style, widget->window,
1395 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1396 x, y, width, height);
1403 gtk_notebook_draw (GtkWidget *widget,
1406 GtkNotebook *notebook;
1407 GdkRectangle child_area;
1409 g_return_if_fail (widget != NULL);
1410 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1411 g_return_if_fail (area != NULL);
1413 if (GTK_WIDGET_DRAWABLE (widget))
1415 notebook = GTK_NOTEBOOK (widget);
1417 gtk_notebook_paint (widget, area);
1418 gtk_widget_draw_focus (widget);
1420 if (notebook->cur_page &&
1421 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1422 gtk_widget_draw (notebook->cur_page->child, &child_area);
1427 gtk_notebook_expose (GtkWidget *widget,
1428 GdkEventExpose *event)
1430 GtkNotebook *notebook;
1431 GdkEventExpose child_event;
1433 g_return_val_if_fail (widget != NULL, FALSE);
1434 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1435 g_return_val_if_fail (event != NULL, FALSE);
1437 if (GTK_WIDGET_DRAWABLE (widget))
1439 notebook = GTK_NOTEBOOK (widget);
1441 gtk_notebook_paint (widget, &event->area);
1442 gtk_widget_draw_focus (widget);
1444 child_event = *event;
1445 if (notebook->cur_page &&
1446 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1447 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1449 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1456 gtk_notebook_button_press (GtkWidget *widget,
1457 GdkEventButton *event)
1459 GtkNotebook *notebook;
1460 GtkNotebookPage *page;
1464 g_return_val_if_fail (widget != NULL, FALSE);
1465 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1466 g_return_val_if_fail (event != NULL, FALSE);
1468 notebook = GTK_NOTEBOOK (widget);
1470 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1471 || notebook->button)
1474 if (!GTK_WIDGET_HAS_FOCUS (widget) && !(GTK_CONTAINER (widget)->focus_child))
1475 gtk_widget_grab_focus (widget);
1477 if (event->window == notebook->panel)
1479 if (!GTK_WIDGET_HAS_FOCUS (widget))
1481 GTK_CONTAINER (widget)->focus_child = NULL;
1482 gtk_widget_grab_focus (widget);
1485 gtk_grab_add (widget);
1486 notebook->button = event->button;
1488 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1490 notebook->click_child = GTK_ARROW_LEFT;
1491 if (event->button == 1)
1493 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1494 if (!notebook->timer)
1496 notebook->timer = gtk_timeout_add
1497 (NOTEBOOK_INIT_SCROLL_DELAY,
1498 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1499 notebook->need_timer = TRUE;
1502 else if (event->button == 2)
1503 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1504 else if (event->button == 3)
1505 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1506 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1510 notebook->click_child = GTK_ARROW_RIGHT;
1511 if (event->button == 1)
1513 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1514 if (!notebook->timer)
1516 notebook->timer = gtk_timeout_add
1517 (NOTEBOOK_INIT_SCROLL_DELAY,
1518 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1519 notebook->need_timer = TRUE;
1522 else if (event->button == 2)
1523 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1524 else if (event->button == 3)
1525 gtk_notebook_switch_focus_tab (notebook,
1526 g_list_last (notebook->children));
1527 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1530 else if (event->window == widget->window)
1532 if (event->button == 3 && notebook->menu)
1534 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1535 NULL, NULL, 3, event->time);
1540 children = notebook->children;
1543 page = children->data;
1545 if (GTK_WIDGET_VISIBLE (page->child) &&
1546 GTK_WIDGET_MAPPED (page->tab_label) &&
1547 (event->x >= page->allocation.x) &&
1548 (event->y >= page->allocation.y) &&
1549 (event->x <= (page->allocation.x + page->allocation.width)) &&
1550 (event->y <= (page->allocation.y + page->allocation.height)))
1552 GTK_CONTAINER (notebook)->focus_child = NULL;
1554 if (page == notebook->cur_page &&
1555 notebook->focus_tab != children &&
1556 GTK_WIDGET_HAS_FOCUS (notebook))
1558 GtkNotebookPage *old_page;
1560 old_page = (GtkNotebookPage *)
1561 (notebook->focus_tab->data);
1562 notebook->focus_tab = children;
1563 gtk_notebook_focus_changed (notebook, old_page);
1567 notebook->focus_tab = children;
1568 gtk_notebook_switch_page (notebook, page, num);
1569 gtk_widget_grab_focus (widget);
1573 children = children->next;
1581 gtk_notebook_button_release (GtkWidget *widget,
1582 GdkEventButton *event)
1584 GtkNotebook *notebook;
1586 g_return_val_if_fail (widget != NULL, FALSE);
1587 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1588 g_return_val_if_fail (event != NULL, FALSE);
1590 if (event->type != GDK_BUTTON_RELEASE)
1593 notebook = GTK_NOTEBOOK (widget);
1595 if (event->button == notebook->button)
1599 if (notebook->timer)
1601 gtk_timeout_remove (notebook->timer);
1602 notebook->timer = 0;
1603 notebook->need_timer = FALSE;
1605 gtk_grab_remove (widget);
1606 click_child = notebook->click_child;
1607 notebook->click_child = 0;
1608 notebook->button = 0;
1609 gtk_notebook_draw_arrow (notebook, click_child);
1616 gtk_notebook_enter_notify (GtkWidget *widget,
1617 GdkEventCrossing *event)
1619 GtkNotebook *notebook;
1621 g_return_val_if_fail (widget != NULL, FALSE);
1622 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1623 g_return_val_if_fail (event != NULL, FALSE);
1625 notebook = GTK_NOTEBOOK (widget);
1627 if (event->window == notebook->panel)
1632 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1634 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1636 notebook->in_child = GTK_ARROW_LEFT;
1638 if (notebook->click_child == 0)
1639 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1643 notebook->in_child = GTK_ARROW_RIGHT;
1645 if (notebook->click_child == 0)
1646 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1654 gtk_notebook_leave_notify (GtkWidget *widget,
1655 GdkEventCrossing *event)
1657 GtkNotebook *notebook;
1659 g_return_val_if_fail (widget != NULL, FALSE);
1660 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1661 g_return_val_if_fail (event != NULL, FALSE);
1663 notebook = GTK_NOTEBOOK (widget);
1665 if (event->window == notebook->panel && !notebook->click_child)
1667 if (notebook->in_child == GTK_ARROW_LEFT)
1669 notebook->in_child = 0;
1670 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1674 notebook->in_child = 0;
1675 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1682 gtk_notebook_motion_notify (GtkWidget *widget,
1683 GdkEventMotion *event)
1685 GtkNotebook *notebook;
1687 g_return_val_if_fail (widget != NULL, FALSE);
1688 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1689 g_return_val_if_fail (event != NULL, FALSE);
1691 notebook = GTK_NOTEBOOK (widget);
1693 if (notebook->button)
1696 if (event->window == notebook->panel)
1702 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1704 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
1705 notebook->in_child == GTK_ARROW_RIGHT)
1707 notebook->in_child = GTK_ARROW_LEFT;
1708 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1709 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1711 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
1712 notebook->in_child == GTK_ARROW_LEFT)
1714 notebook->in_child = GTK_ARROW_RIGHT;
1715 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1716 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1724 gtk_notebook_timer (GtkNotebook *notebook)
1726 g_return_val_if_fail (notebook != NULL, FALSE);
1727 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1729 if (notebook->timer)
1731 if (notebook->click_child == GTK_ARROW_LEFT)
1732 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1733 else if (notebook->click_child == GTK_ARROW_RIGHT)
1734 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1736 if (notebook->need_timer)
1738 notebook->need_timer = FALSE;
1739 notebook->timer = gtk_timeout_add
1740 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
1741 (gpointer) notebook);
1750 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
1752 GtkStateType state_type;
1753 GtkShadowType shadow_type;
1756 g_return_if_fail (notebook != NULL);
1757 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1759 widget = GTK_WIDGET(notebook);
1761 if (GTK_WIDGET_DRAWABLE (notebook))
1763 if (notebook->in_child == arrow)
1765 if (notebook->click_child == arrow)
1766 state_type = GTK_STATE_ACTIVE;
1768 state_type = GTK_STATE_PRELIGHT;
1771 state_type = GTK_STATE_NORMAL;
1773 if (notebook->click_child == arrow)
1774 shadow_type = GTK_SHADOW_IN;
1776 shadow_type = GTK_SHADOW_OUT;
1778 if (arrow == GTK_ARROW_LEFT)
1780 if (notebook->tab_pos == GTK_POS_LEFT ||
1781 notebook->tab_pos == GTK_POS_RIGHT)
1782 arrow = GTK_ARROW_UP;
1783 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1784 shadow_type, arrow, TRUE,
1785 0, 0, ARROW_SIZE, ARROW_SIZE);
1789 if (notebook->tab_pos == GTK_POS_LEFT ||
1790 notebook->tab_pos == GTK_POS_RIGHT)
1791 arrow = GTK_ARROW_DOWN;
1792 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1793 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
1794 0, ARROW_SIZE, ARROW_SIZE);
1800 gtk_real_notebook_switch_page (GtkNotebook *notebook,
1801 GtkNotebookPage *page)
1803 g_return_if_fail (notebook != NULL);
1804 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1805 g_return_if_fail (page != NULL);
1807 if (notebook->cur_page == page)
1810 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
1811 gtk_widget_unmap (notebook->cur_page->child);
1813 notebook->cur_page = page;
1815 if (notebook->focus_tab->data != (gpointer) notebook->cur_page)
1816 notebook->focus_tab =
1817 g_list_find (notebook->children, notebook->cur_page);
1819 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
1821 if (GTK_WIDGET_MAPPED (notebook))
1823 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
1824 gtk_widget_map (notebook->cur_page->child);
1827 gtk_widget_map (notebook->cur_page->child);
1828 gtk_widget_size_allocate (GTK_WIDGET (notebook),
1829 >K_WIDGET (notebook)->allocation);
1833 if (GTK_WIDGET_DRAWABLE (notebook))
1834 gtk_widget_queue_draw (GTK_WIDGET (notebook));
1838 gtk_notebook_draw_tab (GtkNotebook *notebook,
1839 GtkNotebookPage *page,
1842 GdkRectangle child_area;
1843 GdkRectangle page_area;
1844 GtkStateType state_type;
1848 g_return_if_fail (notebook != NULL);
1849 g_return_if_fail (page != NULL);
1850 g_return_if_fail (area != NULL);
1852 if (!GTK_WIDGET_MAPPED (page->tab_label))
1855 page_area.x = page->allocation.x;
1856 page_area.y = page->allocation.y;
1857 page_area.width = page->allocation.width;
1858 page_area.height = page->allocation.height;
1860 if (gdk_rectangle_intersect (&page_area, area, &child_area))
1864 switch (notebook->tab_pos)
1867 if (child_area.x + child_area.width >
1868 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1870 points[0].x = page->allocation.x + page->allocation.width - 1;
1871 points[0].y = page->allocation.y + page->allocation.height - 1;
1873 points[1].x = page->allocation.x + page->allocation.width - 1;
1874 points[1].y = page->allocation.y + TAB_CURVATURE;
1876 points[2].x = page->allocation.x + page->allocation.width
1877 - TAB_CURVATURE - 1;
1878 points[2].y = page->allocation.y;
1883 points[0].x = page->allocation.x + page->allocation.width
1885 points[0].y = page->allocation.y;
1889 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1890 (page == notebook->cur_page ||
1891 page == (GtkNotebookPage *)(notebook->children->data) ||
1892 (notebook->scrollable &&
1893 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1895 points[n].x = page->allocation.x + TAB_CURVATURE;
1896 points[n++].y = page->allocation.y;
1898 points[n].x = page->allocation.x;
1899 points[n++].y = page->allocation.y + TAB_CURVATURE;
1901 points[n].x = page->allocation.x;
1902 points[n++].y = page->allocation.y + page->allocation.height - 1;
1906 points[n].x = page->allocation.x + TAB_OVERLAP;
1907 points[n++].y = page->allocation.y;
1910 case GTK_POS_BOTTOM:
1911 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1912 (page == notebook->cur_page ||
1913 page == (GtkNotebookPage *)(notebook->children->data) ||
1914 (notebook->scrollable &&
1915 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1917 points[0].x = page->allocation.x;
1918 points[0].y = page->allocation.y;
1920 points[1].x = page->allocation.x;
1921 points[1].y = page->allocation.y + page->allocation.height
1922 - TAB_CURVATURE - 1;
1924 points[2].x = page->allocation.x + TAB_CURVATURE;
1925 points[2].y = page->allocation.y + page->allocation.height - 1;
1930 points[0].x = page->allocation.x + TAB_OVERLAP;
1931 points[0].y = page->allocation.y + page->allocation.height - 1;
1935 if (child_area.x + child_area.width >
1936 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1938 points[n].x = page->allocation.x + page->allocation.width
1939 - TAB_CURVATURE - 1;
1940 points[n++].y = page->allocation.y + page->allocation.height - 1;
1942 points[n].x = page->allocation.x + page->allocation.width - 1;
1943 points[n++].y = page->allocation.y + page->allocation.height
1944 - TAB_CURVATURE - 1;
1946 points[n].x = page->allocation.x + page->allocation.width - 1;
1947 points[n++].y = page->allocation.y;
1951 points[n].x = page->allocation.x + page->allocation.width
1953 points[n++].y = page->allocation.y + page->allocation.height - 1;
1957 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1958 (page == notebook->cur_page ||
1959 page == (GtkNotebookPage *)(notebook->children->data) ||
1960 (notebook->scrollable &&
1961 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1963 points[0].x = page->allocation.x + page->allocation.width - 1;
1964 points[0].y = page->allocation.y;
1966 points[1].x = page->allocation.x + TAB_CURVATURE;
1967 points[1].y = page->allocation.y;
1969 points[2].x = page->allocation.x;
1970 points[2].y = page->allocation.y + TAB_CURVATURE;
1975 points[0].x = page->allocation.x;
1976 points[0].y = page->allocation.y + TAB_OVERLAP;
1980 if (child_area.y + child_area.height >
1981 page->allocation.y + page->allocation.height - TAB_OVERLAP)
1983 points[n].x = page->allocation.x;
1984 points[n++].y = page->allocation.y + page->allocation.height
1985 - TAB_CURVATURE - 1;
1987 points[n].x = page->allocation.x + TAB_CURVATURE;
1988 points[n++].y = page->allocation.y + page->allocation.height - 1;
1990 points[n].x = page->allocation.x + page->allocation.width - 1;
1991 points[n++].y = page->allocation.y + page->allocation.height - 1;
1995 points[n].x = page->allocation.x;
1996 points[n++].y = page->allocation.y + page->allocation.height
2001 if (child_area.y + child_area.height >
2002 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2004 points[0].x = page->allocation.x;
2005 points[0].y = page->allocation.y + page->allocation.height - 1;
2007 points[1].x = page->allocation.x + page->allocation.width
2008 - TAB_CURVATURE - 1;
2009 points[1].y = page->allocation.y + page->allocation.height - 1;
2011 points[2].x = page->allocation.x + page->allocation.width - 1;
2012 points[2].y = page->allocation.y + page->allocation.height
2013 - TAB_CURVATURE - 1;
2018 points[0].x = page->allocation.x + page->allocation.width - 1;
2019 points[0].y = page->allocation.y + page->allocation.height
2024 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2025 (page == notebook->cur_page ||
2026 page == (GtkNotebookPage *)(notebook->children->data) ||
2027 (notebook->scrollable &&
2028 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2030 points[n].x = page->allocation.x + page->allocation.width - 1;
2031 points[n++].y = page->allocation.y + TAB_CURVATURE;
2033 points[n].x = page->allocation.x + page->allocation.width
2034 - TAB_CURVATURE - 1;
2035 points[n++].y = page->allocation.y;
2037 points[n].x = page->allocation.x;
2038 points[n++].y = page->allocation.y;
2042 points[n].x = page->allocation.x + page->allocation.width - 1;
2043 points[n++].y = page->allocation.y + TAB_OVERLAP;
2048 widget = GTK_WIDGET(notebook);
2050 if (notebook->cur_page == page)
2052 state_type = GTK_STATE_NORMAL;
2056 state_type = GTK_STATE_ACTIVE;
2057 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2058 TRUE, child_area.x, child_area.y,
2059 child_area.width, child_area.height);
2062 gtk_draw_polygon (widget->style, widget->window, state_type,
2063 GTK_SHADOW_OUT, points, n, FALSE);
2065 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2066 gtk_widget_draw (page->tab_label, &child_area);
2071 gtk_notebook_focus_in (GtkWidget *widget,
2072 GdkEventFocus *event)
2074 g_return_val_if_fail (widget != NULL, FALSE);
2075 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2076 g_return_val_if_fail (event != NULL, FALSE);
2078 if (GTK_CONTAINER (widget)->focus_child)
2080 if (gtk_notebook_page_select (GTK_NOTEBOOK (widget)))
2083 GTK_CONTAINER (widget)->focus_child = NULL;
2086 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2087 gtk_widget_draw_focus (widget);
2093 gtk_notebook_focus_out (GtkWidget *widget,
2094 GdkEventFocus *event)
2096 g_return_val_if_fail (widget != NULL, FALSE);
2097 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2098 g_return_val_if_fail (event != NULL, FALSE);
2100 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2101 gtk_widget_draw_focus (widget);
2107 gtk_notebook_draw_focus (GtkWidget *widget)
2109 GtkNotebook *notebook;
2111 g_return_if_fail (widget != NULL);
2112 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2114 notebook = GTK_NOTEBOOK (widget);
2116 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2117 notebook->focus_tab)
2119 GtkNotebookPage *page;
2122 page = notebook->focus_tab->data;
2124 if (GTK_WIDGET_HAS_FOCUS (widget))
2125 gc = widget->style->black_gc;
2126 else if (page == notebook->cur_page)
2127 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2129 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2131 gdk_draw_rectangle (widget->window,
2133 page->tab_label->allocation.x - 1,
2134 page->tab_label->allocation.y - 1,
2135 page->tab_label->allocation.width + 1,
2136 page->tab_label->allocation.height + 1);
2141 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2145 g_return_if_fail (notebook != NULL);
2146 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2147 g_return_if_fail (old_page != NULL);
2149 widget = GTK_WIDGET (notebook);
2151 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2152 notebook->focus_tab)
2154 GtkNotebookPage *page;
2157 page = notebook->focus_tab->data;
2159 if (GTK_WIDGET_HAS_FOCUS (widget))
2160 gc = widget->style->black_gc;
2161 else if (page == notebook->cur_page)
2162 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2164 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2166 gdk_draw_rectangle (widget->window,
2168 page->tab_label->allocation.x - 1,
2169 page->tab_label->allocation.y - 1,
2170 page->tab_label->allocation.width + 1,
2171 page->tab_label->allocation.height + 1);
2173 if (old_page == notebook->cur_page)
2174 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2176 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2178 gdk_draw_rectangle (widget->window,
2180 old_page->tab_label->allocation.x - 1,
2181 old_page->tab_label->allocation.y - 1,
2182 old_page->tab_label->allocation.width + 1,
2183 old_page->tab_label->allocation.height + 1);
2188 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2194 GtkNotebookPage *page = NULL;
2198 switch (notebook->tab_pos)
2201 case GTK_POS_BOTTOM:
2204 page = children->data;
2205 *tab_space -= page->requisition.width;
2206 if (*tab_space < 0 || children == *end)
2210 *tab_space = - (*tab_space + page->requisition.width);
2215 if (direction == STEP_NEXT)
2216 children = children->next;
2218 children = children->prev;
2225 page = children->data;
2226 *tab_space -= page->requisition.height;
2227 if (*tab_space < 0 || children == *end)
2231 *tab_space = - (*tab_space + page->requisition.height);
2236 if (direction == STEP_NEXT)
2237 children = children->next;
2239 children = children->prev;
2246 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2247 GtkAllocation *allocation)
2250 GtkContainer *container;
2251 GtkNotebookPage *page = NULL;
2252 GtkAllocation child_allocation;
2254 GList *last_child = NULL;
2255 gint showarrow = FALSE;
2264 if (!notebook->show_tabs || !notebook->children)
2267 widget = GTK_WIDGET (notebook);
2268 container = GTK_CONTAINER (notebook);
2270 child_allocation.x = container->border_width;
2271 child_allocation.y = container->border_width;
2273 switch (notebook->tab_pos)
2275 case GTK_POS_BOTTOM:
2276 child_allocation.y = (allocation->height -
2277 notebook->cur_page->requisition.height -
2278 container->border_width);
2280 child_allocation.height = notebook->cur_page->requisition.height;
2283 child_allocation.x = (allocation->width -
2284 notebook->cur_page->requisition.width -
2285 container->border_width);
2287 child_allocation.width = notebook->cur_page->requisition.width;
2291 if (notebook->scrollable)
2293 children = notebook->children;
2294 switch (notebook->tab_pos)
2297 case GTK_POS_BOTTOM:
2300 page = children->data;
2301 children = children->next;
2302 tab_space += page->requisition.width;
2304 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2307 page = notebook->focus_tab->data;
2309 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2310 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2311 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2313 page = notebook->children->data;
2314 if (notebook->tab_pos == GTK_POS_TOP)
2315 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2317 y = (allocation->height - container->border_width -
2318 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2325 page = children->data;
2326 children = children->next;
2327 tab_space += page->requisition.height;
2329 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2332 page = notebook->focus_tab->data;
2333 tab_space = (allocation->height -
2334 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2335 2 * container->border_width - page->requisition.height);
2336 y = allocation->height - container->border_width - ARROW_SIZE;
2338 page = notebook->children->data;
2339 if (notebook->tab_pos == GTK_POS_LEFT)
2340 x = (container->border_width +
2341 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2343 x = (allocation->width - container->border_width -
2344 (2 * ARROW_SIZE - ARROW_SPACING) -
2345 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2349 if (showarrow) /* first_tab <- focus_tab */
2351 children = notebook->focus_tab->prev;
2354 if (notebook->first_tab == children)
2356 children = children->prev;
2360 notebook->first_tab = notebook->focus_tab;
2362 gtk_notebook_calc_tabs (notebook, notebook->focus_tab->prev,
2363 &(notebook->first_tab), &tab_space,
2367 notebook->first_tab = notebook->first_tab->next;
2368 if (!notebook->first_tab)
2369 notebook->first_tab = notebook->focus_tab;
2370 last_child = notebook->focus_tab->next;
2372 else /* focus_tab -> end */
2374 if (!notebook->first_tab)
2375 notebook->first_tab = notebook->children;
2378 gtk_notebook_calc_tabs (notebook, notebook->focus_tab->next,
2379 &children, &tab_space, STEP_NEXT);
2382 last_child = children;
2383 else /* start <- first_tab */
2387 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2388 &children, &tab_space, STEP_PREV);
2390 notebook->first_tab = children->next;
2392 notebook->first_tab = notebook->children;
2396 if (GTK_WIDGET_REALIZED (notebook))
2398 gdk_window_move (notebook->panel, x, y);
2399 gdk_window_show (notebook->panel);
2404 tab_space = -tab_space;
2406 children = notebook->first_tab;
2407 while (children != last_child)
2409 children = children->next;
2416 children = notebook->children;
2417 while (children != notebook->first_tab)
2419 page = children->data;
2420 children = children->next;
2422 if (GTK_WIDGET_MAPPED (page->tab_label))
2423 gtk_widget_unmap (page->tab_label);
2426 children = last_child;
2429 page = children->data;
2430 children = children->next;
2432 if (GTK_WIDGET_MAPPED (page->tab_label))
2433 gtk_widget_unmap (page->tab_label);
2436 else /* !showarrow */
2438 notebook->first_tab = notebook->children;
2440 if (GTK_WIDGET_REALIZED (notebook))
2441 gdk_window_hide (notebook->panel);
2443 children = notebook->first_tab;
2446 children = notebook->children;
2449 while (children != last_child)
2451 page = children->data;
2452 children = children->next;
2454 if (GTK_WIDGET_VISIBLE (page->child))
2456 new_fill = (tab_space * i++) / n;
2457 switch (notebook->tab_pos)
2460 case GTK_POS_BOTTOM:
2461 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2465 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2468 old_fill = new_fill;
2469 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2471 switch (notebook->tab_pos)
2474 case GTK_POS_BOTTOM:
2475 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2479 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2483 if (GTK_WIDGET_REALIZED (notebook) &&
2484 !GTK_WIDGET_MAPPED (page->tab_label))
2485 gtk_widget_map (page->tab_label);
2491 gtk_notebook_page_allocate (GtkNotebook *notebook,
2492 GtkNotebookPage *page,
2493 GtkAllocation *allocation)
2495 GtkAllocation child_allocation;
2496 gint xthickness, ythickness;
2498 g_return_if_fail (notebook != NULL);
2499 g_return_if_fail (page != NULL);
2500 g_return_if_fail (allocation != NULL);
2502 page->allocation = *allocation;
2504 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2505 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2507 if (notebook->cur_page != page)
2509 switch (notebook->tab_pos)
2512 page->allocation.y += ythickness;
2513 case GTK_POS_BOTTOM:
2514 page->allocation.height -= ythickness;
2517 page->allocation.x += xthickness;
2519 page->allocation.width -= xthickness;
2524 switch (notebook->tab_pos)
2527 child_allocation.x = xthickness + notebook->tab_border;
2528 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2529 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2530 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2531 child_allocation.x += page->allocation.x;
2533 case GTK_POS_BOTTOM:
2534 child_allocation.x = xthickness + notebook->tab_border;
2535 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2536 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2537 child_allocation.x += page->allocation.x;
2538 child_allocation.y = page->allocation.y + notebook->tab_border;
2541 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
2542 child_allocation.y = ythickness + notebook->tab_border;
2543 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2544 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2545 child_allocation.y += page->allocation.y;
2548 child_allocation.y = ythickness + notebook->tab_border;
2549 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2550 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2551 child_allocation.x = page->allocation.x + notebook->tab_border;
2552 child_allocation.y += page->allocation.y;
2556 gtk_widget_size_allocate (page->tab_label, &child_allocation);
2560 gtk_notebook_menu_switch_page (GtkWidget *widget,
2561 GtkNotebookPage *page)
2563 GtkNotebook *notebook;
2567 g_return_if_fail (widget != NULL);
2568 g_return_if_fail (page != NULL);
2570 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
2571 (GTK_MENU (widget->parent)));
2573 if (notebook->cur_page == page)
2577 children = notebook->children;
2578 while (children && children->data != page)
2580 children = children->next;
2584 gtk_signal_emit (GTK_OBJECT (notebook),
2585 notebook_signals[SWITCH_PAGE],
2591 gtk_notebook_switch_page (GtkNotebook *notebook,
2592 GtkNotebookPage *page,
2595 g_return_if_fail (notebook != NULL);
2596 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2597 g_return_if_fail (page != NULL);
2599 if (notebook->cur_page == page)
2602 gtk_signal_emit (GTK_OBJECT (notebook),
2603 notebook_signals[SWITCH_PAGE],
2609 gtk_notebook_marshal_signal (GtkObject *object,
2614 GtkNotebookSignal rfunc;
2616 rfunc = (GtkNotebookSignal) func;
2618 (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
2623 gtk_notebook_focus (GtkContainer *container,
2624 GtkDirectionType direction)
2626 GtkNotebook *notebook;
2627 GtkWidget *focus_child;
2628 GtkNotebookPage *page = NULL;
2629 GtkNotebookPage *old_page;
2632 g_return_val_if_fail (container != NULL, FALSE);
2633 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
2635 notebook = GTK_NOTEBOOK (container);
2637 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
2640 focus_child = container->focus_child;
2641 container->focus_child = NULL;
2643 if (!notebook->show_tabs)
2645 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2647 if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
2651 gtk_widget_grab_focus (notebook->cur_page->child);
2655 else if (GTK_IS_CONTAINER (notebook->cur_page->child))
2657 if (gtk_container_focus
2658 (GTK_CONTAINER (notebook->cur_page->child), direction))
2665 old_page = notebook->focus_tab->data;
2668 if (!GTK_WIDGET_HAS_FOCUS (container) && !focus_child)
2670 gtk_widget_grab_focus (GTK_WIDGET (container));
2674 if (focus_child && focus_child == old_page->child)
2676 if (GTK_WIDGET_VISIBLE (old_page->child))
2678 if (GTK_IS_CONTAINER (old_page->child) &&
2679 !GTK_WIDGET_HAS_FOCUS (old_page->child))
2681 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
2685 gtk_widget_grab_focus (GTK_WIDGET(notebook));
2693 case GTK_DIR_TAB_FORWARD:
2696 if (!notebook->focus_tab->next)
2699 notebook->focus_tab = notebook->focus_tab->next;
2700 page = notebook->focus_tab->data;
2703 case GTK_DIR_TAB_BACKWARD:
2706 if (!notebook->focus_tab->prev)
2709 notebook->focus_tab = notebook->focus_tab->prev;
2710 page = notebook->focus_tab->data;
2717 if (GTK_WIDGET_MAPPED (page->tab_label))
2718 gtk_notebook_focus_changed (notebook, old_page);
2721 gtk_notebook_pages_allocate (notebook,
2722 &(GTK_WIDGET (notebook)->allocation));
2723 gtk_notebook_expose_tabs (notebook);
2731 gtk_notebook_page_select (GtkNotebook *notebook)
2733 g_return_val_if_fail (notebook != NULL, FALSE);
2734 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2736 if (notebook->focus_tab)
2738 GtkNotebookPage *page;
2742 page = notebook->focus_tab->data;
2744 children = notebook->children;
2746 while (children != notebook->focus_tab)
2748 children = children->next;
2752 gtk_notebook_switch_page (notebook, page, num);
2754 if (GTK_WIDGET_VISIBLE (page->child))
2756 if (GTK_WIDGET_CAN_FOCUS (page->child))
2758 gtk_widget_grab_focus (page->child);
2761 else if (GTK_IS_CONTAINER (page->child))
2763 if (gtk_container_focus (GTK_CONTAINER (page->child),
2764 GTK_DIR_TAB_FORWARD))
2773 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
2776 GtkNotebookPage *old_page;
2777 GtkNotebookPage *page;
2779 g_return_if_fail (notebook != NULL);
2780 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2782 if (notebook->focus_tab != new_child)
2784 old_page = notebook->focus_tab->data;
2785 notebook->focus_tab = new_child;
2786 page = notebook->focus_tab->data;
2787 if (GTK_WIDGET_MAPPED (page->tab_label))
2788 gtk_notebook_focus_changed (notebook, old_page);
2791 gtk_notebook_pages_allocate (notebook,
2792 &(GTK_WIDGET (notebook)->allocation));
2793 gtk_notebook_expose_tabs (notebook);
2799 gtk_notebook_key_press (GtkWidget *widget,
2802 GtkNotebook *notebook;
2803 GtkDirectionType direction = 0;
2806 g_return_val_if_fail (widget != NULL, FALSE);
2807 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2808 g_return_val_if_fail (event != NULL, FALSE);
2810 notebook = GTK_NOTEBOOK (widget);
2813 if (!notebook->children || !notebook->show_tabs)
2816 switch (event->keyval)
2819 direction = GTK_DIR_UP;
2822 direction = GTK_DIR_LEFT;
2825 direction = GTK_DIR_DOWN;
2828 direction = GTK_DIR_RIGHT;
2831 if (event->state & GDK_SHIFT_MASK)
2832 direction = GTK_DIR_TAB_BACKWARD;
2834 direction = GTK_DIR_TAB_FORWARD;
2837 gtk_notebook_switch_focus_tab (notebook, notebook->children);
2840 gtk_notebook_switch_focus_tab (notebook,
2841 g_list_last (notebook->children));
2845 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
2851 return gtk_container_focus (GTK_CONTAINER (widget), direction);
2856 gtk_notebook_set_tab_border (GtkNotebook *notebook,
2859 g_return_if_fail (notebook != NULL);
2860 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2862 if (notebook->tab_border != tab_border && tab_border > 0)
2864 notebook->tab_border = tab_border;
2866 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
2867 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2872 gtk_notebook_update_labels (GtkNotebook *notebook,
2876 GtkNotebookPage *page;
2883 sprintf (string, "Page %d", page_num);
2884 if (notebook->show_tabs && page->default_tab)
2885 gtk_label_set (GTK_LABEL (page->tab_label), string);
2886 if (notebook->menu && page->default_menu)
2887 gtk_label_set (GTK_LABEL (page->menu_label), string);
2893 gtk_notebook_menu_item_create (GtkNotebook *notebook,
2894 GtkNotebookPage *page,
2897 GtkWidget *menu_item;
2899 if (page->default_menu)
2901 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2902 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
2904 page->menu_label = gtk_label_new ("");
2905 gtk_widget_show (page->menu_label);
2907 menu_item = gtk_menu_item_new ();
2908 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
2909 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
2910 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
2911 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page),
2913 gtk_widget_show (menu_item);
2917 gtk_notebook_popup_enable (GtkNotebook *notebook)
2919 GtkNotebookPage *page;
2922 g_return_if_fail (notebook != NULL);
2923 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2928 notebook->menu = gtk_menu_new ();
2930 children = notebook->children;
2933 page = children->data;
2934 children = children->next;
2935 gtk_notebook_menu_item_create (notebook, page, -1);
2937 gtk_notebook_update_labels (notebook, notebook->children,1);
2939 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
2940 gtk_notebook_menu_detacher);
2944 gtk_notebook_menu_label_unparent (GtkWidget *widget,
2947 gtk_widget_unparent (GTK_BIN(widget)->child);
2948 GTK_BIN(widget)->child = NULL;
2952 gtk_notebook_popup_disable (GtkNotebook *notebook)
2954 g_return_if_fail (notebook != NULL);
2955 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2957 if (!notebook->menu)
2960 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
2961 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
2962 gtk_widget_destroy (notebook->menu);
2966 gtk_notebook_menu_detacher (GtkWidget *widget,
2969 GtkNotebook *notebook;
2971 g_return_if_fail (widget != NULL);
2972 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2974 notebook = GTK_NOTEBOOK (widget);
2975 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
2977 notebook->menu = NULL;