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 void gtk_notebook_set_focus_child (GtkContainer *container,
99 static gint gtk_notebook_focus_in (GtkWidget *widget,
100 GdkEventFocus *event);
101 static gint gtk_notebook_focus_out (GtkWidget *widget,
102 GdkEventFocus *event);
103 static void gtk_notebook_draw_focus (GtkWidget *widget);
104 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
105 GtkNotebookPage *old_page);
106 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
107 GtkAllocation *allocation);
108 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
109 GtkNotebookPage *page,
110 GtkAllocation *allocation);
111 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
113 static gint gtk_notebook_timer (GtkNotebook *notebook);
114 static gint gtk_notebook_focus (GtkContainer *container,
115 GtkDirectionType direction);
116 static gint gtk_notebook_page_select (GtkNotebook *notebook);
117 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
122 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
123 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
125 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
126 GtkNotebookPage *page,
128 static void gtk_notebook_marshal_signal (GtkObject *object,
132 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
133 GtkNotebookPage *page);
134 static void gtk_notebook_update_labels (GtkNotebook *notebook,
137 static void gtk_notebook_menu_detacher (GtkWidget *widget,
139 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
141 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
142 GtkNotebookPage *page,
144 static GtkType gtk_notebook_child_type (GtkContainer *container);
147 static GtkContainerClass *parent_class = NULL;
148 static guint notebook_signals[LAST_SIGNAL] = { 0 };
151 gtk_notebook_get_type (void)
153 static GtkType notebook_type = 0;
157 GtkTypeInfo notebook_info =
160 sizeof (GtkNotebook),
161 sizeof (GtkNotebookClass),
162 (GtkClassInitFunc) gtk_notebook_class_init,
163 (GtkObjectInitFunc) gtk_notebook_init,
164 (GtkArgSetFunc) NULL,
165 (GtkArgGetFunc) NULL,
168 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
171 return notebook_type;
175 gtk_notebook_class_init (GtkNotebookClass *class)
177 GtkObjectClass *object_class;
178 GtkWidgetClass *widget_class;
179 GtkContainerClass *container_class;
181 object_class = (GtkObjectClass*) class;
182 widget_class = (GtkWidgetClass*) class;
183 container_class = (GtkContainerClass*) class;
185 parent_class = gtk_type_class (gtk_container_get_type ());
187 notebook_signals[SWITCH_PAGE] =
188 gtk_signal_new ("switch_page",
191 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
192 gtk_notebook_marshal_signal,
197 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
199 object_class->destroy = gtk_notebook_destroy;
201 widget_class->map = gtk_notebook_map;
202 widget_class->unmap = gtk_notebook_unmap;
203 widget_class->realize = gtk_notebook_realize;
204 widget_class->size_request = gtk_notebook_size_request;
205 widget_class->size_allocate = gtk_notebook_size_allocate;
206 widget_class->draw = gtk_notebook_draw;
207 widget_class->expose_event = gtk_notebook_expose;
208 widget_class->button_press_event = gtk_notebook_button_press;
209 widget_class->button_release_event = gtk_notebook_button_release;
210 widget_class->enter_notify_event = gtk_notebook_enter_notify;
211 widget_class->leave_notify_event = gtk_notebook_leave_notify;
212 widget_class->motion_notify_event = gtk_notebook_motion_notify;
213 widget_class->key_press_event = gtk_notebook_key_press;
214 widget_class->focus_in_event = gtk_notebook_focus_in;
215 widget_class->focus_out_event = gtk_notebook_focus_out;
216 widget_class->draw_focus = gtk_notebook_draw_focus;
218 container_class->add = gtk_notebook_add;
219 container_class->remove = gtk_notebook_remove;
220 container_class->foreach = gtk_notebook_foreach;
221 container_class->focus = gtk_notebook_focus;
222 container_class->set_focus_child = gtk_notebook_set_focus_child;
223 container_class->child_type = gtk_notebook_child_type;
225 class->switch_page = gtk_real_notebook_switch_page;
229 gtk_notebook_child_type (GtkContainer *container)
231 return GTK_TYPE_WIDGET;
235 gtk_notebook_init (GtkNotebook *notebook)
237 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
239 notebook->cur_page = NULL;
240 notebook->children = NULL;
241 notebook->first_tab = NULL;
242 notebook->focus_tab = NULL;
243 notebook->panel = NULL;
244 notebook->menu = NULL;
246 notebook->tab_border = 3;
247 notebook->show_tabs = TRUE;
248 notebook->show_border = TRUE;
249 notebook->tab_pos = GTK_POS_TOP;
250 notebook->scrollable = FALSE;
251 notebook->in_child = 0;
252 notebook->click_child = 0;
253 notebook->button = 0;
254 notebook->need_timer = 0;
255 notebook->child_has_focus = FALSE;
259 gtk_notebook_new (void)
261 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
265 gtk_notebook_destroy (GtkObject *object)
267 GtkNotebook *notebook;
269 g_return_if_fail (object != NULL);
270 g_return_if_fail (GTK_IS_NOTEBOOK (object));
272 notebook = GTK_NOTEBOOK (object);
275 gtk_notebook_popup_disable (notebook);
277 GTK_OBJECT_CLASS (parent_class)->destroy (object);
281 gtk_notebook_append_page (GtkNotebook *notebook,
283 GtkWidget *tab_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, NULL, -1);
293 gtk_notebook_append_page_menu (GtkNotebook *notebook,
295 GtkWidget *tab_label,
296 GtkWidget *menu_label)
298 g_return_if_fail (notebook != NULL);
299 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
300 g_return_if_fail (child != NULL);
302 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
306 gtk_notebook_prepend_page (GtkNotebook *notebook,
308 GtkWidget *tab_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, NULL, 0);
318 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
320 GtkWidget *tab_label,
321 GtkWidget *menu_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, menu_label, 0);
331 gtk_notebook_insert_page (GtkNotebook *notebook,
333 GtkWidget *tab_label,
336 g_return_if_fail (notebook != NULL);
337 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
338 g_return_if_fail (child != NULL);
340 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
344 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
346 GtkWidget *tab_label,
347 GtkWidget *menu_label,
350 GtkNotebookPage *page;
353 g_return_if_fail (notebook != NULL);
354 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
355 g_return_if_fail (child != NULL);
357 page = g_new (GtkNotebookPage, 1);
359 page->requisition.width = 0;
360 page->requisition.height = 0;
361 page->allocation.x = 0;
362 page->allocation.y = 0;
363 page->allocation.width = 0;
364 page->allocation.height = 0;
365 page->default_menu = FALSE;
366 page->default_tab = FALSE;
368 nchildren = g_list_length (notebook->children);
369 if ((position < 0) || (position > nchildren))
370 position = nchildren;
372 notebook->children = g_list_insert (notebook->children, page, position);
376 page->default_tab = TRUE;
377 if (notebook->show_tabs)
378 tab_label = gtk_label_new ("");
380 page->tab_label = tab_label;
381 page->menu_label = menu_label;
384 page->default_menu = TRUE;
387 gtk_widget_ref (page->menu_label);
388 gtk_object_sink (GTK_OBJECT(page->menu_label));
392 gtk_notebook_menu_item_create (notebook, page, position);
394 gtk_notebook_update_labels
395 (notebook, g_list_nth (notebook->children, position), position + 1);
397 if (!notebook->first_tab)
398 notebook->first_tab = notebook->children;
400 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
403 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
404 gtk_widget_show (tab_label);
407 if (!notebook->cur_page)
409 gtk_notebook_switch_page (notebook, page, 0);
410 notebook->focus_tab = NULL;
413 if (GTK_WIDGET_VISIBLE (notebook))
415 if (GTK_WIDGET_REALIZED (notebook) &&
416 !GTK_WIDGET_REALIZED (child))
417 gtk_widget_realize (child);
419 if (GTK_WIDGET_MAPPED (notebook) &&
420 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
421 gtk_widget_map (child);
425 if (GTK_WIDGET_REALIZED (notebook) &&
426 !GTK_WIDGET_REALIZED (tab_label))
427 gtk_widget_realize (tab_label);
429 if (GTK_WIDGET_MAPPED (notebook) &&
430 !GTK_WIDGET_MAPPED (tab_label))
431 gtk_widget_map (tab_label);
435 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
436 gtk_widget_queue_resize (child);
440 gtk_notebook_remove_page (GtkNotebook *notebook,
445 g_return_if_fail (notebook != NULL);
446 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
448 if ((list = g_list_nth (notebook->children, page_num)))
449 gtk_notebook_real_remove (notebook, list, page_num);
453 gtk_notebook_add (GtkContainer *container,
456 g_return_if_fail (container != NULL);
457 g_return_if_fail (GTK_IS_NOTEBOOK (container));
458 g_return_if_fail (widget != NULL);
460 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
465 gtk_notebook_remove (GtkContainer *container,
468 GtkNotebook *notebook;
469 GtkNotebookPage *page;
473 g_return_if_fail (container != NULL);
474 g_return_if_fail (GTK_IS_NOTEBOOK (container));
475 g_return_if_fail (widget != NULL);
477 notebook = GTK_NOTEBOOK (container);
479 children = notebook->children;
483 page = children->data;
484 if (page->child == widget)
486 gtk_notebook_real_remove (notebook, children, page_num);
490 children = children->next;
495 gtk_notebook_real_remove (GtkNotebook *notebook,
499 GtkNotebookPage *page;
501 gint need_resize = FALSE;
505 next_list = list->prev;
510 next_list = list->next;
516 if (notebook->cur_page == list->data)
518 notebook->cur_page = NULL;
521 page = next_list->data;
522 gtk_notebook_switch_page (notebook, page, page_num);
526 if (list == notebook->first_tab)
527 notebook->first_tab = next_list;
528 if (list == notebook->focus_tab)
529 notebook->focus_tab = next_list;
533 if ((GTK_WIDGET_VISIBLE (page->child) ||
534 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
535 && GTK_WIDGET_VISIBLE (notebook))
538 gtk_widget_unparent (page->child);
541 gtk_widget_unparent (page->tab_label);
545 gtk_container_remove (GTK_CONTAINER (notebook->menu),
546 page->menu_label->parent);
547 gtk_widget_queue_resize (notebook->menu);
549 if (!page->default_menu)
550 gtk_widget_unref (page->menu_label);
552 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
554 notebook->children = g_list_remove_link (notebook->children, list);
559 gtk_widget_queue_resize (GTK_WIDGET (notebook));
564 gtk_notebook_current_page (GtkNotebook *notebook)
569 g_return_val_if_fail (notebook != NULL, -1);
570 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
572 if (notebook->cur_page)
575 children = notebook->children;
579 if (children->data == notebook->cur_page)
581 children = children->next;
597 gtk_notebook_set_page (GtkNotebook *notebook,
602 g_return_if_fail (notebook != NULL);
603 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
605 if ((list = g_list_nth (notebook->children, page_num)))
606 gtk_notebook_switch_page (notebook,
607 ((GtkNotebookPage *)(list->data)), page_num);
611 gtk_notebook_next_page (GtkNotebook *notebook)
613 GtkNotebookPage *page;
617 g_return_if_fail (notebook != NULL);
618 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
620 children = notebook->children;
624 if (notebook->cur_page == children->data)
626 children = children->next;
635 children = children->next;
640 children = notebook->children;
644 page = children->data;
645 gtk_notebook_switch_page (notebook, page, num);
649 gtk_notebook_prev_page (GtkNotebook *notebook)
651 GtkNotebookPage *page;
655 g_return_if_fail (notebook != NULL);
656 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
658 children = notebook->children;
662 if (notebook->cur_page == children->data)
664 children = children->next;
673 children = children->prev;
678 while (children->next)
680 children = children->next;
685 page = children->data;
686 gtk_notebook_switch_page (notebook, page, num);
690 gtk_notebook_foreach (GtkContainer *container,
691 GtkCallback callback,
692 gpointer callback_data)
694 GtkNotebook *notebook;
695 GtkNotebookPage *page;
698 g_return_if_fail (container != NULL);
699 g_return_if_fail (GTK_IS_NOTEBOOK (container));
700 g_return_if_fail (callback != NULL);
702 notebook = GTK_NOTEBOOK (container);
704 children = notebook->children;
707 page = children->data;
708 children = children->next;
709 (* callback) (page->child, callback_data);
714 gtk_notebook_expose_tabs (GtkNotebook *notebook)
717 GtkNotebookPage *page;
718 GdkEventExpose event;
721 widget = GTK_WIDGET (notebook);
722 border = GTK_CONTAINER (notebook)->border_width;
724 page = notebook->first_tab->data;
726 event.type = GDK_EXPOSE;
727 event.window = widget->window;
729 event.area.x = border;
730 event.area.y = border;
732 switch (notebook->tab_pos)
735 event.area.y = widget->allocation.height - border
736 - page->allocation.height - widget->style->klass->ythickness;
737 if (notebook->first_tab->data != notebook->cur_page)
738 event.area.y -= widget->style->klass->ythickness;
740 event.area.width = widget->allocation.width - 2 * border;
741 event.area.height = page->allocation.height
742 + widget->style->klass->ythickness;
743 if (notebook->first_tab->data != notebook->cur_page)
744 event.area.height += widget->style->klass->ythickness;
747 event.area.x = widget->allocation.width - border
748 - page->allocation.width - widget->style->klass->xthickness;
749 if (notebook->first_tab->data != notebook->cur_page)
750 event.area.x -= widget->style->klass->xthickness;
752 event.area.width = page->allocation.width
753 + widget->style->klass->xthickness;
754 event.area.height = widget->allocation.height - 2 * border;
755 if (notebook->first_tab->data != notebook->cur_page)
756 event.area.width += widget->style->klass->xthickness;
759 gtk_widget_event (widget, (GdkEvent *) &event);
763 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
766 g_return_if_fail (notebook != NULL);
767 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
769 if (notebook->tab_pos != pos)
771 notebook->tab_pos = pos;
773 if (GTK_WIDGET_VISIBLE (notebook))
775 gtk_widget_queue_resize (GTK_WIDGET (notebook));
777 gdk_window_clear (notebook->panel);
783 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
786 GtkNotebookPage *page;
789 g_return_if_fail (notebook != NULL);
790 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
792 if (notebook->show_tabs == show_tabs)
795 notebook->show_tabs = show_tabs;
796 children = notebook->children;
800 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
804 page = children->data;
805 children = children->next;
806 if (page->default_tab)
808 gtk_widget_destroy (page->tab_label);
809 page->tab_label = NULL;
812 gtk_widget_hide (page->tab_label);
816 gdk_window_hide (notebook->panel);
823 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
827 page = children->data;
828 children = children->next;
829 if (page->default_tab)
831 sprintf (string, "Page %d", i);
832 page->tab_label = gtk_label_new (string);
833 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
835 gtk_widget_show (page->tab_label);
839 gtk_widget_queue_resize (GTK_WIDGET (notebook));
843 gtk_notebook_set_show_border (GtkNotebook *notebook,
846 g_return_if_fail (notebook != NULL);
847 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
849 if (notebook->show_border != show_border)
851 notebook->show_border = show_border;
853 if (GTK_WIDGET_VISIBLE (notebook))
854 gtk_widget_queue_resize (GTK_WIDGET (notebook));
859 gtk_notebook_set_scrollable (GtkNotebook *notebook,
862 g_return_if_fail (notebook != NULL);
863 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
865 if (scrollable != notebook->scrollable)
867 if ( (notebook->scrollable = (scrollable != 0)) )
868 gtk_notebook_panel_realize (notebook);
869 else if (notebook->panel)
871 gdk_window_destroy (notebook->panel);
872 notebook->panel = NULL;
874 gtk_widget_queue_resize (GTK_WIDGET(notebook));
879 gtk_notebook_map (GtkWidget *widget)
881 GtkNotebook *notebook;
882 GtkNotebookPage *page;
885 g_return_if_fail (widget != NULL);
886 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
888 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
889 gdk_window_show (widget->window);
891 notebook = GTK_NOTEBOOK (widget);
893 if (notebook->cur_page &&
894 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
895 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
896 gtk_widget_map (notebook->cur_page->child);
898 if (notebook->scrollable)
899 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
902 children = notebook->children;
906 page = children->data;
907 children = children->next;
909 if (page->tab_label &&
910 GTK_WIDGET_VISIBLE (page->child) &&
911 !GTK_WIDGET_MAPPED (page->tab_label))
912 gtk_widget_map (page->tab_label);
918 gtk_notebook_unmap (GtkWidget *widget)
920 g_return_if_fail (widget != NULL);
921 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
923 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
924 gdk_window_hide (widget->window);
925 if (GTK_NOTEBOOK (widget)->panel)
926 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
930 gtk_notebook_realize (GtkWidget *widget)
932 GtkNotebook *notebook;
933 GdkWindowAttr attributes;
934 gint attributes_mask;
936 g_return_if_fail (widget != NULL);
937 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
939 notebook = GTK_NOTEBOOK (widget);
940 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
942 attributes.window_type = GDK_WINDOW_CHILD;
943 attributes.x = widget->allocation.x;
944 attributes.y = widget->allocation.y;
945 attributes.width = widget->allocation.width;
946 attributes.height = widget->allocation.height;
947 attributes.wclass = GDK_INPUT_OUTPUT;
948 attributes.visual = gtk_widget_get_visual (widget);
949 attributes.colormap = gtk_widget_get_colormap (widget);
950 attributes.event_mask = gtk_widget_get_events (widget);
951 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
952 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
954 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
956 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
957 gdk_window_set_user_data (widget->window, notebook);
959 widget->style = gtk_style_attach (widget->style, widget->window);
960 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
962 if (notebook->scrollable)
963 gtk_notebook_panel_realize (notebook);
967 gtk_notebook_panel_realize (GtkNotebook *notebook)
970 GdkWindowAttr attributes;
971 gint attributes_mask;
973 g_return_if_fail (notebook != NULL);
974 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
976 widget = GTK_WIDGET (notebook);
978 attributes.window_type = GDK_WINDOW_CHILD;
979 attributes.wclass = GDK_INPUT_OUTPUT;
980 attributes.visual = gtk_widget_get_visual (widget);
981 attributes.colormap = gtk_widget_get_colormap (widget);
982 attributes.event_mask = gtk_widget_get_events (widget);
983 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
984 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
985 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
987 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
989 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
990 attributes.height = ARROW_SIZE;
992 attributes.x = widget->allocation.width - attributes.width -
993 GTK_CONTAINER (notebook)->border_width;
994 attributes.y = widget->allocation.height - ARROW_SIZE -
995 GTK_CONTAINER (notebook)->border_width;
996 if (notebook->tab_pos == GTK_POS_TOP)
997 attributes.y = GTK_CONTAINER (notebook)->border_width;
998 else if (notebook->tab_pos == GTK_POS_LEFT)
999 attributes.x = widget->allocation.x
1000 + GTK_CONTAINER (notebook)->border_width;
1003 notebook->panel = gdk_window_new (widget->window, &attributes,
1005 gtk_style_set_background (widget->style, notebook->panel,
1007 gdk_window_set_user_data (notebook->panel, widget);
1011 gtk_notebook_size_request (GtkWidget *widget,
1012 GtkRequisition *requisition)
1014 GtkNotebook *notebook;
1015 GtkNotebookPage *page;
1018 g_return_if_fail (widget != NULL);
1019 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1020 g_return_if_fail (requisition != NULL);
1022 notebook = GTK_NOTEBOOK (widget);
1023 widget->requisition.width = 0;
1024 widget->requisition.height = 0;
1026 children = notebook->children;
1029 page = children->data;
1030 children = children->next;
1032 if (GTK_WIDGET_VISIBLE (page->child))
1034 gtk_widget_size_request (page->child, &page->child->requisition);
1036 widget->requisition.width = MAX (widget->requisition.width,
1037 page->child->requisition.width);
1038 widget->requisition.height = MAX (widget->requisition.height,
1039 page->child->requisition.height);
1043 if (notebook->show_border || notebook->show_tabs)
1045 widget->requisition.width += widget->style->klass->xthickness * 2;
1046 widget->requisition.height += widget->style->klass->ythickness * 2;
1048 if (notebook->show_tabs)
1051 gint tab_height = 0;
1054 children = notebook->children;
1057 page = children->data;
1058 children = children->next;
1060 if (GTK_WIDGET_VISIBLE (page->child))
1062 gtk_widget_size_request (page->tab_label,
1063 &page->tab_label->requisition);
1065 page->requisition.width =
1066 (page->tab_label->requisition.width +
1067 (widget->style->klass->xthickness + notebook->tab_border)
1069 page->requisition.height =
1070 (page->tab_label->requisition.height +
1071 (widget->style->klass->ythickness + notebook->tab_border)
1074 switch (notebook->tab_pos)
1077 case GTK_POS_BOTTOM:
1078 page->requisition.width -= TAB_OVERLAP;
1080 tab_width += page->requisition.width;
1081 tab_height = MAX (tab_height, page->requisition.height);
1082 tab_max = MAX (tab_max, page->requisition.width);
1086 page->requisition.height -= TAB_OVERLAP;
1088 tab_width = MAX (tab_width, page->requisition.width);
1089 tab_height += page->requisition.height;
1090 tab_max = MAX (tab_max, page->requisition.height);
1096 children = notebook->children;
1098 if (children && children->next && notebook->scrollable)
1100 if ((notebook->tab_pos == GTK_POS_TOP) ||
1101 (notebook->tab_pos == GTK_POS_BOTTOM))
1103 if (widget->requisition.width < tab_width)
1105 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1106 tab_height = MAX (tab_height, ARROW_SIZE);
1111 if (widget->requisition.height < tab_height)
1113 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1114 tab_width = MAX (tab_width,
1115 ARROW_SPACING + 2 * ARROW_SIZE);
1122 page = children->data;
1123 children = children->next;
1125 if (GTK_WIDGET_VISIBLE (page->child))
1127 if ((notebook->tab_pos == GTK_POS_TOP) ||
1128 (notebook->tab_pos == GTK_POS_BOTTOM))
1129 page->requisition.height = tab_height;
1131 page->requisition.width = tab_width;
1135 switch (notebook->tab_pos)
1138 case GTK_POS_BOTTOM:
1139 tab_width += widget->style->klass->xthickness;
1140 widget->requisition.width = MAX (widget->requisition.width,
1142 widget->requisition.height += tab_height;
1146 tab_height += widget->style->klass->ythickness;
1147 widget->requisition.width += tab_width;
1148 widget->requisition.height = MAX (widget->requisition.height,
1154 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1155 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1159 gtk_notebook_size_allocate (GtkWidget *widget,
1160 GtkAllocation *allocation)
1162 GtkNotebook *notebook;
1163 GtkNotebookPage *page;
1164 GtkAllocation child_allocation;
1167 g_return_if_fail (widget != NULL);
1168 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1169 g_return_if_fail (allocation != NULL);
1171 widget->allocation = *allocation;
1172 if (GTK_WIDGET_REALIZED (widget))
1173 gdk_window_move_resize (widget->window,
1174 allocation->x, allocation->y,
1175 allocation->width, allocation->height);
1177 notebook = GTK_NOTEBOOK (widget);
1178 if (notebook->children)
1180 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1181 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1182 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1183 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1185 if (notebook->show_tabs || notebook->show_border)
1187 child_allocation.x += widget->style->klass->xthickness;
1188 child_allocation.y += widget->style->klass->ythickness;
1189 child_allocation.width = MAX (1,
1190 child_allocation.width - widget->style->klass->xthickness * 2);
1191 child_allocation.height = MAX (1,
1192 child_allocation.height - widget->style->klass->ythickness * 2);
1194 if (notebook->show_tabs && notebook->children)
1196 switch (notebook->tab_pos)
1199 child_allocation.y += notebook->cur_page->requisition.height;
1200 case GTK_POS_BOTTOM:
1201 child_allocation.height = MAX (1,
1202 child_allocation.height - notebook->cur_page->requisition.height);
1205 child_allocation.x += notebook->cur_page->requisition.width;
1207 child_allocation.width = MAX (1,
1208 child_allocation.width - notebook->cur_page->requisition.width);
1214 children = notebook->children;
1217 page = children->data;
1218 children = children->next;
1220 if (GTK_WIDGET_VISIBLE (page->child))
1221 gtk_widget_size_allocate (page->child, &child_allocation);
1224 gtk_notebook_pages_allocate (notebook, allocation);
1229 gtk_notebook_paint (GtkWidget *widget,
1232 GtkNotebook *notebook;
1233 GtkNotebookPage *page;
1240 g_return_if_fail (widget != NULL);
1241 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1242 g_return_if_fail (area != NULL);
1244 if (GTK_WIDGET_DRAWABLE (widget))
1246 notebook = GTK_NOTEBOOK (widget);
1248 gdk_window_clear_area (widget->window,
1250 area->width, area->height);
1252 if (notebook->show_tabs || notebook->show_border)
1254 x = GTK_CONTAINER (widget)->border_width;
1255 y = GTK_CONTAINER (widget)->border_width;
1256 width = widget->allocation.width - x * 2;
1257 height = widget->allocation.height - y * 2;
1259 if (notebook->show_tabs && notebook->children)
1262 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1264 GtkNotebookPage *page;
1266 page = notebook->first_tab->data;
1268 switch (notebook->tab_pos)
1271 y += page->allocation.height +
1272 widget->style->klass->ythickness;
1273 case GTK_POS_BOTTOM:
1274 height -= page->allocation.height +
1275 widget->style->klass->ythickness;
1278 x += page->allocation.width +
1279 widget->style->klass->xthickness;
1281 width -= page->allocation.width +
1282 widget->style->klass->xthickness;
1285 gtk_draw_shadow (widget->style, widget->window,
1286 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1287 x, y, width, height);
1291 switch (notebook->tab_pos)
1294 y += notebook->cur_page->allocation.height;
1295 case GTK_POS_BOTTOM:
1296 height -= notebook->cur_page->allocation.height;
1299 x += notebook->cur_page->allocation.width;
1301 width -= notebook->cur_page->allocation.width;
1305 switch (notebook->tab_pos)
1308 points[0].x = notebook->cur_page->allocation.x;
1313 points[2].y = y + height - 1;
1314 points[3].x = x + width - 1;
1315 points[3].y = y + height - 1;
1316 points[4].x = x + width - 1;
1318 points[5].x = (notebook->cur_page->allocation.x +
1319 notebook->cur_page->allocation.width -
1320 widget->style->klass->xthickness);
1323 if (points[5].x == (x + width))
1326 case GTK_POS_BOTTOM:
1327 points[0].x = (notebook->cur_page->allocation.x +
1328 notebook->cur_page->allocation.width -
1329 widget->style->klass->xthickness);
1330 points[0].y = y + height - 1;
1331 points[1].x = x + width - 1;
1332 points[1].y = y + height - 1;
1333 points[2].x = x + width - 1;
1338 points[4].y = y + height - 1;
1339 points[5].x = notebook->cur_page->allocation.x;
1340 points[5].y = y + height - 1;
1342 if (points[0].x == (x + width))
1347 points[0].y = (notebook->cur_page->allocation.y +
1348 notebook->cur_page->allocation.height -
1349 widget->style->klass->ythickness);
1351 points[1].y = y + height - 1;
1352 points[2].x = x + width - 1;
1353 points[2].y = y + height - 1;
1354 points[3].x = x + width - 1;
1359 points[5].y = notebook->cur_page->allocation.y;
1361 if (points[0].y == (y + height))
1365 points[0].x = x + width - 1;
1366 points[0].y = notebook->cur_page->allocation.y;
1367 points[1].x = x + width - 1;
1372 points[3].y = y + height - 1;
1373 points[4].x = x + width - 1;
1374 points[4].y = y + height - 1;
1375 points[5].x = x + width - 1;
1376 points[5].y = (notebook->cur_page->allocation.y +
1377 notebook->cur_page->allocation.height -
1378 widget->style->klass->ythickness);
1380 if (points[5].y == (y + height))
1385 gtk_draw_polygon (widget->style, widget->window,
1386 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1389 children = g_list_last (notebook->children);
1394 page = children->data;
1395 children = children->prev;
1397 if (!GTK_WIDGET_MAPPED (page->tab_label))
1399 else if (notebook->cur_page != page)
1400 gtk_notebook_draw_tab (notebook, page, area);
1403 if (showarrow && notebook->scrollable && notebook->show_tabs)
1405 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1406 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1408 if (notebook->cur_page &&
1409 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1410 (notebook->cur_page))->tab_label))
1411 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1413 else if (notebook->show_border)
1415 gtk_draw_shadow (widget->style, widget->window,
1416 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1417 x, y, width, height);
1424 gtk_notebook_draw (GtkWidget *widget,
1427 GtkNotebook *notebook;
1428 GdkRectangle child_area;
1430 g_return_if_fail (widget != NULL);
1431 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1432 g_return_if_fail (area != NULL);
1434 if (GTK_WIDGET_DRAWABLE (widget))
1436 notebook = GTK_NOTEBOOK (widget);
1438 gtk_notebook_paint (widget, area);
1439 gtk_widget_draw_focus (widget);
1441 if (notebook->cur_page &&
1442 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1443 gtk_widget_draw (notebook->cur_page->child, &child_area);
1448 gtk_notebook_expose (GtkWidget *widget,
1449 GdkEventExpose *event)
1451 GtkNotebook *notebook;
1452 GdkEventExpose child_event;
1454 g_return_val_if_fail (widget != NULL, FALSE);
1455 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1456 g_return_val_if_fail (event != NULL, FALSE);
1458 if (GTK_WIDGET_DRAWABLE (widget))
1460 notebook = GTK_NOTEBOOK (widget);
1462 gtk_notebook_paint (widget, &event->area);
1463 gtk_widget_draw_focus (widget);
1465 child_event = *event;
1466 if (notebook->cur_page &&
1467 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1468 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1470 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1477 gtk_notebook_button_press (GtkWidget *widget,
1478 GdkEventButton *event)
1480 GtkNotebook *notebook;
1481 GtkNotebookPage *page;
1485 g_return_val_if_fail (widget != NULL, FALSE);
1486 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1487 g_return_val_if_fail (event != NULL, FALSE);
1489 notebook = GTK_NOTEBOOK (widget);
1491 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1492 || notebook->button)
1495 if (event->window == notebook->panel)
1497 if (!GTK_WIDGET_HAS_FOCUS (widget))
1498 gtk_widget_grab_focus (widget);
1500 gtk_grab_add (widget);
1501 notebook->button = event->button;
1503 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1505 notebook->click_child = GTK_ARROW_LEFT;
1506 if (event->button == 1)
1508 if (!notebook->focus_tab || notebook->focus_tab->prev)
1509 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1511 if (!notebook->timer)
1513 notebook->timer = gtk_timeout_add
1514 (NOTEBOOK_INIT_SCROLL_DELAY,
1515 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1516 notebook->need_timer = TRUE;
1519 else if (event->button == 2)
1520 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1521 else if (event->button == 3)
1522 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1523 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1527 notebook->click_child = GTK_ARROW_RIGHT;
1528 if (event->button == 1)
1530 if (!notebook->focus_tab || notebook->focus_tab->next)
1531 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1532 if (!notebook->timer)
1534 notebook->timer = gtk_timeout_add
1535 (NOTEBOOK_INIT_SCROLL_DELAY,
1536 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1537 notebook->need_timer = TRUE;
1540 else if (event->button == 2)
1541 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1542 else if (event->button == 3)
1543 gtk_notebook_switch_focus_tab (notebook,
1544 g_list_last (notebook->children));
1545 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1548 else if (event->window == widget->window)
1550 if (event->button == 3 && notebook->menu)
1552 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1553 NULL, NULL, 3, event->time);
1558 children = notebook->children;
1561 page = children->data;
1563 if (GTK_WIDGET_VISIBLE (page->child) &&
1564 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1565 (event->x >= page->allocation.x) &&
1566 (event->y >= page->allocation.y) &&
1567 (event->x <= (page->allocation.x + page->allocation.width)) &&
1568 (event->y <= (page->allocation.y + page->allocation.height)))
1570 if (page == notebook->cur_page && notebook->focus_tab &&
1571 notebook->focus_tab != children &&
1572 GTK_WIDGET_HAS_FOCUS (notebook))
1574 GtkNotebookPage *old_page;
1576 notebook->child_has_focus = FALSE;
1577 old_page = (GtkNotebookPage *)
1578 (notebook->focus_tab->data);
1579 notebook->focus_tab = children;
1580 gtk_notebook_focus_changed (notebook, old_page);
1584 notebook->focus_tab = children;
1585 gtk_notebook_switch_page (notebook, page, num);
1586 gtk_widget_grab_focus (widget);
1590 children = children->next;
1593 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1594 gtk_widget_grab_focus (widget);
1600 gtk_notebook_button_release (GtkWidget *widget,
1601 GdkEventButton *event)
1603 GtkNotebook *notebook;
1605 g_return_val_if_fail (widget != NULL, FALSE);
1606 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1607 g_return_val_if_fail (event != NULL, FALSE);
1609 if (event->type != GDK_BUTTON_RELEASE)
1612 notebook = GTK_NOTEBOOK (widget);
1614 if (event->button == notebook->button)
1618 if (notebook->timer)
1620 gtk_timeout_remove (notebook->timer);
1621 notebook->timer = 0;
1622 notebook->need_timer = FALSE;
1624 gtk_grab_remove (widget);
1625 click_child = notebook->click_child;
1626 notebook->click_child = 0;
1627 notebook->button = 0;
1628 gtk_notebook_draw_arrow (notebook, click_child);
1635 gtk_notebook_enter_notify (GtkWidget *widget,
1636 GdkEventCrossing *event)
1638 GtkNotebook *notebook;
1640 g_return_val_if_fail (widget != NULL, FALSE);
1641 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1642 g_return_val_if_fail (event != NULL, FALSE);
1644 notebook = GTK_NOTEBOOK (widget);
1646 if (event->window == notebook->panel)
1651 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1653 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1655 notebook->in_child = GTK_ARROW_LEFT;
1657 if (notebook->click_child == 0)
1658 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1662 notebook->in_child = GTK_ARROW_RIGHT;
1664 if (notebook->click_child == 0)
1665 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1673 gtk_notebook_leave_notify (GtkWidget *widget,
1674 GdkEventCrossing *event)
1676 GtkNotebook *notebook;
1678 g_return_val_if_fail (widget != NULL, FALSE);
1679 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1680 g_return_val_if_fail (event != NULL, FALSE);
1682 notebook = GTK_NOTEBOOK (widget);
1684 if (event->window == notebook->panel && !notebook->click_child)
1686 if (notebook->in_child == GTK_ARROW_LEFT)
1688 notebook->in_child = 0;
1689 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1693 notebook->in_child = 0;
1694 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1701 gtk_notebook_motion_notify (GtkWidget *widget,
1702 GdkEventMotion *event)
1704 GtkNotebook *notebook;
1706 g_return_val_if_fail (widget != NULL, FALSE);
1707 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1708 g_return_val_if_fail (event != NULL, FALSE);
1710 notebook = GTK_NOTEBOOK (widget);
1712 if (notebook->button)
1715 if (event->window == notebook->panel)
1721 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1723 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
1724 notebook->in_child == GTK_ARROW_RIGHT)
1726 notebook->in_child = GTK_ARROW_LEFT;
1727 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1728 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1730 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
1731 notebook->in_child == GTK_ARROW_LEFT)
1733 notebook->in_child = GTK_ARROW_RIGHT;
1734 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1735 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1743 gtk_notebook_timer (GtkNotebook *notebook)
1745 g_return_val_if_fail (notebook != NULL, FALSE);
1746 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
1748 if (notebook->timer)
1750 if (notebook->click_child == GTK_ARROW_LEFT)
1752 if (!notebook->focus_tab || notebook->focus_tab->prev)
1753 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1755 else if (notebook->click_child == GTK_ARROW_RIGHT)
1757 if (!notebook->focus_tab || notebook->focus_tab->next)
1758 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1761 if (notebook->need_timer)
1763 notebook->need_timer = FALSE;
1764 notebook->timer = gtk_timeout_add
1765 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
1766 (gpointer) notebook);
1775 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
1777 GtkStateType state_type;
1778 GtkShadowType shadow_type;
1781 g_return_if_fail (notebook != NULL);
1782 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1784 widget = GTK_WIDGET(notebook);
1786 if (GTK_WIDGET_DRAWABLE (notebook))
1788 if (notebook->in_child == arrow)
1790 if (notebook->click_child == arrow)
1791 state_type = GTK_STATE_ACTIVE;
1793 state_type = GTK_STATE_PRELIGHT;
1796 state_type = GTK_STATE_NORMAL;
1798 if (notebook->click_child == arrow)
1799 shadow_type = GTK_SHADOW_IN;
1801 shadow_type = GTK_SHADOW_OUT;
1803 if (arrow == GTK_ARROW_LEFT)
1805 if (notebook->tab_pos == GTK_POS_LEFT ||
1806 notebook->tab_pos == GTK_POS_RIGHT)
1807 arrow = GTK_ARROW_UP;
1808 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1809 shadow_type, arrow, TRUE,
1810 0, 0, ARROW_SIZE, ARROW_SIZE);
1814 if (notebook->tab_pos == GTK_POS_LEFT ||
1815 notebook->tab_pos == GTK_POS_RIGHT)
1816 arrow = GTK_ARROW_DOWN;
1817 gtk_draw_arrow (widget->style, notebook->panel, state_type,
1818 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
1819 0, ARROW_SIZE, ARROW_SIZE);
1825 gtk_real_notebook_switch_page (GtkNotebook *notebook,
1826 GtkNotebookPage *page,
1829 g_return_if_fail (notebook != NULL);
1830 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1831 g_return_if_fail (page != NULL);
1833 if (notebook->cur_page == page)
1836 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
1837 gtk_widget_unmap (notebook->cur_page->child);
1839 notebook->cur_page = page;
1841 if (!notebook->focus_tab ||
1842 notebook->focus_tab->data != (gpointer) notebook->cur_page)
1843 notebook->focus_tab =
1844 g_list_find (notebook->children, notebook->cur_page);
1846 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
1848 if (GTK_WIDGET_MAPPED (notebook))
1850 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
1851 gtk_widget_map (notebook->cur_page->child);
1854 gtk_widget_map (notebook->cur_page->child);
1855 gtk_widget_size_allocate (GTK_WIDGET (notebook),
1856 >K_WIDGET (notebook)->allocation);
1860 if (GTK_WIDGET_DRAWABLE (notebook))
1861 gtk_widget_queue_draw (GTK_WIDGET (notebook));
1865 gtk_notebook_draw_tab (GtkNotebook *notebook,
1866 GtkNotebookPage *page,
1869 GdkRectangle child_area;
1870 GdkRectangle page_area;
1871 GtkStateType state_type;
1875 g_return_if_fail (notebook != NULL);
1876 g_return_if_fail (page != NULL);
1877 g_return_if_fail (area != NULL);
1879 if (!GTK_WIDGET_MAPPED (page->tab_label))
1882 page_area.x = page->allocation.x;
1883 page_area.y = page->allocation.y;
1884 page_area.width = page->allocation.width;
1885 page_area.height = page->allocation.height;
1887 if (gdk_rectangle_intersect (&page_area, area, &child_area))
1891 switch (notebook->tab_pos)
1894 if (child_area.x + child_area.width >
1895 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1897 points[0].x = page->allocation.x + page->allocation.width - 1;
1898 points[0].y = page->allocation.y + page->allocation.height - 1;
1900 points[1].x = page->allocation.x + page->allocation.width - 1;
1901 points[1].y = page->allocation.y + TAB_CURVATURE;
1903 points[2].x = page->allocation.x + page->allocation.width
1904 - TAB_CURVATURE - 1;
1905 points[2].y = page->allocation.y;
1910 points[0].x = page->allocation.x + page->allocation.width
1912 points[0].y = page->allocation.y;
1916 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1917 (page == notebook->cur_page ||
1918 page == (GtkNotebookPage *)(notebook->children->data) ||
1919 (notebook->scrollable &&
1920 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1922 points[n].x = page->allocation.x + TAB_CURVATURE;
1923 points[n++].y = page->allocation.y;
1925 points[n].x = page->allocation.x;
1926 points[n++].y = page->allocation.y + TAB_CURVATURE;
1928 points[n].x = page->allocation.x;
1929 points[n++].y = page->allocation.y + page->allocation.height - 1;
1933 points[n].x = page->allocation.x + TAB_OVERLAP;
1934 points[n++].y = page->allocation.y;
1937 case GTK_POS_BOTTOM:
1938 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1939 (page == notebook->cur_page ||
1940 page == (GtkNotebookPage *)(notebook->children->data) ||
1941 (notebook->scrollable &&
1942 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1944 points[0].x = page->allocation.x;
1945 points[0].y = page->allocation.y;
1947 points[1].x = page->allocation.x;
1948 points[1].y = page->allocation.y + page->allocation.height
1949 - TAB_CURVATURE - 1;
1951 points[2].x = page->allocation.x + TAB_CURVATURE;
1952 points[2].y = page->allocation.y + page->allocation.height - 1;
1957 points[0].x = page->allocation.x + TAB_OVERLAP;
1958 points[0].y = page->allocation.y + page->allocation.height - 1;
1962 if (child_area.x + child_area.width >
1963 page->allocation.x + page->allocation.width - TAB_OVERLAP)
1965 points[n].x = page->allocation.x + page->allocation.width
1966 - TAB_CURVATURE - 1;
1967 points[n++].y = page->allocation.y + page->allocation.height - 1;
1969 points[n].x = page->allocation.x + page->allocation.width - 1;
1970 points[n++].y = page->allocation.y + page->allocation.height
1971 - TAB_CURVATURE - 1;
1973 points[n].x = page->allocation.x + page->allocation.width - 1;
1974 points[n++].y = page->allocation.y;
1978 points[n].x = page->allocation.x + page->allocation.width
1980 points[n++].y = page->allocation.y + page->allocation.height - 1;
1984 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1985 (page == notebook->cur_page ||
1986 page == (GtkNotebookPage *)(notebook->children->data) ||
1987 (notebook->scrollable &&
1988 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
1990 points[0].x = page->allocation.x + page->allocation.width - 1;
1991 points[0].y = page->allocation.y;
1993 points[1].x = page->allocation.x + TAB_CURVATURE;
1994 points[1].y = page->allocation.y;
1996 points[2].x = page->allocation.x;
1997 points[2].y = page->allocation.y + TAB_CURVATURE;
2002 points[0].x = page->allocation.x;
2003 points[0].y = page->allocation.y + TAB_OVERLAP;
2007 if (child_area.y + child_area.height >
2008 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2010 points[n].x = page->allocation.x;
2011 points[n++].y = page->allocation.y + page->allocation.height
2012 - TAB_CURVATURE - 1;
2014 points[n].x = page->allocation.x + TAB_CURVATURE;
2015 points[n++].y = page->allocation.y + page->allocation.height - 1;
2017 points[n].x = page->allocation.x + page->allocation.width - 1;
2018 points[n++].y = page->allocation.y + page->allocation.height - 1;
2022 points[n].x = page->allocation.x;
2023 points[n++].y = page->allocation.y + page->allocation.height
2028 if (child_area.y + child_area.height >
2029 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2031 points[0].x = page->allocation.x;
2032 points[0].y = page->allocation.y + page->allocation.height - 1;
2034 points[1].x = page->allocation.x + page->allocation.width
2035 - TAB_CURVATURE - 1;
2036 points[1].y = page->allocation.y + page->allocation.height - 1;
2038 points[2].x = page->allocation.x + page->allocation.width - 1;
2039 points[2].y = page->allocation.y + page->allocation.height
2040 - TAB_CURVATURE - 1;
2045 points[0].x = page->allocation.x + page->allocation.width - 1;
2046 points[0].y = page->allocation.y + page->allocation.height
2051 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2052 (page == notebook->cur_page ||
2053 page == (GtkNotebookPage *)(notebook->children->data) ||
2054 (notebook->scrollable &&
2055 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2057 points[n].x = page->allocation.x + page->allocation.width - 1;
2058 points[n++].y = page->allocation.y + TAB_CURVATURE;
2060 points[n].x = page->allocation.x + page->allocation.width
2061 - TAB_CURVATURE - 1;
2062 points[n++].y = page->allocation.y;
2064 points[n].x = page->allocation.x;
2065 points[n++].y = page->allocation.y;
2069 points[n].x = page->allocation.x + page->allocation.width - 1;
2070 points[n++].y = page->allocation.y + TAB_OVERLAP;
2075 widget = GTK_WIDGET(notebook);
2077 if (notebook->cur_page == page)
2079 state_type = GTK_STATE_NORMAL;
2083 state_type = GTK_STATE_ACTIVE;
2084 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2085 TRUE, child_area.x, child_area.y,
2086 child_area.width, child_area.height);
2089 gtk_draw_polygon (widget->style, widget->window, state_type,
2090 GTK_SHADOW_OUT, points, n, FALSE);
2092 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2093 gtk_widget_draw (page->tab_label, &child_area);
2098 gtk_notebook_set_focus_child (GtkContainer *container,
2101 GtkNotebook *notebook;
2103 g_return_if_fail (container != NULL);
2104 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2108 g_return_if_fail (GTK_IS_WIDGET (child));
2110 notebook = GTK_NOTEBOOK (container);
2112 notebook->child_has_focus = TRUE;
2113 if (!notebook->focus_tab)
2116 GtkNotebookPage *page;
2118 children = notebook->children;
2121 page = children->data;
2122 if (page->child == child || page->tab_label == child)
2123 notebook->focus_tab = children;
2124 children = children->next;
2128 parent_class->set_focus_child (container, child);
2132 gtk_notebook_focus_in (GtkWidget *widget,
2133 GdkEventFocus *event)
2135 g_return_val_if_fail (widget != NULL, FALSE);
2136 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2137 g_return_val_if_fail (event != NULL, FALSE);
2139 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2140 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2141 gtk_widget_draw_focus (widget);
2147 gtk_notebook_focus_out (GtkWidget *widget,
2148 GdkEventFocus *event)
2150 g_return_val_if_fail (widget != NULL, FALSE);
2151 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2152 g_return_val_if_fail (event != NULL, FALSE);
2154 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2155 gtk_widget_draw_focus (widget);
2161 gtk_notebook_draw_focus (GtkWidget *widget)
2163 GtkNotebook *notebook;
2165 g_return_if_fail (widget != NULL);
2166 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2168 notebook = GTK_NOTEBOOK (widget);
2170 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2171 notebook->focus_tab)
2173 GtkNotebookPage *page;
2176 page = notebook->focus_tab->data;
2178 if (GTK_WIDGET_HAS_FOCUS (widget))
2179 gc = widget->style->black_gc;
2180 else if (page == notebook->cur_page)
2181 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2183 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2185 gdk_draw_rectangle (widget->window,
2187 page->tab_label->allocation.x - 1,
2188 page->tab_label->allocation.y - 1,
2189 page->tab_label->allocation.width + 1,
2190 page->tab_label->allocation.height + 1);
2195 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2199 g_return_if_fail (notebook != NULL);
2200 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2202 widget = GTK_WIDGET (notebook);
2204 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs)
2208 if (notebook->focus_tab)
2210 GtkNotebookPage *page;
2212 page = notebook->focus_tab->data;
2214 if (GTK_WIDGET_HAS_FOCUS (widget))
2215 gc = widget->style->black_gc;
2216 else if (page == notebook->cur_page)
2217 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2219 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2221 gdk_draw_rectangle (widget->window,
2223 page->tab_label->allocation.x - 1,
2224 page->tab_label->allocation.y - 1,
2225 page->tab_label->allocation.width + 1,
2226 page->tab_label->allocation.height + 1);
2231 if (old_page == notebook->cur_page)
2232 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2234 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2236 gdk_draw_rectangle (widget->window,
2238 old_page->tab_label->allocation.x - 1,
2239 old_page->tab_label->allocation.y - 1,
2240 old_page->tab_label->allocation.width + 1,
2241 old_page->tab_label->allocation.height + 1);
2247 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2253 GtkNotebookPage *page = NULL;
2257 switch (notebook->tab_pos)
2260 case GTK_POS_BOTTOM:
2263 page = children->data;
2264 *tab_space -= page->requisition.width;
2265 if (*tab_space < 0 || children == *end)
2269 *tab_space = - (*tab_space + page->requisition.width);
2274 if (direction == STEP_NEXT)
2275 children = children->next;
2277 children = children->prev;
2284 page = children->data;
2285 *tab_space -= page->requisition.height;
2286 if (*tab_space < 0 || children == *end)
2290 *tab_space = - (*tab_space + page->requisition.height);
2295 if (direction == STEP_NEXT)
2296 children = children->next;
2298 children = children->prev;
2305 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2306 GtkAllocation *allocation)
2309 GtkContainer *container;
2310 GtkNotebookPage *page = NULL;
2311 GtkAllocation child_allocation;
2313 GList *last_child = NULL;
2314 gint showarrow = FALSE;
2323 if (!notebook->show_tabs || !notebook->children)
2326 widget = GTK_WIDGET (notebook);
2327 container = GTK_CONTAINER (notebook);
2329 child_allocation.x = container->border_width;
2330 child_allocation.y = container->border_width;
2332 switch (notebook->tab_pos)
2334 case GTK_POS_BOTTOM:
2335 child_allocation.y = (allocation->height -
2336 notebook->cur_page->requisition.height -
2337 container->border_width);
2339 child_allocation.height = notebook->cur_page->requisition.height;
2342 child_allocation.x = (allocation->width -
2343 notebook->cur_page->requisition.width -
2344 container->border_width);
2346 child_allocation.width = notebook->cur_page->requisition.width;
2350 if (notebook->scrollable)
2354 children = notebook->children;
2356 if (notebook->focus_tab)
2357 focus_tab = notebook->focus_tab;
2358 else if (notebook->first_tab)
2359 focus_tab = notebook->first_tab;
2361 focus_tab = notebook->children;
2363 switch (notebook->tab_pos)
2366 case GTK_POS_BOTTOM:
2369 page = children->data;
2370 children = children->next;
2371 tab_space += page->requisition.width;
2373 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2376 page = focus_tab->data;
2378 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2379 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2380 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2382 page = notebook->children->data;
2383 if (notebook->tab_pos == GTK_POS_TOP)
2384 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2386 y = (allocation->height - container->border_width -
2387 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2394 page = children->data;
2395 children = children->next;
2396 tab_space += page->requisition.height;
2398 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2401 page = focus_tab->data;
2402 tab_space = (allocation->height -
2403 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2404 2 * container->border_width - page->requisition.height);
2405 y = allocation->height - container->border_width - ARROW_SIZE;
2407 page = notebook->children->data;
2408 if (notebook->tab_pos == GTK_POS_LEFT)
2409 x = (container->border_width +
2410 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2412 x = (allocation->width - container->border_width -
2413 (2 * ARROW_SIZE - ARROW_SPACING) -
2414 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2418 if (showarrow) /* first_tab <- focus_tab */
2420 children = focus_tab->prev;
2423 if (notebook->first_tab == children)
2425 children = children->prev;
2429 notebook->first_tab = focus_tab;
2431 gtk_notebook_calc_tabs (notebook, focus_tab->prev,
2432 &(notebook->first_tab), &tab_space,
2436 notebook->first_tab = notebook->first_tab->next;
2437 if (!notebook->first_tab)
2438 notebook->first_tab = focus_tab;
2439 last_child = focus_tab->next;
2441 else /* focus_tab -> end */
2443 if (!notebook->first_tab)
2444 notebook->first_tab = notebook->children;
2447 gtk_notebook_calc_tabs (notebook, focus_tab->next,
2448 &children, &tab_space, STEP_NEXT);
2451 last_child = children;
2452 else /* start <- first_tab */
2456 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2457 &children, &tab_space, STEP_PREV);
2459 notebook->first_tab = children->next;
2461 notebook->first_tab = notebook->children;
2465 if (GTK_WIDGET_REALIZED (notebook))
2467 gdk_window_move (notebook->panel, x, y);
2468 gdk_window_show (notebook->panel);
2473 tab_space = -tab_space;
2475 children = notebook->first_tab;
2476 while (children != last_child)
2478 children = children->next;
2485 children = notebook->children;
2486 while (children != notebook->first_tab)
2488 page = children->data;
2489 children = children->next;
2491 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2492 gtk_widget_unmap (page->tab_label);
2495 children = last_child;
2498 page = children->data;
2499 children = children->next;
2501 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2502 gtk_widget_unmap (page->tab_label);
2505 else /* !showarrow */
2507 notebook->first_tab = notebook->children;
2509 if (GTK_WIDGET_REALIZED (notebook))
2510 gdk_window_hide (notebook->panel);
2512 children = notebook->first_tab;
2515 children = notebook->children;
2518 while (children != last_child)
2520 page = children->data;
2521 children = children->next;
2523 if (GTK_WIDGET_VISIBLE (page->child))
2525 new_fill = (tab_space * i++) / n;
2526 switch (notebook->tab_pos)
2529 case GTK_POS_BOTTOM:
2530 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2534 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2537 old_fill = new_fill;
2538 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2540 switch (notebook->tab_pos)
2543 case GTK_POS_BOTTOM:
2544 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2548 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2552 if (GTK_WIDGET_REALIZED (notebook) &&
2553 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2554 gtk_widget_map (page->tab_label);
2560 gtk_notebook_page_allocate (GtkNotebook *notebook,
2561 GtkNotebookPage *page,
2562 GtkAllocation *allocation)
2564 GtkAllocation child_allocation;
2565 gint xthickness, ythickness;
2567 g_return_if_fail (notebook != NULL);
2568 g_return_if_fail (page != NULL);
2569 g_return_if_fail (allocation != NULL);
2571 page->allocation = *allocation;
2573 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2574 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2576 if (notebook->cur_page != page)
2578 switch (notebook->tab_pos)
2581 page->allocation.y += ythickness;
2582 case GTK_POS_BOTTOM:
2583 page->allocation.height -= ythickness;
2586 page->allocation.x += xthickness;
2588 page->allocation.width -= xthickness;
2593 switch (notebook->tab_pos)
2596 child_allocation.x = xthickness + notebook->tab_border;
2597 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2598 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2599 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2600 child_allocation.x += page->allocation.x;
2602 case GTK_POS_BOTTOM:
2603 child_allocation.x = xthickness + notebook->tab_border;
2604 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2605 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2606 child_allocation.x += page->allocation.x;
2607 child_allocation.y = page->allocation.y + notebook->tab_border;
2610 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
2611 child_allocation.y = ythickness + notebook->tab_border;
2612 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2613 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2614 child_allocation.y += page->allocation.y;
2617 child_allocation.y = ythickness + notebook->tab_border;
2618 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
2619 child_allocation.height = page->allocation.height - child_allocation.y * 2;
2620 child_allocation.x = page->allocation.x + notebook->tab_border;
2621 child_allocation.y += page->allocation.y;
2625 if (page->tab_label)
2626 gtk_widget_size_allocate (page->tab_label, &child_allocation);
2630 gtk_notebook_menu_switch_page (GtkWidget *widget,
2631 GtkNotebookPage *page)
2633 GtkNotebook *notebook;
2637 g_return_if_fail (widget != NULL);
2638 g_return_if_fail (page != NULL);
2640 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
2641 (GTK_MENU (widget->parent)));
2643 if (notebook->cur_page == page)
2647 children = notebook->children;
2648 while (children && children->data != page)
2650 children = children->next;
2654 gtk_signal_emit (GTK_OBJECT (notebook),
2655 notebook_signals[SWITCH_PAGE],
2661 gtk_notebook_switch_page (GtkNotebook *notebook,
2662 GtkNotebookPage *page,
2665 g_return_if_fail (notebook != NULL);
2666 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2667 g_return_if_fail (page != NULL);
2669 if (notebook->cur_page == page)
2672 gtk_signal_emit (GTK_OBJECT (notebook),
2673 notebook_signals[SWITCH_PAGE],
2679 gtk_notebook_marshal_signal (GtkObject *object,
2684 GtkNotebookSignal rfunc;
2686 rfunc = (GtkNotebookSignal) func;
2688 (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
2693 gtk_notebook_focus (GtkContainer *container,
2694 GtkDirectionType direction)
2696 GtkNotebook *notebook;
2697 GtkWidget *focus_child;
2698 GtkNotebookPage *page = NULL;
2699 GtkNotebookPage *old_page = NULL;
2702 g_return_val_if_fail (container != NULL, FALSE);
2703 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
2705 notebook = GTK_NOTEBOOK (container);
2707 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
2710 focus_child = container->focus_child;
2711 gtk_container_set_focus_child (container, NULL);
2713 if (!notebook->show_tabs)
2715 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2717 if (GTK_IS_CONTAINER (notebook->cur_page->child))
2719 if (gtk_container_focus
2720 (GTK_CONTAINER (notebook->cur_page->child), direction))
2723 else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
2727 gtk_widget_grab_focus (notebook->cur_page->child);
2735 if (notebook->focus_tab)
2736 old_page = notebook->focus_tab->data;
2740 if (focus_child && old_page && focus_child == old_page->child &&
2741 notebook->child_has_focus)
2743 if (GTK_WIDGET_VISIBLE (old_page->child))
2745 if (GTK_IS_CONTAINER (old_page->child) &&
2746 !GTK_WIDGET_HAS_FOCUS (old_page->child))
2748 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
2752 gtk_widget_grab_focus (GTK_WIDGET(notebook));
2760 case GTK_DIR_TAB_FORWARD:
2763 if (!notebook->focus_tab)
2764 notebook->focus_tab = notebook->children;
2766 notebook->focus_tab = notebook->focus_tab->next;
2768 if (!notebook->focus_tab)
2770 gtk_notebook_focus_changed (notebook, old_page);
2774 page = notebook->focus_tab->data;
2777 case GTK_DIR_TAB_BACKWARD:
2780 if (!notebook->focus_tab)
2781 notebook->focus_tab = g_list_last (notebook->children);
2783 notebook->focus_tab = notebook->focus_tab->prev;
2785 if (!notebook->focus_tab)
2787 gtk_notebook_focus_changed (notebook, old_page);
2791 page = notebook->focus_tab->data;
2798 if (!GTK_WIDGET_HAS_FOCUS (container) )
2799 gtk_widget_grab_focus (GTK_WIDGET (container));
2801 if (GTK_WIDGET_MAPPED (page->tab_label))
2802 gtk_notebook_focus_changed (notebook, old_page);
2805 gtk_notebook_pages_allocate (notebook,
2806 &(GTK_WIDGET (notebook)->allocation));
2807 gtk_notebook_expose_tabs (notebook);
2815 gtk_notebook_page_select (GtkNotebook *notebook)
2817 g_return_val_if_fail (notebook != NULL, FALSE);
2818 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2820 if (notebook->focus_tab)
2822 GtkNotebookPage *page;
2826 page = notebook->focus_tab->data;
2828 children = notebook->children;
2830 while (children != notebook->focus_tab)
2832 children = children->next;
2836 gtk_notebook_switch_page (notebook, page, num);
2838 if (GTK_WIDGET_VISIBLE (page->child))
2840 if (GTK_IS_CONTAINER (page->child))
2842 if (gtk_container_focus (GTK_CONTAINER (page->child),
2843 GTK_DIR_TAB_FORWARD))
2846 else if (GTK_WIDGET_CAN_FOCUS (page->child))
2848 gtk_widget_grab_focus (page->child);
2857 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
2860 GtkNotebookPage *old_page = NULL;
2861 GtkNotebookPage *page;
2863 g_return_if_fail (notebook != NULL);
2864 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2866 if (notebook->focus_tab != new_child)
2868 if (notebook->focus_tab)
2869 old_page = notebook->focus_tab->data;
2871 notebook->focus_tab = new_child;
2872 page = notebook->focus_tab->data;
2873 if (GTK_WIDGET_MAPPED (page->tab_label))
2874 gtk_notebook_focus_changed (notebook, old_page);
2877 gtk_notebook_pages_allocate (notebook,
2878 &(GTK_WIDGET (notebook)->allocation));
2879 gtk_notebook_expose_tabs (notebook);
2885 gtk_notebook_key_press (GtkWidget *widget,
2888 GtkNotebook *notebook;
2889 GtkDirectionType direction = 0;
2892 g_return_val_if_fail (widget != NULL, FALSE);
2893 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2894 g_return_val_if_fail (event != NULL, FALSE);
2896 notebook = GTK_NOTEBOOK (widget);
2899 if (!notebook->children || !notebook->show_tabs)
2902 switch (event->keyval)
2905 direction = GTK_DIR_UP;
2908 direction = GTK_DIR_LEFT;
2911 direction = GTK_DIR_DOWN;
2914 direction = GTK_DIR_RIGHT;
2917 case GDK_ISO_Left_Tab:
2918 if (event->state & GDK_SHIFT_MASK)
2919 direction = GTK_DIR_TAB_BACKWARD;
2921 direction = GTK_DIR_TAB_FORWARD;
2924 gtk_notebook_switch_focus_tab (notebook, notebook->children);
2927 gtk_notebook_switch_focus_tab (notebook,
2928 g_list_last (notebook->children));
2932 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
2938 return gtk_container_focus (GTK_CONTAINER (widget), direction);
2943 gtk_notebook_set_tab_border (GtkNotebook *notebook,
2946 g_return_if_fail (notebook != NULL);
2947 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2949 if (notebook->tab_border != tab_border && tab_border > 0)
2951 notebook->tab_border = tab_border;
2953 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
2954 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2959 gtk_notebook_update_labels (GtkNotebook *notebook,
2963 GtkNotebookPage *page;
2970 sprintf (string, "Page %d", page_num);
2971 if (notebook->show_tabs && page->default_tab)
2972 gtk_label_set (GTK_LABEL (page->tab_label), string);
2973 if (notebook->menu && page->default_menu)
2975 if (GTK_IS_LABEL (page->tab_label))
2976 gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
2978 gtk_label_set (GTK_LABEL (page->menu_label), string);
2985 gtk_notebook_menu_item_create (GtkNotebook *notebook,
2986 GtkNotebookPage *page,
2989 GtkWidget *menu_item;
2991 if (page->default_menu)
2993 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2994 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
2996 page->menu_label = gtk_label_new ("");
2997 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
2999 gtk_widget_show (page->menu_label);
3000 menu_item = gtk_menu_item_new ();
3001 gtk_widget_freeze_accelerators (menu_item);
3002 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3003 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
3004 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3005 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page),
3007 gtk_widget_show (menu_item);
3011 gtk_notebook_popup_enable (GtkNotebook *notebook)
3013 GtkNotebookPage *page;
3016 g_return_if_fail (notebook != NULL);
3017 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3022 notebook->menu = gtk_menu_new ();
3024 children = notebook->children;
3027 page = children->data;
3028 children = children->next;
3029 gtk_notebook_menu_item_create (notebook, page, -1);
3031 gtk_notebook_update_labels (notebook, notebook->children,1);
3033 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
3034 gtk_notebook_menu_detacher);
3038 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3041 gtk_widget_unparent (GTK_BIN(widget)->child);
3042 GTK_BIN(widget)->child = NULL;
3046 gtk_notebook_popup_disable (GtkNotebook *notebook)
3048 g_return_if_fail (notebook != NULL);
3049 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3051 if (!notebook->menu)
3054 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
3055 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
3056 gtk_widget_destroy (notebook->menu);
3060 gtk_notebook_menu_detacher (GtkWidget *widget,
3063 GtkNotebook *notebook;
3065 g_return_if_fail (widget != NULL);
3066 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3068 notebook = GTK_NOTEBOOK (widget);
3069 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3071 notebook->menu = NULL;