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"
30 #include "gtkmenuitem.h"
32 #include <gdk/gdkkeysyms.h>
35 #include "gtkmarshalers.h"
36 #include "gtkbindings.h"
40 #define TAB_CURVATURE 1
42 #define ARROW_SPACING 0
43 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
44 #define NOTEBOOK_SCROLL_DELAY (100)
70 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
71 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
90 CHILD_PROP_MENU_LABEL,
92 CHILD_PROP_TAB_EXPAND,
97 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
99 struct _GtkNotebookPage
102 GtkWidget *tab_label;
103 GtkWidget *menu_label;
104 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
106 guint default_menu : 1; /* If true, we create the menu label ourself */
107 guint default_tab : 1; /* If true, we create the tab label ourself */
112 GtkRequisition requisition;
113 GtkAllocation allocation;
115 guint mnemonic_activate_signal;
118 #ifdef G_DISABLE_CHECKS
119 #define CHECK_FIND_CHILD(notebook, child) \
120 gtk_notebook_find_child (notebook, child, G_STRLOC)
122 #define CHECK_FIND_CHILD(notebook, child) \
123 gtk_notebook_find_child (notebook, child, NULL)
126 /*** GtkNotebook Methods ***/
127 static void gtk_notebook_class_init (GtkNotebookClass *klass);
128 static void gtk_notebook_init (GtkNotebook *notebook);
130 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
131 gboolean move_focus);
132 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
133 GtkNotebookTab type);
134 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
136 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
137 GtkDirectionType direction_type);
139 /*** GtkObject Methods ***/
140 static void gtk_notebook_destroy (GtkObject *object);
141 static void gtk_notebook_set_property (GObject *object,
145 static void gtk_notebook_get_property (GObject *object,
150 /*** GtkWidget Methods ***/
151 static void gtk_notebook_map (GtkWidget *widget);
152 static void gtk_notebook_unmap (GtkWidget *widget);
153 static void gtk_notebook_realize (GtkWidget *widget);
154 static void gtk_notebook_unrealize (GtkWidget *widget);
155 static void gtk_notebook_size_request (GtkWidget *widget,
156 GtkRequisition *requisition);
157 static void gtk_notebook_size_allocate (GtkWidget *widget,
158 GtkAllocation *allocation);
159 static gint gtk_notebook_expose (GtkWidget *widget,
160 GdkEventExpose *event);
161 static gint gtk_notebook_button_press (GtkWidget *widget,
162 GdkEventButton *event);
163 static gint gtk_notebook_button_release (GtkWidget *widget,
164 GdkEventButton *event);
165 static gint gtk_notebook_enter_notify (GtkWidget *widget,
166 GdkEventCrossing *event);
167 static gint gtk_notebook_leave_notify (GtkWidget *widget,
168 GdkEventCrossing *event);
169 static gint gtk_notebook_motion_notify (GtkWidget *widget,
170 GdkEventMotion *event);
171 static gint gtk_notebook_focus_in (GtkWidget *widget,
172 GdkEventFocus *event);
173 static gint gtk_notebook_focus_out (GtkWidget *widget,
174 GdkEventFocus *event);
175 static void gtk_notebook_grab_notify (GtkWidget *widget,
176 gboolean was_grabbed);
177 static void gtk_notebook_state_changed (GtkWidget *widget,
178 GtkStateType previous_state);
179 static void gtk_notebook_draw_focus (GtkWidget *widget);
180 static gint gtk_notebook_focus (GtkWidget *widget,
181 GtkDirectionType direction);
182 static void gtk_notebook_style_set (GtkWidget *widget,
185 /*** GtkContainer Methods ***/
186 static void gtk_notebook_set_child_property (GtkContainer *container,
191 static void gtk_notebook_get_child_property (GtkContainer *container,
196 static void gtk_notebook_add (GtkContainer *container,
198 static void gtk_notebook_remove (GtkContainer *container,
200 static void gtk_notebook_set_focus_child (GtkContainer *container,
202 static GType gtk_notebook_child_type (GtkContainer *container);
203 static void gtk_notebook_forall (GtkContainer *container,
204 gboolean include_internals,
205 GtkCallback callback,
206 gpointer callback_data);
208 /*** GtkNotebook Private Functions ***/
209 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
210 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
211 static void gtk_notebook_real_remove (GtkNotebook *notebook,
213 gboolean destroying);
214 static void gtk_notebook_update_labels (GtkNotebook *notebook);
215 static gint gtk_notebook_timer (GtkNotebook *notebook);
216 static gint gtk_notebook_page_compare (gconstpointer a,
218 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
220 const gchar *function);
221 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
223 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
226 gboolean find_visible);
228 /*** GtkNotebook Drawing Functions ***/
229 static void gtk_notebook_paint (GtkWidget *widget,
231 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
232 GtkNotebookPage *page,
234 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
235 GtkNotebookArrow arrow);
237 /*** GtkNotebook Size Allocate Functions ***/
238 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
239 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
240 GtkNotebookPage *page,
241 GtkAllocation *allocation);
242 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
248 /*** GtkNotebook Page Switch Methods ***/
249 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
250 GtkNotebookPage *page,
253 /*** GtkNotebook Page Switch Functions ***/
254 static void gtk_notebook_switch_page (GtkNotebook *notebook,
255 GtkNotebookPage *page,
257 static gint gtk_notebook_page_select (GtkNotebook *notebook,
258 gboolean move_focus);
259 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
261 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
262 GtkNotebookPage *page);
264 /*** GtkNotebook Menu Functions ***/
265 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
267 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
269 static void gtk_notebook_menu_detacher (GtkWidget *widget,
272 /*** GtkNotebook Private Setters ***/
273 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
274 gboolean homogeneous);
275 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
277 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
279 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
282 static gboolean focus_tabs_in (GtkNotebook *notebook);
283 static gboolean focus_child_in (GtkNotebook *notebook,
284 GtkDirectionType direction);
286 static GtkContainerClass *parent_class = NULL;
287 static guint notebook_signals[LAST_SIGNAL] = { 0 };
290 gtk_notebook_get_type (void)
292 static GType notebook_type = 0;
296 static const GTypeInfo notebook_info =
298 sizeof (GtkNotebookClass),
299 NULL, /* base_init */
300 NULL, /* base_finalize */
301 (GClassInitFunc) gtk_notebook_class_init,
302 NULL, /* class_finalize */
303 NULL, /* class_data */
304 sizeof (GtkNotebook),
306 (GInstanceInitFunc) gtk_notebook_init,
309 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
313 return notebook_type;
317 add_tab_bindings (GtkBindingSet *binding_set,
318 GdkModifierType modifiers,
319 GtkDirectionType direction)
321 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
323 GTK_TYPE_DIRECTION_TYPE, direction);
324 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
326 GTK_TYPE_DIRECTION_TYPE, direction);
330 add_arrow_bindings (GtkBindingSet *binding_set,
332 GtkDirectionType direction)
334 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
336 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
338 GTK_TYPE_DIRECTION_TYPE, direction);
339 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
341 GTK_TYPE_DIRECTION_TYPE, direction);
345 gtk_notebook_class_init (GtkNotebookClass *class)
347 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
348 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
349 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
350 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
351 GtkBindingSet *binding_set;
353 parent_class = g_type_class_peek_parent (class);
355 gobject_class->set_property = gtk_notebook_set_property;
356 gobject_class->get_property = gtk_notebook_get_property;
357 object_class->destroy = gtk_notebook_destroy;
359 widget_class->map = gtk_notebook_map;
360 widget_class->unmap = gtk_notebook_unmap;
361 widget_class->realize = gtk_notebook_realize;
362 widget_class->unrealize = gtk_notebook_unrealize;
363 widget_class->size_request = gtk_notebook_size_request;
364 widget_class->size_allocate = gtk_notebook_size_allocate;
365 widget_class->expose_event = gtk_notebook_expose;
366 widget_class->button_press_event = gtk_notebook_button_press;
367 widget_class->button_release_event = gtk_notebook_button_release;
368 widget_class->enter_notify_event = gtk_notebook_enter_notify;
369 widget_class->leave_notify_event = gtk_notebook_leave_notify;
370 widget_class->motion_notify_event = gtk_notebook_motion_notify;
371 widget_class->grab_notify = gtk_notebook_grab_notify;
372 widget_class->state_changed = gtk_notebook_state_changed;
373 widget_class->focus_in_event = gtk_notebook_focus_in;
374 widget_class->focus_out_event = gtk_notebook_focus_out;
375 widget_class->focus = gtk_notebook_focus;
376 widget_class->style_set = gtk_notebook_style_set;
378 container_class->add = gtk_notebook_add;
379 container_class->remove = gtk_notebook_remove;
380 container_class->forall = gtk_notebook_forall;
381 container_class->set_focus_child = gtk_notebook_set_focus_child;
382 container_class->get_child_property = gtk_notebook_get_child_property;
383 container_class->set_child_property = gtk_notebook_set_child_property;
384 container_class->child_type = gtk_notebook_child_type;
386 class->switch_page = gtk_notebook_real_switch_page;
388 class->focus_tab = gtk_notebook_focus_tab;
389 class->select_page = gtk_notebook_select_page;
390 class->change_current_page = gtk_notebook_change_current_page;
391 class->move_focus_out = gtk_notebook_move_focus_out;
393 g_object_class_install_property (gobject_class,
395 g_param_spec_int ("page",
397 _("The index of the current page"),
402 g_object_class_install_property (gobject_class,
404 g_param_spec_enum ("tab_pos",
406 _("Which side of the notebook holds the tabs"),
407 GTK_TYPE_POSITION_TYPE,
410 g_object_class_install_property (gobject_class,
412 g_param_spec_uint ("tab_border",
414 _("Width of the border around the tab labels"),
419 g_object_class_install_property (gobject_class,
421 g_param_spec_uint ("tab_hborder",
422 _("Horizontal Tab Border"),
423 _("Width of the horizontal border of tab labels"),
428 g_object_class_install_property (gobject_class,
430 g_param_spec_uint ("tab_vborder",
431 _("Vertical Tab Border"),
432 _("Width of the vertical border of tab labels"),
437 g_object_class_install_property (gobject_class,
439 g_param_spec_boolean ("show_tabs",
441 _("Whether tabs should be shown or not"),
444 g_object_class_install_property (gobject_class,
446 g_param_spec_boolean ("show_border",
448 _("Whether the border should be shown or not"),
451 g_object_class_install_property (gobject_class,
453 g_param_spec_boolean ("scrollable",
455 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
458 g_object_class_install_property (gobject_class,
460 g_param_spec_boolean ("enable_popup",
462 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
465 g_object_class_install_property (gobject_class,
467 g_param_spec_boolean ("homogeneous",
469 _("Whether tabs should have homogeneous sizes"),
473 gtk_container_class_install_child_property (container_class,
474 CHILD_PROP_TAB_LABEL,
475 g_param_spec_string ("tab_label",
477 _("The string displayed on the childs tab label"),
480 gtk_container_class_install_child_property (container_class,
481 CHILD_PROP_MENU_LABEL,
482 g_param_spec_string ("menu_label",
484 _("The string displayed in the childs menu entry"),
487 gtk_container_class_install_child_property (container_class,
489 g_param_spec_int ("position",
491 _("The index of the child in the parent"),
494 gtk_container_class_install_child_property (container_class,
495 CHILD_PROP_TAB_EXPAND,
496 g_param_spec_boolean ("tab_expand",
498 _("Whether to expand the childs tab or not"),
501 gtk_container_class_install_child_property (container_class,
503 g_param_spec_boolean ("tab_fill",
505 _("Wheather the childs tab should fill the allocated area or not"),
508 gtk_container_class_install_child_property (container_class,
510 g_param_spec_enum ("tab_pack",
512 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
513 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
517 * GtkNotebook:has-secondary-backward-stepper:
519 * The "has-secondary-backward-stepper" property determines whether
520 * a second backward arrow button is displayed on the opposite end
525 gtk_widget_class_install_style_property (widget_class,
526 g_param_spec_boolean ("has_secondary backward_stepper",
527 _("Secondary backward stepper"),
528 _("Display a second backward arrow button on the opposite end of the tab area"),
534 * GtkNotebook:has-secondary-forward-stepper:
536 * The "has-secondary-forward-stepper" property determines whether
537 * a second forward arrow button is displayed on the opposite end
542 gtk_widget_class_install_style_property (widget_class,
543 g_param_spec_boolean ("has_secondary_forward_stepper",
544 _("Secondary forward stepper"),
545 _("Display a second forward arrow button on the opposite end of the tab area"),
551 * GtkNotebook:has-backward-stepper:
553 * The "has-backward-stepper" property determines whether
554 * the standard backward arrow button is displayed.
558 gtk_widget_class_install_style_property (widget_class,
559 g_param_spec_boolean ("has_backward_stepper",
560 _("Backward stepper"),
561 _("Display the standard backward arrow button"),
567 * GtkNotebook:has-forward-stepper:
569 * The "has-forward-stepper" property determines whether
570 * the standard forward arrow button is displayed.
574 gtk_widget_class_install_style_property (widget_class,
575 g_param_spec_boolean ("has_forward_stepper",
576 _("Forward stepper"),
577 _("Display the standard forward arrow button"),
582 notebook_signals[SWITCH_PAGE] =
583 g_signal_new ("switch_page",
584 G_TYPE_FROM_CLASS (gobject_class),
586 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
588 _gtk_marshal_VOID__POINTER_UINT,
592 notebook_signals[FOCUS_TAB] =
593 g_signal_new ("focus_tab",
594 G_TYPE_FROM_CLASS (gobject_class),
595 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
596 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
598 _gtk_marshal_BOOLEAN__ENUM,
600 GTK_TYPE_NOTEBOOK_TAB);
601 notebook_signals[SELECT_PAGE] =
602 g_signal_new ("select_page",
603 G_TYPE_FROM_CLASS (gobject_class),
604 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
605 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
607 _gtk_marshal_BOOLEAN__BOOLEAN,
610 notebook_signals[CHANGE_CURRENT_PAGE] =
611 g_signal_new ("change_current_page",
612 G_TYPE_FROM_CLASS (gobject_class),
613 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
614 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
616 _gtk_marshal_VOID__INT,
619 notebook_signals[MOVE_FOCUS_OUT] =
620 g_signal_new ("move_focus_out",
621 G_TYPE_FROM_CLASS (gobject_class),
622 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
623 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
625 _gtk_marshal_VOID__ENUM,
627 GTK_TYPE_DIRECTION_TYPE);
630 binding_set = gtk_binding_set_by_class (class);
631 gtk_binding_entry_add_signal (binding_set,
634 G_TYPE_BOOLEAN, FALSE);
635 gtk_binding_entry_add_signal (binding_set,
638 G_TYPE_BOOLEAN, FALSE);
640 gtk_binding_entry_add_signal (binding_set,
643 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
644 gtk_binding_entry_add_signal (binding_set,
647 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
648 gtk_binding_entry_add_signal (binding_set,
651 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
652 gtk_binding_entry_add_signal (binding_set,
655 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
657 gtk_binding_entry_add_signal (binding_set,
658 GDK_Page_Up, GDK_CONTROL_MASK,
659 "change_current_page", 1,
661 gtk_binding_entry_add_signal (binding_set,
662 GDK_Page_Down, GDK_CONTROL_MASK,
663 "change_current_page", 1,
666 gtk_binding_entry_add_signal (binding_set,
667 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
668 "change_current_page", 1,
670 gtk_binding_entry_add_signal (binding_set,
671 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
672 "change_current_page", 1,
675 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
676 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
677 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
678 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
680 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
681 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
685 gtk_notebook_init (GtkNotebook *notebook)
687 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
688 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
690 notebook->cur_page = NULL;
691 notebook->children = NULL;
692 notebook->first_tab = NULL;
693 notebook->focus_tab = NULL;
694 notebook->event_window = NULL;
695 notebook->menu = NULL;
697 notebook->tab_hborder = 2;
698 notebook->tab_vborder = 2;
700 notebook->show_tabs = TRUE;
701 notebook->show_border = TRUE;
702 notebook->tab_pos = GTK_POS_TOP;
703 notebook->scrollable = FALSE;
704 notebook->in_child = 0;
705 notebook->click_child = 0;
706 notebook->button = 0;
707 notebook->need_timer = 0;
708 notebook->child_has_focus = FALSE;
709 notebook->have_visible_child = FALSE;
710 notebook->focus_out = FALSE;
712 notebook->has_before_previous = 1;
713 notebook->has_before_next = 0;
714 notebook->has_after_previous = 0;
715 notebook->has_after_next = 1;
719 gtk_notebook_select_page (GtkNotebook *notebook,
722 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
724 gtk_notebook_page_select (notebook, move_focus);
732 gtk_notebook_focus_tab (GtkNotebook *notebook,
737 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
741 case GTK_NOTEBOOK_TAB_FIRST:
742 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
744 gtk_notebook_switch_focus_tab (notebook, list);
746 case GTK_NOTEBOOK_TAB_LAST:
747 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
749 gtk_notebook_switch_focus_tab (notebook, list);
760 gtk_notebook_change_current_page (GtkNotebook *notebook,
763 GList *current = NULL;
765 if (notebook->cur_page)
766 current = g_list_find (notebook->children, notebook->cur_page);
770 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
771 offset += offset < 0 ? 1 : -1;
775 gtk_notebook_switch_page (notebook, current->data, -1);
777 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
780 static GtkDirectionType
781 get_effective_direction (GtkNotebook *notebook,
782 GtkDirectionType direction)
784 /* Remap the directions into the effective direction it would be for a
785 * GTK_POS_TOP notebook
788 #define D(rest) GTK_DIR_##rest
790 static const GtkDirectionType translate_direction[2][4][6] = {
791 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
792 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
793 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
794 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
795 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
796 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
797 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
798 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
803 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
805 return translate_direction[text_dir][notebook->tab_pos][direction];
809 get_effective_tab_pos (GtkNotebook *notebook)
811 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
813 switch (notebook->tab_pos)
816 return GTK_POS_RIGHT;
823 return notebook->tab_pos;
827 gtk_notebook_move_focus_out (GtkNotebook *notebook,
828 GtkDirectionType direction_type)
830 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
833 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
834 if (focus_tabs_in (notebook))
836 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
837 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
840 /* At this point, we know we should be focusing out of the notebook entirely. We
841 * do this by setting a flag, then propagating the focus motion to the notebook.
843 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
844 if (!GTK_WIDGET_TOPLEVEL (toplevel))
847 g_object_ref (notebook);
849 notebook->focus_out = TRUE;
850 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
851 notebook->focus_out = FALSE;
853 g_object_unref (notebook);
860 * Creates a new #GtkNotebook widget with no pages.
862 * Return value: the newly created #GtkNotebook
865 gtk_notebook_new (void)
867 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
870 /* Private GtkObject Methods :
872 * gtk_notebook_destroy
873 * gtk_notebook_set_arg
874 * gtk_notebook_get_arg
877 gtk_notebook_destroy (GtkObject *object)
880 GtkNotebook *notebook = GTK_NOTEBOOK (object);
883 gtk_notebook_popup_disable (notebook);
885 children = notebook->children;
888 GList *child = children;
889 children = child->next;
891 gtk_notebook_real_remove (notebook, child, TRUE);
894 GTK_OBJECT_CLASS (parent_class)->destroy (object);
898 gtk_notebook_set_property (GObject *object,
903 GtkNotebook *notebook;
905 notebook = GTK_NOTEBOOK (object);
910 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
912 case PROP_SHOW_BORDER:
913 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
915 case PROP_SCROLLABLE:
916 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
918 case PROP_ENABLE_POPUP:
919 if (g_value_get_boolean (value))
920 gtk_notebook_popup_enable (notebook);
922 gtk_notebook_popup_disable (notebook);
924 case PROP_HOMOGENEOUS:
925 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
928 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
931 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
933 case PROP_TAB_BORDER:
934 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
936 case PROP_TAB_HBORDER:
937 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
939 case PROP_TAB_VBORDER:
940 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
948 gtk_notebook_get_property (GObject *object,
953 GtkNotebook *notebook;
955 notebook = GTK_NOTEBOOK (object);
960 g_value_set_boolean (value, notebook->show_tabs);
962 case PROP_SHOW_BORDER:
963 g_value_set_boolean (value, notebook->show_border);
965 case PROP_SCROLLABLE:
966 g_value_set_boolean (value, notebook->scrollable);
968 case PROP_ENABLE_POPUP:
969 g_value_set_boolean (value, notebook->menu != NULL);
971 case PROP_HOMOGENEOUS:
972 g_value_set_boolean (value, notebook->homogeneous);
975 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
978 g_value_set_enum (value, notebook->tab_pos);
980 case PROP_TAB_HBORDER:
981 g_value_set_uint (value, notebook->tab_hborder);
983 case PROP_TAB_VBORDER:
984 g_value_set_uint (value, notebook->tab_vborder);
987 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
992 /* Private GtkWidget Methods :
996 * gtk_notebook_realize
997 * gtk_notebook_size_request
998 * gtk_notebook_size_allocate
999 * gtk_notebook_expose
1000 * gtk_notebook_button_press
1001 * gtk_notebook_button_release
1002 * gtk_notebook_enter_notify
1003 * gtk_notebook_leave_notify
1004 * gtk_notebook_motion_notify
1005 * gtk_notebook_focus_in
1006 * gtk_notebook_focus_out
1007 * gtk_notebook_draw_focus
1008 * gtk_notebook_style_set
1011 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1012 GdkRectangle *rectangle)
1014 GtkWidget *widget = GTK_WIDGET (notebook);
1015 gint border_width = GTK_CONTAINER (notebook)->border_width;
1016 GtkNotebookPage *visible_page = NULL;
1018 gint tab_pos = get_effective_tab_pos (notebook);
1020 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1022 GtkNotebookPage *page = tmp_list->data;
1023 if (GTK_WIDGET_VISIBLE (page->child))
1025 visible_page = page;
1030 if (notebook->show_tabs && visible_page)
1034 rectangle->x = widget->allocation.x + border_width;
1035 rectangle->y = widget->allocation.y + border_width;
1040 case GTK_POS_BOTTOM:
1041 rectangle->width = widget->allocation.width - 2 * border_width;
1042 rectangle->height = visible_page->requisition.height;
1043 if (tab_pos == GTK_POS_BOTTOM)
1044 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1048 rectangle->width = visible_page->requisition.width;
1049 rectangle->height = widget->allocation.height - 2 * border_width;
1050 if (tab_pos == GTK_POS_RIGHT)
1051 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1062 rectangle->x = rectangle->y = 0;
1063 rectangle->width = rectangle->height = 10;
1071 gtk_notebook_map (GtkWidget *widget)
1073 GtkNotebook *notebook;
1074 GtkNotebookPage *page;
1077 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1079 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1081 notebook = GTK_NOTEBOOK (widget);
1083 if (notebook->cur_page &&
1084 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1085 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1086 gtk_widget_map (notebook->cur_page->child);
1088 if (notebook->scrollable)
1089 gtk_notebook_pages_allocate (notebook);
1092 children = notebook->children;
1096 page = children->data;
1097 children = children->next;
1099 if (page->tab_label &&
1100 GTK_WIDGET_VISIBLE (page->tab_label) &&
1101 !GTK_WIDGET_MAPPED (page->tab_label))
1102 gtk_widget_map (page->tab_label);
1106 if (gtk_notebook_get_event_window_position (notebook, NULL))
1107 gdk_window_show_unraised (notebook->event_window);
1111 gtk_notebook_unmap (GtkWidget *widget)
1113 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1115 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1117 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1119 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1123 gtk_notebook_realize (GtkWidget *widget)
1125 GtkNotebook *notebook;
1126 GdkWindowAttr attributes;
1127 gint attributes_mask;
1128 GdkRectangle event_window_pos;
1130 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1132 notebook = GTK_NOTEBOOK (widget);
1133 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1135 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1137 widget->window = gtk_widget_get_parent_window (widget);
1138 g_object_ref (widget->window);
1140 attributes.window_type = GDK_WINDOW_CHILD;
1141 attributes.x = event_window_pos.x;
1142 attributes.y = event_window_pos.y;
1143 attributes.width = event_window_pos.width;
1144 attributes.height = event_window_pos.height;
1145 attributes.wclass = GDK_INPUT_ONLY;
1146 attributes.event_mask = gtk_widget_get_events (widget);
1147 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1148 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1150 attributes_mask = GDK_WA_X | GDK_WA_Y;
1152 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1153 &attributes, attributes_mask);
1154 gdk_window_set_user_data (notebook->event_window, notebook);
1156 widget->style = gtk_style_attach (widget->style, widget->window);
1160 gtk_notebook_unrealize (GtkWidget *widget)
1162 GtkNotebook *notebook;
1164 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1166 notebook = GTK_NOTEBOOK (widget);
1168 gdk_window_set_user_data (notebook->event_window, NULL);
1169 gdk_window_destroy (notebook->event_window);
1170 notebook->event_window = NULL;
1172 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1173 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1177 gtk_notebook_size_request (GtkWidget *widget,
1178 GtkRequisition *requisition)
1180 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1181 GtkNotebookPage *page;
1183 GtkRequisition child_requisition;
1184 gboolean switch_page = FALSE;
1188 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1190 widget->requisition.width = 0;
1191 widget->requisition.height = 0;
1193 for (children = notebook->children, vis_pages = 0; children;
1194 children = children->next)
1196 page = children->data;
1198 if (GTK_WIDGET_VISIBLE (page->child))
1201 gtk_widget_size_request (page->child, &child_requisition);
1203 widget->requisition.width = MAX (widget->requisition.width,
1204 child_requisition.width);
1205 widget->requisition.height = MAX (widget->requisition.height,
1206 child_requisition.height);
1208 if (notebook->menu && page->menu_label->parent &&
1209 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1210 gtk_widget_show (page->menu_label->parent);
1214 if (page == notebook->cur_page)
1216 if (notebook->menu && page->menu_label->parent &&
1217 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1218 gtk_widget_hide (page->menu_label->parent);
1222 if (notebook->show_border || notebook->show_tabs)
1224 widget->requisition.width += widget->style->xthickness * 2;
1225 widget->requisition.height += widget->style->ythickness * 2;
1227 if (notebook->show_tabs)
1230 gint tab_height = 0;
1234 for (children = notebook->children; children;
1235 children = children->next)
1237 page = children->data;
1239 if (GTK_WIDGET_VISIBLE (page->child))
1241 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1242 gtk_widget_show (page->tab_label);
1244 gtk_widget_size_request (page->tab_label,
1245 &child_requisition);
1247 page->requisition.width =
1248 child_requisition.width +
1249 2 * widget->style->xthickness;
1250 page->requisition.height =
1251 child_requisition.height +
1252 2 * widget->style->ythickness;
1254 switch (notebook->tab_pos)
1257 case GTK_POS_BOTTOM:
1258 page->requisition.height += 2 * (notebook->tab_vborder +
1260 tab_height = MAX (tab_height, page->requisition.height);
1261 tab_max = MAX (tab_max, page->requisition.width);
1265 page->requisition.width += 2 * (notebook->tab_hborder +
1267 tab_width = MAX (tab_width, page->requisition.width);
1268 tab_max = MAX (tab_max, page->requisition.height);
1272 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1273 gtk_widget_hide (page->tab_label);
1276 children = notebook->children;
1280 switch (notebook->tab_pos)
1283 case GTK_POS_BOTTOM:
1284 if (tab_height == 0)
1287 if (notebook->scrollable && vis_pages > 1 &&
1288 widget->requisition.width < tab_width)
1289 tab_height = MAX (tab_height, ARROW_SIZE);
1291 padding = 2 * (TAB_CURVATURE + focus_width +
1292 notebook->tab_hborder) - TAB_OVERLAP;
1296 page = children->data;
1297 children = children->next;
1299 if (!GTK_WIDGET_VISIBLE (page->child))
1302 if (notebook->homogeneous)
1303 page->requisition.width = tab_max;
1305 page->requisition.width += padding;
1307 tab_width += page->requisition.width;
1308 page->requisition.height = tab_height;
1311 if (notebook->scrollable && vis_pages > 1 &&
1312 widget->requisition.width < tab_width)
1313 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1315 if (notebook->homogeneous && !notebook->scrollable)
1316 widget->requisition.width = MAX (widget->requisition.width,
1317 vis_pages * tab_max +
1320 widget->requisition.width = MAX (widget->requisition.width,
1321 tab_width + TAB_OVERLAP);
1323 widget->requisition.height += tab_height;
1330 if (notebook->scrollable && vis_pages > 1 &&
1331 widget->requisition.height < tab_height)
1332 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1334 padding = 2 * (TAB_CURVATURE + focus_width +
1335 notebook->tab_vborder) - TAB_OVERLAP;
1340 page = children->data;
1341 children = children->next;
1343 if (!GTK_WIDGET_VISIBLE (page->child))
1346 page->requisition.width = tab_width;
1348 if (notebook->homogeneous)
1349 page->requisition.height = tab_max;
1351 page->requisition.height += padding;
1353 tab_height += page->requisition.height;
1356 if (notebook->scrollable && vis_pages > 1 &&
1357 widget->requisition.height < tab_height)
1358 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1360 widget->requisition.width += tab_width;
1362 if (notebook->homogeneous && !notebook->scrollable)
1363 widget->requisition.height =
1364 MAX (widget->requisition.height,
1365 vis_pages * tab_max + TAB_OVERLAP);
1367 widget->requisition.height =
1368 MAX (widget->requisition.height,
1369 tab_height + TAB_OVERLAP);
1371 if (!notebook->homogeneous || notebook->scrollable)
1373 widget->requisition.height = MAX (widget->requisition.height,
1374 vis_pages * tab_max +
1382 for (children = notebook->children; children;
1383 children = children->next)
1385 page = children->data;
1387 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1388 gtk_widget_hide (page->tab_label);
1393 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1394 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1400 for (children = notebook->children; children;
1401 children = children->next)
1403 page = children->data;
1404 if (GTK_WIDGET_VISIBLE (page->child))
1406 gtk_notebook_switch_page (notebook, page, -1);
1411 else if (GTK_WIDGET_VISIBLE (widget))
1413 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1414 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1417 if (vis_pages && !notebook->cur_page)
1419 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1422 notebook->first_tab = children;
1423 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1429 gtk_notebook_size_allocate (GtkWidget *widget,
1430 GtkAllocation *allocation)
1432 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1434 gint tab_pos = get_effective_tab_pos (notebook);
1436 widget->allocation = *allocation;
1437 if (GTK_WIDGET_REALIZED (widget))
1439 GdkRectangle position;
1441 if (gtk_notebook_get_event_window_position (notebook, &position))
1443 gdk_window_move_resize (notebook->event_window,
1444 position.x, position.y,
1445 position.width, position.height);
1446 if (GTK_WIDGET_MAPPED (notebook))
1447 gdk_window_show_unraised (notebook->event_window);
1450 gdk_window_hide (notebook->event_window);
1453 if (notebook->children)
1455 gint border_width = GTK_CONTAINER (widget)->border_width;
1456 GtkNotebookPage *page;
1457 GtkAllocation child_allocation;
1460 child_allocation.x = widget->allocation.x + border_width;
1461 child_allocation.y = widget->allocation.y + border_width;
1462 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1463 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1465 if (notebook->show_tabs || notebook->show_border)
1467 child_allocation.x += widget->style->xthickness;
1468 child_allocation.y += widget->style->ythickness;
1469 child_allocation.width = MAX (1, child_allocation.width -
1470 widget->style->xthickness * 2);
1471 child_allocation.height = MAX (1, child_allocation.height -
1472 widget->style->ythickness * 2);
1474 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1479 child_allocation.y += notebook->cur_page->requisition.height;
1480 case GTK_POS_BOTTOM:
1481 child_allocation.height =
1482 MAX (1, child_allocation.height -
1483 notebook->cur_page->requisition.height);
1486 child_allocation.x += notebook->cur_page->requisition.width;
1488 child_allocation.width =
1489 MAX (1, child_allocation.width -
1490 notebook->cur_page->requisition.width);
1496 children = notebook->children;
1499 page = children->data;
1500 children = children->next;
1502 if (GTK_WIDGET_VISIBLE (page->child))
1504 gtk_widget_size_allocate (page->child, &child_allocation);
1509 gtk_notebook_pages_allocate (notebook);
1512 if ((vis_pages != 0) != notebook->have_visible_child)
1514 notebook->have_visible_child = (vis_pages != 0);
1515 if (notebook->show_tabs)
1516 gtk_widget_queue_draw (widget);
1521 gtk_notebook_expose (GtkWidget *widget,
1522 GdkEventExpose *event)
1524 GtkNotebook *notebook;
1525 GdkRectangle child_area;
1527 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1528 g_return_val_if_fail (event != NULL, FALSE);
1530 if (GTK_WIDGET_DRAWABLE (widget))
1532 notebook = GTK_NOTEBOOK (widget);
1534 gtk_notebook_paint (widget, &event->area);
1535 if (notebook->show_tabs)
1537 if (notebook->cur_page &&
1538 gtk_widget_intersect (notebook->cur_page->tab_label,
1539 &event->area, &child_area))
1540 gtk_notebook_draw_focus (widget);
1544 if (notebook->cur_page)
1545 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1546 notebook->cur_page->child,
1554 gtk_notebook_show_arrows (GtkNotebook *notebook)
1556 gboolean show_arrow = FALSE;
1559 if (!notebook->scrollable)
1562 children = notebook->children;
1565 GtkNotebookPage *page = children->data;
1567 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1570 children = children->next;
1577 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1578 GdkRectangle *rectangle,
1579 GtkNotebookArrow arrow)
1581 GdkRectangle event_window_pos;
1582 gboolean before = ARROW_IS_BEFORE (arrow);
1583 gboolean left = ARROW_IS_LEFT (arrow);
1585 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1587 rectangle->width = ARROW_SIZE;
1588 rectangle->height = ARROW_SIZE;
1590 switch (notebook->tab_pos)
1594 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1595 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1596 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1598 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1600 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1601 rectangle->y = event_window_pos.y;
1603 rectangle->y += event_window_pos.height - rectangle->height;
1606 case GTK_POS_BOTTOM:
1609 if (left || !notebook->has_before_previous)
1610 rectangle->x = event_window_pos.x;
1612 rectangle->x = event_window_pos.x + rectangle->width;
1616 if (!left || !notebook->has_after_next)
1617 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1619 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1621 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1627 static GtkNotebookArrow
1628 gtk_notebook_get_arrow (GtkNotebook *notebook,
1632 GdkRectangle arrow_rect;
1633 GdkRectangle event_window_pos;
1636 GtkNotebookArrow arrow[4];
1638 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1639 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1640 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1641 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1643 if (gtk_notebook_show_arrows (notebook))
1645 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1646 for (i = 0; i < 4; i++)
1648 if (arrow[i] == ARROW_NONE)
1651 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1653 x0 = x - arrow_rect.x;
1654 y0 = y - arrow_rect.y;
1656 if (y0 >= 0 && y0 < arrow_rect.height &&
1657 x0 >= 0 && x0 < arrow_rect.width)
1666 gtk_notebook_do_arrow (GtkNotebook *notebook,
1667 GtkNotebookArrow arrow)
1669 GtkWidget *widget = GTK_WIDGET (notebook);
1670 GtkDirectionType dir;
1671 gboolean is_rtl, left;
1673 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1674 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1675 (!ARROW_IS_LEFT (arrow) && is_rtl);
1677 if (!notebook->focus_tab ||
1678 gtk_notebook_search_page (notebook, notebook->focus_tab,
1679 left ? STEP_PREV : STEP_NEXT,
1682 if (notebook->tab_pos == GTK_POS_LEFT ||
1683 notebook->tab_pos == GTK_POS_RIGHT)
1684 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1686 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1687 gtk_widget_child_focus (widget, dir);
1692 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1693 GtkNotebookArrow arrow,
1694 GdkEventButton *event)
1696 GtkWidget *widget = GTK_WIDGET (notebook);
1697 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1698 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1699 (!ARROW_IS_LEFT (arrow) && is_rtl);
1701 if (!GTK_WIDGET_HAS_FOCUS (widget))
1702 gtk_widget_grab_focus (widget);
1704 notebook->button = event->button;
1705 notebook->click_child = arrow;
1707 if (event->button == 1)
1709 gtk_notebook_do_arrow (notebook, arrow);
1711 if (!notebook->timer)
1713 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1714 (GSourceFunc) gtk_notebook_timer,
1715 (gpointer) notebook);
1716 notebook->need_timer = TRUE;
1719 else if (event->button == 2)
1720 gtk_notebook_page_select (notebook, TRUE);
1721 else if (event->button == 3)
1722 gtk_notebook_switch_focus_tab (notebook,
1723 gtk_notebook_search_page (notebook,
1725 left ? STEP_NEXT : STEP_PREV,
1727 gtk_notebook_redraw_arrows (notebook);
1733 get_widget_coordinates (GtkWidget *widget,
1738 GdkWindow *window = ((GdkEventAny *)event)->window;
1741 if (!gdk_event_get_coords (event, &tx, &ty))
1744 while (window && window != widget->window)
1746 gint window_x, window_y;
1748 gdk_window_get_position (window, &window_x, &window_y);
1752 window = gdk_window_get_parent (window);
1767 gtk_notebook_button_press (GtkWidget *widget,
1768 GdkEventButton *event)
1770 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1771 GtkNotebookPage *page;
1773 GtkNotebookArrow arrow;
1777 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1781 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1784 arrow = gtk_notebook_get_arrow (notebook, x, y);
1786 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1788 if (event->button == 3 && notebook->menu)
1790 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1791 NULL, NULL, 3, event->time);
1795 if (event->button != 1)
1799 children = notebook->children;
1802 page = children->data;
1804 if (GTK_WIDGET_VISIBLE (page->child) &&
1805 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1806 (x >= page->allocation.x) &&
1807 (y >= page->allocation.y) &&
1808 (x <= (page->allocation.x + page->allocation.width)) &&
1809 (y <= (page->allocation.y + page->allocation.height)))
1811 gboolean page_changed = page != notebook->cur_page;
1812 gboolean was_focus = gtk_widget_is_focus (widget);
1814 gtk_notebook_switch_focus_tab (notebook, children);
1815 gtk_widget_grab_focus (widget);
1817 if (page_changed && !was_focus)
1818 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1822 children = children->next;
1830 stop_scrolling (GtkNotebook *notebook)
1832 if (notebook->timer)
1834 g_source_remove (notebook->timer);
1835 notebook->timer = 0;
1836 notebook->need_timer = FALSE;
1838 notebook->click_child = 0;
1839 notebook->button = 0;
1840 gtk_notebook_redraw_arrows (notebook);
1844 gtk_notebook_button_release (GtkWidget *widget,
1845 GdkEventButton *event)
1847 GtkNotebook *notebook;
1849 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1850 g_return_val_if_fail (event != NULL, FALSE);
1852 if (event->type != GDK_BUTTON_RELEASE)
1855 notebook = GTK_NOTEBOOK (widget);
1857 if (event->button == notebook->button)
1859 stop_scrolling (notebook);
1868 gtk_notebook_enter_notify (GtkWidget *widget,
1869 GdkEventCrossing *event)
1871 GtkNotebook *notebook;
1872 GtkNotebookArrow arrow;
1875 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1876 g_return_val_if_fail (event != NULL, FALSE);
1878 notebook = GTK_NOTEBOOK (widget);
1880 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1883 arrow = gtk_notebook_get_arrow (notebook, x, y);
1885 if (arrow != notebook->in_child)
1887 notebook->in_child = arrow;
1888 gtk_notebook_redraw_arrows (notebook);
1897 gtk_notebook_leave_notify (GtkWidget *widget,
1898 GdkEventCrossing *event)
1900 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1901 GtkNotebookArrow arrow;
1904 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1907 arrow = gtk_notebook_get_arrow (notebook, x, y);
1909 if (notebook->in_child)
1911 notebook->in_child = 0;
1912 gtk_notebook_redraw_arrows (notebook);
1919 gtk_notebook_motion_notify (GtkWidget *widget,
1920 GdkEventMotion *event)
1922 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1923 GtkNotebookArrow arrow;
1926 if (notebook->button)
1929 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1932 arrow = gtk_notebook_get_arrow (notebook, x, y);
1934 if (arrow != notebook->in_child)
1936 notebook->in_child = arrow;
1937 gtk_notebook_redraw_arrows (notebook);
1944 gtk_notebook_grab_notify (GtkWidget *widget,
1945 gboolean was_grabbed)
1948 stop_scrolling (GTK_NOTEBOOK (widget));
1952 gtk_notebook_state_changed (GtkWidget *widget,
1953 GtkStateType previous_state)
1955 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1956 stop_scrolling (GTK_NOTEBOOK (widget));
1960 gtk_notebook_focus_in (GtkWidget *widget,
1961 GdkEventFocus *event)
1963 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1965 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
1971 gtk_notebook_focus_out (GtkWidget *widget,
1972 GdkEventFocus *event)
1974 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
1980 gtk_notebook_draw_focus (GtkWidget *widget)
1982 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1984 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1985 notebook->focus_tab)
1987 GtkNotebookPage *page;
1991 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1993 page = notebook->focus_tab->data;
1995 area.x = page->tab_label->allocation.x - focus_width;
1996 area.y = page->tab_label->allocation.y - focus_width;
1997 area.width = page->tab_label->allocation.width + 2 * focus_width;
1998 area.height = page->tab_label->allocation.height + 2 * focus_width;
2000 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2005 gtk_notebook_style_set (GtkWidget *widget,
2008 GtkNotebook *notebook;
2010 gboolean has_before_previous;
2011 gboolean has_before_next;
2012 gboolean has_after_previous;
2013 gboolean has_after_next;
2015 notebook = GTK_NOTEBOOK (widget);
2017 gtk_widget_style_get (widget,
2018 "has_backward_stepper", &has_before_previous,
2019 "has_secondary_forward_stepper", &has_before_next,
2020 "has_secondary_backward_stepper", &has_after_previous,
2021 "has_forward_stepper", &has_after_next,
2024 notebook->has_before_previous = has_before_previous;
2025 notebook->has_before_next = has_before_next;
2026 notebook->has_after_previous = has_after_previous;
2027 notebook->has_after_next = has_after_next;
2029 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2032 /* Private GtkContainer Methods :
2034 * gtk_notebook_set_child_arg
2035 * gtk_notebook_get_child_arg
2037 * gtk_notebook_remove
2038 * gtk_notebook_focus
2039 * gtk_notebook_set_focus_child
2040 * gtk_notebook_child_type
2041 * gtk_notebook_forall
2044 gtk_notebook_set_child_property (GtkContainer *container,
2047 const GValue *value,
2052 GtkPackType pack_type;
2054 /* not finding child's page is valid for menus or labels */
2055 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2058 switch (property_id)
2060 case CHILD_PROP_TAB_LABEL:
2061 /* a NULL pointer indicates a default_tab setting, otherwise
2062 * we need to set the associated label
2064 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2065 g_value_get_string (value));
2067 case CHILD_PROP_MENU_LABEL:
2068 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2069 g_value_get_string (value));
2071 case CHILD_PROP_POSITION:
2072 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2073 g_value_get_int (value));
2075 case CHILD_PROP_TAB_EXPAND:
2076 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2077 &expand, &fill, &pack_type);
2078 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2079 g_value_get_boolean (value),
2082 case CHILD_PROP_TAB_FILL:
2083 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2084 &expand, &fill, &pack_type);
2085 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2087 g_value_get_boolean (value),
2090 case CHILD_PROP_TAB_PACK:
2091 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2092 &expand, &fill, &pack_type);
2093 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2095 g_value_get_enum (value));
2098 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2104 gtk_notebook_get_child_property (GtkContainer *container,
2111 GtkNotebook *notebook;
2115 GtkPackType pack_type;
2117 notebook = GTK_NOTEBOOK (container);
2119 /* not finding child's page is valid for menus or labels */
2120 list = gtk_notebook_find_child (notebook, child, NULL);
2123 /* nothing to set on labels or menus */
2124 g_param_value_set_default (pspec, value);
2128 switch (property_id)
2130 case CHILD_PROP_TAB_LABEL:
2131 label = gtk_notebook_get_tab_label (notebook, child);
2133 if (label && GTK_IS_LABEL (label))
2134 g_value_set_string (value, GTK_LABEL (label)->label);
2136 g_value_set_string (value, NULL);
2138 case CHILD_PROP_MENU_LABEL:
2139 label = gtk_notebook_get_menu_label (notebook, child);
2141 if (label && GTK_IS_LABEL (label))
2142 g_value_set_string (value, GTK_LABEL (label)->label);
2144 g_value_set_string (value, NULL);
2146 case CHILD_PROP_POSITION:
2147 g_value_set_int (value, g_list_position (notebook->children, list));
2149 case CHILD_PROP_TAB_EXPAND:
2150 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2151 &expand, NULL, NULL);
2152 g_value_set_boolean (value, expand);
2154 case CHILD_PROP_TAB_FILL:
2155 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2157 g_value_set_boolean (value, fill);
2159 case CHILD_PROP_TAB_PACK:
2160 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2161 NULL, NULL, &pack_type);
2162 g_value_set_enum (value, pack_type);
2165 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2171 gtk_notebook_add (GtkContainer *container,
2174 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2176 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2181 gtk_notebook_remove (GtkContainer *container,
2184 GtkNotebook *notebook;
2185 GtkNotebookPage *page;
2188 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2189 g_return_if_fail (widget != NULL);
2191 notebook = GTK_NOTEBOOK (container);
2193 children = notebook->children;
2196 page = children->data;
2197 if (page->child == widget)
2199 gtk_notebook_real_remove (notebook, children, FALSE);
2202 children = children->next;
2207 focus_tabs_in (GtkNotebook *notebook)
2209 if (notebook->show_tabs && notebook->cur_page)
2211 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2213 gtk_notebook_switch_focus_tab (notebook,
2214 g_list_find (notebook->children,
2215 notebook->cur_page));
2224 focus_tabs_move (GtkNotebook *notebook,
2225 GtkDirectionType direction,
2226 gint search_direction)
2230 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2231 search_direction, TRUE);
2233 gtk_notebook_switch_focus_tab (notebook, new_page);
2235 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2241 focus_child_in (GtkNotebook *notebook,
2242 GtkDirectionType direction)
2244 if (notebook->cur_page)
2245 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2250 /* Focus in the notebook can either be on the pages, or on
2254 gtk_notebook_focus (GtkWidget *widget,
2255 GtkDirectionType direction)
2257 GtkWidget *old_focus_child;
2258 GtkNotebook *notebook;
2259 GtkDirectionType effective_direction;
2261 gboolean widget_is_focus;
2262 GtkContainer *container;
2264 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2266 container = GTK_CONTAINER (widget);
2267 notebook = GTK_NOTEBOOK (container);
2269 if (notebook->focus_out)
2271 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2275 widget_is_focus = gtk_widget_is_focus (widget);
2276 old_focus_child = container->focus_child;
2278 effective_direction = get_effective_direction (notebook, direction);
2280 if (old_focus_child) /* Focus on page child */
2282 if (gtk_widget_child_focus (old_focus_child, direction))
2285 switch (effective_direction)
2287 case GTK_DIR_TAB_BACKWARD:
2289 /* Focus onto the tabs */
2290 return focus_tabs_in (notebook);
2292 case GTK_DIR_TAB_FORWARD:
2298 else if (widget_is_focus) /* Focus was on tabs */
2300 switch (effective_direction)
2302 case GTK_DIR_TAB_BACKWARD:
2305 case GTK_DIR_TAB_FORWARD:
2307 /* We use TAB_FORWARD rather than direction so that we focus a more
2308 * predictable widget for the user; users may be using arrow focusing
2309 * in this situation even if they don't usually use arrow focusing.
2311 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2313 return focus_tabs_move (notebook, direction, STEP_PREV);
2315 return focus_tabs_move (notebook, direction, STEP_NEXT);
2318 else /* Focus was not on widget */
2320 switch (effective_direction)
2322 case GTK_DIR_TAB_FORWARD:
2324 if (focus_tabs_in (notebook))
2326 if (focus_child_in (notebook, direction))
2329 case GTK_DIR_TAB_BACKWARD:
2331 if (focus_child_in (notebook, direction))
2333 if (focus_tabs_in (notebook))
2338 return focus_child_in (notebook, direction);
2342 g_assert_not_reached ();
2347 gtk_notebook_set_focus_child (GtkContainer *container,
2350 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2351 GtkWidget *page_child;
2352 GtkWidget *toplevel;
2354 /* If the old focus widget was within a page of the notebook,
2355 * (child may either be NULL or not in this case), record it
2356 * for future use if we switch to the page with a mnemonic.
2359 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2360 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2362 page_child = GTK_WINDOW (toplevel)->focus_widget;
2365 if (page_child->parent == GTK_WIDGET (container))
2367 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2370 GtkNotebookPage *page = list->data;
2372 if (page->last_focus_child)
2373 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2375 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2376 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2382 page_child = page_child->parent;
2388 g_return_if_fail (GTK_IS_WIDGET (child));
2390 notebook->child_has_focus = TRUE;
2391 if (!notebook->focus_tab)
2394 GtkNotebookPage *page;
2396 children = notebook->children;
2399 page = children->data;
2400 if (page->child == child || page->tab_label == child)
2401 gtk_notebook_switch_focus_tab (notebook, children);
2402 children = children->next;
2407 parent_class->set_focus_child (container, child);
2411 gtk_notebook_forall (GtkContainer *container,
2412 gboolean include_internals,
2413 GtkCallback callback,
2414 gpointer callback_data)
2416 GtkNotebook *notebook;
2419 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2420 g_return_if_fail (callback != NULL);
2422 notebook = GTK_NOTEBOOK (container);
2424 children = notebook->children;
2427 GtkNotebookPage *page;
2429 page = children->data;
2430 children = children->next;
2431 (* callback) (page->child, callback_data);
2432 if (include_internals)
2434 if (page->tab_label)
2435 (* callback) (page->tab_label, callback_data);
2441 gtk_notebook_child_type (GtkContainer *container)
2443 return GTK_TYPE_WIDGET;
2446 /* Private GtkNotebook Functions:
2448 * gtk_notebook_redraw_tabs
2449 * gtk_notebook_real_remove
2450 * gtk_notebook_update_labels
2451 * gtk_notebook_timer
2452 * gtk_notebook_page_compare
2453 * gtk_notebook_real_page_position
2454 * gtk_notebook_search_page
2457 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2460 GtkNotebookPage *page;
2461 GdkRectangle redraw_rect;
2463 gint tab_pos = get_effective_tab_pos (notebook);
2465 widget = GTK_WIDGET (notebook);
2466 border = GTK_CONTAINER (notebook)->border_width;
2468 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2471 page = notebook->first_tab->data;
2473 redraw_rect.x = border;
2474 redraw_rect.y = border;
2478 case GTK_POS_BOTTOM:
2479 redraw_rect.y = (widget->allocation.height - border -
2480 page->allocation.height -
2481 widget->style->ythickness);
2482 if (page != notebook->cur_page)
2483 redraw_rect.y -= widget->style->ythickness;
2486 redraw_rect.width = widget->allocation.width - 2 * border;
2487 redraw_rect.height = (page->allocation.height +
2488 widget->style->ythickness);
2489 if (page != notebook->cur_page)
2490 redraw_rect.height += widget->style->ythickness;
2493 redraw_rect.x = (widget->allocation.width - border -
2494 page->allocation.width -
2495 widget->style->xthickness);
2496 if (page != notebook->cur_page)
2497 redraw_rect.x -= widget->style->xthickness;
2500 redraw_rect.width = (page->allocation.width +
2501 widget->style->xthickness);
2502 redraw_rect.height = widget->allocation.height - 2 * border;
2503 if (page != notebook->cur_page)
2504 redraw_rect.width += widget->style->xthickness;
2508 redraw_rect.x += widget->allocation.x;
2509 redraw_rect.y += widget->allocation.y;
2511 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2515 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2517 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2521 GtkNotebookArrow arrow[4];
2523 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2524 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2525 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2526 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2528 for (i = 0; i < 4; i++)
2530 if (arrow[i] == ARROW_NONE)
2533 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2534 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2541 gtk_notebook_timer (GtkNotebook *notebook)
2543 gboolean retval = FALSE;
2545 GDK_THREADS_ENTER ();
2547 if (notebook->timer)
2549 gtk_notebook_do_arrow (notebook, notebook->click_child);
2551 if (notebook->need_timer)
2553 notebook->need_timer = FALSE;
2554 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2555 (GSourceFunc) gtk_notebook_timer,
2556 (gpointer) notebook);
2562 GDK_THREADS_LEAVE ();
2568 gtk_notebook_page_compare (gconstpointer a,
2571 return (((GtkNotebookPage *) a)->child != b);
2575 gtk_notebook_find_child (GtkNotebook *notebook,
2577 const gchar *function)
2579 GList *list = g_list_find_custom (notebook->children, child,
2580 gtk_notebook_page_compare);
2582 #ifndef G_DISABLE_CHECKS
2583 if (!list && function)
2584 g_warning ("%s: unable to find child %p in notebook %p",
2585 function, child, notebook);
2592 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2593 GtkNotebookPage *page)
2595 if (page->tab_label)
2597 if (page->mnemonic_activate_signal)
2598 g_signal_handler_disconnect (page->tab_label,
2599 page->mnemonic_activate_signal);
2600 page->mnemonic_activate_signal = 0;
2602 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2603 gtk_widget_unparent (page->tab_label);
2608 gtk_notebook_real_remove (GtkNotebook *notebook,
2610 gboolean destroying)
2612 GtkNotebookPage *page;
2614 gint need_resize = FALSE;
2616 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2618 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2620 if (notebook->cur_page == list->data)
2622 notebook->cur_page = NULL;
2623 if (next_list && !destroying)
2624 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2627 if (list == notebook->first_tab)
2628 notebook->first_tab = next_list;
2629 if (list == notebook->focus_tab && !destroying)
2630 gtk_notebook_switch_focus_tab (notebook, next_list);
2634 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2637 gtk_widget_unparent (page->child);
2639 gtk_notebook_remove_tab_label (notebook, page);
2643 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2644 page->menu_label->parent);
2645 gtk_widget_queue_resize (notebook->menu);
2647 if (!page->default_menu)
2648 g_object_unref (page->menu_label);
2650 notebook->children = g_list_remove_link (notebook->children, list);
2653 if (page->last_focus_child)
2655 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2656 page->last_focus_child = NULL;
2661 gtk_notebook_update_labels (notebook);
2663 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2667 gtk_notebook_update_labels (GtkNotebook *notebook)
2669 GtkNotebookPage *page;
2674 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2676 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2679 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2680 if (notebook->show_tabs)
2682 if (page->default_tab)
2684 if (!page->tab_label)
2686 page->tab_label = gtk_label_new (string);
2687 gtk_widget_set_parent (page->tab_label,
2688 GTK_WIDGET (notebook));
2691 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2694 if (GTK_WIDGET_VISIBLE (page->child) &&
2695 !GTK_WIDGET_VISIBLE (page->tab_label))
2696 gtk_widget_show (page->tab_label);
2697 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2698 GTK_WIDGET_VISIBLE (page->tab_label))
2699 gtk_widget_hide (page->tab_label);
2701 if (notebook->menu && page->default_menu)
2703 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2704 gtk_label_set_text (GTK_LABEL (page->menu_label),
2705 GTK_LABEL (page->tab_label)->label);
2707 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2713 gtk_notebook_real_page_position (GtkNotebook *notebook,
2719 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2720 g_return_val_if_fail (list != NULL, -1);
2722 for (work = notebook->children, count_start = 0;
2723 work && work != list; work = work->next)
2724 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2730 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2733 return (count_start + g_list_length (list) - 1);
2737 gtk_notebook_search_page (GtkNotebook *notebook,
2740 gboolean find_visible)
2742 GtkNotebookPage *page = NULL;
2743 GList *old_list = NULL;
2746 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2751 flag = GTK_PACK_END;
2755 flag = GTK_PACK_START;
2762 if (!page || page->pack == flag)
2770 list = notebook->children;
2775 if (page->pack == flag &&
2776 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2791 if (page->pack != flag &&
2792 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2800 /* Private GtkNotebook Drawing Functions:
2802 * gtk_notebook_paint
2803 * gtk_notebook_draw_tab
2804 * gtk_notebook_draw_arrow
2807 gtk_notebook_paint (GtkWidget *widget,
2810 GtkNotebook *notebook;
2811 GtkNotebookPage *page;
2816 gint border_width = GTK_CONTAINER (widget)->border_width;
2817 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2821 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2822 g_return_if_fail (area != NULL);
2824 if (!GTK_WIDGET_DRAWABLE (widget))
2827 notebook = GTK_NOTEBOOK (widget);
2828 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2829 tab_pos = get_effective_tab_pos (notebook);
2831 if ((!notebook->show_tabs && !notebook->show_border) ||
2832 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2835 x = widget->allocation.x + border_width;
2836 y = widget->allocation.y + border_width;
2837 width = widget->allocation.width - border_width * 2;
2838 height = widget->allocation.height - border_width * 2;
2840 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2842 gtk_paint_box (widget->style, widget->window,
2843 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2844 area, widget, "notebook",
2845 x, y, width, height);
2850 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2852 page = notebook->first_tab->data;
2857 y += page->allocation.height + widget->style->ythickness;
2858 case GTK_POS_BOTTOM:
2859 height -= page->allocation.height + widget->style->ythickness;
2862 x += page->allocation.width + widget->style->xthickness;
2864 width -= page->allocation.width + widget->style->xthickness;
2867 gtk_paint_box (widget->style, widget->window,
2868 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2869 area, widget, "notebook",
2870 x, y, width, height);
2877 y += notebook->cur_page->allocation.height;
2878 case GTK_POS_BOTTOM:
2879 height -= notebook->cur_page->allocation.height;
2882 x += notebook->cur_page->allocation.width;
2884 width -= notebook->cur_page->allocation.width;
2891 case GTK_POS_BOTTOM:
2892 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2893 gap_width = notebook->cur_page->allocation.width;
2894 step = is_rtl ? STEP_NEXT : STEP_PREV;
2898 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2899 gap_width = notebook->cur_page->allocation.height;
2903 gtk_paint_box_gap (widget->style, widget->window,
2904 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2905 area, widget, "notebook",
2906 x, y, width, height,
2907 tab_pos, gap_x, gap_width);
2911 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2914 page = children->data;
2915 children = gtk_notebook_search_page (notebook, children,
2917 if (!GTK_WIDGET_VISIBLE (page->child))
2919 if (!GTK_WIDGET_MAPPED (page->tab_label))
2921 else if (page != notebook->cur_page)
2922 gtk_notebook_draw_tab (notebook, page, area);
2925 if (showarrow && notebook->scrollable)
2927 if (notebook->has_before_previous)
2928 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2929 if (notebook->has_before_next)
2930 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2931 if (notebook->has_after_previous)
2932 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2933 if (notebook->has_after_next)
2934 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2936 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2940 gtk_notebook_draw_tab (GtkNotebook *notebook,
2941 GtkNotebookPage *page,
2944 GdkRectangle child_area;
2945 GdkRectangle page_area;
2946 GtkStateType state_type;
2947 GtkPositionType gap_side;
2948 gint tab_pos = get_effective_tab_pos (notebook);
2950 g_return_if_fail (notebook != NULL);
2951 g_return_if_fail (page != NULL);
2952 g_return_if_fail (area != NULL);
2954 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2955 (page->allocation.width == 0) || (page->allocation.height == 0))
2958 page_area.x = page->allocation.x;
2959 page_area.y = page->allocation.y;
2960 page_area.width = page->allocation.width;
2961 page_area.height = page->allocation.height;
2963 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2967 widget = GTK_WIDGET (notebook);
2972 gap_side = GTK_POS_BOTTOM;
2974 case GTK_POS_BOTTOM:
2975 gap_side = GTK_POS_TOP;
2978 gap_side = GTK_POS_RIGHT;
2981 gap_side = GTK_POS_LEFT;
2985 if (notebook->cur_page == page)
2986 state_type = GTK_STATE_NORMAL;
2988 state_type = GTK_STATE_ACTIVE;
2989 gtk_paint_extension(widget->style, widget->window,
2990 state_type, GTK_SHADOW_OUT,
2991 area, widget, "tab",
2992 page_area.x, page_area.y,
2993 page_area.width, page_area.height,
2995 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2996 notebook->focus_tab && (notebook->focus_tab->data == page))
3000 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3002 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3003 area, widget, "tab",
3004 page->tab_label->allocation.x - focus_width,
3005 page->tab_label->allocation.y - focus_width,
3006 page->tab_label->allocation.width + 2 * focus_width,
3007 page->tab_label->allocation.height + 2 * focus_width);
3009 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3010 GTK_WIDGET_DRAWABLE (page->tab_label))
3012 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3014 /* This is a lame hack since all this code needs rewriting anyhow */
3016 expose_event->expose.window = g_object_ref (page->tab_label->window);
3017 expose_event->expose.area = child_area;
3018 expose_event->expose.region = gdk_region_rectangle (&child_area);
3019 expose_event->expose.send_event = TRUE;
3020 expose_event->expose.count = 0;
3022 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3024 gdk_event_free (expose_event);
3030 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3031 GtkNotebookArrow nbarrow)
3033 GtkStateType state_type;
3034 GtkShadowType shadow_type;
3036 GdkRectangle arrow_rect;
3038 gboolean is_rtl, left;
3040 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3042 widget = GTK_WIDGET (notebook);
3044 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3045 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3046 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3048 if (GTK_WIDGET_DRAWABLE (notebook))
3050 if (notebook->in_child == nbarrow)
3052 if (notebook->click_child == nbarrow)
3053 state_type = GTK_STATE_ACTIVE;
3055 state_type = GTK_STATE_PRELIGHT;
3058 state_type = GTK_WIDGET_STATE (widget);
3060 if (notebook->click_child == nbarrow)
3061 shadow_type = GTK_SHADOW_IN;
3063 shadow_type = GTK_SHADOW_OUT;
3065 if (notebook->focus_tab &&
3066 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3067 left? STEP_PREV : STEP_NEXT, TRUE))
3069 shadow_type = GTK_SHADOW_ETCHED_IN;
3070 state_type = GTK_STATE_INSENSITIVE;
3073 if (notebook->tab_pos == GTK_POS_LEFT ||
3074 notebook->tab_pos == GTK_POS_RIGHT)
3075 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3077 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3079 gtk_paint_arrow (widget->style, widget->window, state_type,
3080 shadow_type, NULL, widget, "notebook",
3081 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3082 ARROW_SIZE, ARROW_SIZE);
3086 /* Private GtkNotebook Size Allocate Functions:
3088 * gtk_notebook_pages_allocate
3089 * gtk_notebook_page_allocate
3090 * gtk_notebook_calc_tabs
3093 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3095 GtkWidget *widget = GTK_WIDGET (notebook);
3096 GtkContainer *container = GTK_CONTAINER (notebook);
3097 GtkNotebookPage *page = NULL;
3098 GtkAllocation *allocation = &widget->allocation;
3099 GtkAllocation child_allocation;
3100 GList *children = NULL;
3101 GList *last_child = NULL;
3102 gboolean showarrow = FALSE;
3109 gint tab_pos = get_effective_tab_pos (notebook);
3110 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3111 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3114 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3117 child_allocation.x = widget->allocation.x + container->border_width;
3118 child_allocation.y = widget->allocation.y + container->border_width;
3122 case GTK_POS_BOTTOM:
3123 child_allocation.y = (widget->allocation.y +
3124 allocation->height -
3125 notebook->cur_page->requisition.height -
3126 container->border_width);
3129 child_allocation.height = notebook->cur_page->requisition.height;
3133 child_allocation.x = (widget->allocation.x +
3135 notebook->cur_page->requisition.width -
3136 container->border_width);
3139 child_allocation.width = notebook->cur_page->requisition.width;
3143 if (notebook->scrollable)
3147 children = notebook->children;
3149 if (notebook->focus_tab)
3150 focus_tab = notebook->focus_tab;
3151 else if (notebook->first_tab)
3152 focus_tab = notebook->first_tab;
3154 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3159 case GTK_POS_BOTTOM:
3162 page = children->data;
3163 children = children->next;
3165 if (GTK_WIDGET_VISIBLE (page->child))
3166 tab_space += page->requisition.width;
3169 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3172 page = focus_tab->data;
3174 tab_space = allocation->width - TAB_OVERLAP -
3175 page->requisition.width - 2 * container->border_width;
3176 if (notebook->has_after_previous)
3177 tab_space -= ARROW_SPACING + ARROW_SIZE;
3178 if (notebook->has_after_next)
3179 tab_space -= ARROW_SPACING + ARROW_SIZE;
3180 if (notebook->has_before_previous)
3182 tab_space -= ARROW_SPACING + ARROW_SIZE;
3183 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3185 if (notebook->has_before_next)
3187 tab_space -= ARROW_SPACING + ARROW_SIZE;
3188 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3196 page = children->data;
3197 children = children->next;
3199 if (GTK_WIDGET_VISIBLE (page->child))
3200 tab_space += page->requisition.height;
3203 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3206 page = focus_tab->data;
3207 tab_space = allocation->height
3208 - TAB_OVERLAP - 2 * container->border_width
3209 - page->requisition.height;
3210 if (notebook->has_after_previous || notebook->has_after_next)
3211 tab_space -= ARROW_SPACING + ARROW_SIZE;
3212 if (notebook->has_before_previous || notebook->has_before_next)
3214 tab_space -= ARROW_SPACING + ARROW_SIZE;
3215 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3220 if (showarrow) /* first_tab <- focus_tab */
3224 notebook->first_tab = focus_tab;
3225 last_child = gtk_notebook_search_page (notebook, focus_tab,
3231 if (notebook->first_tab && notebook->first_tab != focus_tab)
3233 /* Is first_tab really predecessor of focus_tab ? */
3234 page = notebook->first_tab->data;
3235 if (GTK_WIDGET_VISIBLE (page->child))
3236 for (children = focus_tab;
3237 children && children != notebook->first_tab;
3238 children = gtk_notebook_search_page (notebook,
3244 notebook->first_tab = focus_tab;
3246 gtk_notebook_calc_tabs (notebook,
3247 gtk_notebook_search_page (notebook,
3251 &(notebook->first_tab), &tab_space,
3256 notebook->first_tab =
3257 gtk_notebook_search_page (notebook, notebook->first_tab,
3259 if (!notebook->first_tab)
3260 notebook->first_tab = focus_tab;
3261 last_child = gtk_notebook_search_page (notebook, focus_tab,
3264 else /* focus_tab -> end */
3266 if (!notebook->first_tab)
3267 notebook->first_tab = gtk_notebook_search_page (notebook,
3272 gtk_notebook_calc_tabs (notebook,
3273 gtk_notebook_search_page (notebook,
3277 &children, &tab_space, STEP_NEXT);
3280 last_child = children;
3281 else /* start <- first_tab */
3285 gtk_notebook_calc_tabs
3287 gtk_notebook_search_page (notebook,
3288 notebook->first_tab,
3291 &children, &tab_space, STEP_PREV);
3292 notebook->first_tab = gtk_notebook_search_page(notebook,
3302 tab_space = -tab_space;
3304 for (children = notebook->first_tab;
3305 children && children != last_child;
3306 children = gtk_notebook_search_page (notebook, children,
3313 /*unmap all non-visible tabs*/
3314 for (children = gtk_notebook_search_page (notebook, NULL,
3316 children && children != notebook->first_tab;
3317 children = gtk_notebook_search_page (notebook, children,
3320 page = children->data;
3321 if (page->tab_label)
3322 gtk_widget_set_child_visible (page->tab_label, FALSE);
3324 for (children = last_child; children;
3325 children = gtk_notebook_search_page (notebook, children,
3328 page = children->data;
3329 if (page->tab_label)
3330 gtk_widget_set_child_visible (page->tab_label, FALSE);
3333 else /* !showarrow */
3335 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3346 children = notebook->children;
3350 case GTK_POS_BOTTOM:
3353 page = children->data;
3354 children = children->next;
3356 if (GTK_WIDGET_VISIBLE (page->child))
3359 tab_space += page->requisition.width;
3364 tab_space -= allocation->width;
3370 page = children->data;
3371 children = children->next;
3373 if (GTK_WIDGET_VISIBLE (page->child))
3376 tab_space += page->requisition.height;
3381 tab_space -= allocation->height;
3383 tab_space += 2 * container->border_width + TAB_OVERLAP;
3385 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3387 if (notebook->homogeneous && n)
3391 children = notebook->first_tab;
3394 memo_x = child_allocation.x;
3395 if (notebook->children && is_rtl)
3397 child_allocation.x = (allocation->x + allocation->width -
3398 container->border_width);
3401 if (notebook->has_after_previous)
3402 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3403 if (notebook->has_after_next)
3404 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3410 if (children == last_child)
3412 /* FIXME double check */
3416 page = children->data;
3417 if (!showarrow && page->pack != GTK_PACK_START)
3419 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3422 if (n && (showarrow || page->expand || notebook->homogeneous))
3424 new_fill = (tab_space * i++) / n;
3425 delta = new_fill - old_fill;
3426 old_fill = new_fill;
3432 case GTK_POS_BOTTOM:
3433 child_allocation.width = (page->requisition.width +
3434 TAB_OVERLAP + delta);
3436 child_allocation.x -= child_allocation.width;
3440 child_allocation.height = (page->requisition.height +
3441 TAB_OVERLAP + delta);
3445 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3450 case GTK_POS_BOTTOM:
3452 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3454 child_allocation.x += TAB_OVERLAP;
3458 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3462 if (page->tab_label)
3463 gtk_widget_set_child_visible (page->tab_label, TRUE);
3468 children = notebook->children;
3473 case GTK_POS_BOTTOM:
3475 child_allocation.x = (allocation->x + allocation->width -
3476 container->border_width);
3478 child_allocation.x = memo_x;
3482 child_allocation.y = (allocation->y + allocation->height -
3483 container->border_width);
3487 while (children != last_child)
3489 page = children->data;
3490 children = children->next;
3492 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3496 if (n && (page->expand || notebook->homogeneous))
3498 new_fill = (tab_space * i++) / n;
3499 delta = new_fill - old_fill;
3500 old_fill = new_fill;
3506 case GTK_POS_BOTTOM:
3507 child_allocation.width = (page->requisition.width +
3508 TAB_OVERLAP + delta);
3510 child_allocation.x -= child_allocation.width;
3514 child_allocation.height = (page->requisition.height +
3515 TAB_OVERLAP + delta);
3516 child_allocation.y -= child_allocation.height;
3520 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3525 case GTK_POS_BOTTOM:
3527 child_allocation.x += TAB_OVERLAP;
3529 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3533 child_allocation.y += TAB_OVERLAP;
3537 if (page->tab_label)
3538 gtk_widget_set_child_visible (page->tab_label, TRUE);
3543 gtk_notebook_redraw_tabs (notebook);
3547 gtk_notebook_page_allocate (GtkNotebook *notebook,
3548 GtkNotebookPage *page,
3549 GtkAllocation *allocation)
3551 GtkWidget *widget = GTK_WIDGET (notebook);
3552 GtkAllocation child_allocation;
3553 GtkRequisition tab_requisition;
3558 gint tab_pos = get_effective_tab_pos (notebook);
3560 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3562 xthickness = widget->style->xthickness;
3563 ythickness = widget->style->ythickness;
3565 /* If the size of the notebook tabs change, we need to queue
3566 * a redraw on the tab area
3568 if ((allocation->width != page->allocation.width) ||
3569 (allocation->height != page->allocation.height))
3571 gint x, y, width, height, border_width;
3573 border_width = GTK_CONTAINER (notebook)->border_width;
3578 width = widget->allocation.width;
3579 height = MAX (page->allocation.height, allocation->height) + ythickness;
3584 case GTK_POS_BOTTOM:
3585 width = widget->allocation.width + xthickness;
3586 height = MAX (page->allocation.height, allocation->height) + ythickness;
3588 y = widget->allocation.height - height - border_width;
3592 width = MAX (page->allocation.width, allocation->width) + xthickness;
3593 height = widget->allocation.height;
3599 default: /* quiet gcc */
3600 width = MAX (page->allocation.width, allocation->width) + xthickness;
3601 height = widget->allocation.height;
3602 x = widget->allocation.width - width - border_width;
3607 gtk_widget_queue_draw_area (widget, x, y, width, height);
3610 page->allocation = *allocation;
3611 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3613 if (notebook->cur_page != page)
3618 page->allocation.y += ythickness;
3619 case GTK_POS_BOTTOM:
3620 if (page->allocation.height > ythickness)
3621 page->allocation.height -= ythickness;
3624 page->allocation.x += xthickness;
3626 if (page->allocation.width > xthickness)
3627 page->allocation.width -= xthickness;
3635 case GTK_POS_BOTTOM:
3636 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3639 child_allocation.x = (xthickness + focus_width +
3640 notebook->tab_hborder);
3641 child_allocation.width = MAX (1, (page->allocation.width -
3642 2 * child_allocation.x));
3643 child_allocation.x += page->allocation.x;
3647 child_allocation.x = (page->allocation.x +
3648 (page->allocation.width -
3649 tab_requisition.width) / 2);
3650 child_allocation.width = tab_requisition.width;
3652 child_allocation.y = (notebook->tab_vborder + focus_width +
3653 page->allocation.y);
3654 if (tab_pos == GTK_POS_TOP)
3655 child_allocation.y += ythickness;
3656 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3657 2 * (notebook->tab_vborder + focus_width)));
3661 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3664 child_allocation.y = ythickness + padding;
3665 child_allocation.height = MAX (1, (page->allocation.height -
3666 2 * child_allocation.y));
3667 child_allocation.y += page->allocation.y;
3671 child_allocation.y = (page->allocation.y + (page->allocation.height -
3672 tab_requisition.height) / 2);
3673 child_allocation.height = tab_requisition.height;
3675 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3676 if (tab_pos == GTK_POS_LEFT)
3677 child_allocation.x += xthickness;
3678 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3679 2 * (notebook->tab_hborder + focus_width)));
3683 if (page->tab_label)
3684 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3688 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3694 GtkNotebookPage *page = NULL;
3696 GList *last_list = NULL;
3698 gint tab_pos = get_effective_tab_pos (notebook);
3704 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3705 if (pack == GTK_PACK_END)
3706 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3713 case GTK_POS_BOTTOM:
3716 page = children->data;
3717 if (GTK_WIDGET_VISIBLE (page->child))
3719 if (page->pack == pack)
3721 *tab_space -= page->requisition.width;
3722 if (*tab_space < 0 || children == *end)
3726 *tab_space = - (*tab_space +
3727 page->requisition.width);
3733 last_list = children;
3735 if (direction == STEP_NEXT)
3736 children = children->next;
3738 children = children->prev;
3745 page = children->data;
3746 if (GTK_WIDGET_VISIBLE (page->child))
3748 if (page->pack == pack)
3750 *tab_space -= page->requisition.height;
3751 if (*tab_space < 0 || children == *end)
3755 *tab_space = - (*tab_space +
3756 page->requisition.height);
3762 last_list = children;
3764 if (direction == STEP_NEXT)
3765 children = children->next;
3767 children = children->prev;
3771 if (direction == STEP_PREV)
3773 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3774 direction = STEP_PREV;
3775 children = last_list;
3780 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3784 for (list = notebook->children; list != NULL; list = list->next)
3786 GtkNotebookPage *page = list->data;
3788 if (page->tab_label)
3790 if (page == notebook->cur_page)
3791 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3793 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3798 /* Private GtkNotebook Page Switch Methods:
3800 * gtk_notebook_real_switch_page
3803 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3804 GtkNotebookPage *page,
3807 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3808 g_return_if_fail (page != NULL);
3810 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3813 if (notebook->cur_page)
3814 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3816 notebook->cur_page = page;
3818 if (!notebook->focus_tab ||
3819 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3820 notebook->focus_tab =
3821 g_list_find (notebook->children, notebook->cur_page);
3823 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3825 /* If the focus was on the previous page, move it to the first
3826 * element on the new page, if possible, or if not, to the
3829 if (notebook->child_has_focus)
3831 if (notebook->cur_page->last_focus_child &&
3832 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3833 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3835 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3836 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3839 gtk_notebook_update_tab_states (notebook);
3840 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3841 g_object_notify (G_OBJECT (notebook), "page");
3844 /* Private GtkNotebook Page Switch Functions:
3846 * gtk_notebook_switch_page
3847 * gtk_notebook_page_select
3848 * gtk_notebook_switch_focus_tab
3849 * gtk_notebook_menu_switch_page
3852 gtk_notebook_switch_page (GtkNotebook *notebook,
3853 GtkNotebookPage *page,
3856 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3857 g_return_if_fail (page != NULL);
3859 if (notebook->cur_page == page)
3863 page_num = g_list_index (notebook->children, page);
3865 g_signal_emit (notebook,
3866 notebook_signals[SWITCH_PAGE],
3873 gtk_notebook_page_select (GtkNotebook *notebook,
3874 gboolean move_focus)
3876 GtkNotebookPage *page;
3877 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3878 gint tab_pos = get_effective_tab_pos (notebook);
3880 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3882 if (!notebook->focus_tab)
3885 page = notebook->focus_tab->data;
3886 gtk_notebook_switch_page (notebook, page, -1);
3895 case GTK_POS_BOTTOM:
3899 dir = GTK_DIR_RIGHT;
3906 if (gtk_widget_child_focus (page->child, dir))
3913 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3917 GtkNotebookPage *old_page = NULL;
3918 GtkNotebookPage *page;
3920 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3922 if (notebook->focus_tab == new_child)
3925 old_child = notebook->focus_tab;
3926 notebook->focus_tab = new_child;
3928 if (notebook->scrollable)
3929 gtk_notebook_redraw_arrows (notebook);
3931 if (!notebook->show_tabs || !notebook->focus_tab)
3935 old_page = old_child->data;
3937 page = notebook->focus_tab->data;
3938 if (GTK_WIDGET_MAPPED (page->tab_label))
3939 gtk_notebook_redraw_tabs (notebook);
3941 gtk_notebook_pages_allocate (notebook);
3943 gtk_notebook_switch_page (notebook, page,
3944 g_list_index (notebook->children, page));
3948 gtk_notebook_menu_switch_page (GtkWidget *widget,
3949 GtkNotebookPage *page)
3951 GtkNotebook *notebook;
3955 g_return_if_fail (widget != NULL);
3956 g_return_if_fail (page != NULL);
3958 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3959 (GTK_MENU (widget->parent)));
3961 if (notebook->cur_page == page)
3965 children = notebook->children;
3966 while (children && children->data != page)
3968 children = children->next;
3972 g_signal_emit (notebook,
3973 notebook_signals[SWITCH_PAGE],
3979 /* Private GtkNotebook Menu Functions:
3981 * gtk_notebook_menu_item_create
3982 * gtk_notebook_menu_label_unparent
3983 * gtk_notebook_menu_detacher
3986 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3989 GtkNotebookPage *page;
3990 GtkWidget *menu_item;
3993 if (page->default_menu)
3995 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3996 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3998 page->menu_label = gtk_label_new ("");
3999 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
4002 gtk_widget_show (page->menu_label);
4003 menu_item = gtk_menu_item_new ();
4004 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
4005 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
4006 gtk_notebook_real_page_position (notebook, list));
4007 g_signal_connect (menu_item, "activate",
4008 G_CALLBACK (gtk_notebook_menu_switch_page), page);
4009 if (GTK_WIDGET_VISIBLE (page->child))
4010 gtk_widget_show (menu_item);
4014 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4017 gtk_widget_unparent (GTK_BIN(widget)->child);
4018 GTK_BIN(widget)->child = NULL;
4022 gtk_notebook_menu_detacher (GtkWidget *widget,
4025 GtkNotebook *notebook;
4027 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4029 notebook = GTK_NOTEBOOK (widget);
4030 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4032 notebook->menu = NULL;
4035 /* Private GtkNotebook Setter Functions:
4037 * gtk_notebook_set_homogeneous_tabs_internal
4038 * gtk_notebook_set_tab_border_internal
4039 * gtk_notebook_set_tab_hborder_internal
4040 * gtk_notebook_set_tab_vborder_internal
4043 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4044 gboolean homogeneous)
4046 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4048 if (homogeneous == notebook->homogeneous)
4051 notebook->homogeneous = homogeneous;
4052 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4054 g_object_notify (G_OBJECT (notebook), "homogeneous");
4058 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4061 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4063 notebook->tab_hborder = border_width;
4064 notebook->tab_vborder = border_width;
4066 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4067 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4069 g_object_freeze_notify (G_OBJECT (notebook));
4070 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4071 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4072 g_object_thaw_notify (G_OBJECT (notebook));
4076 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4079 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4081 if (notebook->tab_hborder == tab_hborder)
4084 notebook->tab_hborder = tab_hborder;
4086 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4087 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4089 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4093 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4096 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4098 if (notebook->tab_vborder == tab_vborder)
4101 notebook->tab_vborder = tab_vborder;
4103 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4104 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4106 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4109 /* Public GtkNotebook Page Insert/Remove Methods :
4111 * gtk_notebook_append_page
4112 * gtk_notebook_append_page_menu
4113 * gtk_notebook_prepend_page
4114 * gtk_notebook_prepend_page_menu
4115 * gtk_notebook_insert_page
4116 * gtk_notebook_insert_page_menu
4117 * gtk_notebook_remove_page
4120 * gtk_notebook_append_page:
4121 * @notebook: a #GtkNotebook
4122 * @child: the #GtkWidget to use as the contents of the page.
4123 * @tab_label: the #GtkWidget to be used as the label for the page,
4124 * or %NULL to use the default label, 'page N'.
4126 * Appends a page to @notebook.
4129 gtk_notebook_append_page (GtkNotebook *notebook,
4131 GtkWidget *tab_label)
4133 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4134 g_return_if_fail (GTK_IS_WIDGET (child));
4135 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4137 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4141 * gtk_notebook_append_page_menu:
4142 * @notebook: a #GtkNotebook
4143 * @child: the #GtkWidget to use as the contents of the page.
4144 * @tab_label: the #GtkWidget to be used as the label for the page,
4145 * or %NULL to use the default label, 'page N'.
4146 * @menu_label: the widget to use as a label for the page-switch
4147 * menu, if that is enabled. If %NULL, and @tab_label
4148 * is a #GtkLabel or %NULL, then the menu label will be
4149 * a newly created label with the same text as @tab_label;
4150 * If @tab_label is not a #GtkLabel, @menu_label must be
4151 * specified if the page-switch menu is to be used.
4153 * Appends a page to @notebook, specifying the widget to use as the
4154 * label in the popup menu.
4157 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4159 GtkWidget *tab_label,
4160 GtkWidget *menu_label)
4162 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4163 g_return_if_fail (GTK_IS_WIDGET (child));
4164 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4165 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4167 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4171 * gtk_notebook_prepend_page:
4172 * @notebook: a #GtkNotebook
4173 * @child: the #GtkWidget to use as the contents of the page.
4174 * @tab_label: the #GtkWidget to be used as the label for the page,
4175 * or %NULL to use the default label, 'page N'.
4177 * Prepends a page to @notebook.
4180 gtk_notebook_prepend_page (GtkNotebook *notebook,
4182 GtkWidget *tab_label)
4184 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4185 g_return_if_fail (GTK_IS_WIDGET (child));
4186 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4188 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4192 * gtk_notebook_prepend_page_menu:
4193 * @notebook: a #GtkNotebook
4194 * @child: the #GtkWidget to use as the contents of the page.
4195 * @tab_label: the #GtkWidget to be used as the label for the page,
4196 * or %NULL to use the default label, 'page N'.
4197 * @menu_label: the widget to use as a label for the page-switch
4198 * menu, if that is enabled. If %NULL, and @tab_label
4199 * is a #GtkLabel or %NULL, then the menu label will be
4200 * a newly created label with the same text as @tab_label;
4201 * If @tab_label is not a #GtkLabel, @menu_label must be
4202 * specified if the page-switch menu is to be used.
4204 * Prepends a page to @notebook, specifying the widget to use as the
4205 * label in the popup menu.
4208 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4210 GtkWidget *tab_label,
4211 GtkWidget *menu_label)
4213 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4214 g_return_if_fail (GTK_IS_WIDGET (child));
4215 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4216 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4218 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4222 * gtk_notebook_insert_page:
4223 * @notebook: a #GtkNotebook
4224 * @child: the #GtkWidget to use as the contents of the page.
4225 * @tab_label: the #GtkWidget to be used as the label for the page,
4226 * or %NULL to use the default label, 'page N'.
4227 * @position: the index (starting at 0) at which to insert the page,
4228 * or -1 to append the page after all other pages.
4230 * Insert a page into @notebook at the given position
4233 gtk_notebook_insert_page (GtkNotebook *notebook,
4235 GtkWidget *tab_label,
4238 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4239 g_return_if_fail (GTK_IS_WIDGET (child));
4240 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4242 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4247 gtk_notebook_page_compare_tab (gconstpointer a,
4250 return (((GtkNotebookPage *) a)->tab_label != b);
4254 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4258 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4261 list = g_list_find_custom (notebook->children, child,
4262 gtk_notebook_page_compare_tab);
4265 GtkNotebookPage *page = list->data;
4267 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4268 gtk_notebook_switch_page (notebook, page, -1);
4269 focus_tabs_in (notebook);
4276 * gtk_notebook_insert_page_menu:
4277 * @notebook: a #GtkNotebook
4278 * @child: the #GtkWidget to use as the contents of the page.
4279 * @tab_label: the #GtkWidget to be used as the label for the page,
4280 * or %NULL to use the default label, 'page N'.
4281 * @menu_label: the widget to use as a label for the page-switch
4282 * menu, if that is enabled. If %NULL, and @tab_label
4283 * is a #GtkLabel or %NULL, then the menu label will be
4284 * a newly created label with the same text as @tab_label;
4285 * If @tab_label is not a #GtkLabel, @menu_label must be
4286 * specified if the page-switch menu is to be used.
4287 * @position: the index (starting at 0) at which to insert the page,
4288 * or -1 to append the page after all other pages.
4290 * Insert a page into @notebook at the given position, specifying
4291 * the widget to use as the label in the popup menu.
4294 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4296 GtkWidget *tab_label,
4297 GtkWidget *menu_label,
4300 GtkNotebookPage *page;
4303 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4304 g_return_if_fail (GTK_IS_WIDGET (child));
4305 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4306 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4308 gtk_widget_freeze_child_notify (child);
4310 page = g_new (GtkNotebookPage, 1);
4311 page->child = child;
4312 page->last_focus_child = NULL;
4313 page->requisition.width = 0;
4314 page->requisition.height = 0;
4315 page->allocation.x = 0;
4316 page->allocation.y = 0;
4317 page->allocation.width = 0;
4318 page->allocation.height = 0;
4319 page->default_menu = FALSE;
4320 page->default_tab = FALSE;
4321 page->mnemonic_activate_signal = 0;
4323 nchildren = g_list_length (notebook->children);
4324 if ((position < 0) || (position > nchildren))
4325 position = nchildren;
4327 notebook->children = g_list_insert (notebook->children, page, position);
4331 page->default_tab = TRUE;
4332 if (notebook->show_tabs)
4333 tab_label = gtk_label_new ("");
4335 page->tab_label = tab_label;
4336 page->menu_label = menu_label;
4337 page->expand = FALSE;
4339 page->pack = GTK_PACK_START;
4342 page->default_menu = TRUE;
4345 g_object_ref (page->menu_label);
4346 gtk_object_sink (GTK_OBJECT (page->menu_label));
4350 gtk_notebook_menu_item_create (notebook,
4351 g_list_find (notebook->children, page));
4353 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4355 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4357 gtk_notebook_update_labels (notebook);
4359 if (!notebook->first_tab)
4360 notebook->first_tab = notebook->children;
4362 if (!notebook->cur_page)
4363 gtk_widget_set_child_visible (child, TRUE);
4365 gtk_widget_set_child_visible (child, FALSE);
4369 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4370 gtk_widget_show (tab_label);
4372 gtk_widget_hide (tab_label);
4375 if (!notebook->cur_page)
4377 gtk_notebook_switch_page (notebook, page, 0);
4378 gtk_notebook_switch_focus_tab (notebook, NULL);
4381 gtk_notebook_update_tab_states (notebook);
4384 page->mnemonic_activate_signal =
4385 g_signal_connect (tab_label,
4386 "mnemonic_activate",
4387 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4390 gtk_widget_child_notify (child, "tab_expand");
4391 gtk_widget_child_notify (child, "tab_fill");
4392 gtk_widget_child_notify (child, "tab_pack");
4393 gtk_widget_child_notify (child, "tab_label");
4394 gtk_widget_child_notify (child, "menu_label");
4395 gtk_widget_child_notify (child, "position");
4396 gtk_widget_thaw_child_notify (child);
4400 * gtk_notebook_remove_page:
4401 * @notebook: a #GtkNotebook.
4402 * @page_num: the index of a notebook page, starting
4403 * from 0. If -1, the last page will
4406 * Removes a page from the notebook given its index
4410 gtk_notebook_remove_page (GtkNotebook *notebook,
4415 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4419 list = g_list_nth (notebook->children, page_num);
4421 gtk_notebook_real_remove (notebook, list, FALSE);
4425 list = g_list_last (notebook->children);
4427 gtk_notebook_real_remove (notebook, list, FALSE);
4431 /* Public GtkNotebook Page Switch Methods :
4432 * gtk_notebook_get_current_page
4433 * gtk_notebook_page_num
4434 * gtk_notebook_set_current_page
4435 * gtk_notebook_next_page
4436 * gtk_notebook_prev_page
4439 * gtk_notebook_get_current_page:
4440 * @notebook: a #GtkNotebook
4442 * Returns the page number of the current page.
4444 * Return value: the index (starting from 0) of the current
4445 * page in the notebook. If the notebook has no pages, then
4446 * -1 will be returned.
4449 gtk_notebook_get_current_page (GtkNotebook *notebook)
4451 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4453 if (!notebook->cur_page)
4456 return g_list_index (notebook->children, notebook->cur_page);
4460 * gtk_notebook_get_nth_page:
4461 * @notebook: a #GtkNotebook
4462 * @page_num: the index of a page in the noteobok, or -1
4463 * to get the last page.
4465 * Returns the child widget contained in page number @page_num.
4467 * Return value: the child widget, or %NULL if @page_num is
4471 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4474 GtkNotebookPage *page;
4477 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4480 list = g_list_nth (notebook->children, page_num);
4482 list = g_list_last (notebook->children);
4494 * gtk_notebook_get_n_pages:
4495 * @notebook: a #GtkNotebook
4497 * Gets the number of pages in a notebook.
4499 * Return value: the number of pages in the notebook.
4504 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4506 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4508 return g_list_length (notebook->children);
4512 * gtk_notebook_page_num:
4513 * @notebook: a #GtkNotebook
4514 * @child: a #GtkWidget
4516 * Finds the index of the page which contains the given child
4519 * Return value: the index of the page containing @child, or
4520 * -1 if @child is not in the notebook.
4523 gtk_notebook_page_num (GtkNotebook *notebook,
4529 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4532 children = notebook->children;
4535 GtkNotebookPage *page = children->data;
4537 if (page->child == child)
4540 children = children->next;
4548 * gtk_notebook_set_current_page:
4549 * @notebook: a #GtkNotebook
4550 * @page_num: index of the page to switch to, starting from 0.
4551 * If negative, the last page will be used. If greater
4552 * than the number of pages in the notebook, nothing
4555 * Switches to the page number @page_num.
4558 gtk_notebook_set_current_page (GtkNotebook *notebook,
4563 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4566 list = g_list_nth (notebook->children, page_num);
4568 list = g_list_last (notebook->children);
4570 page_num = g_list_index (notebook->children, list);
4573 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4577 * gtk_notebook_next_page:
4578 * @notebook: a #GtkNotebook
4580 * Switches to the next page. Nothing happens if the current page is
4584 gtk_notebook_next_page (GtkNotebook *notebook)
4588 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4590 list = g_list_find (notebook->children, notebook->cur_page);
4594 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4598 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4602 * gtk_notebook_prev_page:
4603 * @notebook: a #GtkNotebook
4605 * Switches to the previous page. Nothing happens if the current page
4606 * is the first page.
4609 gtk_notebook_prev_page (GtkNotebook *notebook)
4613 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4615 list = g_list_find (notebook->children, notebook->cur_page);
4619 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4623 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4626 /* Public GtkNotebook/Tab Style Functions
4628 * gtk_notebook_set_show_border
4629 * gtk_notebook_set_show_tabs
4630 * gtk_notebook_set_tab_pos
4631 * gtk_notebook_set_homogeneous_tabs
4632 * gtk_notebook_set_tab_border
4633 * gtk_notebook_set_tab_hborder
4634 * gtk_notebook_set_tab_vborder
4635 * gtk_notebook_set_scrollable
4638 * gtk_notebook_set_show_border:
4639 * @notebook: a #GtkNotebook
4640 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4642 * Sets whether a bevel will be drawn around the notebook pages.
4643 * This only has a visual effect when the tabs are not shown.
4644 * See gtk_notebook_set_show_tabs().
4647 gtk_notebook_set_show_border (GtkNotebook *notebook,
4648 gboolean show_border)
4650 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4652 if (notebook->show_border != show_border)
4654 notebook->show_border = show_border;
4656 if (GTK_WIDGET_VISIBLE (notebook))
4657 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4659 g_object_notify (G_OBJECT (notebook), "show_border");
4664 * gtk_notebook_get_show_border:
4665 * @notebook: a #GtkNotebook
4667 * Returns whether a bevel will be drawn around the notebook pages. See
4668 * gtk_notebook_set_show_border().
4670 * Return value: %TRUE if the bevel is drawn
4673 gtk_notebook_get_show_border (GtkNotebook *notebook)
4675 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4677 return notebook->show_border;
4681 * gtk_notebook_set_show_tabs:
4682 * @notebook: a #GtkNotebook
4683 * @show_tabs: %TRUE if the tabs should be shown.
4685 * Sets whether to show the tabs for the notebook or not.
4688 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4691 GtkNotebookPage *page;
4694 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4696 show_tabs = show_tabs != FALSE;
4698 if (notebook->show_tabs == show_tabs)
4701 notebook->show_tabs = show_tabs;
4702 children = notebook->children;
4706 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4710 page = children->data;
4711 children = children->next;
4712 if (page->default_tab)
4714 gtk_widget_destroy (page->tab_label);
4715 page->tab_label = NULL;
4718 gtk_widget_hide (page->tab_label);
4723 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4724 gtk_notebook_update_labels (notebook);
4726 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4728 g_object_notify (G_OBJECT (notebook), "show_tabs");
4732 * gtk_notebook_get_show_tabs:
4733 * @notebook: a #GtkNotebook
4735 * Returns whether the tabs of the notebook are shown. See
4736 * gtk_notebook_set_show_tabs().
4738 * Return value: %TRUE if the tabs are shown
4741 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4743 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4745 return notebook->show_tabs;
4749 * gtk_notebook_set_tab_pos:
4750 * @notebook: a #GtkNotebook.
4751 * @pos: the edge to draw the tabs at.
4753 * Sets the edge at which the tabs for switching pages in the
4754 * notebook are drawn.
4757 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4758 GtkPositionType pos)
4760 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4762 if (notebook->tab_pos != pos)
4764 notebook->tab_pos = pos;
4765 if (GTK_WIDGET_VISIBLE (notebook))
4766 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4769 g_object_notify (G_OBJECT (notebook), "tab_pos");
4773 * gtk_notebook_get_tab_pos:
4774 * @notebook: a #GtkNotebook
4776 * Gets the edge at which the tabs for switching pages in the
4777 * notebook are drawn.
4779 * Return value: the edge at which the tabs are drawn
4782 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4784 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4786 return notebook->tab_pos;
4790 * gtk_notebook_set_homogeneous_tabs:
4791 * @notebook: a #GtkNotebook
4792 * @homogeneous: %TRUE if all tabs should be the same size.
4794 * Sets whether the tabs must have all the same size or not.
4797 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4798 gboolean homogeneous)
4800 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4802 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4806 * gtk_notebook_set_tab_border:
4807 * @notebook: a #GtkNotebook
4808 * @border_width: width of the border around the tab labels.
4810 * Sets the width the border around the tab labels
4811 * in a notebook. This is equivalent to calling
4812 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4813 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4816 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4819 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4821 gtk_notebook_set_tab_border_internal (notebook, border_width);
4825 * gtk_notebook_set_tab_hborder:
4826 * @notebook: a #GtkNotebook
4827 * @tab_hborder: width of the horizontal border of tab labels.
4829 * Sets the width of the horizontal border of tab labels.
4832 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4835 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4837 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4841 * gtk_notebook_set_tab_vborder:
4842 * @notebook: a #GtkNotebook
4843 * @tab_vborder: width of the vertical border of tab labels.
4845 * Sets the width of the vertical border of tab labels.
4848 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4851 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4853 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4857 * gtk_notebook_set_scrollable:
4858 * @notebook: a #GtkNotebook
4859 * @scrollable: %TRUE if scroll arrows should be added
4861 * Sets whether the tab label area will have arrows for scrolling if
4862 * there are too many tabs to fit in the area.
4865 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4866 gboolean scrollable)
4868 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4870 scrollable = (scrollable != FALSE);
4872 if (scrollable != notebook->scrollable)
4874 notebook->scrollable = scrollable;
4876 if (GTK_WIDGET_VISIBLE (notebook))
4877 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4879 g_object_notify (G_OBJECT (notebook), "scrollable");
4884 * gtk_notebook_get_scrollable:
4885 * @notebook: a #GtkNotebook
4887 * Returns whether the tab label area has arrows for scrolling. See
4888 * gtk_notebook_set_scrollable().
4890 * Return value: %TRUE if arrows for scrolling are present
4893 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4895 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4897 return notebook->scrollable;
4900 /* Public GtkNotebook Popup Menu Methods:
4902 * gtk_notebook_popup_enable
4903 * gtk_notebook_popup_disable
4908 * gtk_notebook_popup_enable:
4909 * @notebook: a #GtkNotebook
4911 * Enables the popup menu: if the user clicks with the right mouse button on
4912 * the bookmarks, a menu with all the pages will be popped up.
4915 gtk_notebook_popup_enable (GtkNotebook *notebook)
4919 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4924 notebook->menu = gtk_menu_new ();
4925 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4927 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4928 gtk_notebook_menu_item_create (notebook, list);
4930 gtk_notebook_update_labels (notebook);
4931 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4932 GTK_WIDGET (notebook),
4933 gtk_notebook_menu_detacher);
4935 g_object_notify (G_OBJECT (notebook), "enable_popup");
4939 * gtk_notebook_popup_disable:
4940 * @notebook: a #GtkNotebook
4942 * Disables the popup menu.
4945 gtk_notebook_popup_disable (GtkNotebook *notebook)
4947 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4949 if (!notebook->menu)
4952 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4953 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4954 gtk_widget_destroy (notebook->menu);
4956 g_object_notify (G_OBJECT (notebook), "enable_popup");
4959 /* Public GtkNotebook Page Properties Functions:
4961 * gtk_notebook_get_tab_label
4962 * gtk_notebook_set_tab_label
4963 * gtk_notebook_set_tab_label_text
4964 * gtk_notebook_get_menu_label
4965 * gtk_notebook_set_menu_label
4966 * gtk_notebook_set_menu_label_text
4967 * gtk_notebook_set_tab_label_packing
4968 * gtk_notebook_query_tab_label_packing
4972 * gtk_notebook_get_tab_label:
4973 * @notebook: a #GtkNotebook
4976 * Returns the tab label widget for the page @child. %NULL is returned
4977 * if @child is not in @notebook or if no tab label has specifically
4978 * been set for @child.
4980 * Return value: the tab label
4983 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4988 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4989 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4991 list = CHECK_FIND_CHILD (notebook, child);
4995 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4998 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5002 * gtk_notebook_set_tab_label:
5003 * @notebook: a #GtkNotebook
5005 * @tab_label: the tab label widget to use, or %NULL for default tab
5008 * Changes the tab label for @child. If %NULL is specified
5009 * for @tab_label, then the page will have the label 'page N'.
5012 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5014 GtkWidget *tab_label)
5016 GtkNotebookPage *page;
5019 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5020 g_return_if_fail (GTK_IS_WIDGET (child));
5022 list = CHECK_FIND_CHILD (notebook, child);
5026 /* a NULL pointer indicates a default_tab setting, otherwise
5027 * we need to set the associated label
5031 if (page->tab_label == tab_label)
5035 gtk_notebook_remove_tab_label (notebook, page);
5039 page->default_tab = FALSE;
5040 page->tab_label = tab_label;
5041 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5045 page->default_tab = TRUE;
5046 page->tab_label = NULL;
5048 if (notebook->show_tabs)
5052 g_snprintf (string, sizeof(string), _("Page %u"),
5053 gtk_notebook_real_page_position (notebook, list));
5054 page->tab_label = gtk_label_new (string);
5055 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5059 if (page->tab_label)
5060 page->mnemonic_activate_signal =
5061 g_signal_connect (page->tab_label,
5062 "mnemonic_activate",
5063 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5066 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5068 gtk_widget_show (page->tab_label);
5069 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5072 gtk_notebook_update_tab_states (notebook);
5073 gtk_widget_child_notify (child, "tab_label");
5077 * gtk_notebook_set_tab_label_text:
5078 * @notebook: a #GtkNotebook
5080 * @tab_text: the label text
5082 * Creates a new label and sets it as the tab label for the page
5083 * containing @child.
5086 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5088 const gchar *tab_text)
5090 GtkWidget *tab_label = NULL;
5092 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5095 tab_label = gtk_label_new (tab_text);
5096 gtk_notebook_set_tab_label (notebook, child, tab_label);
5097 gtk_widget_child_notify (child, "tab_label");
5101 * gtk_notebook_get_tab_label_text:
5102 * @notebook: a #GtkNotebook
5103 * @child: a widget contained in a page of @notebook
5105 * Retrieves the text of the tab label for the page containing
5108 * Returns value: the text of the tab label, or %NULL if the
5109 * tab label widget is not a #GtkLabel. The
5110 * string is owned by the widget and must not
5113 G_CONST_RETURN gchar *
5114 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5117 GtkWidget *tab_label;
5119 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5120 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5122 tab_label = gtk_notebook_get_tab_label (notebook, child);
5124 if (tab_label && GTK_IS_LABEL (tab_label))
5125 return gtk_label_get_text (GTK_LABEL (tab_label));
5131 * gtk_notebook_get_menu_label:
5132 * @notebook: a #GtkNotebook
5133 * @child: a widget contained in a page of @notebook
5135 * Retrieves the menu label widget of the page containing @child.
5137 * Return value: the menu label, or %NULL if the
5138 * notebook page does not have a menu label other
5139 * than the default (the tab label).
5142 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5147 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5148 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5150 list = CHECK_FIND_CHILD (notebook, child);
5154 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5157 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5161 * gtk_notebook_set_menu_label:
5162 * @notebook: a #GtkNotebook
5163 * @child: the child widget
5164 * @menu_label: the menu label, or NULL for default
5166 * Changes the menu label for the page containing @child.
5169 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5171 GtkWidget *menu_label)
5173 GtkNotebookPage *page;
5176 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5177 g_return_if_fail (GTK_IS_WIDGET (child));
5179 list = CHECK_FIND_CHILD (notebook, child);
5184 if (page->menu_label)
5187 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5188 page->menu_label->parent);
5190 if (!page->default_menu)
5191 g_object_unref (page->menu_label);
5196 page->menu_label = menu_label;
5197 g_object_ref (page->menu_label);
5198 gtk_object_sink (GTK_OBJECT(page->menu_label));
5199 page->default_menu = FALSE;
5202 page->default_menu = TRUE;
5205 gtk_notebook_menu_item_create (notebook, list);
5206 gtk_widget_child_notify (child, "menu_label");
5210 * gtk_notebook_set_menu_label_text:
5211 * @notebook: a #GtkNotebook
5212 * @child: the child widget
5213 * @menu_text: the label text
5215 * Creates a new label and sets it as the menu label of @child.
5218 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5220 const gchar *menu_text)
5222 GtkWidget *menu_label = NULL;
5224 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5227 menu_label = gtk_label_new (menu_text);
5228 gtk_notebook_set_menu_label (notebook, child, menu_label);
5229 gtk_widget_child_notify (child, "menu_label");
5233 * gtk_notebook_get_menu_label_text:
5234 * @notebook: a #GtkNotebook
5235 * @child: the child widget of a page of the notebook.
5237 * Retrieves the text of the menu label for the page containing
5240 * Returns value: the text of the tab label, or %NULL if the
5241 * widget does not have a menu label other than
5242 * the default menu label, or the menu label widget
5243 * is not a #GtkLabel. The string is owned by
5244 * the widget and must not be freed.
5246 G_CONST_RETURN gchar *
5247 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5250 GtkWidget *menu_label;
5252 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5253 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5255 menu_label = gtk_notebook_get_menu_label (notebook, child);
5257 if (menu_label && GTK_IS_LABEL (menu_label))
5258 return gtk_label_get_text (GTK_LABEL (menu_label));
5263 /* Helper function called when pages are reordered
5266 gtk_notebook_child_reordered (GtkNotebook *notebook,
5267 GtkNotebookPage *page)
5271 GtkWidget *menu_item;
5273 menu_item = page->menu_label->parent;
5274 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5275 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5276 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5279 gtk_notebook_update_tab_states (notebook);
5280 gtk_notebook_update_labels (notebook);
5284 * gtk_notebook_set_tab_label_packing:
5285 * @notebook: a #GtkNotebook
5286 * @child: the child widget
5287 * @expand: whether to expand the bookmark or not
5288 * @fill: whether the bookmark should fill the allocated area or not
5289 * @pack_type: the position of the bookmark
5291 * Sets the packing parameters for the tab label of the page
5292 * containing @child. See gtk_box_pack_start() for the exact meaning
5293 * of the parameters.
5296 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5300 GtkPackType pack_type)
5302 GtkNotebookPage *page;
5305 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5306 g_return_if_fail (GTK_IS_WIDGET (child));
5308 list = CHECK_FIND_CHILD (notebook, child);
5313 expand = expand != FALSE;
5314 fill = fill != FALSE;
5315 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5318 gtk_widget_freeze_child_notify (child);
5319 page->expand = expand;
5320 gtk_widget_child_notify (child, "tab_expand");
5322 gtk_widget_child_notify (child, "tab_fill");
5323 if (page->pack != pack_type)
5325 page->pack = pack_type;
5326 gtk_notebook_child_reordered (notebook, page);
5328 gtk_widget_child_notify (child, "tab_pack");
5329 gtk_widget_child_notify (child, "position");
5330 if (notebook->show_tabs)
5331 gtk_notebook_pages_allocate (notebook);
5332 gtk_widget_thaw_child_notify (child);
5336 * gtk_notebook_query_tab_label_packing:
5337 * @notebook: a #GtkNotebook
5339 * @expand: location to store the expand value (or NULL)
5340 * @fill: location to store the fill value (or NULL)
5341 * @pack_type: location to store the pack_type (or NULL)
5343 * Query the packing attributes for the tab label of the page
5344 * containing @child.
5347 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5351 GtkPackType *pack_type)
5355 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5356 g_return_if_fail (GTK_IS_WIDGET (child));
5358 list = CHECK_FIND_CHILD (notebook, child);
5363 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5365 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5367 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5371 * gtk_notebook_reorder_child:
5372 * @notebook: a #GtkNotebook
5373 * @child: the child to move
5374 * @position: the new position, or -1 to move to the end
5376 * Reorders the page containing @child, so that it appears in position
5377 * @position. If @position is greater than or equal to the number of
5378 * children in the list or negative, @child will be moved to the end
5382 gtk_notebook_reorder_child (GtkNotebook *notebook,
5386 GList *list, *new_list;
5387 GtkNotebookPage *page;
5391 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5392 g_return_if_fail (GTK_IS_WIDGET (child));
5394 list = CHECK_FIND_CHILD (notebook, child);
5398 max_pos = g_list_length (notebook->children) - 1;
5399 if (position < 0 || position > max_pos)
5402 old_pos = g_list_position (notebook->children, list);
5404 if (old_pos == position)
5408 notebook->children = g_list_delete_link (notebook->children, list);
5410 notebook->children = g_list_insert (notebook->children, page, position);
5411 new_list = g_list_nth (notebook->children, position);
5413 /* Fix up GList references in GtkNotebook structure */
5414 if (notebook->first_tab == list)
5415 notebook->first_tab = new_list;
5416 if (notebook->focus_tab == list)
5417 notebook->focus_tab = new_list;
5419 gtk_widget_freeze_child_notify (child);
5421 /* Move around the menu items if necessary */
5422 gtk_notebook_child_reordered (notebook, page);
5423 gtk_widget_child_notify (child, "tab_pack");
5424 gtk_widget_child_notify (child, "position");
5426 if (notebook->show_tabs)
5427 gtk_notebook_pages_allocate (notebook);
5429 gtk_widget_thaw_child_notify (child);