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
44 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
45 #define NOTEBOOK_SCROLL_DELAY (100)
78 CHILD_PROP_MENU_LABEL,
80 CHILD_PROP_TAB_EXPAND,
85 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
87 struct _GtkNotebookPage
91 GtkWidget *menu_label;
93 guint default_menu : 1; /* If true, we create the menu label ourself */
94 guint default_tab : 1; /* If true, we create the tab label ourself */
99 GtkRequisition requisition;
100 GtkAllocation allocation;
102 guint mnemonic_activate_signal;
105 #ifdef G_DISABLE_CHECKS
106 #define CHECK_FIND_CHILD(notebook, child) \
107 gtk_notebook_find_child (notebook, child, G_STRLOC)
109 #define CHECK_FIND_CHILD(notebook, child) \
110 gtk_notebook_find_child (notebook, child, NULL)
113 /*** GtkNotebook Methods ***/
114 static void gtk_notebook_class_init (GtkNotebookClass *klass);
115 static void gtk_notebook_init (GtkNotebook *notebook);
117 static void gtk_notebook_select_page (GtkNotebook *notebook,
118 gboolean move_focus);
119 static void gtk_notebook_focus_tab (GtkNotebook *notebook,
120 GtkNotebookTab type);
121 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
125 /*** GtkObject Methods ***/
126 static void gtk_notebook_destroy (GtkObject *object);
127 static void gtk_notebook_set_property (GObject *object,
131 static void gtk_notebook_get_property (GObject *object,
136 /*** GtkWidget Methods ***/
137 static void gtk_notebook_map (GtkWidget *widget);
138 static void gtk_notebook_unmap (GtkWidget *widget);
139 static void gtk_notebook_realize (GtkWidget *widget);
140 static void gtk_notebook_unrealize (GtkWidget *widget);
141 static void gtk_notebook_size_request (GtkWidget *widget,
142 GtkRequisition *requisition);
143 static void gtk_notebook_size_allocate (GtkWidget *widget,
144 GtkAllocation *allocation);
145 static gint gtk_notebook_expose (GtkWidget *widget,
146 GdkEventExpose *event);
147 static gint gtk_notebook_button_press (GtkWidget *widget,
148 GdkEventButton *event);
149 static gint gtk_notebook_button_release (GtkWidget *widget,
150 GdkEventButton *event);
151 static gint gtk_notebook_enter_notify (GtkWidget *widget,
152 GdkEventCrossing *event);
153 static gint gtk_notebook_leave_notify (GtkWidget *widget,
154 GdkEventCrossing *event);
155 static gint gtk_notebook_motion_notify (GtkWidget *widget,
156 GdkEventMotion *event);
157 static gint gtk_notebook_focus_in (GtkWidget *widget,
158 GdkEventFocus *event);
159 static void gtk_notebook_draw_focus (GtkWidget *widget);
160 static gint gtk_notebook_focus (GtkWidget *widget,
161 GtkDirectionType direction);
163 /*** GtkContainer Methods ***/
164 static void gtk_notebook_set_child_property (GtkContainer *container,
169 static void gtk_notebook_get_child_property (GtkContainer *container,
174 static void gtk_notebook_add (GtkContainer *container,
176 static void gtk_notebook_remove (GtkContainer *container,
178 static void gtk_notebook_set_focus_child (GtkContainer *container,
180 static GtkType gtk_notebook_child_type (GtkContainer *container);
181 static void gtk_notebook_forall (GtkContainer *container,
182 gboolean include_internals,
183 GtkCallback callback,
184 gpointer callback_data);
186 /*** GtkNotebook Private Functions ***/
187 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
188 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
189 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
190 GtkNotebookPage *old_page);
191 static void gtk_notebook_real_remove (GtkNotebook *notebook,
193 static void gtk_notebook_update_labels (GtkNotebook *notebook);
194 static gint gtk_notebook_timer (GtkNotebook *notebook);
195 static gint gtk_notebook_page_compare (gconstpointer a,
197 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
199 const gchar *function);
200 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
202 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
205 gboolean find_visible);
207 /*** GtkNotebook Drawing Functions ***/
208 static void gtk_notebook_paint (GtkWidget *widget,
210 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
211 GtkNotebookPage *page,
213 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
216 /*** GtkNotebook Size Allocate Functions ***/
217 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
218 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
219 GtkNotebookPage *page,
220 GtkAllocation *allocation);
221 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
227 /*** GtkNotebook Page Switch Methods ***/
228 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
229 GtkNotebookPage *page,
232 /*** GtkNotebook Page Switch Functions ***/
233 static void gtk_notebook_switch_page (GtkNotebook *notebook,
234 GtkNotebookPage *page,
236 static gint gtk_notebook_page_select (GtkNotebook *notebook,
237 gboolean move_focus);
238 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
240 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
241 GtkNotebookPage *page);
243 /*** GtkNotebook Menu Functions ***/
244 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
246 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
248 static void gtk_notebook_menu_detacher (GtkWidget *widget,
252 static GtkContainerClass *parent_class = NULL;
253 static guint notebook_signals[LAST_SIGNAL] = { 0 };
256 gtk_notebook_get_type (void)
258 static GtkType notebook_type = 0;
262 static const GtkTypeInfo notebook_info =
265 sizeof (GtkNotebook),
266 sizeof (GtkNotebookClass),
267 (GtkClassInitFunc) gtk_notebook_class_init,
268 (GtkObjectInitFunc) gtk_notebook_init,
269 /* reserved_1 */ NULL,
270 /* reserved_2 */ NULL,
271 (GtkClassInitFunc) NULL,
274 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
277 return notebook_type;
281 gtk_notebook_class_init (GtkNotebookClass *class)
283 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
284 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
285 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
286 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
287 GtkBindingSet *binding_set;
289 parent_class = g_type_class_peek_parent (class);
291 gobject_class->set_property = gtk_notebook_set_property;
292 gobject_class->get_property = gtk_notebook_get_property;
293 object_class->destroy = gtk_notebook_destroy;
295 widget_class->map = gtk_notebook_map;
296 widget_class->unmap = gtk_notebook_unmap;
297 widget_class->realize = gtk_notebook_realize;
298 widget_class->unrealize = gtk_notebook_unrealize;
299 widget_class->size_request = gtk_notebook_size_request;
300 widget_class->size_allocate = gtk_notebook_size_allocate;
301 widget_class->expose_event = gtk_notebook_expose;
302 widget_class->button_press_event = gtk_notebook_button_press;
303 widget_class->button_release_event = gtk_notebook_button_release;
304 widget_class->enter_notify_event = gtk_notebook_enter_notify;
305 widget_class->leave_notify_event = gtk_notebook_leave_notify;
306 widget_class->motion_notify_event = gtk_notebook_motion_notify;
307 widget_class->focus_in_event = gtk_notebook_focus_in;
308 widget_class->focus = gtk_notebook_focus;
310 container_class->add = gtk_notebook_add;
311 container_class->remove = gtk_notebook_remove;
312 container_class->forall = gtk_notebook_forall;
313 container_class->set_focus_child = gtk_notebook_set_focus_child;
314 container_class->get_child_property = gtk_notebook_get_child_property;
315 container_class->set_child_property = gtk_notebook_set_child_property;
316 container_class->child_type = gtk_notebook_child_type;
318 class->switch_page = gtk_notebook_real_switch_page;
320 class->focus_tab = gtk_notebook_focus_tab;
321 class->select_page = gtk_notebook_select_page;
322 class->change_current_page = gtk_notebook_change_current_page;
324 g_object_class_install_property (gobject_class,
326 g_param_spec_int ("page",
328 _("The index of the current page"),
333 g_object_class_install_property (gobject_class,
335 g_param_spec_enum ("tab_pos",
337 _("Which side of the notebook holds the tabs"),
338 GTK_TYPE_POSITION_TYPE,
341 g_object_class_install_property (gobject_class,
343 g_param_spec_uint ("tab_border",
345 _("Width of the border around the tab labels"),
350 g_object_class_install_property (gobject_class,
352 g_param_spec_uint ("tab_hborder",
353 _("Horizontal Tab Border"),
354 _("Width of the horizontal border of tab labels"),
359 g_object_class_install_property (gobject_class,
361 g_param_spec_uint ("tab_vborder",
362 _("Vertical Tab Border"),
363 _("Width of the vertical border of tab labels"),
368 g_object_class_install_property (gobject_class,
370 g_param_spec_boolean ("show_tabs",
372 _("Whether tabs should be shown or not"),
375 g_object_class_install_property (gobject_class,
377 g_param_spec_boolean ("show_border",
379 _("Whether the border should be shown or not"),
382 g_object_class_install_property (gobject_class,
384 g_param_spec_boolean ("scrollable",
386 _("If TRUE, scroll arrows are added if there are to many tabs to fit"),
389 g_object_class_install_property (gobject_class,
391 g_param_spec_boolean ("enable_popup",
393 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
396 g_object_class_install_property (gobject_class,
398 g_param_spec_boolean ("homogeneous",
400 _("Whether tabs should have homogeneous sizes"),
404 gtk_container_class_install_child_property (container_class,
405 CHILD_PROP_TAB_LABEL,
406 g_param_spec_string ("tab_label", NULL, NULL,
409 gtk_container_class_install_child_property (container_class,
410 CHILD_PROP_MENU_LABEL,
411 g_param_spec_string ("menu_label", NULL, NULL,
414 gtk_container_class_install_child_property (container_class,
416 g_param_spec_int ("position", NULL, NULL,
419 gtk_container_class_install_child_property (container_class,
420 CHILD_PROP_TAB_EXPAND,
421 g_param_spec_boolean ("tab_expand", NULL, NULL,
424 gtk_container_class_install_child_property (container_class,
426 g_param_spec_boolean ("tab_fill", NULL, NULL,
429 gtk_container_class_install_child_property (container_class,
431 g_param_spec_enum ("tab_pack", NULL, NULL,
432 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
435 notebook_signals[SWITCH_PAGE] =
436 gtk_signal_new ("switch_page",
438 GTK_CLASS_TYPE (object_class),
439 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
440 _gtk_marshal_VOID__POINTER_UINT,
444 notebook_signals[FOCUS_TAB] =
445 g_signal_new ("focus_tab",
446 G_TYPE_FROM_CLASS (object_class),
447 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
448 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
450 _gtk_marshal_VOID__ENUM,
452 GTK_TYPE_NOTEBOOK_TAB);
453 notebook_signals[SELECT_PAGE] =
454 g_signal_new ("select_page",
455 G_TYPE_FROM_CLASS (object_class),
456 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
457 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
459 _gtk_marshal_VOID__BOOLEAN,
462 notebook_signals[CHANGE_CURRENT_PAGE] =
463 g_signal_new ("change_current_page",
464 G_TYPE_FROM_CLASS (object_class),
465 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
466 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
468 gtk_marshal_VOID__INT,
472 binding_set = gtk_binding_set_by_class (object_class);
473 gtk_binding_entry_add_signal (binding_set,
476 G_TYPE_BOOLEAN, TRUE);
477 gtk_binding_entry_add_signal (binding_set,
480 G_TYPE_BOOLEAN, TRUE);
481 gtk_binding_entry_add_signal (binding_set,
484 G_TYPE_BOOLEAN, FALSE);
485 gtk_binding_entry_add_signal (binding_set,
488 G_TYPE_BOOLEAN, FALSE);
490 gtk_binding_entry_add_signal (binding_set,
493 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
494 gtk_binding_entry_add_signal (binding_set,
497 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
498 gtk_binding_entry_add_signal (binding_set,
501 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
502 gtk_binding_entry_add_signal (binding_set,
505 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
507 gtk_binding_entry_add_signal (binding_set,
508 GDK_Page_Up, GDK_CONTROL_MASK,
509 "change_current_page", 1,
511 gtk_binding_entry_add_signal (binding_set,
512 GDK_Page_Down, GDK_CONTROL_MASK,
513 "change_current_page", 1,
518 gtk_notebook_init (GtkNotebook *notebook)
520 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
521 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
523 notebook->cur_page = NULL;
524 notebook->children = NULL;
525 notebook->first_tab = NULL;
526 notebook->focus_tab = NULL;
527 notebook->event_window = NULL;
528 notebook->menu = NULL;
530 notebook->tab_hborder = 2;
531 notebook->tab_vborder = 2;
533 notebook->show_tabs = TRUE;
534 notebook->show_border = TRUE;
535 notebook->tab_pos = GTK_POS_TOP;
536 notebook->scrollable = FALSE;
537 notebook->in_child = 0;
538 notebook->click_child = 0;
539 notebook->button = 0;
540 notebook->need_timer = 0;
541 notebook->child_has_focus = FALSE;
542 notebook->have_visible_child = FALSE;
546 gtk_notebook_select_page (GtkNotebook *notebook,
549 gtk_notebook_page_select (notebook, move_focus);
553 gtk_notebook_focus_tab (GtkNotebook *notebook,
560 case GTK_NOTEBOOK_TAB_FIRST:
561 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
563 gtk_notebook_switch_focus_tab (notebook, list);
565 case GTK_NOTEBOOK_TAB_LAST:
566 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
568 gtk_notebook_switch_focus_tab (notebook, list);
574 gtk_notebook_change_current_page (GtkNotebook *notebook,
577 GList *current = NULL;
579 if (notebook->cur_page)
580 current = g_list_find (notebook->children, notebook->cur_page);
584 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
585 offset += offset < 0 ? 1 : -1;
589 gtk_notebook_switch_page (notebook, current->data, -1);
595 * Creates a new #GtkNotebook widget with no pages.
597 * Return value: the newly created #GtkNotebook
600 gtk_notebook_new (void)
602 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
605 /* Private GtkObject Methods :
607 * gtk_notebook_destroy
608 * gtk_notebook_set_arg
609 * gtk_notebook_get_arg
612 gtk_notebook_destroy (GtkObject *object)
614 GtkNotebook *notebook = GTK_NOTEBOOK (object);
617 gtk_notebook_popup_disable (notebook);
619 GTK_OBJECT_CLASS (parent_class)->destroy (object);
623 gtk_notebook_set_property (GObject *object,
628 GtkNotebook *notebook;
630 notebook = GTK_NOTEBOOK (object);
635 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
637 case PROP_SHOW_BORDER:
638 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
640 case PROP_SCROLLABLE:
641 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
643 case PROP_ENABLE_POPUP:
644 if (g_value_get_boolean (value))
645 gtk_notebook_popup_enable (notebook);
647 gtk_notebook_popup_disable (notebook);
649 case PROP_HOMOGENEOUS:
650 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
653 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
656 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
658 case PROP_TAB_BORDER:
659 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
661 case PROP_TAB_HBORDER:
662 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
664 case PROP_TAB_VBORDER:
665 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
673 gtk_notebook_get_property (GObject *object,
678 GtkNotebook *notebook;
680 notebook = GTK_NOTEBOOK (object);
685 g_value_set_boolean (value, notebook->show_tabs);
687 case PROP_SHOW_BORDER:
688 g_value_set_boolean (value, notebook->show_border);
690 case PROP_SCROLLABLE:
691 g_value_set_boolean (value, notebook->scrollable);
693 case PROP_ENABLE_POPUP:
694 g_value_set_boolean (value, notebook->menu != NULL);
696 case PROP_HOMOGENEOUS:
697 g_value_set_boolean (value, notebook->homogeneous);
700 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
703 g_value_set_enum (value, notebook->tab_pos);
705 case PROP_TAB_HBORDER:
706 g_value_set_uint (value, notebook->tab_hborder);
708 case PROP_TAB_VBORDER:
709 g_value_set_uint (value, notebook->tab_vborder);
712 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
717 /* Private GtkWidget Methods :
721 * gtk_notebook_realize
722 * gtk_notebook_size_request
723 * gtk_notebook_size_allocate
724 * gtk_notebook_expose
725 * gtk_notebook_button_press
726 * gtk_notebook_button_release
727 * gtk_notebook_enter_notify
728 * gtk_notebook_leave_notify
729 * gtk_notebook_motion_notify
730 * gtk_notebook_focus_in
731 * gtk_notebook_focus_out
732 * gtk_notebook_draw_focus
733 * gtk_notebook_style_set
736 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
737 GdkRectangle *rectangle)
739 GtkWidget *widget = GTK_WIDGET (notebook);
740 gint border_width = GTK_CONTAINER (notebook)->border_width;
742 if (notebook->show_tabs && notebook->children)
746 GtkNotebookPage *page = notebook->children->data;
748 rectangle->x = widget->allocation.x + border_width;
749 rectangle->y = widget->allocation.y + border_width;
751 switch (notebook->tab_pos)
755 rectangle->width = widget->allocation.width - 2 * border_width;
756 rectangle->height = page->requisition.height;
757 if (notebook->tab_pos == GTK_POS_BOTTOM)
758 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
762 rectangle->width = page->requisition.width;
763 rectangle->height = widget->allocation.height - 2 * border_width;
764 if (notebook->tab_pos == GTK_POS_RIGHT)
765 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
776 rectangle->x = rectangle->y = 0;
777 rectangle->width = rectangle->height = 10;
785 gtk_notebook_map (GtkWidget *widget)
787 GtkNotebook *notebook;
788 GtkNotebookPage *page;
791 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
793 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
795 notebook = GTK_NOTEBOOK (widget);
797 if (notebook->cur_page &&
798 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
799 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
800 gtk_widget_map (notebook->cur_page->child);
802 if (notebook->scrollable)
803 gtk_notebook_pages_allocate (notebook);
806 children = notebook->children;
810 page = children->data;
811 children = children->next;
813 if (page->tab_label &&
814 GTK_WIDGET_VISIBLE (page->tab_label) &&
815 !GTK_WIDGET_MAPPED (page->tab_label))
816 gtk_widget_map (page->tab_label);
820 if (gtk_notebook_get_event_window_position (notebook, NULL))
821 gdk_window_show_unraised (notebook->event_window);
825 gtk_notebook_unmap (GtkWidget *widget)
827 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
829 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
831 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
833 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
837 gtk_notebook_realize (GtkWidget *widget)
839 GtkNotebook *notebook;
840 GdkWindowAttr attributes;
841 gint attributes_mask;
842 GdkRectangle event_window_pos;
844 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
846 notebook = GTK_NOTEBOOK (widget);
847 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
849 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
851 widget->window = gtk_widget_get_parent_window (widget);
852 gdk_window_ref (widget->window);
854 attributes.window_type = GDK_WINDOW_CHILD;
855 attributes.x = event_window_pos.x;
856 attributes.y = event_window_pos.y;
857 attributes.width = event_window_pos.width;
858 attributes.height = event_window_pos.height;
859 attributes.wclass = GDK_INPUT_ONLY;
860 attributes.event_mask = gtk_widget_get_events (widget);
861 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
862 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
864 attributes_mask = GDK_WA_X | GDK_WA_Y;
866 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
867 &attributes, attributes_mask);
868 gdk_window_set_user_data (notebook->event_window, notebook);
870 widget->style = gtk_style_attach (widget->style, widget->window);
874 gtk_notebook_unrealize (GtkWidget *widget)
876 GtkNotebook *notebook;
878 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
880 notebook = GTK_NOTEBOOK (widget);
882 gdk_window_set_user_data (notebook->event_window, NULL);
883 gdk_window_destroy (notebook->event_window);
884 notebook->event_window = NULL;
886 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
887 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
891 gtk_notebook_size_request (GtkWidget *widget,
892 GtkRequisition *requisition)
894 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
895 GtkNotebookPage *page;
897 GtkRequisition child_requisition;
898 gboolean switch_page = FALSE;
902 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
904 widget->requisition.width = 0;
905 widget->requisition.height = 0;
907 for (children = notebook->children, vis_pages = 0; children;
908 children = children->next)
910 page = children->data;
912 if (GTK_WIDGET_VISIBLE (page->child))
915 gtk_widget_size_request (page->child, &child_requisition);
917 widget->requisition.width = MAX (widget->requisition.width,
918 child_requisition.width);
919 widget->requisition.height = MAX (widget->requisition.height,
920 child_requisition.height);
922 if (notebook->menu && page->menu_label->parent &&
923 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
924 gtk_widget_show (page->menu_label->parent);
928 if (page == notebook->cur_page)
930 if (notebook->menu && page->menu_label->parent &&
931 GTK_WIDGET_VISIBLE (page->menu_label->parent))
932 gtk_widget_hide (page->menu_label->parent);
936 if (notebook->show_border || notebook->show_tabs)
938 widget->requisition.width += widget->style->xthickness * 2;
939 widget->requisition.height += widget->style->ythickness * 2;
941 if (notebook->show_tabs)
948 for (children = notebook->children; children;
949 children = children->next)
951 page = children->data;
953 if (GTK_WIDGET_VISIBLE (page->child))
955 if (!GTK_WIDGET_VISIBLE (page->tab_label))
956 gtk_widget_show (page->tab_label);
958 gtk_widget_size_request (page->tab_label,
961 page->requisition.width =
962 child_requisition.width +
963 2 * widget->style->xthickness;
964 page->requisition.height =
965 child_requisition.height +
966 2 * widget->style->ythickness;
968 switch (notebook->tab_pos)
972 page->requisition.height += 2 * (notebook->tab_vborder +
974 tab_height = MAX (tab_height, page->requisition.height);
975 tab_max = MAX (tab_max, page->requisition.width);
979 page->requisition.width += 2 * (notebook->tab_hborder +
981 tab_width = MAX (tab_width, page->requisition.width);
982 tab_max = MAX (tab_max, page->requisition.height);
986 else if (GTK_WIDGET_VISIBLE (page->tab_label))
987 gtk_widget_hide (page->tab_label);
990 children = notebook->children;
994 switch (notebook->tab_pos)
1001 if (notebook->scrollable && vis_pages > 1 &&
1002 widget->requisition.width < tab_width)
1003 tab_height = MAX (tab_height, ARROW_SIZE);
1005 padding = 2 * (TAB_CURVATURE + focus_width +
1006 notebook->tab_hborder) - TAB_OVERLAP;
1010 page = children->data;
1011 children = children->next;
1013 if (!GTK_WIDGET_VISIBLE (page->child))
1016 if (notebook->homogeneous)
1017 page->requisition.width = tab_max;
1019 page->requisition.width += padding;
1021 tab_width += page->requisition.width;
1022 page->requisition.height = tab_height;
1025 if (notebook->scrollable && vis_pages > 1 &&
1026 widget->requisition.width < tab_width)
1027 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1029 if (notebook->homogeneous && !notebook->scrollable)
1030 widget->requisition.width = MAX (widget->requisition.width,
1031 vis_pages * tab_max +
1034 widget->requisition.width = MAX (widget->requisition.width,
1035 tab_width + TAB_OVERLAP);
1037 widget->requisition.height += tab_height;
1044 if (notebook->scrollable && vis_pages > 1 &&
1045 widget->requisition.height < tab_height)
1046 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1048 padding = 2 * (TAB_CURVATURE + focus_width +
1049 notebook->tab_vborder) - TAB_OVERLAP;
1054 page = children->data;
1055 children = children->next;
1057 if (!GTK_WIDGET_VISIBLE (page->child))
1060 page->requisition.width = tab_width;
1062 if (notebook->homogeneous)
1063 page->requisition.height = tab_max;
1065 page->requisition.height += padding;
1067 tab_height += page->requisition.height;
1070 if (notebook->scrollable && vis_pages > 1 &&
1071 widget->requisition.height < tab_height)
1072 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1074 widget->requisition.width += tab_width;
1076 if (notebook->homogeneous && !notebook->scrollable)
1077 widget->requisition.height =
1078 MAX (widget->requisition.height,
1079 vis_pages * tab_max + TAB_OVERLAP);
1081 widget->requisition.height =
1082 MAX (widget->requisition.height,
1083 tab_height + TAB_OVERLAP);
1085 if (!notebook->homogeneous || notebook->scrollable)
1087 widget->requisition.height = MAX (widget->requisition.height,
1088 vis_pages * tab_max +
1096 for (children = notebook->children; children;
1097 children = children->next)
1099 page = children->data;
1101 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1102 gtk_widget_hide (page->tab_label);
1107 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1108 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1114 for (children = notebook->children; children;
1115 children = children->next)
1117 page = children->data;
1118 if (GTK_WIDGET_VISIBLE (page->child))
1120 gtk_notebook_switch_page (notebook, page, -1);
1125 else if (GTK_WIDGET_VISIBLE (widget))
1127 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1128 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1131 if (vis_pages && !notebook->cur_page)
1133 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1136 notebook->first_tab = children;
1137 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1143 gtk_notebook_size_allocate (GtkWidget *widget,
1144 GtkAllocation *allocation)
1146 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1148 widget->allocation = *allocation;
1149 if (GTK_WIDGET_REALIZED (widget))
1151 GdkRectangle position;
1153 if (gtk_notebook_get_event_window_position (notebook, &position))
1154 gdk_window_move_resize (notebook->event_window,
1155 position.x, position.y,
1156 position.width, position.height);
1159 if (notebook->children)
1161 gint border_width = GTK_CONTAINER (widget)->border_width;
1162 GtkNotebookPage *page;
1163 GtkAllocation child_allocation;
1166 child_allocation.x = widget->allocation.x + border_width;
1167 child_allocation.y = widget->allocation.y + border_width;
1168 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1169 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1171 if (notebook->show_tabs || notebook->show_border)
1173 child_allocation.x += widget->style->xthickness;
1174 child_allocation.y += widget->style->ythickness;
1175 child_allocation.width = MAX (1, child_allocation.width -
1176 widget->style->xthickness * 2);
1177 child_allocation.height = MAX (1, child_allocation.height -
1178 widget->style->ythickness * 2);
1180 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1182 switch (notebook->tab_pos)
1185 child_allocation.y += notebook->cur_page->requisition.height;
1186 case GTK_POS_BOTTOM:
1187 child_allocation.height =
1188 MAX (1, child_allocation.height -
1189 notebook->cur_page->requisition.height);
1192 child_allocation.x += notebook->cur_page->requisition.width;
1194 child_allocation.width =
1195 MAX (1, child_allocation.width -
1196 notebook->cur_page->requisition.width);
1202 children = notebook->children;
1205 page = children->data;
1206 children = children->next;
1208 if (GTK_WIDGET_VISIBLE (page->child))
1209 gtk_widget_size_allocate (page->child, &child_allocation);
1212 gtk_notebook_pages_allocate (notebook);
1217 gtk_notebook_expose (GtkWidget *widget,
1218 GdkEventExpose *event)
1220 GtkNotebook *notebook;
1221 GdkRectangle child_area;
1223 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1224 g_return_val_if_fail (event != NULL, FALSE);
1226 if (GTK_WIDGET_DRAWABLE (widget))
1228 notebook = GTK_NOTEBOOK (widget);
1230 gtk_notebook_paint (widget, &event->area);
1231 if (notebook->show_tabs)
1233 if (notebook->cur_page &&
1234 gtk_widget_intersect (notebook->cur_page->tab_label,
1235 &event->area, &child_area))
1236 gtk_notebook_draw_focus (widget);
1240 if (notebook->cur_page)
1241 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1242 notebook->cur_page->child,
1250 gtk_notebook_show_arrows (GtkNotebook *notebook)
1252 gboolean show_arrow = FALSE;
1255 if (!notebook->scrollable)
1258 children = notebook->children;
1261 GtkNotebookPage *page = children->data;
1263 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1266 children = children->next;
1273 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1274 GdkRectangle *rectangle)
1276 GdkRectangle event_window_pos;
1278 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1280 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1281 rectangle->height = ARROW_SIZE;
1283 switch (notebook->tab_pos)
1287 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1288 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1291 case GTK_POS_BOTTOM:
1292 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1293 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1300 gtk_notebook_get_arrow (GtkNotebook *notebook,
1304 GdkRectangle arrow_rect;
1305 GdkRectangle event_window_pos;
1307 if (gtk_notebook_show_arrows (notebook))
1309 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1310 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1315 if (y >= 0 && y < arrow_rect.height)
1317 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1318 return GTK_ARROW_LEFT;
1319 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1320 return GTK_ARROW_RIGHT;
1328 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1330 GdkEventButton *event)
1332 GtkWidget *widget = GTK_WIDGET (notebook);
1334 if (!GTK_WIDGET_HAS_FOCUS (widget))
1335 gtk_widget_grab_focus (widget);
1337 notebook->button = event->button;
1338 notebook->click_child = arrow;
1340 if (event->button == 1)
1342 GtkDirectionType dir;
1343 if (!notebook->focus_tab ||
1344 gtk_notebook_search_page (notebook, notebook->focus_tab,
1345 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1348 if (notebook->tab_pos == GTK_POS_LEFT ||
1349 notebook->tab_pos == GTK_POS_RIGHT)
1350 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1352 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1353 gtk_widget_child_focus (widget, dir);
1356 if (!notebook->timer)
1358 notebook->timer = gtk_timeout_add
1359 (NOTEBOOK_INIT_SCROLL_DELAY,
1360 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1361 notebook->need_timer = TRUE;
1364 else if (event->button == 2)
1365 gtk_notebook_page_select (notebook, TRUE);
1366 else if (event->button == 3)
1367 gtk_notebook_switch_focus_tab (notebook,
1368 gtk_notebook_search_page (notebook,
1370 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1372 gtk_notebook_redraw_arrows (notebook);
1378 get_widget_coordinates (GtkWidget *widget,
1383 GdkWindow *window = ((GdkEventAny *)event)->window;
1386 if (!gdk_event_get_coords (event, &tx, &ty))
1389 while (window && window != widget->window)
1391 gint window_x, window_y;
1393 gdk_window_get_position (window, &window_x, &window_y);
1397 window = gdk_window_get_parent (window);
1412 gtk_notebook_button_press (GtkWidget *widget,
1413 GdkEventButton *event)
1415 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1416 GtkNotebookPage *page;
1422 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1426 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1429 arrow = gtk_notebook_get_arrow (notebook, x, y);
1431 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1433 if (event->button == 3 && notebook->menu)
1435 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1436 NULL, NULL, 3, event->time);
1441 children = notebook->children;
1444 page = children->data;
1446 if (GTK_WIDGET_VISIBLE (page->child) &&
1447 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1448 (x >= page->allocation.x) &&
1449 (y >= page->allocation.y) &&
1450 (x <= (page->allocation.x + page->allocation.width)) &&
1451 (y <= (page->allocation.y + page->allocation.height)))
1453 if (page == notebook->cur_page && notebook->focus_tab &&
1454 notebook->focus_tab != children &&
1455 GTK_WIDGET_HAS_FOCUS (notebook))
1457 GtkNotebookPage *old_page;
1459 notebook->child_has_focus = FALSE;
1460 old_page = (GtkNotebookPage *)
1461 (notebook->focus_tab->data);
1462 gtk_notebook_switch_focus_tab (notebook, children);
1463 gtk_notebook_focus_changed (notebook, old_page);
1467 gtk_notebook_switch_focus_tab (notebook, children);
1468 gtk_widget_grab_focus (widget);
1469 gtk_notebook_switch_page (notebook, page, num);
1473 children = children->next;
1476 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1477 gtk_widget_grab_focus (widget);
1483 gtk_notebook_button_release (GtkWidget *widget,
1484 GdkEventButton *event)
1486 GtkNotebook *notebook;
1488 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1489 g_return_val_if_fail (event != NULL, FALSE);
1491 if (event->type != GDK_BUTTON_RELEASE)
1494 notebook = GTK_NOTEBOOK (widget);
1496 if (event->button == notebook->button)
1500 if (notebook->timer)
1502 gtk_timeout_remove (notebook->timer);
1503 notebook->timer = 0;
1504 notebook->need_timer = FALSE;
1506 click_child = notebook->click_child;
1507 notebook->click_child = 0;
1508 notebook->button = 0;
1509 gtk_notebook_redraw_arrows (notebook);
1518 gtk_notebook_enter_notify (GtkWidget *widget,
1519 GdkEventCrossing *event)
1521 GtkNotebook *notebook;
1525 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1526 g_return_val_if_fail (event != NULL, FALSE);
1528 notebook = GTK_NOTEBOOK (widget);
1530 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1533 arrow = gtk_notebook_get_arrow (notebook, x, y);
1535 if (arrow != notebook->in_child)
1537 notebook->in_child = arrow;
1538 gtk_notebook_redraw_arrows (notebook);
1547 gtk_notebook_leave_notify (GtkWidget *widget,
1548 GdkEventCrossing *event)
1550 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1554 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1557 arrow = gtk_notebook_get_arrow (notebook, x, y);
1559 if (notebook->in_child)
1561 notebook->in_child = 0;
1562 gtk_notebook_redraw_arrows (notebook);
1569 gtk_notebook_motion_notify (GtkWidget *widget,
1570 GdkEventMotion *event)
1572 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1576 if (notebook->button)
1579 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1582 arrow = gtk_notebook_get_arrow (notebook, x, y);
1584 if (arrow != notebook->in_child)
1586 notebook->in_child = arrow;
1587 gtk_notebook_redraw_arrows (notebook);
1594 gtk_notebook_focus_in (GtkWidget *widget,
1595 GdkEventFocus *event)
1597 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1599 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1603 gtk_notebook_draw_focus (GtkWidget *widget)
1605 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1607 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1608 notebook->focus_tab)
1610 GtkNotebookPage *page;
1614 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1616 page = notebook->focus_tab->data;
1618 area.x = page->tab_label->allocation.x - focus_width;
1619 area.y = page->tab_label->allocation.y - focus_width;
1620 area.width = page->tab_label->allocation.width + 2 * focus_width;
1621 area.height = page->tab_label->allocation.height + 2 * focus_width;
1623 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1627 /* Private GtkContainer Methods :
1629 * gtk_notebook_set_child_arg
1630 * gtk_notebook_get_child_arg
1632 * gtk_notebook_remove
1633 * gtk_notebook_focus
1634 * gtk_notebook_set_focus_child
1635 * gtk_notebook_child_type
1636 * gtk_notebook_forall
1639 gtk_notebook_set_child_property (GtkContainer *container,
1642 const GValue *value,
1647 GtkPackType pack_type;
1649 /* not finding child's page is valid for menus or labels */
1650 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1653 switch (property_id)
1655 case CHILD_PROP_TAB_LABEL:
1656 /* a NULL pointer indicates a default_tab setting, otherwise
1657 * we need to set the associated label
1659 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1660 g_value_get_string (value));
1662 case CHILD_PROP_MENU_LABEL:
1663 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1664 g_value_get_string (value));
1666 case CHILD_PROP_POSITION:
1667 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1668 g_value_get_int (value));
1670 case CHILD_PROP_TAB_EXPAND:
1671 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1672 &expand, &fill, &pack_type);
1673 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1674 g_value_get_boolean (value),
1677 case CHILD_PROP_TAB_FILL:
1678 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1679 &expand, &fill, &pack_type);
1680 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1682 g_value_get_boolean (value),
1685 case CHILD_PROP_TAB_PACK:
1686 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1687 &expand, &fill, &pack_type);
1688 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1690 g_value_get_enum (value));
1693 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1699 gtk_notebook_get_child_property (GtkContainer *container,
1706 GtkNotebook *notebook;
1710 GtkPackType pack_type;
1712 notebook = GTK_NOTEBOOK (container);
1714 /* not finding child's page is valid for menus or labels */
1715 list = gtk_notebook_find_child (notebook, child, NULL);
1718 /* nothing to set on labels or menus */
1719 g_param_value_set_default (pspec, value);
1723 switch (property_id)
1725 case CHILD_PROP_TAB_LABEL:
1726 label = gtk_notebook_get_tab_label (notebook, child);
1728 if (label && GTK_IS_LABEL (label))
1729 g_value_set_string (value, GTK_LABEL (label)->label);
1731 g_value_set_string (value, NULL);
1733 case CHILD_PROP_MENU_LABEL:
1734 label = gtk_notebook_get_menu_label (notebook, child);
1736 if (label && GTK_IS_LABEL (label))
1737 g_value_set_string (value, GTK_LABEL (label)->label);
1739 g_value_set_string (value, NULL);
1741 case CHILD_PROP_POSITION:
1742 g_value_set_int (value, g_list_position (notebook->children, list));
1744 case CHILD_PROP_TAB_EXPAND:
1745 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1746 &expand, NULL, NULL);
1747 g_value_set_boolean (value, expand);
1749 case CHILD_PROP_TAB_FILL:
1750 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1752 g_value_set_boolean (value, fill);
1754 case CHILD_PROP_TAB_PACK:
1755 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1756 NULL, NULL, &pack_type);
1757 g_value_set_enum (value, pack_type);
1760 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1766 gtk_notebook_add (GtkContainer *container,
1769 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1771 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1776 gtk_notebook_remove (GtkContainer *container,
1779 GtkNotebook *notebook;
1780 GtkNotebookPage *page;
1784 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1785 g_return_if_fail (widget != NULL);
1787 notebook = GTK_NOTEBOOK (container);
1789 children = notebook->children;
1793 page = children->data;
1794 if (page->child == widget)
1796 gtk_notebook_real_remove (notebook, children);
1800 children = children->next;
1805 focus_tabs_in (GtkNotebook *notebook)
1807 if (notebook->cur_page)
1809 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1811 gtk_notebook_switch_focus_tab (notebook,
1812 g_list_find (notebook->children,
1813 notebook->cur_page));
1822 focus_tabs_move (GtkNotebook *notebook,
1823 GtkDirectionType direction,
1824 gint search_direction)
1828 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1829 search_direction, TRUE);
1831 new_page = (search_direction == STEP_NEXT) ?
1832 notebook->children :
1833 g_list_last (notebook->children);
1835 gtk_notebook_switch_focus_tab (notebook, new_page);
1841 focus_child_in (GtkNotebook *notebook,
1842 GtkDirectionType direction)
1844 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1847 /* Focus in the notebook can either be on the pages, or on
1851 gtk_notebook_focus (GtkWidget *widget,
1852 GtkDirectionType direction)
1854 GtkWidget *old_focus_child;
1855 GtkNotebook *notebook;
1856 GtkDirectionType effective_direction;
1858 /* Remap the directions into the effective direction it would be for a
1859 * GTK_POS_TOP notebook
1861 #define D(rest) GTK_DIR_##rest
1863 static const GtkDirectionType translate_direction[4][6] = {
1864 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1865 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1866 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1867 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
1872 gboolean widget_is_focus;
1873 GtkContainer *container;
1875 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1877 container = GTK_CONTAINER (widget);
1878 notebook = GTK_NOTEBOOK (container);
1880 widget_is_focus = gtk_widget_is_focus (widget);
1881 old_focus_child = container->focus_child;
1883 effective_direction = translate_direction[notebook->tab_pos][direction];
1885 if (old_focus_child) /* Focus on page child */
1887 if (gtk_widget_child_focus (old_focus_child, direction))
1890 switch (effective_direction)
1892 case GTK_DIR_TAB_BACKWARD:
1894 /* Focus onto the tabs */
1895 if (notebook->show_tabs)
1896 return focus_tabs_in (notebook);
1900 case GTK_DIR_TAB_FORWARD:
1906 else if (widget_is_focus) /* Focus was on tabs */
1908 switch (effective_direction)
1910 case GTK_DIR_TAB_BACKWARD:
1913 case GTK_DIR_TAB_FORWARD:
1915 return focus_child_in (notebook, direction);
1917 return focus_tabs_move (notebook, direction, STEP_PREV);
1919 return focus_tabs_move (notebook, direction, STEP_NEXT);
1922 else /* Focus was not on widget */
1924 switch (effective_direction)
1926 case GTK_DIR_TAB_FORWARD:
1928 if (focus_tabs_in (notebook))
1930 if (focus_child_in (notebook, direction))
1933 case GTK_DIR_TAB_BACKWARD:
1935 if (focus_child_in (notebook, direction))
1937 if (focus_tabs_in (notebook))
1942 return focus_child_in (notebook, direction);
1946 g_assert_not_reached ();
1951 gtk_notebook_set_focus_child (GtkContainer *container,
1954 GtkNotebook *notebook;
1956 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1960 g_return_if_fail (GTK_IS_WIDGET (child));
1962 notebook = GTK_NOTEBOOK (container);
1964 notebook->child_has_focus = TRUE;
1965 if (!notebook->focus_tab)
1968 GtkNotebookPage *page;
1970 children = notebook->children;
1973 page = children->data;
1974 if (page->child == child || page->tab_label == child)
1975 gtk_notebook_switch_focus_tab (notebook, children);
1976 children = children->next;
1980 parent_class->set_focus_child (container, child);
1984 gtk_notebook_forall (GtkContainer *container,
1985 gboolean include_internals,
1986 GtkCallback callback,
1987 gpointer callback_data)
1989 GtkNotebook *notebook;
1992 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1993 g_return_if_fail (callback != NULL);
1995 notebook = GTK_NOTEBOOK (container);
1997 children = notebook->children;
2000 GtkNotebookPage *page;
2002 page = children->data;
2003 children = children->next;
2004 (* callback) (page->child, callback_data);
2005 if (include_internals)
2007 if (page->tab_label)
2008 (* callback) (page->tab_label, callback_data);
2009 if (page->menu_label)
2010 (* callback) (page->menu_label, callback_data);
2016 gtk_notebook_child_type (GtkContainer *container)
2018 return GTK_TYPE_WIDGET;
2021 /* Private GtkNotebook Functions:
2023 * gtk_notebook_redraw_tabs
2024 * gtk_notebook_focus_changed
2025 * gtk_notebook_real_remove
2026 * gtk_notebook_update_labels
2027 * gtk_notebook_timer
2028 * gtk_notebook_page_compare
2029 * gtk_notebook_real_page_position
2030 * gtk_notebook_search_page
2033 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2036 GtkNotebookPage *page;
2037 GdkRectangle redraw_rect;
2040 widget = GTK_WIDGET (notebook);
2041 border = GTK_CONTAINER (notebook)->border_width;
2043 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2046 page = notebook->first_tab->data;
2048 redraw_rect.x = border;
2049 redraw_rect.y = border;
2051 switch (notebook->tab_pos)
2053 case GTK_POS_BOTTOM:
2054 redraw_rect.y = (widget->allocation.height - border -
2055 page->allocation.height -
2056 widget->style->ythickness);
2057 if (page != notebook->cur_page)
2058 redraw_rect.y -= widget->style->ythickness;
2061 redraw_rect.width = widget->allocation.width - 2 * border;
2062 redraw_rect.height = (page->allocation.height +
2063 widget->style->ythickness);
2064 if (page != notebook->cur_page)
2065 redraw_rect.height += widget->style->ythickness;
2068 redraw_rect.x = (widget->allocation.width - border -
2069 page->allocation.width -
2070 widget->style->xthickness);
2071 if (page != notebook->cur_page)
2072 redraw_rect.x -= widget->style->xthickness;
2075 redraw_rect.width = (page->allocation.width +
2076 widget->style->xthickness);
2077 redraw_rect.height = widget->allocation.height - 2 * border;
2078 if (page != notebook->cur_page)
2079 redraw_rect.width += widget->style->xthickness;
2083 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2087 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2089 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2093 gtk_notebook_get_arrow_rect (notebook, &rect);
2094 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2099 gtk_notebook_focus_changed (GtkNotebook *notebook,
2100 GtkNotebookPage *old_page)
2102 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2104 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2109 gtk_widget_style_get (GTK_WIDGET (notebook), "focus-line-width", &focus_width, NULL);
2111 if (notebook->focus_tab)
2113 GtkNotebookPage *page;
2115 page = notebook->focus_tab->data;
2117 area.x = page->tab_label->allocation.x - focus_width;
2118 area.y = page->tab_label->allocation.y - focus_width;
2119 area.width = page->tab_label->allocation.width + 2 * focus_width;
2120 area.height = page->tab_label->allocation.height + 2 * focus_width;
2122 gtk_notebook_draw_tab (notebook, page, &area);
2127 area.x = old_page->tab_label->allocation.x - focus_width;
2128 area.y = old_page->tab_label->allocation.y - focus_width;
2129 area.width = old_page->tab_label->allocation.width + 2 * focus_width;
2130 area.height = old_page->tab_label->allocation.height + 2 * focus_width;
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))
2591 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2593 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2594 area, widget, "tab",
2595 page->tab_label->allocation.x - focus_width,
2596 page->tab_label->allocation.y - focus_width,
2597 page->tab_label->allocation.width + 2 * focus_width,
2598 page->tab_label->allocation.height + 2 * focus_width);
2600 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2601 GTK_WIDGET_DRAWABLE (page->tab_label))
2603 GdkEventExpose expose_event;
2605 /* This is a lame hack since all this code needs rewriting anyhow */
2607 expose_event.window = page->tab_label->window;
2608 expose_event.area = child_area;
2609 expose_event.region = gdk_region_rectangle (&child_area);
2610 expose_event.send_event = TRUE;
2611 expose_event.type = GDK_EXPOSE;
2612 expose_event.count = 0;
2614 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
2616 gdk_region_destroy (expose_event.region);
2622 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2625 GtkStateType state_type;
2626 GtkShadowType shadow_type;
2628 GdkRectangle arrow_rect;
2630 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2632 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2634 widget = GTK_WIDGET(notebook);
2636 if (GTK_WIDGET_DRAWABLE (notebook))
2638 if (notebook->in_child == arrow)
2640 if (notebook->click_child == arrow)
2641 state_type = GTK_STATE_ACTIVE;
2643 state_type = GTK_STATE_PRELIGHT;
2646 state_type = GTK_STATE_NORMAL;
2648 if (notebook->click_child == arrow)
2649 shadow_type = GTK_SHADOW_IN;
2651 shadow_type = GTK_SHADOW_OUT;
2653 if (arrow == GTK_ARROW_LEFT)
2655 if (notebook->focus_tab &&
2656 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2659 shadow_type = GTK_SHADOW_ETCHED_IN;
2660 state_type = GTK_STATE_NORMAL;
2663 if (notebook->tab_pos == GTK_POS_LEFT ||
2664 notebook->tab_pos == GTK_POS_RIGHT)
2665 arrow = GTK_ARROW_UP;
2667 gtk_paint_arrow (widget->style, widget->window, state_type,
2668 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2670 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2674 if (notebook->focus_tab &&
2675 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2678 shadow_type = GTK_SHADOW_ETCHED_IN;
2679 state_type = GTK_STATE_NORMAL;
2682 if (notebook->tab_pos == GTK_POS_LEFT ||
2683 notebook->tab_pos == GTK_POS_RIGHT)
2684 arrow = GTK_ARROW_DOWN;
2686 gtk_paint_arrow (widget->style, widget->window, state_type,
2687 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2688 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2689 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2694 /* Private GtkNotebook Size Allocate Functions:
2696 * gtk_notebook_pages_allocate
2697 * gtk_notebook_page_allocate
2698 * gtk_notebook_calc_tabs
2701 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2703 GtkWidget *widget = GTK_WIDGET (notebook);
2704 GtkContainer *container = GTK_CONTAINER (notebook);
2705 GtkNotebookPage *page = NULL;
2706 GtkAllocation *allocation = &widget->allocation;
2707 GtkAllocation child_allocation;
2708 GList *children = NULL;
2709 GList *last_child = NULL;
2710 gboolean showarrow = FALSE;
2720 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2723 child_allocation.x = widget->allocation.x + container->border_width;
2724 child_allocation.y = widget->allocation.y + container->border_width;
2726 switch (notebook->tab_pos)
2728 case GTK_POS_BOTTOM:
2729 child_allocation.y = (widget->allocation.y +
2730 allocation->height -
2731 notebook->cur_page->requisition.height -
2732 container->border_width);
2735 child_allocation.height = notebook->cur_page->requisition.height;
2739 child_allocation.x = (widget->allocation.x +
2741 notebook->cur_page->requisition.width -
2742 container->border_width);
2745 child_allocation.width = notebook->cur_page->requisition.width;
2749 if (notebook->scrollable)
2753 children = notebook->children;
2755 if (notebook->focus_tab)
2756 focus_tab = notebook->focus_tab;
2757 else if (notebook->first_tab)
2758 focus_tab = notebook->first_tab;
2760 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2762 switch (notebook->tab_pos)
2765 case GTK_POS_BOTTOM:
2768 page = children->data;
2769 children = children->next;
2771 if (GTK_WIDGET_VISIBLE (page->child))
2772 tab_space += page->requisition.width;
2775 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2778 page = focus_tab->data;
2780 tab_space = (allocation->width - TAB_OVERLAP -
2781 page->requisition.width -
2782 2 * (container->border_width + ARROW_SPACING +
2784 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2785 container->border_width);
2787 page = notebook->children->data;
2788 if (notebook->tab_pos == GTK_POS_TOP)
2789 y = (container->border_width +
2790 (page->requisition.height - ARROW_SIZE) / 2);
2792 y = (allocation->height - container->border_width -
2793 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2800 page = children->data;
2801 children = children->next;
2803 if (GTK_WIDGET_VISIBLE (page->child))
2804 tab_space += page->requisition.height;
2807 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2810 page = focus_tab->data;
2811 tab_space = (allocation->height -
2812 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2813 2 * container->border_width -
2814 page->requisition.height);
2815 y = allocation->height - container->border_width - ARROW_SIZE;
2817 page = notebook->children->data;
2818 if (notebook->tab_pos == GTK_POS_LEFT)
2819 x = (container->border_width +
2820 (page->requisition.width -
2821 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2823 x = (allocation->width - container->border_width -
2824 (2 * ARROW_SIZE - ARROW_SPACING) -
2825 (page->requisition.width -
2826 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2830 if (showarrow) /* first_tab <- focus_tab */
2834 notebook->first_tab = focus_tab;
2835 last_child = gtk_notebook_search_page (notebook, focus_tab,
2841 if (notebook->first_tab && notebook->first_tab != focus_tab)
2843 /* Is first_tab really predecessor of focus_tab ? */
2844 page = notebook->first_tab->data;
2845 if (GTK_WIDGET_VISIBLE (page->child))
2846 for (children = focus_tab;
2847 children && children != notebook->first_tab;
2848 children = gtk_notebook_search_page (notebook,
2854 notebook->first_tab = focus_tab;
2856 gtk_notebook_calc_tabs (notebook,
2857 gtk_notebook_search_page (notebook,
2861 &(notebook->first_tab), &tab_space,
2866 notebook->first_tab =
2867 gtk_notebook_search_page (notebook, notebook->first_tab,
2869 if (!notebook->first_tab)
2870 notebook->first_tab = focus_tab;
2871 last_child = gtk_notebook_search_page (notebook, focus_tab,
2874 else /* focus_tab -> end */
2876 if (!notebook->first_tab)
2877 notebook->first_tab = gtk_notebook_search_page (notebook,
2882 gtk_notebook_calc_tabs (notebook,
2883 gtk_notebook_search_page (notebook,
2887 &children, &tab_space, STEP_NEXT);
2890 last_child = children;
2891 else /* start <- first_tab */
2895 gtk_notebook_calc_tabs
2897 gtk_notebook_search_page (notebook,
2898 notebook->first_tab,
2901 &children, &tab_space, STEP_PREV);
2902 notebook->first_tab = gtk_notebook_search_page(notebook,
2912 tab_space = -tab_space;
2914 for (children = notebook->first_tab;
2915 children && children != last_child;
2916 children = gtk_notebook_search_page (notebook, children,
2923 /*unmap all non-visible tabs*/
2924 for (children = gtk_notebook_search_page (notebook, NULL,
2926 children && children != notebook->first_tab;
2927 children = gtk_notebook_search_page (notebook, children,
2930 page = children->data;
2931 if (page->tab_label)
2932 gtk_widget_set_child_visible (page->tab_label, FALSE);
2934 for (children = last_child; children;
2935 children = gtk_notebook_search_page (notebook, children,
2938 page = children->data;
2939 if (page->tab_label)
2940 gtk_widget_set_child_visible (page->tab_label, FALSE);
2943 else /* !showarrow */
2945 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2956 children = notebook->children;
2957 switch (notebook->tab_pos)
2960 case GTK_POS_BOTTOM:
2963 page = children->data;
2964 children = children->next;
2966 if (GTK_WIDGET_VISIBLE (page->child))
2969 tab_space += page->requisition.width;
2974 tab_space -= allocation->width;
2980 page = children->data;
2981 children = children->next;
2983 if (GTK_WIDGET_VISIBLE (page->child))
2986 tab_space += page->requisition.height;
2991 tab_space -= allocation->height;
2993 tab_space += 2 * container->border_width + TAB_OVERLAP;
2995 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2997 if (notebook->homogeneous && n)
3001 children = notebook->first_tab;
3005 if (children == last_child)
3007 /* FIXME double check */
3011 page = children->data;
3012 if (!showarrow && page->pack != GTK_PACK_START)
3014 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3017 if (n && (showarrow || page->expand || notebook->homogeneous))
3019 new_fill = (tab_space * i++) / n;
3020 delta = new_fill - old_fill;
3021 old_fill = new_fill;
3024 switch (notebook->tab_pos)
3027 case GTK_POS_BOTTOM:
3028 child_allocation.width = (page->requisition.width +
3029 TAB_OVERLAP + delta);
3033 child_allocation.height = (page->requisition.height +
3034 TAB_OVERLAP + delta);
3038 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3040 switch (notebook->tab_pos)
3043 case GTK_POS_BOTTOM:
3044 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3048 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3052 if (page->tab_label)
3053 gtk_widget_set_child_visible (page->tab_label, TRUE);
3058 children = notebook->children;
3059 switch (notebook->tab_pos)
3062 case GTK_POS_BOTTOM:
3063 child_allocation.x = (allocation->x + allocation->width -
3064 container->border_width);
3068 child_allocation.y = (allocation->y + allocation->height -
3069 container->border_width);
3073 while (children != last_child)
3075 page = children->data;
3076 children = children->next;
3078 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3082 if (n && (page->expand || notebook->homogeneous))
3084 new_fill = (tab_space * i++) / n;
3085 delta = new_fill - old_fill;
3086 old_fill = new_fill;
3089 switch (notebook->tab_pos)
3092 case GTK_POS_BOTTOM:
3093 child_allocation.width = (page->requisition.width +
3094 TAB_OVERLAP + delta);
3095 child_allocation.x -= child_allocation.width;
3099 child_allocation.height = (page->requisition.height +
3100 TAB_OVERLAP + delta);
3101 child_allocation.y -= child_allocation.height;
3105 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3107 switch (notebook->tab_pos)
3110 case GTK_POS_BOTTOM:
3111 child_allocation.x += TAB_OVERLAP;
3115 child_allocation.y += TAB_OVERLAP;
3119 if (page->tab_label)
3120 gtk_widget_set_child_visible (page->tab_label, TRUE);
3125 gtk_notebook_redraw_tabs (notebook);
3129 gtk_notebook_page_allocate (GtkNotebook *notebook,
3130 GtkNotebookPage *page,
3131 GtkAllocation *allocation)
3133 GtkWidget *widget = GTK_WIDGET (notebook);
3134 GtkAllocation child_allocation;
3135 GtkRequisition tab_requisition;
3141 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3143 xthickness = widget->style->xthickness;
3144 ythickness = widget->style->ythickness;
3146 /* If the size of the notebook tabs change, we need to queue
3147 * a redraw on the tab area
3149 if ((allocation->width != page->allocation.width) ||
3150 (allocation->height != page->allocation.height))
3152 gint x, y, width, height, border_width;
3154 border_width = GTK_CONTAINER (notebook)->border_width;
3156 switch (notebook->tab_pos)
3159 width = widget->allocation.width;
3160 height = MAX (page->allocation.height, allocation->height) + ythickness;
3165 case GTK_POS_BOTTOM:
3166 width = widget->allocation.width + xthickness;
3167 height = MAX (page->allocation.height, allocation->height) + ythickness;
3169 y = widget->allocation.height - height - border_width;
3173 width = MAX (page->allocation.width, allocation->width) + xthickness;
3174 height = widget->allocation.height;
3180 default: /* quiet gcc */
3181 width = MAX (page->allocation.width, allocation->width) + xthickness;
3182 height = widget->allocation.height;
3183 x = widget->allocation.width - width - border_width;
3188 gtk_widget_queue_clear_area (widget, x, y, width, height);
3191 page->allocation = *allocation;
3192 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3194 if (notebook->cur_page != page)
3196 switch (notebook->tab_pos)
3199 page->allocation.y += ythickness;
3200 case GTK_POS_BOTTOM:
3201 if (page->allocation.height > ythickness)
3202 page->allocation.height -= ythickness;
3205 page->allocation.x += xthickness;
3207 if (page->allocation.width > xthickness)
3208 page->allocation.width -= xthickness;
3213 switch (notebook->tab_pos)
3216 case GTK_POS_BOTTOM:
3217 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3220 child_allocation.x = (xthickness + focus_width +
3221 notebook->tab_hborder);
3222 child_allocation.width = MAX (1, (page->allocation.width -
3223 2 * child_allocation.x));
3224 child_allocation.x += page->allocation.x;
3228 child_allocation.x = (page->allocation.x +
3229 (page->allocation.width -
3230 tab_requisition.width) / 2);
3231 child_allocation.width = tab_requisition.width;
3233 child_allocation.y = (notebook->tab_vborder + focus_width +
3234 page->allocation.y);
3235 if (notebook->tab_pos == GTK_POS_TOP)
3236 child_allocation.y += ythickness;
3237 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3238 2 * (notebook->tab_vborder + focus_width)));
3242 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3245 child_allocation.y = ythickness + padding;
3246 child_allocation.height = MAX (1, (page->allocation.height -
3247 2 * child_allocation.y));
3248 child_allocation.y += page->allocation.y;
3252 child_allocation.y = (page->allocation.y + (page->allocation.height -
3253 tab_requisition.height) / 2);
3254 child_allocation.height = tab_requisition.height;
3256 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3257 if (notebook->tab_pos == GTK_POS_LEFT)
3258 child_allocation.x += xthickness;
3259 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3260 2 * (notebook->tab_hborder + focus_width)));
3264 if (page->tab_label)
3265 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3269 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3275 GtkNotebookPage *page = NULL;
3277 GList *last_list = NULL;
3284 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3285 if (pack == GTK_PACK_END)
3286 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3290 switch (notebook->tab_pos)
3293 case GTK_POS_BOTTOM:
3296 page = children->data;
3297 if (GTK_WIDGET_VISIBLE (page->child))
3299 if (page->pack == pack)
3301 *tab_space -= page->requisition.width;
3302 if (*tab_space < 0 || children == *end)
3306 *tab_space = - (*tab_space +
3307 page->requisition.width);
3313 last_list = children;
3315 if (direction == STEP_NEXT)
3316 children = children->next;
3318 children = children->prev;
3325 page = children->data;
3326 if (GTK_WIDGET_VISIBLE (page->child))
3328 if (page->pack == pack)
3330 *tab_space -= page->requisition.height;
3331 if (*tab_space < 0 || children == *end)
3335 *tab_space = - (*tab_space +
3336 page->requisition.height);
3342 last_list = children;
3344 if (direction == STEP_NEXT)
3345 children = children->next;
3347 children = children->prev;
3351 if (direction == STEP_PREV)
3353 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3354 direction = STEP_PREV;
3355 children = last_list;
3359 /* Private GtkNotebook Page Switch Methods:
3361 * gtk_notebook_real_switch_page
3364 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3365 GtkNotebookPage *page,
3368 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3369 g_return_if_fail (page != NULL);
3371 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3374 if (notebook->cur_page)
3375 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3377 notebook->cur_page = page;
3379 if (!notebook->focus_tab ||
3380 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3381 notebook->focus_tab =
3382 g_list_find (notebook->children, notebook->cur_page);
3384 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3386 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3387 g_object_notify (G_OBJECT (notebook), "page");
3390 /* Private GtkNotebook Page Switch Functions:
3392 * gtk_notebook_switch_page
3393 * gtk_notebook_page_select
3394 * gtk_notebook_switch_focus_tab
3395 * gtk_notebook_menu_switch_page
3398 gtk_notebook_switch_page (GtkNotebook *notebook,
3399 GtkNotebookPage *page,
3402 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3403 g_return_if_fail (page != NULL);
3405 if (notebook->cur_page == page)
3409 page_num = g_list_index (notebook->children, page);
3411 gtk_signal_emit (GTK_OBJECT (notebook),
3412 notebook_signals[SWITCH_PAGE],
3418 gtk_notebook_page_select (GtkNotebook *notebook,
3419 gboolean move_focus)
3421 GtkNotebookPage *page;
3422 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3424 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3426 if (!notebook->focus_tab)
3429 page = notebook->focus_tab->data;
3430 gtk_notebook_switch_page (notebook, page, -1);
3434 switch (notebook->tab_pos)
3439 case GTK_POS_BOTTOM:
3443 dir = GTK_DIR_RIGHT;
3450 if (gtk_widget_child_focus (page->child, dir))
3457 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3461 GtkNotebookPage *old_page = NULL;
3462 GtkNotebookPage *page;
3464 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3466 if (notebook->focus_tab == new_child)
3469 old_child = notebook->focus_tab;
3470 notebook->focus_tab = new_child;
3472 if (notebook->scrollable)
3473 gtk_notebook_redraw_arrows (notebook);
3475 if (!notebook->show_tabs || !notebook->focus_tab)
3479 old_page = old_child->data;
3481 page = notebook->focus_tab->data;
3482 if (GTK_WIDGET_MAPPED (page->tab_label))
3483 gtk_notebook_focus_changed (notebook, old_page);
3485 gtk_notebook_pages_allocate (notebook);
3489 gtk_notebook_menu_switch_page (GtkWidget *widget,
3490 GtkNotebookPage *page)
3492 GtkNotebook *notebook;
3496 g_return_if_fail (widget != NULL);
3497 g_return_if_fail (page != NULL);
3499 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3500 (GTK_MENU (widget->parent)));
3502 if (notebook->cur_page == page)
3506 children = notebook->children;
3507 while (children && children->data != page)
3509 children = children->next;
3513 gtk_signal_emit (GTK_OBJECT (notebook),
3514 notebook_signals[SWITCH_PAGE],
3519 /* Private GtkNotebook Menu Functions:
3521 * gtk_notebook_menu_item_create
3522 * gtk_notebook_menu_label_unparent
3523 * gtk_notebook_menu_detacher
3526 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3529 GtkNotebookPage *page;
3530 GtkWidget *menu_item;
3533 if (page->default_menu)
3535 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3536 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3538 page->menu_label = gtk_label_new ("");
3539 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3542 gtk_widget_show (page->menu_label);
3543 menu_item = gtk_menu_item_new ();
3544 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3545 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3546 gtk_notebook_real_page_position (notebook, list));
3547 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3548 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3549 if (GTK_WIDGET_VISIBLE (page->child))
3550 gtk_widget_show (menu_item);
3554 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3557 gtk_widget_unparent (GTK_BIN(widget)->child);
3558 GTK_BIN(widget)->child = NULL;
3562 gtk_notebook_menu_detacher (GtkWidget *widget,
3565 GtkNotebook *notebook;
3567 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3569 notebook = GTK_NOTEBOOK (widget);
3570 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3572 notebook->menu = NULL;
3575 /* Public GtkNotebook Page Insert/Remove Methods :
3577 * gtk_notebook_append_page
3578 * gtk_notebook_append_page_menu
3579 * gtk_notebook_prepend_page
3580 * gtk_notebook_prepend_page_menu
3581 * gtk_notebook_insert_page
3582 * gtk_notebook_insert_page_menu
3583 * gtk_notebook_remove_page
3586 * gtk_notebook_append_page:
3587 * @notebook: a #GtkNotebook
3588 * @child: the #GtkWidget to use as the contents of the page.
3589 * @tab_label: the #GtkWidget to be used as the label for the page,
3590 * or %NULL to use the default label, 'page N'.
3592 * Appends a page to @notebook.
3595 gtk_notebook_append_page (GtkNotebook *notebook,
3597 GtkWidget *tab_label)
3599 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3600 g_return_if_fail (GTK_IS_WIDGET (child));
3601 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3603 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3607 * gtk_notebook_append_page_menu:
3608 * @notebook: a #GtkNotebook
3609 * @child: the #GtkWidget to use as the contents of the page.
3610 * @tab_label: the #GtkWidget to be used as the label for the page,
3611 * or %NULL to use the default label, 'page N'.
3612 * @menu_label: the widget to use as a label for the page-switch
3613 * menu, if that is enabled. If %NULL, and @tab_label
3614 * is a #GtkLabel or %NULL, then the menu label will be
3615 * a newly created label with the same text as @tab_label;
3616 * If @tab_label is not a #GtkLabel, @menu_label must be
3617 * specified if the page-switch menu is to be used.
3619 * Appends a page to @notebook, specifying the widget to use as the
3620 * label in the popup menu.
3623 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3625 GtkWidget *tab_label,
3626 GtkWidget *menu_label)
3628 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3629 g_return_if_fail (GTK_IS_WIDGET (child));
3630 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3631 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3633 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3637 * gtk_notebook_prepend_page:
3638 * @notebook: a #GtkNotebook
3639 * @child: the #GtkWidget to use as the contents of the page.
3640 * @tab_label: the #GtkWidget to be used as the label for the page,
3641 * or %NULL to use the default label, 'page N'.
3643 * Prepends a page to @notebook.
3646 gtk_notebook_prepend_page (GtkNotebook *notebook,
3648 GtkWidget *tab_label)
3650 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3651 g_return_if_fail (GTK_IS_WIDGET (child));
3652 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3654 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3658 * gtk_notebook_prepend_page_menu:
3659 * @notebook: a #GtkNotebook
3660 * @child: the #GtkWidget to use as the contents of the page.
3661 * @tab_label: the #GtkWidget to be used as the label for the page,
3662 * or %NULL to use the default label, 'page N'.
3663 * @menu_label: the widget to use as a label for the page-switch
3664 * menu, if that is enabled. If %NULL, and @tab_label
3665 * is a #GtkLabel or %NULL, then the menu label will be
3666 * a newly created label with the same text as @tab_label;
3667 * If @tab_label is not a #GtkLabel, @menu_label must be
3668 * specified if the page-switch menu is to be used.
3670 * Prepends a page to @notebook, specifying the widget to use as the
3671 * label in the popup menu.
3674 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3676 GtkWidget *tab_label,
3677 GtkWidget *menu_label)
3679 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3680 g_return_if_fail (GTK_IS_WIDGET (child));
3681 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3682 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3684 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3688 * gtk_notebook_insert_page:
3689 * @notebook: a #GtkNotebook
3690 * @child: the #GtkWidget to use as the contents of the page.
3691 * @tab_label: the #GtkWidget to be used as the label for the page,
3692 * or %NULL to use the default label, 'page N'.
3693 * @position: the index (starting at 0) at which to insert the page,
3694 * or -1 to append the page after all other pages.
3696 * Insert a page into @notebook at the given position
3699 gtk_notebook_insert_page (GtkNotebook *notebook,
3701 GtkWidget *tab_label,
3704 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3705 g_return_if_fail (GTK_IS_WIDGET (child));
3706 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3708 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3713 gtk_notebook_page_compare_tab (gconstpointer a,
3716 return (((GtkNotebookPage *) a)->tab_label != b);
3720 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3724 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3727 list = g_list_find_custom (notebook->children, child,
3728 gtk_notebook_page_compare_tab);
3731 GtkNotebookPage *page = list->data;
3733 gtk_notebook_switch_page (notebook, page, -1);
3740 * gtk_notebook_insert_page_menu:
3741 * @notebook: a #GtkNotebook
3742 * @child: the #GtkWidget to use as the contents of the page.
3743 * @tab_label: the #GtkWidget to be used as the label for the page,
3744 * or %NULL to use the default label, 'page N'.
3745 * @menu_label: the widget to use as a label for the page-switch
3746 * menu, if that is enabled. If %NULL, and @tab_label
3747 * is a #GtkLabel or %NULL, then the menu label will be
3748 * a newly created label with the same text as @tab_label;
3749 * If @tab_label is not a #GtkLabel, @menu_label must be
3750 * specified if the page-switch menu is to be used.
3751 * @position: the index (starting at 0) at which to insert the page,
3752 * or -1 to append the page after all other pages.
3754 * Insert a page into @notebook at the given position, specifying
3755 * the widget to use as the label in the popup menu.
3758 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3760 GtkWidget *tab_label,
3761 GtkWidget *menu_label,
3764 GtkNotebookPage *page;
3767 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3768 g_return_if_fail (GTK_IS_WIDGET (child));
3769 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3770 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3772 gtk_widget_freeze_child_notify (child);
3774 page = g_new (GtkNotebookPage, 1);
3775 page->child = child;
3776 page->requisition.width = 0;
3777 page->requisition.height = 0;
3778 page->allocation.x = 0;
3779 page->allocation.y = 0;
3780 page->allocation.width = 0;
3781 page->allocation.height = 0;
3782 page->default_menu = FALSE;
3783 page->default_tab = FALSE;
3784 page->mnemonic_activate_signal = 0;
3786 nchildren = g_list_length (notebook->children);
3787 if ((position < 0) || (position > nchildren))
3788 position = nchildren;
3790 notebook->children = g_list_insert (notebook->children, page, position);
3794 page->default_tab = TRUE;
3795 if (notebook->show_tabs)
3796 tab_label = gtk_label_new ("");
3798 page->tab_label = tab_label;
3799 page->menu_label = menu_label;
3800 page->expand = FALSE;
3802 page->pack = GTK_PACK_START;
3805 page->default_menu = TRUE;
3808 gtk_widget_ref (page->menu_label);
3809 gtk_object_sink (GTK_OBJECT (page->menu_label));
3813 gtk_notebook_menu_item_create (notebook,
3814 g_list_find (notebook->children, page));
3816 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3818 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3820 gtk_notebook_update_labels (notebook);
3822 if (!notebook->first_tab)
3823 notebook->first_tab = notebook->children;
3825 if (!notebook->cur_page)
3826 gtk_widget_set_child_visible (child, TRUE);
3828 gtk_widget_set_child_visible (child, FALSE);
3832 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3833 gtk_widget_show (tab_label);
3835 gtk_widget_hide (tab_label);
3838 if (!notebook->cur_page)
3840 gtk_notebook_switch_page (notebook, page, 0);
3841 gtk_notebook_switch_focus_tab (notebook, NULL);
3845 page->mnemonic_activate_signal =
3846 gtk_signal_connect (GTK_OBJECT (tab_label),
3847 "mnemonic_activate",
3848 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
3851 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
3852 gdk_window_show_unraised (notebook->event_window);
3854 gtk_widget_child_notify (child, "tab_expand");
3855 gtk_widget_child_notify (child, "tab_fill");
3856 gtk_widget_child_notify (child, "tab_pack");
3857 gtk_widget_child_notify (child, "tab_label");
3858 gtk_widget_child_notify (child, "menu_label");
3859 gtk_widget_child_notify (child, "position");
3860 gtk_widget_thaw_child_notify (child);
3864 * gtk_notebook_remove_page:
3865 * @notebook: a #GtkNotebook.
3866 * @page_num: the index of a notebook page, starting
3867 * from 0. If -1, the last page will
3870 * Removes a page from the notebook given its index
3874 gtk_notebook_remove_page (GtkNotebook *notebook,
3879 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3883 list = g_list_nth (notebook->children, page_num);
3885 gtk_notebook_real_remove (notebook, list);
3889 list = g_list_last (notebook->children);
3891 gtk_notebook_real_remove (notebook, list);
3895 /* Public GtkNotebook Page Switch Methods :
3896 * gtk_notebook_get_current_page
3897 * gtk_notebook_page_num
3898 * gtk_notebook_set_current_page
3899 * gtk_notebook_next_page
3900 * gtk_notebook_prev_page
3903 * gtk_notebook_get_current_page:
3904 * @notebook: a #GtkNotebook
3906 * Returns the page number of the current page.
3908 * Return value: the index (starting from 0) of the current
3909 * page in the notebook. If the notebook has no pages, then
3910 * -1 will be returned.
3913 gtk_notebook_get_current_page (GtkNotebook *notebook)
3915 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3917 if (!notebook->cur_page)
3920 return g_list_index (notebook->children, notebook->cur_page);
3924 * gtk_notebook_get_nth_page:
3925 * @notebook: a #GtkNotebook
3926 * @page_num: the index of a page in the noteobok
3928 * Returns the child widget contained in page number @page_num.
3930 * Return value: the child widget, or %NULL if @page_num is
3934 gtk_notebook_get_nth_page (GtkNotebook *notebook,
3937 GtkNotebookPage *page;
3939 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3941 page = g_list_nth_data (notebook->children, page_num);
3950 * gtk_notebook_page_num:
3951 * @notebook: a #GtkNotebook
3952 * @child: a #GtkWidget
3954 * Finds the index of the page which contains the given child
3957 * Return value: the index of the page containing @child, or
3958 * -1 if @child is not in the notebook.
3961 gtk_notebook_page_num (GtkNotebook *notebook,
3967 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3970 children = notebook->children;
3973 GtkNotebookPage *page = children->data;
3975 if (page->child == child)
3978 children = children->next;
3986 * gtk_notebook_set_current_page:
3987 * @notebook: a #GtkNotebook
3988 * @page_num: index of the page to switch to, starting from 0.
3989 * If negative, or greater than the number of pages
3990 * in the notebook the last page will be used.
3992 * Switches to the page number @page_num.
3995 gtk_notebook_set_current_page (GtkNotebook *notebook,
4000 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4003 list = g_list_nth (notebook->children, page_num);
4005 list = g_list_last (notebook->children);
4007 page_num = g_list_index (notebook->children, list);
4010 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4014 * gtk_notebook_next_page:
4015 * @notebook: a #GtkNotebook
4017 * Switches to the next page. Nothing happens if the current page is
4021 gtk_notebook_next_page (GtkNotebook *notebook)
4025 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4027 list = g_list_find (notebook->children, notebook->cur_page);
4031 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4035 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4039 * gtk_notebook_prev_page:
4040 * @notebook: a #GtkNotebook
4042 * Switches to the previous page. Nothing happens if the current page
4043 * is the first page.
4046 gtk_notebook_prev_page (GtkNotebook *notebook)
4050 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4052 list = g_list_find (notebook->children, notebook->cur_page);
4056 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4060 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4063 /* Public GtkNotebook/Tab Style Functions
4065 * gtk_notebook_set_show_border
4066 * gtk_notebook_set_show_tabs
4067 * gtk_notebook_set_tab_pos
4068 * gtk_notebook_set_homogeneous_tabs
4069 * gtk_notebook_set_tab_border
4070 * gtk_notebook_set_tab_hborder
4071 * gtk_notebook_set_tab_vborder
4072 * gtk_notebook_set_scrollable
4075 * gtk_notebook_set_show_border:
4076 * @notebook: a #GtkNotebook
4077 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4079 * Sets whether a bevel will be drawn around the notebook pages.
4080 * this is only has an effect when the tabs are not shown.
4081 * See gtk_notebook_set_show_tabs().
4084 gtk_notebook_set_show_border (GtkNotebook *notebook,
4085 gboolean show_border)
4087 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4089 if (notebook->show_border != show_border)
4091 notebook->show_border = show_border;
4093 if (GTK_WIDGET_VISIBLE (notebook))
4094 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4096 g_object_notify (G_OBJECT (notebook), "show_border");
4101 * gtk_notebook_get_show_border:
4102 * @notebook: a #GtkNotebook
4104 * Returns whether a bevel will be drawn around the notebook pages. See
4105 * gtk_notebook_set_show_border().
4107 * Return value: %TRUE if the bevel is drawn
4110 gtk_notebook_get_show_border (GtkNotebook *notebook)
4112 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4114 return notebook->show_border;
4118 * gtk_notebook_set_show_tabs:
4119 * @notebook: a #GtkNotebook
4120 * @show_tabs: %TRUE if the tabs should be shown.
4122 * Sets whether to show the tabs for the notebook or not.
4125 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4128 GtkNotebookPage *page;
4131 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4133 show_tabs = show_tabs != FALSE;
4135 if (notebook->show_tabs == show_tabs)
4138 notebook->show_tabs = show_tabs;
4139 children = notebook->children;
4143 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4147 page = children->data;
4148 children = children->next;
4149 if (page->default_tab)
4151 gtk_widget_destroy (page->tab_label);
4152 page->tab_label = NULL;
4155 gtk_widget_hide (page->tab_label);
4160 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4161 gtk_notebook_update_labels (notebook);
4163 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4165 g_object_notify (G_OBJECT (notebook), "show_tabs");
4169 * gtk_notebook_get_show_tabs:
4170 * @notebook: a #GtkNotebook
4172 * Returns whether the tabs of the notebook are shown. See
4173 * gtk_notebook_set_show_tabs().
4175 * Return value: %TRUE if the tabs are shown
4178 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4180 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4182 return notebook->show_tabs;
4186 * gtk_notebook_set_tab_pos:
4187 * @notebook: a #GtkNotebook.
4188 * @pos: the edge to draw the tabs at.
4190 * Sets the edge at which the tabs for switching pages in the
4191 * notebook are drawn.
4194 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4195 GtkPositionType pos)
4197 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4199 if (notebook->tab_pos != pos)
4201 notebook->tab_pos = pos;
4202 if (GTK_WIDGET_VISIBLE (notebook))
4203 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4206 g_object_notify (G_OBJECT (notebook), "tab_pos");
4210 * gtk_notebook_get_tab_pos:
4211 * @notebook: a #GtkNotebook
4213 * Gets the edge at which the tabs for switching pages in the
4214 * notebook are drawn.
4216 * Return value: the edge at which the tabs are drawn
4219 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4221 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4223 return notebook->tab_pos;
4227 * gtk_notebook_set_homogeneous_tabs:
4228 * @notebook: a #GtkNotebook
4229 * @homogeneous: %TRUE if all tabs should be the same size.
4231 * Sets whether the tabs must have all the same size or not.
4234 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4235 gboolean homogeneous)
4237 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4239 if (homogeneous == notebook->homogeneous)
4242 notebook->homogeneous = homogeneous;
4243 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4245 g_object_notify (G_OBJECT (notebook), "homogeneous");
4249 * gtk_notebook_set_tab_border:
4250 * @notebook: a #GtkNotebook
4251 * @border_width: width of the border around the tab labels.
4253 * Sets the width the border around the tab labels
4254 * in a notebook. This is equivalent to calling
4255 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4256 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4259 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4262 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4264 notebook->tab_hborder = border_width;
4265 notebook->tab_vborder = border_width;
4267 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4268 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4270 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4274 * gtk_notebook_set_tab_hborder:
4275 * @notebook: a #GtkNotebook
4276 * @tab_hborder: width of the horizontal border of tab labels.
4278 * Sets the width of the horizontal border of tab labels.
4281 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4284 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4286 if (notebook->tab_hborder == tab_hborder)
4289 notebook->tab_hborder = tab_hborder;
4291 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4292 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4294 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4298 * gtk_notebook_set_tab_vborder:
4299 * @notebook: a #GtkNotebook
4300 * @tab_vborder: width of the vertical border of tab labels.
4302 * Sets the width of the vertical border of tab labels.
4305 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4308 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4310 if (notebook->tab_vborder == tab_vborder)
4313 notebook->tab_vborder = tab_vborder;
4315 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4316 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4320 * gtk_notebook_set_scrollable:
4321 * @notebook: a #GtkNotebook
4322 * @scrollable: %TRUE if scroll arrows should be added
4324 * Sets whether the tab label area will have arrows for scrolling if
4325 * there are too many tabs to fit in the area.
4328 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4329 gboolean scrollable)
4331 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4333 scrollable = (scrollable != FALSE);
4335 if (scrollable != notebook->scrollable)
4337 notebook->scrollable = scrollable;
4339 if (GTK_WIDGET_VISIBLE (notebook))
4340 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4342 g_object_notify (G_OBJECT (notebook), "scrollable");
4347 * gtk_notebook_get_scrollable:
4348 * @notebook: a #GtkNotebook
4350 * Returns whether the tab label area has arrows for scrolling. See
4351 * gtk_notebook_set_scrollable().
4353 * Return value: %TRUE if arrows for scrolling are present
4356 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4358 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4360 return notebook->scrollable;
4363 /* Public GtkNotebook Popup Menu Methods:
4365 * gtk_notebook_popup_enable
4366 * gtk_notebook_popup_disable
4371 * gtk_notebook_popup_enable:
4372 * @notebook: a #GtkNotebook
4374 * Enables the popup menu: if the user clicks with the right mouse button on
4375 * the bookmarks, a menu with all the pages will be popped up.
4378 gtk_notebook_popup_enable (GtkNotebook *notebook)
4382 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4387 notebook->menu = gtk_menu_new ();
4388 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4390 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4391 gtk_notebook_menu_item_create (notebook, list);
4393 gtk_notebook_update_labels (notebook);
4394 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4395 GTK_WIDGET (notebook),
4396 gtk_notebook_menu_detacher);
4398 g_object_notify (G_OBJECT (notebook), "enable_popup");
4402 * gtk_notebook_popup_disable:
4403 * @notebook: a #GtkNotebook
4405 * Disables the popup menu.
4408 gtk_notebook_popup_disable (GtkNotebook *notebook)
4410 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4412 if (!notebook->menu)
4415 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4416 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4417 gtk_widget_destroy (notebook->menu);
4419 g_object_notify (G_OBJECT (notebook), "enable_popup");
4422 /* Public GtkNotebook Page Properties Functions:
4424 * gtk_notebook_get_tab_label
4425 * gtk_notebook_set_tab_label
4426 * gtk_notebook_set_tab_label_text
4427 * gtk_notebook_get_menu_label
4428 * gtk_notebook_set_menu_label
4429 * gtk_notebook_set_menu_label_text
4430 * gtk_notebook_set_tab_label_packing
4431 * gtk_notebook_query_tab_label_packing
4435 * gtk_notebook_get_tab_label:
4436 * @notebook: a #GtkNotebook
4439 * Returns the tab label widget for the page @child. %NULL is returned
4440 * if @child is not in @notebook or if no tab label has specifically
4441 * been set for @child.
4443 * Return value: the tab label
4446 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4451 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4452 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4454 list = CHECK_FIND_CHILD (notebook, child);
4458 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4461 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4465 * gtk_notebook_set_tab_label:
4466 * @notebook: a #GtkNotebook
4468 * @tab_label: the tab label widget to use, or %NULL for default tab
4471 * Changes the tab label for @child. If %NULL is specified
4472 * for @tab_label, then the page will have the label 'page N'.
4475 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4477 GtkWidget *tab_label)
4479 GtkNotebookPage *page;
4482 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4483 g_return_if_fail (GTK_IS_WIDGET (child));
4485 list = CHECK_FIND_CHILD (notebook, child);
4489 /* a NULL pointer indicates a default_tab setting, otherwise
4490 * we need to set the associated label
4494 if (page->tab_label == tab_label)
4497 gtk_notebook_remove_tab_label (notebook, page);
4501 page->default_tab = FALSE;
4502 page->tab_label = tab_label;
4503 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4507 page->default_tab = TRUE;
4508 page->tab_label = NULL;
4510 if (notebook->show_tabs)
4514 g_snprintf (string, sizeof(string), _("Page %u"),
4515 gtk_notebook_real_page_position (notebook, list));
4516 page->tab_label = gtk_label_new (string);
4517 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4521 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4523 gtk_widget_show (page->tab_label);
4524 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4526 gtk_widget_child_notify (child, "tab_label");
4530 * gtk_notebook_set_tab_label_text:
4531 * @notebook: a #GtkNotebook
4533 * @tab_text: the label text
4535 * Creates a new label and sets it as the tab label for the page
4536 * containing @child.
4539 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4541 const gchar *tab_text)
4543 GtkWidget *tab_label = NULL;
4545 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4548 tab_label = gtk_label_new (tab_text);
4549 gtk_notebook_set_tab_label (notebook, child, tab_label);
4550 gtk_widget_child_notify (child, "tab_label");
4554 * gtk_notebook_get_tab_label_text:
4555 * @notebook: a #GtkNotebook
4556 * @child: a widget contained in a page of @notebook
4558 * Retrieves the text of the tab label for the page containing
4561 * Returns value: the text of the tab label, or %NULL if the
4562 * tab label widget is not a #GtkLabel. The
4563 * string is owned by the widget and must not
4566 G_CONST_RETURN gchar *
4567 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4570 GtkWidget *tab_label;
4572 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4573 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4575 tab_label = gtk_notebook_get_tab_label (notebook, child);
4577 if (tab_label && GTK_IS_LABEL (tab_label))
4578 return gtk_label_get_text (GTK_LABEL (tab_label));
4584 * gtk_notebook_get_menu_label:
4585 * @notebook: a #GtkNotebook
4586 * @child: a widget contained in a page of @notebook
4588 * Retrieves the menu label widget of the page containing @child.
4590 * Return value: the menu label, or %NULL if the
4591 * notebook page does not have a menu label other
4592 * than the default (the tab label).
4595 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4600 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4601 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4603 list = CHECK_FIND_CHILD (notebook, child);
4607 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4610 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4614 * gtk_notebook_set_menu_label:
4615 * @notebook: a #GtkNotebook
4616 * @child: the child widget
4617 * @menu_label: the menu label, or NULL for default
4619 * Changes the menu label for the page containing @child.
4622 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4624 GtkWidget *menu_label)
4626 GtkNotebookPage *page;
4629 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4630 g_return_if_fail (GTK_IS_WIDGET (child));
4632 list = CHECK_FIND_CHILD (notebook, child);
4637 if (page->menu_label)
4640 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4641 page->menu_label->parent);
4643 if (!page->default_menu)
4644 gtk_widget_unref (page->menu_label);
4649 page->menu_label = menu_label;
4650 gtk_widget_ref (page->menu_label);
4651 gtk_object_sink (GTK_OBJECT(page->menu_label));
4652 page->default_menu = FALSE;
4655 page->default_menu = TRUE;
4658 gtk_notebook_menu_item_create (notebook, list);
4659 gtk_widget_child_notify (child, "menu_label");
4663 * gtk_notebook_set_menu_label_text:
4664 * @notebook: a #GtkNotebook
4665 * @child: the child widget
4666 * @menu_text: the label text
4668 * Creates a new label and sets it as the menu label of @child.
4671 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4673 const gchar *menu_text)
4675 GtkWidget *menu_label = NULL;
4677 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4680 menu_label = gtk_label_new (menu_text);
4681 gtk_notebook_set_menu_label (notebook, child, menu_label);
4682 gtk_widget_child_notify (child, "menu_label");
4686 * gtk_notebook_get_menu_label_text:
4687 * @notebook: a #GtkNotebook
4688 * @child: the child widget of a page of the notebook.
4690 * Retrieves the text of the menu label for the page containing
4693 * Returns value: the text of the tab label, or %NULL if the
4694 * widget does not have a menu label other than
4695 * the default menu label, or the menu label widget
4696 * is not a #GtkLabel. The string is owned by
4697 * the widget and must not be freed.
4699 G_CONST_RETURN gchar *
4700 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4703 GtkWidget *menu_label;
4705 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4706 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4708 menu_label = gtk_notebook_get_menu_label (notebook, child);
4710 if (menu_label && GTK_IS_LABEL (menu_label))
4711 return gtk_label_get_text (GTK_LABEL (menu_label));
4716 /* Helper function called when pages are reordered
4719 gtk_notebook_child_reordered (GtkNotebook *notebook,
4720 GtkNotebookPage *page)
4724 GtkWidget *menu_item;
4726 menu_item = page->menu_label->parent;
4727 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4728 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4729 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4732 gtk_notebook_update_labels (notebook);
4736 * gtk_notebook_set_tab_label_packing:
4737 * @notebook: a #GtkNotebook
4738 * @child: the child widget
4739 * @expand: whether to expand the bookmark or not
4740 * @fill: whether the bookmark should fill the allocated area or not
4741 * @pack_type: the position of the bookmark
4743 * Sets the packing parameters for the tab label of the page
4744 * containing @child. See gtk_box_pack_start() for the exact meaning
4745 * of the parameters.
4748 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4752 GtkPackType pack_type)
4754 GtkNotebookPage *page;
4757 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4758 g_return_if_fail (GTK_IS_WIDGET (child));
4760 list = CHECK_FIND_CHILD (notebook, child);
4765 expand = expand != FALSE;
4766 fill = fill != FALSE;
4767 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4770 gtk_widget_freeze_child_notify (child);
4771 page->expand = expand;
4772 gtk_widget_child_notify (child, "tab_expand");
4774 gtk_widget_child_notify (child, "tab_fill");
4775 if (page->pack != pack_type)
4777 page->pack = pack_type;
4778 gtk_notebook_child_reordered (notebook, page);
4780 gtk_widget_child_notify (child, "tab_pack");
4781 gtk_widget_child_notify (child, "position");
4782 if (notebook->show_tabs)
4783 gtk_notebook_pages_allocate (notebook);
4784 gtk_widget_thaw_child_notify (child);
4788 * gtk_notebook_query_tab_label_packing:
4789 * @notebook: a #GtkNotebook
4791 * @expand: location to store the expand value (or NULL)
4792 * @fill: location to store the fill value (or NULL)
4793 * @pack_type: location to store the pack_type (or NULL)
4795 * Query the packing attributes for the tab label of the page
4796 * containing @child.
4799 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4803 GtkPackType *pack_type)
4807 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4808 g_return_if_fail (GTK_IS_WIDGET (child));
4810 list = CHECK_FIND_CHILD (notebook, child);
4815 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
4817 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
4819 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
4823 * gtk_notebook_reorder_child:
4824 * @notebook: a #GtkNotebook
4825 * @child: the child to move
4826 * @position: the new position
4828 * Reorders the page containing @child, so that it appears in position
4829 * @position. Out of bounds @position will be clamped.
4832 gtk_notebook_reorder_child (GtkNotebook *notebook,
4836 GList *list, *new_list;
4837 GtkNotebookPage *page;
4840 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4841 g_return_if_fail (GTK_IS_WIDGET (child));
4843 list = CHECK_FIND_CHILD (notebook, child);
4847 old_pos = g_list_position (notebook->children, list);
4849 if (old_pos == position)
4853 notebook->children = g_list_delete_link (notebook->children, list);
4855 position = CLAMP (position, 0, g_list_length (notebook->children));
4857 notebook->children = g_list_insert (notebook->children, page, position);
4858 new_list = g_list_nth (notebook->children, position);
4860 /* Fix up GList references in GtkNotebook structure */
4861 if (notebook->first_tab == list)
4862 notebook->first_tab = new_list;
4863 if (notebook->focus_tab == list)
4864 notebook->focus_tab = new_list;
4866 gtk_widget_freeze_child_notify (child);
4868 /* Move around the menu items if necesary */
4869 gtk_notebook_child_reordered (notebook, page);
4870 gtk_widget_child_notify (child, "tab_pack");
4871 gtk_widget_child_notify (child, "position");
4873 if (notebook->show_tabs)
4874 gtk_notebook_pages_allocate (notebook);
4876 gtk_widget_thaw_child_notify (child);