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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtknotebook.h"
28 #include "gtksignal.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
36 #include "gtkmarshalers.h"
37 #include "gtkbindings.h"
41 #define TAB_CURVATURE 1
43 #define ARROW_SPACING 0
45 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
46 #define NOTEBOOK_SCROLL_DELAY (100)
79 CHILD_PROP_MENU_LABEL,
81 CHILD_PROP_TAB_EXPAND,
86 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
88 struct _GtkNotebookPage
92 GtkWidget *menu_label;
94 guint default_menu : 1; /* If true, we create the menu label ourself */
95 guint default_tab : 1; /* If true, we create the tab label ourself */
100 GtkRequisition requisition;
101 GtkAllocation allocation;
103 guint mnemonic_activate_signal;
106 #ifdef G_DISABLE_CHECKS
107 #define CHECK_FIND_CHILD(notebook, child) \
108 gtk_notebook_find_child (notebook, child, G_STRLOC)
110 #define CHECK_FIND_CHILD(notebook, child) \
111 gtk_notebook_find_child (notebook, child, NULL)
114 /*** GtkNotebook Methods ***/
115 static void gtk_notebook_class_init (GtkNotebookClass *klass);
116 static void gtk_notebook_init (GtkNotebook *notebook);
118 static void gtk_notebook_select_page (GtkNotebook *notebook,
119 gboolean move_focus);
120 static void gtk_notebook_focus_tab (GtkNotebook *notebook,
121 GtkNotebookTab type);
122 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
126 /*** GtkObject Methods ***/
127 static void gtk_notebook_destroy (GtkObject *object);
128 static void gtk_notebook_set_property (GObject *object,
132 static void gtk_notebook_get_property (GObject *object,
137 /*** GtkWidget Methods ***/
138 static void gtk_notebook_map (GtkWidget *widget);
139 static void gtk_notebook_unmap (GtkWidget *widget);
140 static void gtk_notebook_realize (GtkWidget *widget);
141 static void gtk_notebook_unrealize (GtkWidget *widget);
142 static void gtk_notebook_size_request (GtkWidget *widget,
143 GtkRequisition *requisition);
144 static void gtk_notebook_size_allocate (GtkWidget *widget,
145 GtkAllocation *allocation);
146 static gint gtk_notebook_expose (GtkWidget *widget,
147 GdkEventExpose *event);
148 static gint gtk_notebook_button_press (GtkWidget *widget,
149 GdkEventButton *event);
150 static gint gtk_notebook_button_release (GtkWidget *widget,
151 GdkEventButton *event);
152 static gint gtk_notebook_enter_notify (GtkWidget *widget,
153 GdkEventCrossing *event);
154 static gint gtk_notebook_leave_notify (GtkWidget *widget,
155 GdkEventCrossing *event);
156 static gint gtk_notebook_motion_notify (GtkWidget *widget,
157 GdkEventMotion *event);
158 static gint gtk_notebook_focus_in (GtkWidget *widget,
159 GdkEventFocus *event);
160 static void gtk_notebook_draw_focus (GtkWidget *widget);
161 static gint gtk_notebook_focus (GtkWidget *widget,
162 GtkDirectionType direction);
164 /*** GtkContainer Methods ***/
165 static void gtk_notebook_set_child_property (GtkContainer *container,
170 static void gtk_notebook_get_child_property (GtkContainer *container,
175 static void gtk_notebook_add (GtkContainer *container,
177 static void gtk_notebook_remove (GtkContainer *container,
179 static void gtk_notebook_set_focus_child (GtkContainer *container,
181 static GtkType gtk_notebook_child_type (GtkContainer *container);
182 static void gtk_notebook_forall (GtkContainer *container,
183 gboolean include_internals,
184 GtkCallback callback,
185 gpointer callback_data);
187 /*** GtkNotebook Private Functions ***/
188 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
189 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
190 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
191 GtkNotebookPage *old_page);
192 static void gtk_notebook_real_remove (GtkNotebook *notebook,
194 static void gtk_notebook_update_labels (GtkNotebook *notebook);
195 static gint gtk_notebook_timer (GtkNotebook *notebook);
196 static gint gtk_notebook_page_compare (gconstpointer a,
198 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
200 const gchar *function);
201 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
203 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
206 gboolean find_visible);
208 /*** GtkNotebook Drawing Functions ***/
209 static void gtk_notebook_paint (GtkWidget *widget,
211 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
212 GtkNotebookPage *page,
214 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
217 /*** GtkNotebook Size Allocate Functions ***/
218 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
219 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
220 GtkNotebookPage *page,
221 GtkAllocation *allocation);
222 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
228 /*** GtkNotebook Page Switch Methods ***/
229 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
230 GtkNotebookPage *page,
233 /*** GtkNotebook Page Switch Functions ***/
234 static void gtk_notebook_switch_page (GtkNotebook *notebook,
235 GtkNotebookPage *page,
237 static gint gtk_notebook_page_select (GtkNotebook *notebook,
238 gboolean move_focus);
239 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
241 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
242 GtkNotebookPage *page);
244 /*** GtkNotebook Menu Functions ***/
245 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
247 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
249 static void gtk_notebook_menu_detacher (GtkWidget *widget,
253 static GtkContainerClass *parent_class = NULL;
254 static guint notebook_signals[LAST_SIGNAL] = { 0 };
257 gtk_notebook_get_type (void)
259 static GtkType notebook_type = 0;
263 static const GtkTypeInfo notebook_info =
266 sizeof (GtkNotebook),
267 sizeof (GtkNotebookClass),
268 (GtkClassInitFunc) gtk_notebook_class_init,
269 (GtkObjectInitFunc) gtk_notebook_init,
270 /* reserved_1 */ NULL,
271 /* reserved_2 */ NULL,
272 (GtkClassInitFunc) NULL,
275 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
278 return notebook_type;
282 gtk_notebook_class_init (GtkNotebookClass *class)
284 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
285 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
286 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
287 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
288 GtkBindingSet *binding_set;
290 parent_class = g_type_class_peek_parent (class);
292 gobject_class->set_property = gtk_notebook_set_property;
293 gobject_class->get_property = gtk_notebook_get_property;
294 object_class->destroy = gtk_notebook_destroy;
296 widget_class->map = gtk_notebook_map;
297 widget_class->unmap = gtk_notebook_unmap;
298 widget_class->realize = gtk_notebook_realize;
299 widget_class->unrealize = gtk_notebook_unrealize;
300 widget_class->size_request = gtk_notebook_size_request;
301 widget_class->size_allocate = gtk_notebook_size_allocate;
302 widget_class->expose_event = gtk_notebook_expose;
303 widget_class->button_press_event = gtk_notebook_button_press;
304 widget_class->button_release_event = gtk_notebook_button_release;
305 widget_class->enter_notify_event = gtk_notebook_enter_notify;
306 widget_class->leave_notify_event = gtk_notebook_leave_notify;
307 widget_class->motion_notify_event = gtk_notebook_motion_notify;
308 widget_class->focus_in_event = gtk_notebook_focus_in;
309 widget_class->focus = gtk_notebook_focus;
311 container_class->add = gtk_notebook_add;
312 container_class->remove = gtk_notebook_remove;
313 container_class->forall = gtk_notebook_forall;
314 container_class->set_focus_child = gtk_notebook_set_focus_child;
315 container_class->get_child_property = gtk_notebook_get_child_property;
316 container_class->set_child_property = gtk_notebook_set_child_property;
317 container_class->child_type = gtk_notebook_child_type;
319 class->switch_page = gtk_notebook_real_switch_page;
321 class->focus_tab = gtk_notebook_focus_tab;
322 class->select_page = gtk_notebook_select_page;
323 class->change_current_page = gtk_notebook_change_current_page;
325 g_object_class_install_property (gobject_class,
327 g_param_spec_int ("page",
329 _("The index of the current page"),
334 g_object_class_install_property (gobject_class,
336 g_param_spec_enum ("tab_pos",
338 _("Which side of the notebook holds the tabs"),
339 GTK_TYPE_POSITION_TYPE,
342 g_object_class_install_property (gobject_class,
344 g_param_spec_uint ("tab_border",
346 _("Width of the border around the tab labels"),
351 g_object_class_install_property (gobject_class,
353 g_param_spec_uint ("tab_hborder",
354 _("Horizontal Tab Border"),
355 _("Width of the horizontal border of tab labels"),
360 g_object_class_install_property (gobject_class,
362 g_param_spec_uint ("tab_vborder",
363 _("Vertical Tab Border"),
364 _("Width of the vertical border of tab labels"),
369 g_object_class_install_property (gobject_class,
371 g_param_spec_boolean ("show_tabs",
373 _("Whether tabs should be shown or not"),
376 g_object_class_install_property (gobject_class,
378 g_param_spec_boolean ("show_border",
380 _("Whether the border should be shown or not"),
383 g_object_class_install_property (gobject_class,
385 g_param_spec_boolean ("scrollable",
387 _("If TRUE, scroll arrows are added if there are to many tabs to fit"),
390 g_object_class_install_property (gobject_class,
392 g_param_spec_boolean ("enable_popup",
394 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
397 g_object_class_install_property (gobject_class,
399 g_param_spec_boolean ("homogeneous",
401 _("Whether tabs should have homogeneous sizes"),
405 gtk_container_class_install_child_property (container_class,
406 CHILD_PROP_TAB_LABEL,
407 g_param_spec_string ("tab_label", NULL, NULL,
410 gtk_container_class_install_child_property (container_class,
411 CHILD_PROP_MENU_LABEL,
412 g_param_spec_string ("menu_label", NULL, NULL,
415 gtk_container_class_install_child_property (container_class,
417 g_param_spec_int ("position", NULL, NULL,
420 gtk_container_class_install_child_property (container_class,
421 CHILD_PROP_TAB_EXPAND,
422 g_param_spec_boolean ("tab_expand", NULL, NULL,
425 gtk_container_class_install_child_property (container_class,
427 g_param_spec_boolean ("tab_fill", NULL, NULL,
430 gtk_container_class_install_child_property (container_class,
432 g_param_spec_enum ("tab_pack", NULL, NULL,
433 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
436 notebook_signals[SWITCH_PAGE] =
437 gtk_signal_new ("switch_page",
439 GTK_CLASS_TYPE (object_class),
440 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
441 _gtk_marshal_VOID__POINTER_UINT,
445 notebook_signals[FOCUS_TAB] =
446 g_signal_new ("focus_tab",
447 G_TYPE_FROM_CLASS (object_class),
448 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
449 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
451 _gtk_marshal_VOID__ENUM,
453 GTK_TYPE_NOTEBOOK_TAB);
454 notebook_signals[SELECT_PAGE] =
455 g_signal_new ("select_page",
456 G_TYPE_FROM_CLASS (object_class),
457 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
458 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
460 _gtk_marshal_VOID__BOOLEAN,
463 notebook_signals[CHANGE_CURRENT_PAGE] =
464 g_signal_new ("change_current_page",
465 G_TYPE_FROM_CLASS (object_class),
466 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
467 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
469 gtk_marshal_VOID__INT,
473 binding_set = gtk_binding_set_by_class (object_class);
474 gtk_binding_entry_add_signal (binding_set,
477 G_TYPE_BOOLEAN, TRUE);
478 gtk_binding_entry_add_signal (binding_set,
481 G_TYPE_BOOLEAN, TRUE);
482 gtk_binding_entry_add_signal (binding_set,
485 G_TYPE_BOOLEAN, FALSE);
486 gtk_binding_entry_add_signal (binding_set,
489 G_TYPE_BOOLEAN, FALSE);
491 gtk_binding_entry_add_signal (binding_set,
494 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
495 gtk_binding_entry_add_signal (binding_set,
498 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
499 gtk_binding_entry_add_signal (binding_set,
502 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
503 gtk_binding_entry_add_signal (binding_set,
506 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
508 gtk_binding_entry_add_signal (binding_set,
509 GDK_Page_Up, GDK_CONTROL_MASK,
510 "change_current_page", 1,
512 gtk_binding_entry_add_signal (binding_set,
513 GDK_Page_Down, GDK_CONTROL_MASK,
514 "change_current_page", 1,
519 gtk_notebook_init (GtkNotebook *notebook)
521 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
522 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
524 notebook->cur_page = NULL;
525 notebook->children = NULL;
526 notebook->first_tab = NULL;
527 notebook->focus_tab = NULL;
528 notebook->event_window = NULL;
529 notebook->menu = NULL;
531 notebook->tab_hborder = 2;
532 notebook->tab_vborder = 2;
534 notebook->show_tabs = TRUE;
535 notebook->show_border = TRUE;
536 notebook->tab_pos = GTK_POS_TOP;
537 notebook->scrollable = FALSE;
538 notebook->in_child = 0;
539 notebook->click_child = 0;
540 notebook->button = 0;
541 notebook->need_timer = 0;
542 notebook->child_has_focus = FALSE;
543 notebook->have_visible_child = FALSE;
547 gtk_notebook_select_page (GtkNotebook *notebook,
550 gtk_notebook_page_select (notebook, move_focus);
554 gtk_notebook_focus_tab (GtkNotebook *notebook,
561 case GTK_NOTEBOOK_TAB_FIRST:
562 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
564 gtk_notebook_switch_focus_tab (notebook, list);
566 case GTK_NOTEBOOK_TAB_LAST:
567 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
569 gtk_notebook_switch_focus_tab (notebook, list);
575 gtk_notebook_change_current_page (GtkNotebook *notebook,
578 GList *current = NULL;
580 if (notebook->cur_page)
581 current = g_list_find (notebook->children, notebook->cur_page);
585 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
586 offset += offset < 0 ? 1 : -1;
590 gtk_notebook_switch_page (notebook, current->data, -1);
596 * Creates a new #GtkNotebook widget with no pages.
598 * Return value: the newly created #GtkNotebook
601 gtk_notebook_new (void)
603 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
606 /* Private GtkObject Methods :
608 * gtk_notebook_destroy
609 * gtk_notebook_set_arg
610 * gtk_notebook_get_arg
613 gtk_notebook_destroy (GtkObject *object)
615 GtkNotebook *notebook;
617 g_return_if_fail (GTK_IS_NOTEBOOK (object));
619 notebook = GTK_NOTEBOOK (object);
622 gtk_notebook_popup_disable (notebook);
624 GTK_OBJECT_CLASS (parent_class)->destroy (object);
628 gtk_notebook_set_property (GObject *object,
633 GtkNotebook *notebook;
635 notebook = GTK_NOTEBOOK (object);
640 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
642 case PROP_SHOW_BORDER:
643 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
645 case PROP_SCROLLABLE:
646 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
648 case PROP_ENABLE_POPUP:
649 if (g_value_get_boolean (value))
650 gtk_notebook_popup_enable (notebook);
652 gtk_notebook_popup_disable (notebook);
654 case PROP_HOMOGENEOUS:
655 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
658 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
661 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
663 case PROP_TAB_BORDER:
664 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
666 case PROP_TAB_HBORDER:
667 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
669 case PROP_TAB_VBORDER:
670 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
678 gtk_notebook_get_property (GObject *object,
683 GtkNotebook *notebook;
685 notebook = GTK_NOTEBOOK (object);
690 g_value_set_boolean (value, notebook->show_tabs);
692 case PROP_SHOW_BORDER:
693 g_value_set_boolean (value, notebook->show_border);
695 case PROP_SCROLLABLE:
696 g_value_set_boolean (value, notebook->scrollable);
698 case PROP_ENABLE_POPUP:
699 g_value_set_boolean (value, notebook->menu != NULL);
701 case PROP_HOMOGENEOUS:
702 g_value_set_boolean (value, notebook->homogeneous);
705 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
708 g_value_set_enum (value, notebook->tab_pos);
710 case PROP_TAB_HBORDER:
711 g_value_set_uint (value, notebook->tab_hborder);
713 case PROP_TAB_VBORDER:
714 g_value_set_uint (value, notebook->tab_vborder);
717 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
722 /* Private GtkWidget Methods :
726 * gtk_notebook_realize
727 * gtk_notebook_size_request
728 * gtk_notebook_size_allocate
729 * gtk_notebook_expose
730 * gtk_notebook_button_press
731 * gtk_notebook_button_release
732 * gtk_notebook_enter_notify
733 * gtk_notebook_leave_notify
734 * gtk_notebook_motion_notify
735 * gtk_notebook_focus_in
736 * gtk_notebook_focus_out
737 * gtk_notebook_draw_focus
738 * gtk_notebook_style_set
741 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
742 GdkRectangle *rectangle)
744 GtkWidget *widget = GTK_WIDGET (notebook);
745 gint border_width = GTK_CONTAINER (notebook)->border_width;
747 if (notebook->show_tabs && notebook->children)
751 GtkNotebookPage *page = notebook->children->data;
753 rectangle->x = widget->allocation.x + border_width;
754 rectangle->y = widget->allocation.y + border_width;
756 switch (notebook->tab_pos)
760 rectangle->width = widget->allocation.width - 2 * border_width;
761 rectangle->height = page->requisition.height;
762 if (notebook->tab_pos == GTK_POS_BOTTOM)
763 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
767 rectangle->width = page->requisition.width;
768 rectangle->height = widget->allocation.height - 2 * border_width;
769 if (notebook->tab_pos == GTK_POS_RIGHT)
770 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
781 rectangle->x = rectangle->y = 0;
782 rectangle->width = rectangle->height = 10;
790 gtk_notebook_map (GtkWidget *widget)
792 GtkNotebook *notebook;
793 GtkNotebookPage *page;
796 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
798 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
800 notebook = GTK_NOTEBOOK (widget);
802 if (notebook->cur_page &&
803 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
804 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
805 gtk_widget_map (notebook->cur_page->child);
807 if (notebook->scrollable)
808 gtk_notebook_pages_allocate (notebook);
811 children = notebook->children;
815 page = children->data;
816 children = children->next;
818 if (page->tab_label &&
819 GTK_WIDGET_VISIBLE (page->tab_label) &&
820 !GTK_WIDGET_MAPPED (page->tab_label))
821 gtk_widget_map (page->tab_label);
825 if (gtk_notebook_get_event_window_position (notebook, NULL))
826 gdk_window_show_unraised (notebook->event_window);
830 gtk_notebook_unmap (GtkWidget *widget)
832 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
834 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
836 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
838 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
842 gtk_notebook_realize (GtkWidget *widget)
844 GtkNotebook *notebook;
845 GdkWindowAttr attributes;
846 gint attributes_mask;
847 GdkRectangle event_window_pos;
849 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
851 notebook = GTK_NOTEBOOK (widget);
852 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
854 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
856 widget->window = gtk_widget_get_parent_window (widget);
857 gdk_window_ref (widget->window);
859 attributes.window_type = GDK_WINDOW_CHILD;
860 attributes.x = event_window_pos.x;
861 attributes.y = event_window_pos.y;
862 attributes.width = event_window_pos.width;
863 attributes.height = event_window_pos.height;
864 attributes.wclass = GDK_INPUT_ONLY;
865 attributes.event_mask = gtk_widget_get_events (widget);
866 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
867 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
869 attributes_mask = GDK_WA_X | GDK_WA_Y;
871 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
872 &attributes, attributes_mask);
873 gdk_window_set_user_data (notebook->event_window, notebook);
875 widget->style = gtk_style_attach (widget->style, widget->window);
879 gtk_notebook_unrealize (GtkWidget *widget)
881 GtkNotebook *notebook;
883 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
885 notebook = GTK_NOTEBOOK (widget);
887 gdk_window_set_user_data (notebook->event_window, NULL);
888 gdk_window_destroy (notebook->event_window);
889 notebook->event_window = NULL;
891 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
892 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
896 gtk_notebook_size_request (GtkWidget *widget,
897 GtkRequisition *requisition)
899 GtkNotebook *notebook;
900 GtkNotebookPage *page;
902 GtkRequisition child_requisition;
903 gboolean switch_page = FALSE;
906 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
907 g_return_if_fail (requisition != NULL);
909 notebook = GTK_NOTEBOOK (widget);
910 widget->requisition.width = 0;
911 widget->requisition.height = 0;
913 for (children = notebook->children, vis_pages = 0; children;
914 children = children->next)
916 page = children->data;
918 if (GTK_WIDGET_VISIBLE (page->child))
921 gtk_widget_size_request (page->child, &child_requisition);
923 widget->requisition.width = MAX (widget->requisition.width,
924 child_requisition.width);
925 widget->requisition.height = MAX (widget->requisition.height,
926 child_requisition.height);
928 if (notebook->menu && page->menu_label->parent &&
929 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
930 gtk_widget_show (page->menu_label->parent);
934 if (page == notebook->cur_page)
936 if (notebook->menu && page->menu_label->parent &&
937 GTK_WIDGET_VISIBLE (page->menu_label->parent))
938 gtk_widget_hide (page->menu_label->parent);
942 if (notebook->show_border || notebook->show_tabs)
944 widget->requisition.width += widget->style->xthickness * 2;
945 widget->requisition.height += widget->style->ythickness * 2;
947 if (notebook->show_tabs)
954 for (children = notebook->children; children;
955 children = children->next)
957 page = children->data;
959 if (GTK_WIDGET_VISIBLE (page->child))
961 if (!GTK_WIDGET_VISIBLE (page->tab_label))
962 gtk_widget_show (page->tab_label);
964 gtk_widget_size_request (page->tab_label,
967 page->requisition.width =
968 child_requisition.width +
969 2 * widget->style->xthickness;
970 page->requisition.height =
971 child_requisition.height +
972 2 * widget->style->ythickness;
974 switch (notebook->tab_pos)
978 page->requisition.height += 2 * (notebook->tab_vborder +
980 tab_height = MAX (tab_height, page->requisition.height);
981 tab_max = MAX (tab_max, page->requisition.width);
985 page->requisition.width += 2 * (notebook->tab_hborder +
987 tab_width = MAX (tab_width, page->requisition.width);
988 tab_max = MAX (tab_max, page->requisition.height);
992 else if (GTK_WIDGET_VISIBLE (page->tab_label))
993 gtk_widget_hide (page->tab_label);
996 children = notebook->children;
1000 switch (notebook->tab_pos)
1003 case GTK_POS_BOTTOM:
1004 if (tab_height == 0)
1007 if (notebook->scrollable && vis_pages > 1 &&
1008 widget->requisition.width < tab_width)
1009 tab_height = MAX (tab_height, ARROW_SIZE);
1011 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
1012 notebook->tab_hborder) - TAB_OVERLAP;
1016 page = children->data;
1017 children = children->next;
1019 if (!GTK_WIDGET_VISIBLE (page->child))
1022 if (notebook->homogeneous)
1023 page->requisition.width = tab_max;
1025 page->requisition.width += padding;
1027 tab_width += page->requisition.width;
1028 page->requisition.height = tab_height;
1031 if (notebook->scrollable && vis_pages > 1 &&
1032 widget->requisition.width < tab_width)
1033 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1035 if (notebook->homogeneous && !notebook->scrollable)
1036 widget->requisition.width = MAX (widget->requisition.width,
1037 vis_pages * tab_max +
1040 widget->requisition.width = MAX (widget->requisition.width,
1041 tab_width + TAB_OVERLAP);
1043 widget->requisition.height += tab_height;
1050 if (notebook->scrollable && vis_pages > 1 &&
1051 widget->requisition.height < tab_height)
1052 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1054 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
1055 notebook->tab_vborder) - TAB_OVERLAP;
1060 page = children->data;
1061 children = children->next;
1063 if (!GTK_WIDGET_VISIBLE (page->child))
1066 page->requisition.width = tab_width;
1068 if (notebook->homogeneous)
1069 page->requisition.height = tab_max;
1071 page->requisition.height += padding;
1073 tab_height += page->requisition.height;
1076 if (notebook->scrollable && vis_pages > 1 &&
1077 widget->requisition.height < tab_height)
1078 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1080 widget->requisition.width += tab_width;
1082 if (notebook->homogeneous && !notebook->scrollable)
1083 widget->requisition.height =
1084 MAX (widget->requisition.height,
1085 vis_pages * tab_max + TAB_OVERLAP);
1087 widget->requisition.height =
1088 MAX (widget->requisition.height,
1089 tab_height + TAB_OVERLAP);
1091 if (!notebook->homogeneous || notebook->scrollable)
1093 widget->requisition.height = MAX (widget->requisition.height,
1094 vis_pages * tab_max +
1102 for (children = notebook->children; children;
1103 children = children->next)
1105 page = children->data;
1107 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1108 gtk_widget_hide (page->tab_label);
1113 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1114 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1120 for (children = notebook->children; children;
1121 children = children->next)
1123 page = children->data;
1124 if (GTK_WIDGET_VISIBLE (page->child))
1126 gtk_notebook_switch_page (notebook, page, -1);
1131 else if (GTK_WIDGET_VISIBLE (widget))
1133 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1134 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1137 if (vis_pages && !notebook->cur_page)
1139 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1142 notebook->first_tab = children;
1143 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1149 gtk_notebook_size_allocate (GtkWidget *widget,
1150 GtkAllocation *allocation)
1152 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1154 widget->allocation = *allocation;
1155 if (GTK_WIDGET_REALIZED (widget))
1157 GdkRectangle position;
1159 if (gtk_notebook_get_event_window_position (notebook, &position))
1160 gdk_window_move_resize (notebook->event_window,
1161 position.x, position.y,
1162 position.width, position.height);
1165 if (notebook->children)
1167 gint border_width = GTK_CONTAINER (widget)->border_width;
1168 GtkNotebookPage *page;
1169 GtkAllocation child_allocation;
1172 child_allocation.x = widget->allocation.x + border_width;
1173 child_allocation.y = widget->allocation.y + border_width;
1174 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1175 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1177 if (notebook->show_tabs || notebook->show_border)
1179 child_allocation.x += widget->style->xthickness;
1180 child_allocation.y += widget->style->ythickness;
1181 child_allocation.width = MAX (1, child_allocation.width -
1182 widget->style->xthickness * 2);
1183 child_allocation.height = MAX (1, child_allocation.height -
1184 widget->style->ythickness * 2);
1186 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1188 switch (notebook->tab_pos)
1191 child_allocation.y += notebook->cur_page->requisition.height;
1192 case GTK_POS_BOTTOM:
1193 child_allocation.height =
1194 MAX (1, child_allocation.height -
1195 notebook->cur_page->requisition.height);
1198 child_allocation.x += notebook->cur_page->requisition.width;
1200 child_allocation.width =
1201 MAX (1, child_allocation.width -
1202 notebook->cur_page->requisition.width);
1208 children = notebook->children;
1211 page = children->data;
1212 children = children->next;
1214 if (GTK_WIDGET_VISIBLE (page->child))
1215 gtk_widget_size_allocate (page->child, &child_allocation);
1218 gtk_notebook_pages_allocate (notebook);
1223 gtk_notebook_expose (GtkWidget *widget,
1224 GdkEventExpose *event)
1226 GtkNotebook *notebook;
1227 GdkRectangle child_area;
1229 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1230 g_return_val_if_fail (event != NULL, FALSE);
1232 if (GTK_WIDGET_DRAWABLE (widget))
1234 notebook = GTK_NOTEBOOK (widget);
1236 gtk_notebook_paint (widget, &event->area);
1237 if (notebook->show_tabs)
1239 if (notebook->cur_page &&
1240 gtk_widget_intersect (notebook->cur_page->tab_label,
1241 &event->area, &child_area))
1242 gtk_notebook_draw_focus (widget);
1246 if (notebook->cur_page)
1247 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1248 notebook->cur_page->child,
1256 gtk_notebook_show_arrows (GtkNotebook *notebook)
1258 gboolean show_arrow = FALSE;
1261 if (!notebook->scrollable)
1264 children = notebook->children;
1267 GtkNotebookPage *page = children->data;
1269 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1272 children = children->next;
1279 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1280 GdkRectangle *rectangle)
1282 GdkRectangle event_window_pos;
1284 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1286 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1287 rectangle->height = ARROW_SIZE;
1289 switch (notebook->tab_pos)
1293 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1294 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1297 case GTK_POS_BOTTOM:
1298 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1299 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1306 gtk_notebook_get_arrow (GtkNotebook *notebook,
1310 GdkRectangle arrow_rect;
1311 GdkRectangle event_window_pos;
1313 if (gtk_notebook_show_arrows (notebook))
1315 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1316 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1321 if (y >= 0 && y < arrow_rect.height)
1323 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1324 return GTK_ARROW_LEFT;
1325 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1326 return GTK_ARROW_RIGHT;
1334 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1336 GdkEventButton *event)
1338 GtkWidget *widget = GTK_WIDGET (notebook);
1340 if (!GTK_WIDGET_HAS_FOCUS (widget))
1341 gtk_widget_grab_focus (widget);
1343 notebook->button = event->button;
1344 notebook->click_child = arrow;
1346 if (event->button == 1)
1348 GtkDirectionType dir;
1349 if (!notebook->focus_tab ||
1350 gtk_notebook_search_page (notebook, notebook->focus_tab,
1351 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1354 if (notebook->tab_pos == GTK_POS_LEFT ||
1355 notebook->tab_pos == GTK_POS_RIGHT)
1356 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1358 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1359 gtk_widget_child_focus (widget, dir);
1362 if (!notebook->timer)
1364 notebook->timer = gtk_timeout_add
1365 (NOTEBOOK_INIT_SCROLL_DELAY,
1366 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1367 notebook->need_timer = TRUE;
1370 else if (event->button == 2)
1371 gtk_notebook_page_select (notebook, TRUE);
1372 else if (event->button == 3)
1373 gtk_notebook_switch_focus_tab (notebook,
1374 gtk_notebook_search_page (notebook,
1376 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1378 gtk_notebook_redraw_arrows (notebook);
1384 get_widget_coordinates (GtkWidget *widget,
1389 GdkWindow *window = ((GdkEventAny *)event)->window;
1392 if (!gdk_event_get_coords (event, &tx, &ty))
1395 while (window && window != widget->window)
1397 gint window_x, window_y;
1399 gdk_window_get_position (window, &window_x, &window_y);
1403 window = gdk_window_get_parent (window);
1418 gtk_notebook_button_press (GtkWidget *widget,
1419 GdkEventButton *event)
1421 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1422 GtkNotebookPage *page;
1428 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1432 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1435 arrow = gtk_notebook_get_arrow (notebook, x, y);
1437 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1439 if (event->button == 3 && notebook->menu)
1441 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1442 NULL, NULL, 3, event->time);
1447 children = notebook->children;
1450 page = children->data;
1452 if (GTK_WIDGET_VISIBLE (page->child) &&
1453 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1454 (x >= page->allocation.x) &&
1455 (y >= page->allocation.y) &&
1456 (x <= (page->allocation.x + page->allocation.width)) &&
1457 (y <= (page->allocation.y + page->allocation.height)))
1459 if (page == notebook->cur_page && notebook->focus_tab &&
1460 notebook->focus_tab != children &&
1461 GTK_WIDGET_HAS_FOCUS (notebook))
1463 GtkNotebookPage *old_page;
1465 notebook->child_has_focus = FALSE;
1466 old_page = (GtkNotebookPage *)
1467 (notebook->focus_tab->data);
1468 gtk_notebook_switch_focus_tab (notebook, children);
1469 gtk_notebook_focus_changed (notebook, old_page);
1473 gtk_notebook_switch_focus_tab (notebook, children);
1474 gtk_widget_grab_focus (widget);
1475 gtk_notebook_switch_page (notebook, page, num);
1479 children = children->next;
1482 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1483 gtk_widget_grab_focus (widget);
1489 gtk_notebook_button_release (GtkWidget *widget,
1490 GdkEventButton *event)
1492 GtkNotebook *notebook;
1494 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1495 g_return_val_if_fail (event != NULL, FALSE);
1497 if (event->type != GDK_BUTTON_RELEASE)
1500 notebook = GTK_NOTEBOOK (widget);
1502 if (event->button == notebook->button)
1506 if (notebook->timer)
1508 gtk_timeout_remove (notebook->timer);
1509 notebook->timer = 0;
1510 notebook->need_timer = FALSE;
1512 click_child = notebook->click_child;
1513 notebook->click_child = 0;
1514 notebook->button = 0;
1515 gtk_notebook_redraw_arrows (notebook);
1524 gtk_notebook_enter_notify (GtkWidget *widget,
1525 GdkEventCrossing *event)
1527 GtkNotebook *notebook;
1531 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1532 g_return_val_if_fail (event != NULL, FALSE);
1534 notebook = GTK_NOTEBOOK (widget);
1536 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1539 arrow = gtk_notebook_get_arrow (notebook, x, y);
1541 if (arrow != notebook->in_child)
1543 notebook->in_child = arrow;
1544 gtk_notebook_redraw_arrows (notebook);
1553 gtk_notebook_leave_notify (GtkWidget *widget,
1554 GdkEventCrossing *event)
1556 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1560 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1563 arrow = gtk_notebook_get_arrow (notebook, x, y);
1565 if (notebook->in_child)
1567 notebook->in_child = 0;
1568 gtk_notebook_redraw_arrows (notebook);
1575 gtk_notebook_motion_notify (GtkWidget *widget,
1576 GdkEventMotion *event)
1578 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1582 if (notebook->button)
1585 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1588 arrow = gtk_notebook_get_arrow (notebook, x, y);
1590 if (arrow != notebook->in_child)
1592 notebook->in_child = arrow;
1593 gtk_notebook_redraw_arrows (notebook);
1600 gtk_notebook_focus_in (GtkWidget *widget,
1601 GdkEventFocus *event)
1603 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1605 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1609 gtk_notebook_draw_focus (GtkWidget *widget)
1611 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1613 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1614 notebook->focus_tab)
1616 GtkNotebookPage *page;
1619 page = notebook->focus_tab->data;
1621 area.x = page->tab_label->allocation.x - 1;
1622 area.y = page->tab_label->allocation.y - 1;
1623 area.width = page->tab_label->allocation.width + 2;
1624 area.height = page->tab_label->allocation.height + 2;
1626 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1630 /* Private GtkContainer Methods :
1632 * gtk_notebook_set_child_arg
1633 * gtk_notebook_get_child_arg
1635 * gtk_notebook_remove
1636 * gtk_notebook_focus
1637 * gtk_notebook_set_focus_child
1638 * gtk_notebook_child_type
1639 * gtk_notebook_forall
1642 gtk_notebook_set_child_property (GtkContainer *container,
1645 const GValue *value,
1650 GtkPackType pack_type;
1652 /* not finding child's page is valid for menus or labels */
1653 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1656 switch (property_id)
1658 case CHILD_PROP_TAB_LABEL:
1659 /* a NULL pointer indicates a default_tab setting, otherwise
1660 * we need to set the associated label
1662 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1663 g_value_get_string (value));
1665 case CHILD_PROP_MENU_LABEL:
1666 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1667 g_value_get_string (value));
1669 case CHILD_PROP_POSITION:
1670 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1671 g_value_get_int (value));
1673 case CHILD_PROP_TAB_EXPAND:
1674 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1675 &expand, &fill, &pack_type);
1676 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1677 g_value_get_boolean (value),
1680 case CHILD_PROP_TAB_FILL:
1681 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1682 &expand, &fill, &pack_type);
1683 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1685 g_value_get_boolean (value),
1688 case CHILD_PROP_TAB_PACK:
1689 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1690 &expand, &fill, &pack_type);
1691 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1693 g_value_get_enum (value));
1696 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1702 gtk_notebook_get_child_property (GtkContainer *container,
1709 GtkNotebook *notebook;
1713 GtkPackType pack_type;
1715 notebook = GTK_NOTEBOOK (container);
1717 /* not finding child's page is valid for menus or labels */
1718 list = gtk_notebook_find_child (notebook, child, NULL);
1721 /* nothing to set on labels or menus */
1722 g_param_value_set_default (pspec, value);
1726 switch (property_id)
1728 case CHILD_PROP_TAB_LABEL:
1729 label = gtk_notebook_get_tab_label (notebook, child);
1731 if (label && GTK_IS_LABEL (label))
1732 g_value_set_string (value, GTK_LABEL (label)->label);
1734 g_value_set_string (value, NULL);
1736 case CHILD_PROP_MENU_LABEL:
1737 label = gtk_notebook_get_menu_label (notebook, child);
1739 if (label && GTK_IS_LABEL (label))
1740 g_value_set_string (value, GTK_LABEL (label)->label);
1742 g_value_set_string (value, NULL);
1744 case CHILD_PROP_POSITION:
1745 g_value_set_int (value, g_list_position (notebook->children, list));
1747 case CHILD_PROP_TAB_EXPAND:
1748 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1749 &expand, NULL, NULL);
1750 g_value_set_boolean (value, expand);
1752 case CHILD_PROP_TAB_FILL:
1753 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1755 g_value_set_boolean (value, fill);
1757 case CHILD_PROP_TAB_PACK:
1758 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1759 NULL, NULL, &pack_type);
1760 g_value_set_enum (value, pack_type);
1763 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1769 gtk_notebook_add (GtkContainer *container,
1772 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1774 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1779 gtk_notebook_remove (GtkContainer *container,
1782 GtkNotebook *notebook;
1783 GtkNotebookPage *page;
1787 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1788 g_return_if_fail (widget != NULL);
1790 notebook = GTK_NOTEBOOK (container);
1792 children = notebook->children;
1796 page = children->data;
1797 if (page->child == widget)
1799 gtk_notebook_real_remove (notebook, children);
1803 children = children->next;
1808 focus_tabs_in (GtkNotebook *notebook)
1810 if (notebook->cur_page)
1812 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1814 gtk_notebook_switch_focus_tab (notebook,
1815 g_list_find (notebook->children,
1816 notebook->cur_page));
1825 focus_tabs_move (GtkNotebook *notebook,
1826 GtkDirectionType direction,
1827 gint search_direction)
1831 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1832 search_direction, TRUE);
1834 new_page = (search_direction == STEP_NEXT) ?
1835 notebook->children :
1836 g_list_last (notebook->children);
1838 gtk_notebook_switch_focus_tab (notebook, new_page);
1844 focus_child_in (GtkNotebook *notebook,
1845 GtkDirectionType direction)
1847 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1850 /* Focus in the notebook can either be on the pages, or on
1854 gtk_notebook_focus (GtkWidget *widget,
1855 GtkDirectionType direction)
1857 GtkWidget *old_focus_child;
1858 GtkNotebook *notebook;
1859 GtkDirectionType effective_direction;
1861 /* Remap the directions into the effective direction it would be for a
1862 * GTK_POS_TOP notebook
1864 #define D(rest) GTK_DIR_##rest
1866 static const GtkDirectionType translate_direction[4][6] = {
1867 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1868 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1869 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1870 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
1875 gboolean widget_is_focus;
1876 GtkContainer *container;
1878 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1880 container = GTK_CONTAINER (widget);
1881 notebook = GTK_NOTEBOOK (container);
1883 widget_is_focus = gtk_widget_is_focus (widget);
1884 old_focus_child = container->focus_child;
1886 effective_direction = translate_direction[notebook->tab_pos][direction];
1888 if (old_focus_child) /* Focus on page child */
1890 if (gtk_widget_child_focus (old_focus_child, direction))
1893 switch (effective_direction)
1895 case GTK_DIR_TAB_BACKWARD:
1897 /* Focus onto the tabs */
1898 if (notebook->show_tabs)
1899 return focus_tabs_in (notebook);
1903 case GTK_DIR_TAB_FORWARD:
1909 else if (widget_is_focus) /* Focus was on tabs */
1911 switch (effective_direction)
1913 case GTK_DIR_TAB_BACKWARD:
1916 case GTK_DIR_TAB_FORWARD:
1918 return focus_child_in (notebook, direction);
1920 return focus_tabs_move (notebook, direction, STEP_PREV);
1922 return focus_tabs_move (notebook, direction, STEP_NEXT);
1925 else /* Focus was not on widget */
1927 switch (effective_direction)
1929 case GTK_DIR_TAB_FORWARD:
1931 if (focus_tabs_in (notebook))
1933 if (focus_child_in (notebook, direction))
1936 case GTK_DIR_TAB_BACKWARD:
1938 if (focus_child_in (notebook, direction))
1940 if (focus_tabs_in (notebook))
1945 return focus_child_in (notebook, direction);
1949 g_assert_not_reached ();
1954 gtk_notebook_set_focus_child (GtkContainer *container,
1957 GtkNotebook *notebook;
1959 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1963 g_return_if_fail (GTK_IS_WIDGET (child));
1965 notebook = GTK_NOTEBOOK (container);
1967 notebook->child_has_focus = TRUE;
1968 if (!notebook->focus_tab)
1971 GtkNotebookPage *page;
1973 children = notebook->children;
1976 page = children->data;
1977 if (page->child == child || page->tab_label == child)
1978 gtk_notebook_switch_focus_tab (notebook, children);
1979 children = children->next;
1983 parent_class->set_focus_child (container, child);
1987 gtk_notebook_forall (GtkContainer *container,
1988 gboolean include_internals,
1989 GtkCallback callback,
1990 gpointer callback_data)
1992 GtkNotebook *notebook;
1995 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1996 g_return_if_fail (callback != NULL);
1998 notebook = GTK_NOTEBOOK (container);
2000 children = notebook->children;
2003 GtkNotebookPage *page;
2005 page = children->data;
2006 children = children->next;
2007 (* callback) (page->child, callback_data);
2008 if (include_internals)
2010 if (page->tab_label)
2011 (* callback) (page->tab_label, callback_data);
2012 if (page->menu_label)
2013 (* callback) (page->menu_label, callback_data);
2019 gtk_notebook_child_type (GtkContainer *container)
2021 return GTK_TYPE_WIDGET;
2024 /* Private GtkNotebook Functions:
2026 * gtk_notebook_redraw_tabs
2027 * gtk_notebook_focus_changed
2028 * gtk_notebook_real_remove
2029 * gtk_notebook_update_labels
2030 * gtk_notebook_timer
2031 * gtk_notebook_page_compare
2032 * gtk_notebook_real_page_position
2033 * gtk_notebook_search_page
2036 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2039 GtkNotebookPage *page;
2040 GdkRectangle redraw_rect;
2043 widget = GTK_WIDGET (notebook);
2044 border = GTK_CONTAINER (notebook)->border_width;
2046 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2049 page = notebook->first_tab->data;
2051 redraw_rect.x = border;
2052 redraw_rect.y = border;
2054 switch (notebook->tab_pos)
2056 case GTK_POS_BOTTOM:
2057 redraw_rect.y = (widget->allocation.height - border -
2058 page->allocation.height -
2059 widget->style->ythickness);
2060 if (page != notebook->cur_page)
2061 redraw_rect.y -= widget->style->ythickness;
2064 redraw_rect.width = widget->allocation.width - 2 * border;
2065 redraw_rect.height = (page->allocation.height +
2066 widget->style->ythickness);
2067 if (page != notebook->cur_page)
2068 redraw_rect.height += widget->style->ythickness;
2071 redraw_rect.x = (widget->allocation.width - border -
2072 page->allocation.width -
2073 widget->style->xthickness);
2074 if (page != notebook->cur_page)
2075 redraw_rect.x -= widget->style->xthickness;
2078 redraw_rect.width = (page->allocation.width +
2079 widget->style->xthickness);
2080 redraw_rect.height = widget->allocation.height - 2 * border;
2081 if (page != notebook->cur_page)
2082 redraw_rect.width += widget->style->xthickness;
2086 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2090 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2092 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2096 gtk_notebook_get_arrow_rect (notebook, &rect);
2097 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2102 gtk_notebook_focus_changed (GtkNotebook *notebook,
2103 GtkNotebookPage *old_page)
2105 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2107 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2111 if (notebook->focus_tab)
2113 GtkNotebookPage *page;
2115 page = notebook->focus_tab->data;
2117 area.x = page->tab_label->allocation.x - 1;
2118 area.y = page->tab_label->allocation.y - 1;
2119 area.width = page->tab_label->allocation.width + 2;
2120 area.height = page->tab_label->allocation.height + 2;
2122 gtk_notebook_draw_tab (notebook, page, &area);
2127 area.x = old_page->tab_label->allocation.x - 1;
2128 area.y = old_page->tab_label->allocation.y - 1;
2129 area.width = old_page->tab_label->allocation.width + 2;
2130 area.height = old_page->tab_label->allocation.height + 2;
2132 gtk_notebook_draw_tab (notebook, old_page, &area);
2138 gtk_notebook_timer (GtkNotebook *notebook)
2140 gboolean retval = FALSE;
2142 GDK_THREADS_ENTER ();
2144 if (notebook->timer)
2146 if (notebook->click_child == GTK_ARROW_LEFT)
2148 if (!notebook->focus_tab ||
2149 gtk_notebook_search_page (notebook, notebook->focus_tab,
2151 gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_LEFT);
2153 else if (notebook->click_child == GTK_ARROW_RIGHT)
2155 if (!notebook->focus_tab ||
2156 gtk_notebook_search_page (notebook, notebook->focus_tab,
2158 gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_RIGHT);
2160 if (notebook->need_timer)
2162 notebook->need_timer = FALSE;
2163 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2164 (GtkFunction) gtk_notebook_timer,
2165 (gpointer) notebook);
2171 GDK_THREADS_LEAVE ();
2177 gtk_notebook_page_compare (gconstpointer a,
2180 return (((GtkNotebookPage *) a)->child != b);
2184 gtk_notebook_find_child (GtkNotebook *notebook,
2186 const gchar *function)
2188 GList *list = g_list_find_custom (notebook->children, child,
2189 gtk_notebook_page_compare);
2191 #ifndef G_DISABLE_CHECKS
2192 if (!list && function)
2193 g_warning ("%s: unable to find child %p in notebook %p",
2194 function, child, notebook);
2201 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2202 GtkNotebookPage *page)
2204 if (page->tab_label)
2206 if (page->mnemonic_activate_signal)
2207 gtk_signal_disconnect (page->tab_label,
2208 page->mnemonic_activate_signal);
2209 page->mnemonic_activate_signal = 0;
2211 gtk_widget_unparent (page->tab_label);
2216 gtk_notebook_real_remove (GtkNotebook *notebook,
2219 GtkNotebookPage *page;
2221 gint need_resize = FALSE;
2223 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2225 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2227 if (notebook->cur_page == list->data)
2229 notebook->cur_page = NULL;
2231 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2234 if (list == notebook->first_tab)
2235 notebook->first_tab = next_list;
2236 if (list == notebook->focus_tab)
2237 gtk_notebook_switch_focus_tab (notebook, next_list);
2241 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2244 gtk_widget_unparent (page->child);
2246 gtk_notebook_remove_tab_label (notebook, page);
2250 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2251 page->menu_label->parent);
2252 gtk_widget_queue_resize (notebook->menu);
2254 if (!page->default_menu)
2255 gtk_widget_unref (page->menu_label);
2257 notebook->children = g_list_remove_link (notebook->children, list);
2261 if (!notebook->children && notebook->show_tabs &&
2262 GTK_WIDGET_MAPPED (notebook))
2263 gdk_window_hide (notebook->event_window);
2265 gtk_notebook_update_labels (notebook);
2267 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2271 gtk_notebook_update_labels (GtkNotebook *notebook)
2273 GtkNotebookPage *page;
2278 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2280 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2283 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2284 if (notebook->show_tabs)
2286 if (page->default_tab)
2288 if (!page->tab_label)
2290 page->tab_label = gtk_label_new (string);
2291 gtk_widget_set_parent (page->tab_label,
2292 GTK_WIDGET (notebook));
2295 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2298 if (GTK_WIDGET_VISIBLE (page->child) &&
2299 !GTK_WIDGET_VISIBLE (page->tab_label))
2300 gtk_widget_show (page->tab_label);
2301 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2302 GTK_WIDGET_VISIBLE (page->tab_label))
2303 gtk_widget_hide (page->tab_label);
2305 if (notebook->menu && page->default_menu)
2307 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2308 gtk_label_set_text (GTK_LABEL (page->menu_label),
2309 GTK_LABEL (page->tab_label)->label);
2311 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2317 gtk_notebook_real_page_position (GtkNotebook *notebook,
2323 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2324 g_return_val_if_fail (list != NULL, -1);
2326 for (work = notebook->children, count_start = 0;
2327 work && work != list; work = work->next)
2328 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2334 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2337 return (count_start + g_list_length (list) - 1);
2341 gtk_notebook_search_page (GtkNotebook *notebook,
2344 gboolean find_visible)
2346 GtkNotebookPage *page = NULL;
2347 GList *old_list = NULL;
2350 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2355 flag = GTK_PACK_END;
2359 flag = GTK_PACK_START;
2366 if (!page || page->pack == flag)
2374 list = notebook->children;
2379 if (page->pack == flag &&
2380 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2395 if (page->pack != flag &&
2396 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2404 /* Private GtkNotebook Drawing Functions:
2406 * gtk_notebook_paint
2407 * gtk_notebook_draw_tab
2408 * gtk_notebook_draw_arrow
2411 gtk_notebook_paint (GtkWidget *widget,
2414 GtkNotebook *notebook;
2415 GtkNotebookPage *page;
2420 gint border_width = GTK_CONTAINER (widget)->border_width;
2421 gint gap_x = 0, gap_width = 0;
2423 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2424 g_return_if_fail (area != NULL);
2426 if (!GTK_WIDGET_DRAWABLE (widget))
2429 notebook = GTK_NOTEBOOK (widget);
2431 if ((!notebook->show_tabs && !notebook->show_border) ||
2432 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2435 x = widget->allocation.x + border_width;
2436 y = widget->allocation.y + border_width;
2437 width = widget->allocation.width - border_width * 2;
2438 height = widget->allocation.height - border_width * 2;
2440 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2442 gtk_paint_box (widget->style, widget->window,
2443 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2444 area, widget, "notebook",
2445 x, y, width, height);
2450 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2452 page = notebook->first_tab->data;
2454 switch (notebook->tab_pos)
2457 y += page->allocation.height + widget->style->ythickness;
2458 case GTK_POS_BOTTOM:
2459 height -= page->allocation.height + widget->style->ythickness;
2462 x += page->allocation.width + widget->style->xthickness;
2464 width -= page->allocation.width + widget->style->xthickness;
2467 gtk_paint_box (widget->style, widget->window,
2468 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2469 area, widget, "notebook",
2470 x, y, width, height);
2474 switch (notebook->tab_pos)
2477 y += notebook->cur_page->allocation.height;
2478 case GTK_POS_BOTTOM:
2479 height -= notebook->cur_page->allocation.height;
2482 x += notebook->cur_page->allocation.width;
2484 width -= notebook->cur_page->allocation.width;
2488 switch (notebook->tab_pos)
2491 case GTK_POS_BOTTOM:
2492 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2493 gap_width = notebook->cur_page->allocation.width;
2497 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2498 gap_width = notebook->cur_page->allocation.height;
2501 gtk_paint_box_gap(widget->style, widget->window,
2502 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2503 area, widget, "notebook",
2504 x, y, width, height,
2505 notebook->tab_pos, gap_x, gap_width);
2509 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2512 page = children->data;
2513 children = gtk_notebook_search_page (notebook, children,
2515 if (!GTK_WIDGET_VISIBLE (page->child))
2517 if (!GTK_WIDGET_MAPPED (page->tab_label))
2519 else if (page != notebook->cur_page)
2520 gtk_notebook_draw_tab (notebook, page, area);
2523 if (showarrow && notebook->scrollable)
2525 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2526 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2528 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2532 gtk_notebook_draw_tab (GtkNotebook *notebook,
2533 GtkNotebookPage *page,
2536 GdkRectangle child_area;
2537 GdkRectangle page_area;
2538 GtkStateType state_type;
2539 GtkPositionType gap_side;
2541 g_return_if_fail (notebook != NULL);
2542 g_return_if_fail (page != NULL);
2543 g_return_if_fail (area != NULL);
2545 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2546 (page->allocation.width == 0) || (page->allocation.height == 0))
2549 page_area.x = page->allocation.x;
2550 page_area.y = page->allocation.y;
2551 page_area.width = page->allocation.width;
2552 page_area.height = page->allocation.height;
2554 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2558 widget = GTK_WIDGET (notebook);
2560 switch (notebook->tab_pos)
2563 gap_side = GTK_POS_BOTTOM;
2565 case GTK_POS_BOTTOM:
2566 gap_side = GTK_POS_TOP;
2569 gap_side = GTK_POS_RIGHT;
2572 gap_side = GTK_POS_LEFT;
2576 if (notebook->cur_page == page)
2577 state_type = GTK_STATE_NORMAL;
2579 state_type = GTK_STATE_ACTIVE;
2580 gtk_paint_extension(widget->style, widget->window,
2581 state_type, GTK_SHADOW_OUT,
2582 area, widget, "tab",
2583 page_area.x, page_area.y,
2584 page_area.width, page_area.height,
2586 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2587 notebook->focus_tab && (notebook->focus_tab->data == page))
2589 gtk_paint_focus (widget->style, widget->window,
2590 area, widget, "tab",
2591 page->tab_label->allocation.x - 1,
2592 page->tab_label->allocation.y - 1,
2593 page->tab_label->allocation.width + 1,
2594 page->tab_label->allocation.height + 1);
2596 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2597 GTK_WIDGET_DRAWABLE (page->tab_label))
2599 GdkEventExpose expose_event;
2601 /* This is a lame hack since all this code needs rewriting anyhow */
2603 expose_event.window = page->tab_label->window;
2604 expose_event.area = child_area;
2605 expose_event.region = gdk_region_rectangle (&child_area);
2606 expose_event.send_event = TRUE;
2607 expose_event.type = GDK_EXPOSE;
2608 expose_event.count = 0;
2610 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
2612 gdk_region_destroy (expose_event.region);
2618 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2621 GtkStateType state_type;
2622 GtkShadowType shadow_type;
2624 GdkRectangle arrow_rect;
2626 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2628 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2630 widget = GTK_WIDGET(notebook);
2632 if (GTK_WIDGET_DRAWABLE (notebook))
2634 if (notebook->in_child == arrow)
2636 if (notebook->click_child == arrow)
2637 state_type = GTK_STATE_ACTIVE;
2639 state_type = GTK_STATE_PRELIGHT;
2642 state_type = GTK_STATE_NORMAL;
2644 if (notebook->click_child == arrow)
2645 shadow_type = GTK_SHADOW_IN;
2647 shadow_type = GTK_SHADOW_OUT;
2649 if (arrow == GTK_ARROW_LEFT)
2651 if (notebook->focus_tab &&
2652 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2655 shadow_type = GTK_SHADOW_ETCHED_IN;
2656 state_type = GTK_STATE_NORMAL;
2659 if (notebook->tab_pos == GTK_POS_LEFT ||
2660 notebook->tab_pos == GTK_POS_RIGHT)
2661 arrow = GTK_ARROW_UP;
2663 gtk_paint_arrow (widget->style, widget->window, state_type,
2664 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2666 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2670 if (notebook->focus_tab &&
2671 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2674 shadow_type = GTK_SHADOW_ETCHED_IN;
2675 state_type = GTK_STATE_NORMAL;
2678 if (notebook->tab_pos == GTK_POS_LEFT ||
2679 notebook->tab_pos == GTK_POS_RIGHT)
2680 arrow = GTK_ARROW_DOWN;
2682 gtk_paint_arrow (widget->style, widget->window, state_type,
2683 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2684 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2685 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2690 /* Private GtkNotebook Size Allocate Functions:
2692 * gtk_notebook_pages_allocate
2693 * gtk_notebook_page_allocate
2694 * gtk_notebook_calc_tabs
2697 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2699 GtkWidget *widget = GTK_WIDGET (notebook);
2700 GtkContainer *container = GTK_CONTAINER (notebook);
2701 GtkNotebookPage *page = NULL;
2702 GtkAllocation *allocation = &widget->allocation;
2703 GtkAllocation child_allocation;
2704 GList *children = NULL;
2705 GList *last_child = NULL;
2706 gboolean showarrow = FALSE;
2716 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2719 child_allocation.x = widget->allocation.x + container->border_width;
2720 child_allocation.y = widget->allocation.y + container->border_width;
2722 switch (notebook->tab_pos)
2724 case GTK_POS_BOTTOM:
2725 child_allocation.y = (widget->allocation.y +
2726 allocation->height -
2727 notebook->cur_page->requisition.height -
2728 container->border_width);
2731 child_allocation.height = notebook->cur_page->requisition.height;
2735 child_allocation.x = (widget->allocation.x +
2737 notebook->cur_page->requisition.width -
2738 container->border_width);
2741 child_allocation.width = notebook->cur_page->requisition.width;
2745 if (notebook->scrollable)
2749 children = notebook->children;
2751 if (notebook->focus_tab)
2752 focus_tab = notebook->focus_tab;
2753 else if (notebook->first_tab)
2754 focus_tab = notebook->first_tab;
2756 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2758 switch (notebook->tab_pos)
2761 case GTK_POS_BOTTOM:
2764 page = children->data;
2765 children = children->next;
2767 if (GTK_WIDGET_VISIBLE (page->child))
2768 tab_space += page->requisition.width;
2771 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2774 page = focus_tab->data;
2776 tab_space = (allocation->width - TAB_OVERLAP -
2777 page->requisition.width -
2778 2 * (container->border_width + ARROW_SPACING +
2780 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2781 container->border_width);
2783 page = notebook->children->data;
2784 if (notebook->tab_pos == GTK_POS_TOP)
2785 y = (container->border_width +
2786 (page->requisition.height - ARROW_SIZE) / 2);
2788 y = (allocation->height - container->border_width -
2789 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2796 page = children->data;
2797 children = children->next;
2799 if (GTK_WIDGET_VISIBLE (page->child))
2800 tab_space += page->requisition.height;
2803 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2806 page = focus_tab->data;
2807 tab_space = (allocation->height -
2808 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2809 2 * container->border_width -
2810 page->requisition.height);
2811 y = allocation->height - container->border_width - ARROW_SIZE;
2813 page = notebook->children->data;
2814 if (notebook->tab_pos == GTK_POS_LEFT)
2815 x = (container->border_width +
2816 (page->requisition.width -
2817 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2819 x = (allocation->width - container->border_width -
2820 (2 * ARROW_SIZE - ARROW_SPACING) -
2821 (page->requisition.width -
2822 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2826 if (showarrow) /* first_tab <- focus_tab */
2830 notebook->first_tab = focus_tab;
2831 last_child = gtk_notebook_search_page (notebook, focus_tab,
2837 if (notebook->first_tab && notebook->first_tab != focus_tab)
2839 /* Is first_tab really predecessor of focus_tab ? */
2840 page = notebook->first_tab->data;
2841 if (GTK_WIDGET_VISIBLE (page->child))
2842 for (children = focus_tab;
2843 children && children != notebook->first_tab;
2844 children = gtk_notebook_search_page (notebook,
2850 notebook->first_tab = focus_tab;
2852 gtk_notebook_calc_tabs (notebook,
2853 gtk_notebook_search_page (notebook,
2857 &(notebook->first_tab), &tab_space,
2862 notebook->first_tab =
2863 gtk_notebook_search_page (notebook, notebook->first_tab,
2865 if (!notebook->first_tab)
2866 notebook->first_tab = focus_tab;
2867 last_child = gtk_notebook_search_page (notebook, focus_tab,
2870 else /* focus_tab -> end */
2872 if (!notebook->first_tab)
2873 notebook->first_tab = gtk_notebook_search_page (notebook,
2878 gtk_notebook_calc_tabs (notebook,
2879 gtk_notebook_search_page (notebook,
2883 &children, &tab_space, STEP_NEXT);
2886 last_child = children;
2887 else /* start <- first_tab */
2891 gtk_notebook_calc_tabs
2893 gtk_notebook_search_page (notebook,
2894 notebook->first_tab,
2897 &children, &tab_space, STEP_PREV);
2898 notebook->first_tab = gtk_notebook_search_page(notebook,
2908 tab_space = -tab_space;
2910 for (children = notebook->first_tab;
2911 children && children != last_child;
2912 children = gtk_notebook_search_page (notebook, children,
2919 /*unmap all non-visible tabs*/
2920 for (children = gtk_notebook_search_page (notebook, NULL,
2922 children && children != notebook->first_tab;
2923 children = gtk_notebook_search_page (notebook, children,
2926 page = children->data;
2927 if (page->tab_label)
2928 gtk_widget_set_child_visible (page->tab_label, FALSE);
2930 for (children = last_child; children;
2931 children = gtk_notebook_search_page (notebook, children,
2934 page = children->data;
2935 if (page->tab_label)
2936 gtk_widget_set_child_visible (page->tab_label, FALSE);
2939 else /* !showarrow */
2941 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2952 children = notebook->children;
2953 switch (notebook->tab_pos)
2956 case GTK_POS_BOTTOM:
2959 page = children->data;
2960 children = children->next;
2962 if (GTK_WIDGET_VISIBLE (page->child))
2965 tab_space += page->requisition.width;
2970 tab_space -= allocation->width;
2976 page = children->data;
2977 children = children->next;
2979 if (GTK_WIDGET_VISIBLE (page->child))
2982 tab_space += page->requisition.height;
2987 tab_space -= allocation->height;
2989 tab_space += 2 * container->border_width + TAB_OVERLAP;
2991 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2993 if (notebook->homogeneous && n)
2997 children = notebook->first_tab;
3001 if (children == last_child)
3003 /* FIXME double check */
3007 page = children->data;
3008 if (!showarrow && page->pack != GTK_PACK_START)
3010 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3013 if (n && (showarrow || page->expand || notebook->homogeneous))
3015 new_fill = (tab_space * i++) / n;
3016 delta = new_fill - old_fill;
3017 old_fill = new_fill;
3020 switch (notebook->tab_pos)
3023 case GTK_POS_BOTTOM:
3024 child_allocation.width = (page->requisition.width +
3025 TAB_OVERLAP + delta);
3029 child_allocation.height = (page->requisition.height +
3030 TAB_OVERLAP + delta);
3034 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3036 switch (notebook->tab_pos)
3039 case GTK_POS_BOTTOM:
3040 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3044 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3048 if (page->tab_label)
3049 gtk_widget_set_child_visible (page->tab_label, TRUE);
3054 children = notebook->children;
3055 switch (notebook->tab_pos)
3058 case GTK_POS_BOTTOM:
3059 child_allocation.x = (allocation->x + allocation->width -
3060 container->border_width);
3064 child_allocation.y = (allocation->y + allocation->height -
3065 container->border_width);
3069 while (children != last_child)
3071 page = children->data;
3072 children = children->next;
3074 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3078 if (n && (page->expand || notebook->homogeneous))
3080 new_fill = (tab_space * i++) / n;
3081 delta = new_fill - old_fill;
3082 old_fill = new_fill;
3085 switch (notebook->tab_pos)
3088 case GTK_POS_BOTTOM:
3089 child_allocation.width = (page->requisition.width +
3090 TAB_OVERLAP + delta);
3091 child_allocation.x -= child_allocation.width;
3095 child_allocation.height = (page->requisition.height +
3096 TAB_OVERLAP + delta);
3097 child_allocation.y -= child_allocation.height;
3101 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3103 switch (notebook->tab_pos)
3106 case GTK_POS_BOTTOM:
3107 child_allocation.x += TAB_OVERLAP;
3111 child_allocation.y += TAB_OVERLAP;
3115 if (page->tab_label)
3116 gtk_widget_set_child_visible (page->tab_label, TRUE);
3121 gtk_notebook_redraw_tabs (notebook);
3125 gtk_notebook_page_allocate (GtkNotebook *notebook,
3126 GtkNotebookPage *page,
3127 GtkAllocation *allocation)
3130 GtkAllocation child_allocation;
3131 GtkRequisition tab_requisition;
3136 g_return_if_fail (notebook != NULL);
3137 g_return_if_fail (page != NULL);
3138 g_return_if_fail (allocation != NULL);
3140 widget = GTK_WIDGET (notebook);
3142 xthickness = widget->style->xthickness;
3143 ythickness = widget->style->ythickness;
3145 /* If the size of the notebook tabs change, we need to queue
3146 * a redraw on the tab area
3148 if ((allocation->width != page->allocation.width) ||
3149 (allocation->height != page->allocation.height))
3151 gint x, y, width, height, border_width;
3153 border_width = GTK_CONTAINER (notebook)->border_width;
3155 switch (notebook->tab_pos)
3158 width = widget->allocation.width;
3159 height = MAX (page->allocation.height, allocation->height) + ythickness;
3164 case GTK_POS_BOTTOM:
3165 width = widget->allocation.width + xthickness;
3166 height = MAX (page->allocation.height, allocation->height) + ythickness;
3168 y = widget->allocation.height - height - border_width;
3172 width = MAX (page->allocation.width, allocation->width) + xthickness;
3173 height = widget->allocation.height;
3179 default: /* quiet gcc */
3180 width = MAX (page->allocation.width, allocation->width) + xthickness;
3181 height = widget->allocation.height;
3182 x = widget->allocation.width - width - border_width;
3187 gtk_widget_queue_clear_area (widget, x, y, width, height);
3190 page->allocation = *allocation;
3191 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3193 if (notebook->cur_page != page)
3195 switch (notebook->tab_pos)
3198 page->allocation.y += ythickness;
3199 case GTK_POS_BOTTOM:
3200 if (page->allocation.height > ythickness)
3201 page->allocation.height -= ythickness;
3204 page->allocation.x += xthickness;
3206 if (page->allocation.width > xthickness)
3207 page->allocation.width -= xthickness;
3212 switch (notebook->tab_pos)
3215 case GTK_POS_BOTTOM:
3216 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_hborder;
3219 child_allocation.x = (xthickness + FOCUS_WIDTH +
3220 notebook->tab_hborder);
3221 child_allocation.width = MAX (1, (page->allocation.width -
3222 2 * child_allocation.x));
3223 child_allocation.x += page->allocation.x;
3227 child_allocation.x = (page->allocation.x +
3228 (page->allocation.width -
3229 tab_requisition.width) / 2);
3230 child_allocation.width = tab_requisition.width;
3232 child_allocation.y = (notebook->tab_vborder + FOCUS_WIDTH +
3233 page->allocation.y);
3234 if (notebook->tab_pos == GTK_POS_TOP)
3235 child_allocation.y += ythickness;
3236 child_allocation.height = MAX (1, (page->allocation.height - ythickness -
3237 2 * (notebook->tab_vborder + FOCUS_WIDTH)));
3241 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_vborder;
3244 child_allocation.y = ythickness + padding;
3245 child_allocation.height = MAX (1, (page->allocation.height -
3246 2 * child_allocation.y));
3247 child_allocation.y += page->allocation.y;
3251 child_allocation.y = (page->allocation.y + (page->allocation.height -
3252 tab_requisition.height) / 2);
3253 child_allocation.height = tab_requisition.height;
3255 child_allocation.x = page->allocation.x + notebook->tab_hborder + FOCUS_WIDTH;
3256 if (notebook->tab_pos == GTK_POS_LEFT)
3257 child_allocation.x += xthickness;
3258 child_allocation.width = MAX (1, (page->allocation.width - xthickness -
3259 2 * (notebook->tab_hborder + FOCUS_WIDTH)));
3263 if (page->tab_label)
3264 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3268 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3274 GtkNotebookPage *page = NULL;
3276 GList *last_list = NULL;
3283 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3284 if (pack == GTK_PACK_END)
3285 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3289 switch (notebook->tab_pos)
3292 case GTK_POS_BOTTOM:
3295 page = children->data;
3296 if (GTK_WIDGET_VISIBLE (page->child))
3298 if (page->pack == pack)
3300 *tab_space -= page->requisition.width;
3301 if (*tab_space < 0 || children == *end)
3305 *tab_space = - (*tab_space +
3306 page->requisition.width);
3312 last_list = children;
3314 if (direction == STEP_NEXT)
3315 children = children->next;
3317 children = children->prev;
3324 page = children->data;
3325 if (GTK_WIDGET_VISIBLE (page->child))
3327 if (page->pack == pack)
3329 *tab_space -= page->requisition.height;
3330 if (*tab_space < 0 || children == *end)
3334 *tab_space = - (*tab_space +
3335 page->requisition.height);
3341 last_list = children;
3343 if (direction == STEP_NEXT)
3344 children = children->next;
3346 children = children->prev;
3350 if (direction == STEP_PREV)
3352 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3353 direction = STEP_PREV;
3354 children = last_list;
3358 /* Private GtkNotebook Page Switch Methods:
3360 * gtk_notebook_real_switch_page
3363 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3364 GtkNotebookPage *page,
3367 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3368 g_return_if_fail (page != NULL);
3370 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3373 if (notebook->cur_page)
3374 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3376 notebook->cur_page = page;
3378 if (!notebook->focus_tab ||
3379 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3380 notebook->focus_tab =
3381 g_list_find (notebook->children, notebook->cur_page);
3383 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3385 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3386 g_object_notify (G_OBJECT (notebook), "page");
3389 /* Private GtkNotebook Page Switch Functions:
3391 * gtk_notebook_switch_page
3392 * gtk_notebook_page_select
3393 * gtk_notebook_switch_focus_tab
3394 * gtk_notebook_menu_switch_page
3397 gtk_notebook_switch_page (GtkNotebook *notebook,
3398 GtkNotebookPage *page,
3401 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3402 g_return_if_fail (page != NULL);
3404 if (notebook->cur_page == page)
3408 page_num = g_list_index (notebook->children, page);
3410 gtk_signal_emit (GTK_OBJECT (notebook),
3411 notebook_signals[SWITCH_PAGE],
3417 gtk_notebook_page_select (GtkNotebook *notebook,
3418 gboolean move_focus)
3420 GtkNotebookPage *page;
3421 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3423 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3425 if (!notebook->focus_tab)
3428 page = notebook->focus_tab->data;
3429 gtk_notebook_switch_page (notebook, page, -1);
3433 switch (notebook->tab_pos)
3438 case GTK_POS_BOTTOM:
3442 dir = GTK_DIR_RIGHT;
3449 if (gtk_widget_child_focus (page->child, dir))
3456 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3460 GtkNotebookPage *old_page = NULL;
3461 GtkNotebookPage *page;
3463 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3465 if (notebook->focus_tab == new_child)
3468 old_child = notebook->focus_tab;
3469 notebook->focus_tab = new_child;
3471 if (notebook->scrollable)
3472 gtk_notebook_redraw_arrows (notebook);
3474 if (!notebook->show_tabs || !notebook->focus_tab)
3478 old_page = old_child->data;
3480 page = notebook->focus_tab->data;
3481 if (GTK_WIDGET_MAPPED (page->tab_label))
3482 gtk_notebook_focus_changed (notebook, old_page);
3484 gtk_notebook_pages_allocate (notebook);
3488 gtk_notebook_menu_switch_page (GtkWidget *widget,
3489 GtkNotebookPage *page)
3491 GtkNotebook *notebook;
3495 g_return_if_fail (widget != NULL);
3496 g_return_if_fail (page != NULL);
3498 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3499 (GTK_MENU (widget->parent)));
3501 if (notebook->cur_page == page)
3505 children = notebook->children;
3506 while (children && children->data != page)
3508 children = children->next;
3512 gtk_signal_emit (GTK_OBJECT (notebook),
3513 notebook_signals[SWITCH_PAGE],
3518 /* Private GtkNotebook Menu Functions:
3520 * gtk_notebook_menu_item_create
3521 * gtk_notebook_menu_label_unparent
3522 * gtk_notebook_menu_detacher
3525 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3528 GtkNotebookPage *page;
3529 GtkWidget *menu_item;
3532 if (page->default_menu)
3534 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3535 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3537 page->menu_label = gtk_label_new ("");
3538 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3541 gtk_widget_show (page->menu_label);
3542 menu_item = gtk_menu_item_new ();
3543 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3544 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3545 gtk_notebook_real_page_position (notebook, list));
3546 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3547 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3548 if (GTK_WIDGET_VISIBLE (page->child))
3549 gtk_widget_show (menu_item);
3553 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3556 gtk_widget_unparent (GTK_BIN(widget)->child);
3557 GTK_BIN(widget)->child = NULL;
3561 gtk_notebook_menu_detacher (GtkWidget *widget,
3564 GtkNotebook *notebook;
3566 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3568 notebook = GTK_NOTEBOOK (widget);
3569 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3571 notebook->menu = NULL;
3574 /* Public GtkNotebook Page Insert/Remove Methods :
3576 * gtk_notebook_append_page
3577 * gtk_notebook_append_page_menu
3578 * gtk_notebook_prepend_page
3579 * gtk_notebook_prepend_page_menu
3580 * gtk_notebook_insert_page
3581 * gtk_notebook_insert_page_menu
3582 * gtk_notebook_remove_page
3585 * gtk_notebook_append_page:
3586 * @notebook: a #GtkNotebook
3587 * @child: the #GtkWidget to use as the contents of the page.
3588 * @tab_label: the #GtkWidget to be used as the label for the page,
3589 * or %NULL to use the default label, 'page N'.
3591 * Appends a page to @notebook.
3594 gtk_notebook_append_page (GtkNotebook *notebook,
3596 GtkWidget *tab_label)
3598 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3599 g_return_if_fail (GTK_IS_WIDGET (child));
3600 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3602 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3606 * gtk_notebook_append_page_menu:
3607 * @notebook: a #GtkNotebook
3608 * @child: the #GtkWidget to use as the contents of the page.
3609 * @tab_label: the #GtkWidget to be used as the label for the page,
3610 * or %NULL to use the default label, 'page N'.
3611 * @menu_label: the widget to use as a label for the page-switch
3612 * menu, if that is enabled. If %NULL, and @tab_label
3613 * is a #GtkLabel or %NULL, then the menu label will be
3614 * a newly created label with the same text as @tab_label;
3615 * If @tab_label is not a #GtkLabel, @menu_label must be
3616 * specified if the page-switch menu is to be used.
3618 * Appends a page to @notebook, specifying the widget to use as the
3619 * label in the popup menu.
3622 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3624 GtkWidget *tab_label,
3625 GtkWidget *menu_label)
3627 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3628 g_return_if_fail (GTK_IS_WIDGET (child));
3629 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3630 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3632 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3636 * gtk_notebook_prepend_page:
3637 * @notebook: a #GtkNotebook
3638 * @child: the #GtkWidget to use as the contents of the page.
3639 * @tab_label: the #GtkWidget to be used as the label for the page,
3640 * or %NULL to use the default label, 'page N'.
3642 * Prepends a page to @notebook.
3645 gtk_notebook_prepend_page (GtkNotebook *notebook,
3647 GtkWidget *tab_label)
3649 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3650 g_return_if_fail (GTK_IS_WIDGET (child));
3651 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3653 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3657 * gtk_notebook_prepend_page_menu:
3658 * @notebook: a #GtkNotebook
3659 * @child: the #GtkWidget to use as the contents of the page.
3660 * @tab_label: the #GtkWidget to be used as the label for the page,
3661 * or %NULL to use the default label, 'page N'.
3662 * @menu_label: the widget to use as a label for the page-switch
3663 * menu, if that is enabled. If %NULL, and @tab_label
3664 * is a #GtkLabel or %NULL, then the menu label will be
3665 * a newly created label with the same text as @tab_label;
3666 * If @tab_label is not a #GtkLabel, @menu_label must be
3667 * specified if the page-switch menu is to be used.
3669 * Prepends a page to @notebook, specifying the widget to use as the
3670 * label in the popup menu.
3673 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3675 GtkWidget *tab_label,
3676 GtkWidget *menu_label)
3678 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3679 g_return_if_fail (GTK_IS_WIDGET (child));
3680 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3681 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3683 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3687 * gtk_notebook_insert_page:
3688 * @notebook: a #GtkNotebook
3689 * @child: the #GtkWidget to use as the contents of the page.
3690 * @tab_label: the #GtkWidget to be used as the label for the page,
3691 * or %NULL to use the default label, 'page N'.
3692 * @position: the index (starting at 0) at which to insert the page,
3693 * or -1 to append the page after all other pages.
3695 * Insert a page into @notebook at the given position
3698 gtk_notebook_insert_page (GtkNotebook *notebook,
3700 GtkWidget *tab_label,
3703 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3704 g_return_if_fail (GTK_IS_WIDGET (child));
3705 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3707 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3712 gtk_notebook_page_compare_tab (gconstpointer a,
3715 return (((GtkNotebookPage *) a)->tab_label != b);
3719 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3723 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3726 list = g_list_find_custom (notebook->children, child,
3727 gtk_notebook_page_compare_tab);
3730 GtkNotebookPage *page = list->data;
3732 gtk_notebook_switch_page (notebook, page, -1);
3739 * gtk_notebook_insert_page_menu:
3740 * @notebook: a #GtkNotebook
3741 * @child: the #GtkWidget to use as the contents of the page.
3742 * @tab_label: the #GtkWidget to be used as the label for the page,
3743 * or %NULL to use the default label, 'page N'.
3744 * @menu_label: the widget to use as a label for the page-switch
3745 * menu, if that is enabled. If %NULL, and @tab_label
3746 * is a #GtkLabel or %NULL, then the menu label will be
3747 * a newly created label with the same text as @tab_label;
3748 * If @tab_label is not a #GtkLabel, @menu_label must be
3749 * specified if the page-switch menu is to be used.
3750 * @position: the index (starting at 0) at which to insert the page,
3751 * or -1 to append the page after all other pages.
3753 * Insert a page into @notebook at the given position, specifying
3754 * the widget to use as the label in the popup menu.
3757 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3759 GtkWidget *tab_label,
3760 GtkWidget *menu_label,
3763 GtkNotebookPage *page;
3766 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3767 g_return_if_fail (GTK_IS_WIDGET (child));
3768 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3769 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3771 gtk_widget_freeze_child_notify (child);
3773 page = g_new (GtkNotebookPage, 1);
3774 page->child = child;
3775 page->requisition.width = 0;
3776 page->requisition.height = 0;
3777 page->allocation.x = 0;
3778 page->allocation.y = 0;
3779 page->allocation.width = 0;
3780 page->allocation.height = 0;
3781 page->default_menu = FALSE;
3782 page->default_tab = FALSE;
3783 page->mnemonic_activate_signal = 0;
3785 nchildren = g_list_length (notebook->children);
3786 if ((position < 0) || (position > nchildren))
3787 position = nchildren;
3789 notebook->children = g_list_insert (notebook->children, page, position);
3793 page->default_tab = TRUE;
3794 if (notebook->show_tabs)
3795 tab_label = gtk_label_new ("");
3797 page->tab_label = tab_label;
3798 page->menu_label = menu_label;
3799 page->expand = FALSE;
3801 page->pack = GTK_PACK_START;
3804 page->default_menu = TRUE;
3807 gtk_widget_ref (page->menu_label);
3808 gtk_object_sink (GTK_OBJECT (page->menu_label));
3812 gtk_notebook_menu_item_create (notebook,
3813 g_list_find (notebook->children, page));
3815 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3817 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3819 gtk_notebook_update_labels (notebook);
3821 if (!notebook->first_tab)
3822 notebook->first_tab = notebook->children;
3824 if (!notebook->cur_page)
3825 gtk_widget_set_child_visible (child, TRUE);
3827 gtk_widget_set_child_visible (child, FALSE);
3831 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3832 gtk_widget_show (tab_label);
3834 gtk_widget_hide (tab_label);
3837 if (!notebook->cur_page)
3839 gtk_notebook_switch_page (notebook, page, 0);
3840 gtk_notebook_switch_focus_tab (notebook, NULL);
3844 page->mnemonic_activate_signal =
3845 gtk_signal_connect (GTK_OBJECT (tab_label),
3846 "mnemonic_activate",
3847 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
3850 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
3851 gdk_window_show_unraised (notebook->event_window);
3853 gtk_widget_child_notify (child, "tab_expand");
3854 gtk_widget_child_notify (child, "tab_fill");
3855 gtk_widget_child_notify (child, "tab_pack");
3856 gtk_widget_child_notify (child, "tab_label");
3857 gtk_widget_child_notify (child, "menu_label");
3858 gtk_widget_child_notify (child, "position");
3859 gtk_widget_thaw_child_notify (child);
3863 * gtk_notebook_remove_page:
3864 * @notebook: a #GtkNotebook.
3865 * @page_num: the index of a notebook page, starting
3866 * from 0. If -1, the last page will
3869 * Removes a page from the notebook given its index
3873 gtk_notebook_remove_page (GtkNotebook *notebook,
3878 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3882 list = g_list_nth (notebook->children, page_num);
3884 gtk_notebook_real_remove (notebook, list);
3888 list = g_list_last (notebook->children);
3890 gtk_notebook_real_remove (notebook, list);
3894 /* Public GtkNotebook Page Switch Methods :
3895 * gtk_notebook_get_current_page
3896 * gtk_notebook_page_num
3897 * gtk_notebook_set_current_page
3898 * gtk_notebook_next_page
3899 * gtk_notebook_prev_page
3902 * gtk_notebook_get_current_page:
3903 * @notebook: a #GtkNotebook
3905 * Returns the page number of the current page.
3907 * Return value: the index (starting from 0) of the current
3908 * page in the notebook. If the notebook has no pages, then
3909 * -1 will be returned.
3912 gtk_notebook_get_current_page (GtkNotebook *notebook)
3914 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3916 if (!notebook->cur_page)
3919 return g_list_index (notebook->children, notebook->cur_page);
3923 * gtk_notebook_get_nth_page:
3924 * @notebook: a #GtkNotebook
3925 * @page_num: the index of a page in the noteobok
3927 * Returns the child widget contained in page number @page_num.
3929 * Return value: the child widget, or %NULL if @page_num is
3933 gtk_notebook_get_nth_page (GtkNotebook *notebook,
3936 GtkNotebookPage *page;
3938 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3940 page = g_list_nth_data (notebook->children, page_num);
3949 * gtk_notebook_page_num:
3950 * @notebook: a #GtkNotebook
3951 * @child: a #GtkWidget
3953 * Finds the index of the page which contains the given child
3956 * Return value: the index of the page containing @child, or
3957 * -1 if @child is not in the notebook.
3960 gtk_notebook_page_num (GtkNotebook *notebook,
3966 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3969 children = notebook->children;
3972 GtkNotebookPage *page = children->data;
3974 if (page->child == child)
3977 children = children->next;
3985 * gtk_notebook_set_current_page:
3986 * @notebook: a #GtkNotebook
3987 * @page_num: index of the page to switch to, starting from 0.
3988 * If negative, or greater than the number of pages
3989 * in the notebook the last page will be used.
3991 * Switches to the page number @page_num.
3994 gtk_notebook_set_current_page (GtkNotebook *notebook,
3999 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4002 list = g_list_nth (notebook->children, page_num);
4004 list = g_list_last (notebook->children);
4006 page_num = g_list_index (notebook->children, list);
4009 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4013 * gtk_notebook_next_page:
4014 * @notebook: a #GtkNotebook
4016 * Switches to the next page. Nothing happens if the current page is
4020 gtk_notebook_next_page (GtkNotebook *notebook)
4024 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4026 list = g_list_find (notebook->children, notebook->cur_page);
4030 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4034 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4038 * gtk_notebook_prev_page:
4039 * @notebook: a #GtkNotebook
4041 * Switches to the previous page. Nothing happens if the current page
4042 * is the first page.
4045 gtk_notebook_prev_page (GtkNotebook *notebook)
4049 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4051 list = g_list_find (notebook->children, notebook->cur_page);
4055 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4059 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4062 /* Public GtkNotebook/Tab Style Functions
4064 * gtk_notebook_set_show_border
4065 * gtk_notebook_set_show_tabs
4066 * gtk_notebook_set_tab_pos
4067 * gtk_notebook_set_homogeneous_tabs
4068 * gtk_notebook_set_tab_border
4069 * gtk_notebook_set_tab_hborder
4070 * gtk_notebook_set_tab_vborder
4071 * gtk_notebook_set_scrollable
4074 * gtk_notebook_set_show_border:
4075 * @notebook: a #GtkNotebook
4076 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4078 * Sets whether a bevel will be drawn around the notebook pages.
4079 * this is only has an effect when the tabs are not shown.
4080 * See gtk_notebook_set_show_tabs().
4083 gtk_notebook_set_show_border (GtkNotebook *notebook,
4084 gboolean show_border)
4086 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4088 if (notebook->show_border != show_border)
4090 notebook->show_border = show_border;
4092 if (GTK_WIDGET_VISIBLE (notebook))
4093 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4095 g_object_notify (G_OBJECT (notebook), "show_border");
4100 * gtk_notebook_get_show_border:
4101 * @notebook: a #GtkNotebook
4103 * Returns whether a bevel will be drawn around the notebook pages. See
4104 * gtk_notebook_set_show_border().
4106 * Return value: %TRUE if the bevel is drawn
4109 gtk_notebook_get_show_border (GtkNotebook *notebook)
4111 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4113 return notebook->show_border;
4117 * gtk_notebook_set_show_tabs:
4118 * @notebook: a #GtkNotebook
4119 * @show_tabs: %TRUE if the tabs should be shown.
4121 * Sets whether to show the tabs for the notebook or not.
4124 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4127 GtkNotebookPage *page;
4130 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4132 show_tabs = show_tabs != FALSE;
4134 if (notebook->show_tabs == show_tabs)
4137 notebook->show_tabs = show_tabs;
4138 children = notebook->children;
4142 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4146 page = children->data;
4147 children = children->next;
4148 if (page->default_tab)
4150 gtk_widget_destroy (page->tab_label);
4151 page->tab_label = NULL;
4154 gtk_widget_hide (page->tab_label);
4159 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4160 gtk_notebook_update_labels (notebook);
4162 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4164 g_object_notify (G_OBJECT (notebook), "show_tabs");
4168 * gtk_notebook_get_show_tabs:
4169 * @notebook: a #GtkNotebook
4171 * Returns whether the tabs of the notebook are shown. See
4172 * gtk_notebook_set_show_tabs().
4174 * Return value: %TRUE if the tabs are shown
4177 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4179 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4181 return notebook->show_tabs;
4185 * gtk_notebook_set_tab_pos:
4186 * @notebook: a #GtkNotebook.
4187 * @pos: the edge to draw the tabs at.
4189 * Sets the edge at which the tabs for switching pages in the
4190 * notebook are drawn.
4193 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4194 GtkPositionType pos)
4196 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4198 if (notebook->tab_pos != pos)
4200 notebook->tab_pos = pos;
4201 if (GTK_WIDGET_VISIBLE (notebook))
4202 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4205 g_object_notify (G_OBJECT (notebook), "tab_pos");
4209 * gtk_notebook_get_tab_pos:
4210 * @notebook: a #GtkNotebook
4212 * Gets the edge at which the tabs for switching pages in the
4213 * notebook are drawn.
4215 * Return value: the edge at which the tabs are drawn
4218 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4220 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4222 return notebook->tab_pos;
4226 * gtk_notebook_set_homogeneous_tabs:
4227 * @notebook: a #GtkNotebook
4228 * @homogeneous: %TRUE if all tabs should be the same size.
4230 * Sets whether the tabs must have all the same size or not.
4233 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4234 gboolean homogeneous)
4236 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4238 if (homogeneous == notebook->homogeneous)
4241 notebook->homogeneous = homogeneous;
4242 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4244 g_object_notify (G_OBJECT (notebook), "homogeneous");
4248 * gtk_notebook_set_tab_border:
4249 * @notebook: a #GtkNotebook
4250 * @border_width: width of the border around the tab labels.
4252 * Sets the width the border around the tab labels
4253 * in a notebook. This is equivalent to calling
4254 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4255 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4258 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4261 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4263 notebook->tab_hborder = border_width;
4264 notebook->tab_vborder = border_width;
4266 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4267 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4269 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4273 * gtk_notebook_set_tab_hborder:
4274 * @notebook: a #GtkNotebook
4275 * @tab_hborder: width of the horizontal border of tab labels.
4277 * Sets the width of the horizontal border of tab labels.
4280 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4283 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4285 if (notebook->tab_hborder == tab_hborder)
4288 notebook->tab_hborder = tab_hborder;
4290 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4291 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4293 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4297 * gtk_notebook_set_tab_vborder:
4298 * @notebook: a #GtkNotebook
4299 * @tab_vborder: width of the vertical border of tab labels.
4301 * Sets the width of the vertical border of tab labels.
4304 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4307 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4309 if (notebook->tab_vborder == tab_vborder)
4312 notebook->tab_vborder = tab_vborder;
4314 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4315 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4319 * gtk_notebook_set_scrollable:
4320 * @notebook: a #GtkNotebook
4321 * @scrollable: %TRUE if scroll arrows should be added
4323 * Sets whether the tab label area will have arrows for scrolling if
4324 * there are too many tabs to fit in the area.
4327 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4328 gboolean scrollable)
4330 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4332 scrollable = (scrollable != FALSE);
4334 if (scrollable != notebook->scrollable)
4336 notebook->scrollable = scrollable;
4338 if (GTK_WIDGET_VISIBLE (notebook))
4339 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4341 g_object_notify (G_OBJECT (notebook), "scrollable");
4346 * gtk_notebook_get_scrollable:
4347 * @notebook: a #GtkNotebook
4349 * Returns whether the tab label area has arrows for scrolling. See
4350 * gtk_notebook_set_scrollable().
4352 * Return value: %TRUE if arrows for scrolling are present
4355 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4357 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4359 return notebook->scrollable;
4362 /* Public GtkNotebook Popup Menu Methods:
4364 * gtk_notebook_popup_enable
4365 * gtk_notebook_popup_disable
4370 * gtk_notebook_popup_enable:
4371 * @notebook: a #GtkNotebook
4373 * Enables the popup menu: if the user clicks with the right mouse button on
4374 * the bookmarks, a menu with all the pages will be popped up.
4377 gtk_notebook_popup_enable (GtkNotebook *notebook)
4381 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4386 notebook->menu = gtk_menu_new ();
4387 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4389 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4390 gtk_notebook_menu_item_create (notebook, list);
4392 gtk_notebook_update_labels (notebook);
4393 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4394 GTK_WIDGET (notebook),
4395 gtk_notebook_menu_detacher);
4397 g_object_notify (G_OBJECT (notebook), "enable_popup");
4401 * gtk_notebook_popup_disable:
4402 * @notebook: a #GtkNotebook
4404 * Disables the popup menu.
4407 gtk_notebook_popup_disable (GtkNotebook *notebook)
4409 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4411 if (!notebook->menu)
4414 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4415 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4416 gtk_widget_destroy (notebook->menu);
4418 g_object_notify (G_OBJECT (notebook), "enable_popup");
4421 /* Public GtkNotebook Page Properties Functions:
4423 * gtk_notebook_get_tab_label
4424 * gtk_notebook_set_tab_label
4425 * gtk_notebook_set_tab_label_text
4426 * gtk_notebook_get_menu_label
4427 * gtk_notebook_set_menu_label
4428 * gtk_notebook_set_menu_label_text
4429 * gtk_notebook_set_tab_label_packing
4430 * gtk_notebook_query_tab_label_packing
4434 * gtk_notebook_get_tab_label:
4435 * @notebook: a #GtkNotebook
4438 * Returns the tab label widget for the page @child. %NULL is returned
4439 * if @child is not in @notebook or if no tab label has specifically
4440 * been set for @child.
4442 * Return value: the tab label
4445 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4450 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4451 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4453 list = CHECK_FIND_CHILD (notebook, child);
4457 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4460 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4464 * gtk_notebook_set_tab_label:
4465 * @notebook: a #GtkNotebook
4467 * @tab_label: the tab label widget to use, or %NULL for default tab
4470 * Changes the tab label for @child. If %NULL is specified
4471 * for @tab_label, then the page will have the label 'page N'.
4474 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4476 GtkWidget *tab_label)
4478 GtkNotebookPage *page;
4481 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4482 g_return_if_fail (GTK_IS_WIDGET (child));
4484 list = CHECK_FIND_CHILD (notebook, child);
4488 /* a NULL pointer indicates a default_tab setting, otherwise
4489 * we need to set the associated label
4493 if (page->tab_label == tab_label)
4496 gtk_notebook_remove_tab_label (notebook, page);
4500 page->default_tab = FALSE;
4501 page->tab_label = tab_label;
4502 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4506 page->default_tab = TRUE;
4507 page->tab_label = NULL;
4509 if (notebook->show_tabs)
4513 g_snprintf (string, sizeof(string), _("Page %u"),
4514 gtk_notebook_real_page_position (notebook, list));
4515 page->tab_label = gtk_label_new (string);
4516 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4520 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4522 gtk_widget_show (page->tab_label);
4523 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4525 gtk_widget_child_notify (child, "tab_label");
4529 * gtk_notebook_set_tab_label_text:
4530 * @notebook: a #GtkNotebook
4532 * @tab_text: the label text
4534 * Creates a new label and sets it as the tab label for the page
4535 * containing @child.
4538 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4540 const gchar *tab_text)
4542 GtkWidget *tab_label = NULL;
4544 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4547 tab_label = gtk_label_new (tab_text);
4548 gtk_notebook_set_tab_label (notebook, child, tab_label);
4549 gtk_widget_child_notify (child, "tab_label");
4553 * gtk_notebook_get_tab_label_text:
4554 * @notebook: a #GtkNotebook
4555 * @child: a widget contained in a page of @notebook
4557 * Retrieves the text of the tab label for the page containing
4560 * Returns value: the text of the tab label, or %NULL if the
4561 * tab label widget is not a #GtkLabel. The
4562 * string is owned by the widget and must not
4565 G_CONST_RETURN gchar *
4566 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4569 GtkWidget *tab_label;
4571 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4572 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4574 tab_label = gtk_notebook_get_tab_label (notebook, child);
4576 if (tab_label && GTK_IS_LABEL (tab_label))
4577 return gtk_label_get_text (GTK_LABEL (tab_label));
4583 * gtk_notebook_get_menu_label:
4584 * @notebook: a #GtkNotebook
4585 * @child: a widget contained in a page of @notebook
4587 * Retrieves the menu label widget of the page containing @child.
4589 * Return value: the menu label, or %NULL if the
4590 * notebook page does not have a menu label other
4591 * than the default (the tab label).
4594 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4599 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4600 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4602 list = CHECK_FIND_CHILD (notebook, child);
4606 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4609 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4613 * gtk_notebook_set_menu_label:
4614 * @notebook: a #GtkNotebook
4615 * @child: the child widget
4616 * @menu_label: the menu label, or NULL for default
4618 * Changes the menu label for the page containing @child.
4621 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4623 GtkWidget *menu_label)
4625 GtkNotebookPage *page;
4628 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4629 g_return_if_fail (GTK_IS_WIDGET (child));
4631 list = CHECK_FIND_CHILD (notebook, child);
4636 if (page->menu_label)
4639 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4640 page->menu_label->parent);
4642 if (!page->default_menu)
4643 gtk_widget_unref (page->menu_label);
4648 page->menu_label = menu_label;
4649 gtk_widget_ref (page->menu_label);
4650 gtk_object_sink (GTK_OBJECT(page->menu_label));
4651 page->default_menu = FALSE;
4654 page->default_menu = TRUE;
4657 gtk_notebook_menu_item_create (notebook, list);
4658 gtk_widget_child_notify (child, "menu_label");
4662 * gtk_notebook_set_menu_label_text:
4663 * @notebook: a #GtkNotebook
4664 * @child: the child widget
4665 * @menu_text: the label text
4667 * Creates a new label and sets it as the menu label of @child.
4670 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4672 const gchar *menu_text)
4674 GtkWidget *menu_label = NULL;
4676 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4679 menu_label = gtk_label_new (menu_text);
4680 gtk_notebook_set_menu_label (notebook, child, menu_label);
4681 gtk_widget_child_notify (child, "menu_label");
4685 * gtk_notebook_get_menu_label_text:
4686 * @notebook: a #GtkNotebook
4687 * @child: the child widget of a page of the notebook.
4689 * Retrieves the text of the menu label for the page containing
4692 * Returns value: the text of the tab label, or %NULL if the
4693 * widget does not have a menu label other than
4694 * the default menu label, or the menu label widget
4695 * is not a #GtkLabel. The string is owned by
4696 * the widget and must not be freed.
4698 G_CONST_RETURN gchar *
4699 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4702 GtkWidget *menu_label;
4704 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4705 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4707 menu_label = gtk_notebook_get_menu_label (notebook, child);
4709 if (menu_label && GTK_IS_LABEL (menu_label))
4710 return gtk_label_get_text (GTK_LABEL (menu_label));
4715 /* Helper function called when pages are reordered
4718 gtk_notebook_child_reordered (GtkNotebook *notebook,
4719 GtkNotebookPage *page)
4723 GtkWidget *menu_item;
4725 menu_item = page->menu_label->parent;
4726 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4727 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4728 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4731 gtk_notebook_update_labels (notebook);
4735 * gtk_notebook_set_tab_label_packing:
4736 * @notebook: a #GtkNotebook
4737 * @child: the child widget
4738 * @expand: whether to expand the bookmark or not
4739 * @fill: whether the bookmark should fill the allocated area or not
4740 * @pack_type: the position of the bookmark
4742 * Sets the packing parameters for the tab label of the page
4743 * containing @child. See gtk_box_pack_start() for the exact meaning
4744 * of the parameters.
4747 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4751 GtkPackType pack_type)
4753 GtkNotebookPage *page;
4756 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4757 g_return_if_fail (GTK_IS_WIDGET (child));
4759 list = CHECK_FIND_CHILD (notebook, child);
4764 expand = expand != FALSE;
4765 fill = fill != FALSE;
4766 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4769 gtk_widget_freeze_child_notify (child);
4770 page->expand = expand;
4771 gtk_widget_child_notify (child, "tab_expand");
4773 gtk_widget_child_notify (child, "tab_fill");
4774 if (page->pack != pack_type)
4776 page->pack = pack_type;
4777 gtk_notebook_child_reordered (notebook, page);
4779 gtk_widget_child_notify (child, "tab_pack");
4780 gtk_widget_child_notify (child, "position");
4781 if (notebook->show_tabs)
4782 gtk_notebook_pages_allocate (notebook);
4783 gtk_widget_thaw_child_notify (child);
4787 * gtk_notebook_query_tab_label_packing:
4788 * @notebook: a #GtkNotebook
4790 * @expand: location to store the expand value (or NULL)
4791 * @fill: location to store the fill value (or NULL)
4792 * @pack_type: location to store the pack_type (or NULL)
4794 * Query the packing attributes for the tab label of the page
4795 * containing @child.
4798 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4802 GtkPackType *pack_type)
4806 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4807 g_return_if_fail (GTK_IS_WIDGET (child));
4809 list = CHECK_FIND_CHILD (notebook, child);
4814 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
4816 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
4818 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
4822 * gtk_notebook_reorder_child:
4823 * @notebook: a #GtkNotebook
4824 * @child: the child to move
4825 * @position: the new position
4827 * Reorders the page containing @child, so that it appears in position
4828 * @position. Out of bounds @position will be clamped.
4831 gtk_notebook_reorder_child (GtkNotebook *notebook,
4835 GList *list, *new_list;
4836 GtkNotebookPage *page;
4839 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4840 g_return_if_fail (GTK_IS_WIDGET (child));
4842 list = CHECK_FIND_CHILD (notebook, child);
4846 old_pos = g_list_position (notebook->children, list);
4848 if (old_pos == position)
4852 notebook->children = g_list_delete_link (notebook->children, list);
4854 position = CLAMP (position, 0, g_list_length (notebook->children));
4856 notebook->children = g_list_insert (notebook->children, page, position);
4857 new_list = g_list_nth (notebook->children, position);
4859 /* Fix up GList references in GtkNotebook structure */
4860 if (notebook->first_tab == list)
4861 notebook->first_tab = new_list;
4862 if (notebook->focus_tab == list)
4863 notebook->focus_tab = new_list;
4865 gtk_widget_freeze_child_notify (child);
4867 /* Move around the menu items if necesary */
4868 gtk_notebook_child_reordered (notebook, page);
4869 gtk_widget_child_notify (child, "tab_pack");
4870 gtk_widget_child_notify (child, "position");
4872 if (notebook->show_tabs)
4873 gtk_notebook_pages_allocate (notebook);
4875 gtk_widget_thaw_child_notify (child);