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/.
29 #include "gtknotebook.h"
32 #include "gtkmenuitem.h"
34 #include <gdk/gdkkeysyms.h>
37 #include "gtkmarshalers.h"
38 #include "gtkbindings.h"
42 #define TAB_CURVATURE 1
44 #define ARROW_SPACING 0
45 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
46 #define NOTEBOOK_SCROLL_DELAY (100)
72 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
73 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
92 CHILD_PROP_MENU_LABEL,
94 CHILD_PROP_TAB_EXPAND,
99 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
101 struct _GtkNotebookPage
104 GtkWidget *tab_label;
105 GtkWidget *menu_label;
106 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
108 guint default_menu : 1; /* If true, we create the menu label ourself */
109 guint default_tab : 1; /* If true, we create the tab label ourself */
114 GtkRequisition requisition;
115 GtkAllocation allocation;
117 guint mnemonic_activate_signal;
120 #ifdef G_DISABLE_CHECKS
121 #define CHECK_FIND_CHILD(notebook, child) \
122 gtk_notebook_find_child (notebook, child, G_STRLOC)
124 #define CHECK_FIND_CHILD(notebook, child) \
125 gtk_notebook_find_child (notebook, child, NULL)
128 /*** GtkNotebook Methods ***/
129 static void gtk_notebook_class_init (GtkNotebookClass *klass);
130 static void gtk_notebook_init (GtkNotebook *notebook);
132 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
133 gboolean move_focus);
134 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
135 GtkNotebookTab type);
136 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
138 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
139 GtkDirectionType direction_type);
141 /*** GtkObject Methods ***/
142 static void gtk_notebook_destroy (GtkObject *object);
143 static void gtk_notebook_set_property (GObject *object,
147 static void gtk_notebook_get_property (GObject *object,
152 /*** GtkWidget Methods ***/
153 static void gtk_notebook_map (GtkWidget *widget);
154 static void gtk_notebook_unmap (GtkWidget *widget);
155 static void gtk_notebook_realize (GtkWidget *widget);
156 static void gtk_notebook_unrealize (GtkWidget *widget);
157 static void gtk_notebook_size_request (GtkWidget *widget,
158 GtkRequisition *requisition);
159 static void gtk_notebook_size_allocate (GtkWidget *widget,
160 GtkAllocation *allocation);
161 static gint gtk_notebook_expose (GtkWidget *widget,
162 GdkEventExpose *event);
163 static gboolean gtk_notebook_scroll (GtkWidget *widget,
164 GdkEventScroll *event);
165 static gint gtk_notebook_button_press (GtkWidget *widget,
166 GdkEventButton *event);
167 static gint gtk_notebook_button_release (GtkWidget *widget,
168 GdkEventButton *event);
169 static gint gtk_notebook_enter_notify (GtkWidget *widget,
170 GdkEventCrossing *event);
171 static gint gtk_notebook_leave_notify (GtkWidget *widget,
172 GdkEventCrossing *event);
173 static gint gtk_notebook_motion_notify (GtkWidget *widget,
174 GdkEventMotion *event);
175 static gint gtk_notebook_focus_in (GtkWidget *widget,
176 GdkEventFocus *event);
177 static gint gtk_notebook_focus_out (GtkWidget *widget,
178 GdkEventFocus *event);
179 static void gtk_notebook_grab_notify (GtkWidget *widget,
180 gboolean was_grabbed);
181 static void gtk_notebook_state_changed (GtkWidget *widget,
182 GtkStateType previous_state);
183 static void gtk_notebook_draw_focus (GtkWidget *widget);
184 static gint gtk_notebook_focus (GtkWidget *widget,
185 GtkDirectionType direction);
186 static void gtk_notebook_style_set (GtkWidget *widget,
189 /*** GtkContainer Methods ***/
190 static void gtk_notebook_set_child_property (GtkContainer *container,
195 static void gtk_notebook_get_child_property (GtkContainer *container,
200 static void gtk_notebook_add (GtkContainer *container,
202 static void gtk_notebook_remove (GtkContainer *container,
204 static void gtk_notebook_set_focus_child (GtkContainer *container,
206 static GType gtk_notebook_child_type (GtkContainer *container);
207 static void gtk_notebook_forall (GtkContainer *container,
208 gboolean include_internals,
209 GtkCallback callback,
210 gpointer callback_data);
212 /*** GtkNotebook Private Functions ***/
213 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
214 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
215 static void gtk_notebook_real_remove (GtkNotebook *notebook,
217 gboolean destroying);
218 static void gtk_notebook_update_labels (GtkNotebook *notebook);
219 static gint gtk_notebook_timer (GtkNotebook *notebook);
220 static gint gtk_notebook_page_compare (gconstpointer a,
222 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
224 const gchar *function);
225 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
227 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
230 gboolean find_visible);
232 /*** GtkNotebook Drawing Functions ***/
233 static void gtk_notebook_paint (GtkWidget *widget,
235 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
236 GtkNotebookPage *page,
238 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
239 GtkNotebookArrow arrow);
241 /*** GtkNotebook Size Allocate Functions ***/
242 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
243 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
244 GtkNotebookPage *page,
245 GtkAllocation *allocation);
246 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
252 /*** GtkNotebook Page Switch Methods ***/
253 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
254 GtkNotebookPage *page,
257 /*** GtkNotebook Page Switch Functions ***/
258 static void gtk_notebook_switch_page (GtkNotebook *notebook,
259 GtkNotebookPage *page,
261 static gint gtk_notebook_page_select (GtkNotebook *notebook,
262 gboolean move_focus);
263 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
265 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
266 GtkNotebookPage *page);
268 /*** GtkNotebook Menu Functions ***/
269 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
271 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
273 static void gtk_notebook_menu_detacher (GtkWidget *widget,
276 /*** GtkNotebook Private Setters ***/
277 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
278 gboolean homogeneous);
279 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
281 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
283 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
286 static gboolean focus_tabs_in (GtkNotebook *notebook);
287 static gboolean focus_child_in (GtkNotebook *notebook,
288 GtkDirectionType direction);
290 static GtkContainerClass *parent_class = NULL;
291 static guint notebook_signals[LAST_SIGNAL] = { 0 };
294 gtk_notebook_get_type (void)
296 static GType notebook_type = 0;
300 static const GTypeInfo notebook_info =
302 sizeof (GtkNotebookClass),
303 NULL, /* base_init */
304 NULL, /* base_finalize */
305 (GClassInitFunc) gtk_notebook_class_init,
306 NULL, /* class_finalize */
307 NULL, /* class_data */
308 sizeof (GtkNotebook),
310 (GInstanceInitFunc) gtk_notebook_init,
313 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
317 return notebook_type;
321 add_tab_bindings (GtkBindingSet *binding_set,
322 GdkModifierType modifiers,
323 GtkDirectionType direction)
325 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
327 GTK_TYPE_DIRECTION_TYPE, direction);
328 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
330 GTK_TYPE_DIRECTION_TYPE, direction);
334 add_arrow_bindings (GtkBindingSet *binding_set,
336 GtkDirectionType direction)
338 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
340 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
342 GTK_TYPE_DIRECTION_TYPE, direction);
343 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
345 GTK_TYPE_DIRECTION_TYPE, direction);
349 gtk_notebook_class_init (GtkNotebookClass *class)
351 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
352 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
353 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
354 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
355 GtkBindingSet *binding_set;
357 parent_class = g_type_class_peek_parent (class);
359 gobject_class->set_property = gtk_notebook_set_property;
360 gobject_class->get_property = gtk_notebook_get_property;
361 object_class->destroy = gtk_notebook_destroy;
363 widget_class->map = gtk_notebook_map;
364 widget_class->unmap = gtk_notebook_unmap;
365 widget_class->realize = gtk_notebook_realize;
366 widget_class->unrealize = gtk_notebook_unrealize;
367 widget_class->size_request = gtk_notebook_size_request;
368 widget_class->size_allocate = gtk_notebook_size_allocate;
369 widget_class->expose_event = gtk_notebook_expose;
370 widget_class->scroll_event = gtk_notebook_scroll;
371 widget_class->button_press_event = gtk_notebook_button_press;
372 widget_class->button_release_event = gtk_notebook_button_release;
373 widget_class->enter_notify_event = gtk_notebook_enter_notify;
374 widget_class->leave_notify_event = gtk_notebook_leave_notify;
375 widget_class->motion_notify_event = gtk_notebook_motion_notify;
376 widget_class->grab_notify = gtk_notebook_grab_notify;
377 widget_class->state_changed = gtk_notebook_state_changed;
378 widget_class->focus_in_event = gtk_notebook_focus_in;
379 widget_class->focus_out_event = gtk_notebook_focus_out;
380 widget_class->focus = gtk_notebook_focus;
381 widget_class->style_set = gtk_notebook_style_set;
383 container_class->add = gtk_notebook_add;
384 container_class->remove = gtk_notebook_remove;
385 container_class->forall = gtk_notebook_forall;
386 container_class->set_focus_child = gtk_notebook_set_focus_child;
387 container_class->get_child_property = gtk_notebook_get_child_property;
388 container_class->set_child_property = gtk_notebook_set_child_property;
389 container_class->child_type = gtk_notebook_child_type;
391 class->switch_page = gtk_notebook_real_switch_page;
393 class->focus_tab = gtk_notebook_focus_tab;
394 class->select_page = gtk_notebook_select_page;
395 class->change_current_page = gtk_notebook_change_current_page;
396 class->move_focus_out = gtk_notebook_move_focus_out;
398 g_object_class_install_property (gobject_class,
400 g_param_spec_int ("page",
402 P_("The index of the current page"),
407 g_object_class_install_property (gobject_class,
409 g_param_spec_enum ("tab-pos",
411 P_("Which side of the notebook holds the tabs"),
412 GTK_TYPE_POSITION_TYPE,
415 g_object_class_install_property (gobject_class,
417 g_param_spec_uint ("tab-border",
419 P_("Width of the border around the tab labels"),
424 g_object_class_install_property (gobject_class,
426 g_param_spec_uint ("tab-hborder",
427 P_("Horizontal Tab Border"),
428 P_("Width of the horizontal border of tab labels"),
433 g_object_class_install_property (gobject_class,
435 g_param_spec_uint ("tab-vborder",
436 P_("Vertical Tab Border"),
437 P_("Width of the vertical border of tab labels"),
442 g_object_class_install_property (gobject_class,
444 g_param_spec_boolean ("show-tabs",
446 P_("Whether tabs should be shown or not"),
449 g_object_class_install_property (gobject_class,
451 g_param_spec_boolean ("show-border",
453 P_("Whether the border should be shown or not"),
456 g_object_class_install_property (gobject_class,
458 g_param_spec_boolean ("scrollable",
460 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
463 g_object_class_install_property (gobject_class,
465 g_param_spec_boolean ("enable-popup",
467 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
470 g_object_class_install_property (gobject_class,
472 g_param_spec_boolean ("homogeneous",
474 P_("Whether tabs should have homogeneous sizes"),
478 gtk_container_class_install_child_property (container_class,
479 CHILD_PROP_TAB_LABEL,
480 g_param_spec_string ("tab-label",
482 P_("The string displayed on the child's tab label"),
485 gtk_container_class_install_child_property (container_class,
486 CHILD_PROP_MENU_LABEL,
487 g_param_spec_string ("menu-label",
489 P_("The string displayed in the child's menu entry"),
492 gtk_container_class_install_child_property (container_class,
494 g_param_spec_int ("position",
496 P_("The index of the child in the parent"),
499 gtk_container_class_install_child_property (container_class,
500 CHILD_PROP_TAB_EXPAND,
501 g_param_spec_boolean ("tab-expand",
503 P_("Whether to expand the child's tab or not"),
506 gtk_container_class_install_child_property (container_class,
508 g_param_spec_boolean ("tab-fill",
510 P_("Whether the child's tab should fill the allocated area or not"),
513 gtk_container_class_install_child_property (container_class,
515 g_param_spec_enum ("tab-pack",
517 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
518 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
522 * GtkNotebook:has-secondary-backward-stepper:
524 * The "has-secondary-backward-stepper" property determines whether
525 * a second backward arrow button is displayed on the opposite end
530 gtk_widget_class_install_style_property (widget_class,
531 g_param_spec_boolean ("has-secondary-backward-stepper",
532 P_("Secondary backward stepper"),
533 P_("Display a second backward arrow button on the opposite end of the tab area"),
539 * GtkNotebook:has-secondary-forward-stepper:
541 * The "has-secondary-forward-stepper" property determines whether
542 * a second forward arrow button is displayed on the opposite end
547 gtk_widget_class_install_style_property (widget_class,
548 g_param_spec_boolean ("has-secondary-forward-stepper",
549 P_("Secondary forward stepper"),
550 P_("Display a second forward arrow button on the opposite end of the tab area"),
556 * GtkNotebook:has-backward-stepper:
558 * The "has-backward-stepper" property determines whether
559 * the standard backward arrow button is displayed.
563 gtk_widget_class_install_style_property (widget_class,
564 g_param_spec_boolean ("has-backward-stepper",
565 P_("Backward stepper"),
566 P_("Display the standard backward arrow button"),
572 * GtkNotebook:has-forward-stepper:
574 * The "has-forward-stepper" property determines whether
575 * the standard forward arrow button is displayed.
579 gtk_widget_class_install_style_property (widget_class,
580 g_param_spec_boolean ("has-forward-stepper",
581 P_("Forward stepper"),
582 P_("Display the standard forward arrow button"),
587 notebook_signals[SWITCH_PAGE] =
588 g_signal_new ("switch_page",
589 G_TYPE_FROM_CLASS (gobject_class),
591 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
593 _gtk_marshal_VOID__POINTER_UINT,
597 notebook_signals[FOCUS_TAB] =
598 g_signal_new ("focus_tab",
599 G_TYPE_FROM_CLASS (gobject_class),
600 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
601 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
603 _gtk_marshal_BOOLEAN__ENUM,
605 GTK_TYPE_NOTEBOOK_TAB);
606 notebook_signals[SELECT_PAGE] =
607 g_signal_new ("select_page",
608 G_TYPE_FROM_CLASS (gobject_class),
609 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
610 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
612 _gtk_marshal_BOOLEAN__BOOLEAN,
615 notebook_signals[CHANGE_CURRENT_PAGE] =
616 g_signal_new ("change_current_page",
617 G_TYPE_FROM_CLASS (gobject_class),
618 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
619 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
621 _gtk_marshal_VOID__INT,
624 notebook_signals[MOVE_FOCUS_OUT] =
625 g_signal_new ("move_focus_out",
626 G_TYPE_FROM_CLASS (gobject_class),
627 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
628 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
630 _gtk_marshal_VOID__ENUM,
632 GTK_TYPE_DIRECTION_TYPE);
635 binding_set = gtk_binding_set_by_class (class);
636 gtk_binding_entry_add_signal (binding_set,
639 G_TYPE_BOOLEAN, FALSE);
640 gtk_binding_entry_add_signal (binding_set,
643 G_TYPE_BOOLEAN, FALSE);
645 gtk_binding_entry_add_signal (binding_set,
648 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
649 gtk_binding_entry_add_signal (binding_set,
652 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
653 gtk_binding_entry_add_signal (binding_set,
656 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
657 gtk_binding_entry_add_signal (binding_set,
660 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
662 gtk_binding_entry_add_signal (binding_set,
663 GDK_Page_Up, GDK_CONTROL_MASK,
664 "change_current_page", 1,
666 gtk_binding_entry_add_signal (binding_set,
667 GDK_Page_Down, GDK_CONTROL_MASK,
668 "change_current_page", 1,
671 gtk_binding_entry_add_signal (binding_set,
672 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
673 "change_current_page", 1,
675 gtk_binding_entry_add_signal (binding_set,
676 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
677 "change_current_page", 1,
680 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
681 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
682 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
683 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
685 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
686 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
690 gtk_notebook_init (GtkNotebook *notebook)
692 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
693 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
695 notebook->cur_page = NULL;
696 notebook->children = NULL;
697 notebook->first_tab = NULL;
698 notebook->focus_tab = NULL;
699 notebook->event_window = NULL;
700 notebook->menu = NULL;
702 notebook->tab_hborder = 2;
703 notebook->tab_vborder = 2;
705 notebook->show_tabs = TRUE;
706 notebook->show_border = TRUE;
707 notebook->tab_pos = GTK_POS_TOP;
708 notebook->scrollable = FALSE;
709 notebook->in_child = 0;
710 notebook->click_child = 0;
711 notebook->button = 0;
712 notebook->need_timer = 0;
713 notebook->child_has_focus = FALSE;
714 notebook->have_visible_child = FALSE;
715 notebook->focus_out = FALSE;
717 notebook->has_before_previous = 1;
718 notebook->has_before_next = 0;
719 notebook->has_after_previous = 0;
720 notebook->has_after_next = 1;
724 gtk_notebook_select_page (GtkNotebook *notebook,
727 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
729 gtk_notebook_page_select (notebook, move_focus);
737 gtk_notebook_focus_tab (GtkNotebook *notebook,
742 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
746 case GTK_NOTEBOOK_TAB_FIRST:
747 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
749 gtk_notebook_switch_focus_tab (notebook, list);
751 case GTK_NOTEBOOK_TAB_LAST:
752 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
754 gtk_notebook_switch_focus_tab (notebook, list);
765 gtk_notebook_change_current_page (GtkNotebook *notebook,
768 GList *current = NULL;
770 if (notebook->cur_page)
771 current = g_list_find (notebook->children, notebook->cur_page);
775 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
776 offset += offset < 0 ? 1 : -1;
780 gtk_notebook_switch_page (notebook, current->data, -1);
782 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
785 static GtkDirectionType
786 get_effective_direction (GtkNotebook *notebook,
787 GtkDirectionType direction)
789 /* Remap the directions into the effective direction it would be for a
790 * GTK_POS_TOP notebook
793 #define D(rest) GTK_DIR_##rest
795 static const GtkDirectionType translate_direction[2][4][6] = {
796 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
797 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
798 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
799 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
800 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
801 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
802 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
803 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
808 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
810 return translate_direction[text_dir][notebook->tab_pos][direction];
814 get_effective_tab_pos (GtkNotebook *notebook)
816 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
818 switch (notebook->tab_pos)
821 return GTK_POS_RIGHT;
828 return notebook->tab_pos;
832 gtk_notebook_move_focus_out (GtkNotebook *notebook,
833 GtkDirectionType direction_type)
835 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
838 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
839 if (focus_tabs_in (notebook))
841 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
842 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
845 /* At this point, we know we should be focusing out of the notebook entirely. We
846 * do this by setting a flag, then propagating the focus motion to the notebook.
848 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
849 if (!GTK_WIDGET_TOPLEVEL (toplevel))
852 g_object_ref (notebook);
854 notebook->focus_out = TRUE;
855 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
856 notebook->focus_out = FALSE;
858 g_object_unref (notebook);
865 * Creates a new #GtkNotebook widget with no pages.
867 * Return value: the newly created #GtkNotebook
870 gtk_notebook_new (void)
872 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
875 /* Private GtkObject Methods :
877 * gtk_notebook_destroy
878 * gtk_notebook_set_arg
879 * gtk_notebook_get_arg
882 gtk_notebook_destroy (GtkObject *object)
885 GtkNotebook *notebook = GTK_NOTEBOOK (object);
888 gtk_notebook_popup_disable (notebook);
890 children = notebook->children;
893 GList *child = children;
894 children = child->next;
896 gtk_notebook_real_remove (notebook, child, TRUE);
899 GTK_OBJECT_CLASS (parent_class)->destroy (object);
903 gtk_notebook_set_property (GObject *object,
908 GtkNotebook *notebook;
910 notebook = GTK_NOTEBOOK (object);
915 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
917 case PROP_SHOW_BORDER:
918 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
920 case PROP_SCROLLABLE:
921 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
923 case PROP_ENABLE_POPUP:
924 if (g_value_get_boolean (value))
925 gtk_notebook_popup_enable (notebook);
927 gtk_notebook_popup_disable (notebook);
929 case PROP_HOMOGENEOUS:
930 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
933 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
936 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
938 case PROP_TAB_BORDER:
939 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
941 case PROP_TAB_HBORDER:
942 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
944 case PROP_TAB_VBORDER:
945 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
953 gtk_notebook_get_property (GObject *object,
958 GtkNotebook *notebook;
960 notebook = GTK_NOTEBOOK (object);
965 g_value_set_boolean (value, notebook->show_tabs);
967 case PROP_SHOW_BORDER:
968 g_value_set_boolean (value, notebook->show_border);
970 case PROP_SCROLLABLE:
971 g_value_set_boolean (value, notebook->scrollable);
973 case PROP_ENABLE_POPUP:
974 g_value_set_boolean (value, notebook->menu != NULL);
976 case PROP_HOMOGENEOUS:
977 g_value_set_boolean (value, notebook->homogeneous);
980 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
983 g_value_set_enum (value, notebook->tab_pos);
985 case PROP_TAB_HBORDER:
986 g_value_set_uint (value, notebook->tab_hborder);
988 case PROP_TAB_VBORDER:
989 g_value_set_uint (value, notebook->tab_vborder);
992 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
997 /* Private GtkWidget Methods :
1000 * gtk_notebook_unmap
1001 * gtk_notebook_realize
1002 * gtk_notebook_size_request
1003 * gtk_notebook_size_allocate
1004 * gtk_notebook_expose
1005 * gtk_notebook_scroll
1006 * gtk_notebook_button_press
1007 * gtk_notebook_button_release
1008 * gtk_notebook_enter_notify
1009 * gtk_notebook_leave_notify
1010 * gtk_notebook_motion_notify
1011 * gtk_notebook_focus_in
1012 * gtk_notebook_focus_out
1013 * gtk_notebook_draw_focus
1014 * gtk_notebook_style_set
1017 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1018 GdkRectangle *rectangle)
1020 GtkWidget *widget = GTK_WIDGET (notebook);
1021 gint border_width = GTK_CONTAINER (notebook)->border_width;
1022 GtkNotebookPage *visible_page = NULL;
1024 gint tab_pos = get_effective_tab_pos (notebook);
1026 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1028 GtkNotebookPage *page = tmp_list->data;
1029 if (GTK_WIDGET_VISIBLE (page->child))
1031 visible_page = page;
1036 if (notebook->show_tabs && visible_page)
1040 rectangle->x = widget->allocation.x + border_width;
1041 rectangle->y = widget->allocation.y + border_width;
1046 case GTK_POS_BOTTOM:
1047 rectangle->width = widget->allocation.width - 2 * border_width;
1048 rectangle->height = visible_page->requisition.height;
1049 if (tab_pos == GTK_POS_BOTTOM)
1050 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1054 rectangle->width = visible_page->requisition.width;
1055 rectangle->height = widget->allocation.height - 2 * border_width;
1056 if (tab_pos == GTK_POS_RIGHT)
1057 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1068 rectangle->x = rectangle->y = 0;
1069 rectangle->width = rectangle->height = 10;
1077 gtk_notebook_map (GtkWidget *widget)
1079 GtkNotebook *notebook;
1080 GtkNotebookPage *page;
1083 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1085 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1087 notebook = GTK_NOTEBOOK (widget);
1089 if (notebook->cur_page &&
1090 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1091 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1092 gtk_widget_map (notebook->cur_page->child);
1094 if (notebook->scrollable)
1095 gtk_notebook_pages_allocate (notebook);
1098 children = notebook->children;
1102 page = children->data;
1103 children = children->next;
1105 if (page->tab_label &&
1106 GTK_WIDGET_VISIBLE (page->tab_label) &&
1107 !GTK_WIDGET_MAPPED (page->tab_label))
1108 gtk_widget_map (page->tab_label);
1112 if (gtk_notebook_get_event_window_position (notebook, NULL))
1113 gdk_window_show_unraised (notebook->event_window);
1117 gtk_notebook_unmap (GtkWidget *widget)
1119 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1121 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1123 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1125 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1129 gtk_notebook_realize (GtkWidget *widget)
1131 GtkNotebook *notebook;
1132 GdkWindowAttr attributes;
1133 gint attributes_mask;
1134 GdkRectangle event_window_pos;
1136 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1138 notebook = GTK_NOTEBOOK (widget);
1139 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1141 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1143 widget->window = gtk_widget_get_parent_window (widget);
1144 g_object_ref (widget->window);
1146 attributes.window_type = GDK_WINDOW_CHILD;
1147 attributes.x = event_window_pos.x;
1148 attributes.y = event_window_pos.y;
1149 attributes.width = event_window_pos.width;
1150 attributes.height = event_window_pos.height;
1151 attributes.wclass = GDK_INPUT_ONLY;
1152 attributes.event_mask = gtk_widget_get_events (widget);
1153 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1154 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1156 attributes_mask = GDK_WA_X | GDK_WA_Y;
1158 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1159 &attributes, attributes_mask);
1160 gdk_window_set_user_data (notebook->event_window, notebook);
1162 widget->style = gtk_style_attach (widget->style, widget->window);
1166 gtk_notebook_unrealize (GtkWidget *widget)
1168 GtkNotebook *notebook;
1170 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1172 notebook = GTK_NOTEBOOK (widget);
1174 gdk_window_set_user_data (notebook->event_window, NULL);
1175 gdk_window_destroy (notebook->event_window);
1176 notebook->event_window = NULL;
1178 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1179 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1183 gtk_notebook_size_request (GtkWidget *widget,
1184 GtkRequisition *requisition)
1186 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1187 GtkNotebookPage *page;
1189 GtkRequisition child_requisition;
1190 gboolean switch_page = FALSE;
1194 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1196 widget->requisition.width = 0;
1197 widget->requisition.height = 0;
1199 for (children = notebook->children, vis_pages = 0; children;
1200 children = children->next)
1202 page = children->data;
1204 if (GTK_WIDGET_VISIBLE (page->child))
1207 gtk_widget_size_request (page->child, &child_requisition);
1209 widget->requisition.width = MAX (widget->requisition.width,
1210 child_requisition.width);
1211 widget->requisition.height = MAX (widget->requisition.height,
1212 child_requisition.height);
1214 if (notebook->menu && page->menu_label->parent &&
1215 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1216 gtk_widget_show (page->menu_label->parent);
1220 if (page == notebook->cur_page)
1222 if (notebook->menu && page->menu_label->parent &&
1223 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1224 gtk_widget_hide (page->menu_label->parent);
1228 if (notebook->show_border || notebook->show_tabs)
1230 widget->requisition.width += widget->style->xthickness * 2;
1231 widget->requisition.height += widget->style->ythickness * 2;
1233 if (notebook->show_tabs)
1236 gint tab_height = 0;
1240 for (children = notebook->children; children;
1241 children = children->next)
1243 page = children->data;
1245 if (GTK_WIDGET_VISIBLE (page->child))
1247 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1248 gtk_widget_show (page->tab_label);
1250 gtk_widget_size_request (page->tab_label,
1251 &child_requisition);
1253 page->requisition.width =
1254 child_requisition.width +
1255 2 * widget->style->xthickness;
1256 page->requisition.height =
1257 child_requisition.height +
1258 2 * widget->style->ythickness;
1260 switch (notebook->tab_pos)
1263 case GTK_POS_BOTTOM:
1264 page->requisition.height += 2 * (notebook->tab_vborder +
1266 tab_height = MAX (tab_height, page->requisition.height);
1267 tab_max = MAX (tab_max, page->requisition.width);
1271 page->requisition.width += 2 * (notebook->tab_hborder +
1273 tab_width = MAX (tab_width, page->requisition.width);
1274 tab_max = MAX (tab_max, page->requisition.height);
1278 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1279 gtk_widget_hide (page->tab_label);
1282 children = notebook->children;
1286 switch (notebook->tab_pos)
1289 case GTK_POS_BOTTOM:
1290 if (tab_height == 0)
1293 if (notebook->scrollable && vis_pages > 1 &&
1294 widget->requisition.width < tab_width)
1295 tab_height = MAX (tab_height, ARROW_SIZE);
1297 padding = 2 * (TAB_CURVATURE + focus_width +
1298 notebook->tab_hborder) - TAB_OVERLAP;
1302 page = children->data;
1303 children = children->next;
1305 if (!GTK_WIDGET_VISIBLE (page->child))
1308 if (notebook->homogeneous)
1309 page->requisition.width = tab_max;
1311 page->requisition.width += padding;
1313 tab_width += page->requisition.width;
1314 page->requisition.height = tab_height;
1317 if (notebook->scrollable && vis_pages > 1 &&
1318 widget->requisition.width < tab_width)
1319 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1321 if (notebook->homogeneous && !notebook->scrollable)
1322 widget->requisition.width = MAX (widget->requisition.width,
1323 vis_pages * tab_max +
1326 widget->requisition.width = MAX (widget->requisition.width,
1327 tab_width + TAB_OVERLAP);
1329 widget->requisition.height += tab_height;
1336 if (notebook->scrollable && vis_pages > 1 &&
1337 widget->requisition.height < tab_height)
1338 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1340 padding = 2 * (TAB_CURVATURE + focus_width +
1341 notebook->tab_vborder) - TAB_OVERLAP;
1346 page = children->data;
1347 children = children->next;
1349 if (!GTK_WIDGET_VISIBLE (page->child))
1352 page->requisition.width = tab_width;
1354 if (notebook->homogeneous)
1355 page->requisition.height = tab_max;
1357 page->requisition.height += padding;
1359 tab_height += page->requisition.height;
1362 if (notebook->scrollable && vis_pages > 1 &&
1363 widget->requisition.height < tab_height)
1364 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1366 widget->requisition.width += tab_width;
1368 if (notebook->homogeneous && !notebook->scrollable)
1369 widget->requisition.height =
1370 MAX (widget->requisition.height,
1371 vis_pages * tab_max + TAB_OVERLAP);
1373 widget->requisition.height =
1374 MAX (widget->requisition.height,
1375 tab_height + TAB_OVERLAP);
1377 if (!notebook->homogeneous || notebook->scrollable)
1379 widget->requisition.height = MAX (widget->requisition.height,
1380 vis_pages * tab_max +
1388 for (children = notebook->children; children;
1389 children = children->next)
1391 page = children->data;
1393 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1394 gtk_widget_hide (page->tab_label);
1399 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1400 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1406 for (children = notebook->children; children;
1407 children = children->next)
1409 page = children->data;
1410 if (GTK_WIDGET_VISIBLE (page->child))
1412 gtk_notebook_switch_page (notebook, page, -1);
1417 else if (GTK_WIDGET_VISIBLE (widget))
1419 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1420 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1423 if (vis_pages && !notebook->cur_page)
1425 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1428 notebook->first_tab = children;
1429 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1435 gtk_notebook_size_allocate (GtkWidget *widget,
1436 GtkAllocation *allocation)
1438 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1440 gint tab_pos = get_effective_tab_pos (notebook);
1442 widget->allocation = *allocation;
1443 if (GTK_WIDGET_REALIZED (widget))
1445 GdkRectangle position;
1447 if (gtk_notebook_get_event_window_position (notebook, &position))
1449 gdk_window_move_resize (notebook->event_window,
1450 position.x, position.y,
1451 position.width, position.height);
1452 if (GTK_WIDGET_MAPPED (notebook))
1453 gdk_window_show_unraised (notebook->event_window);
1456 gdk_window_hide (notebook->event_window);
1459 if (notebook->children)
1461 gint border_width = GTK_CONTAINER (widget)->border_width;
1462 GtkNotebookPage *page;
1463 GtkAllocation child_allocation;
1466 child_allocation.x = widget->allocation.x + border_width;
1467 child_allocation.y = widget->allocation.y + border_width;
1468 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1469 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1471 if (notebook->show_tabs || notebook->show_border)
1473 child_allocation.x += widget->style->xthickness;
1474 child_allocation.y += widget->style->ythickness;
1475 child_allocation.width = MAX (1, child_allocation.width -
1476 widget->style->xthickness * 2);
1477 child_allocation.height = MAX (1, child_allocation.height -
1478 widget->style->ythickness * 2);
1480 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1485 child_allocation.y += notebook->cur_page->requisition.height;
1486 case GTK_POS_BOTTOM:
1487 child_allocation.height =
1488 MAX (1, child_allocation.height -
1489 notebook->cur_page->requisition.height);
1492 child_allocation.x += notebook->cur_page->requisition.width;
1494 child_allocation.width =
1495 MAX (1, child_allocation.width -
1496 notebook->cur_page->requisition.width);
1502 children = notebook->children;
1505 page = children->data;
1506 children = children->next;
1508 if (GTK_WIDGET_VISIBLE (page->child))
1510 gtk_widget_size_allocate (page->child, &child_allocation);
1515 gtk_notebook_pages_allocate (notebook);
1520 gtk_notebook_expose (GtkWidget *widget,
1521 GdkEventExpose *event)
1523 GtkNotebook *notebook;
1524 GdkRectangle child_area;
1526 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1527 g_return_val_if_fail (event != NULL, FALSE);
1529 if (GTK_WIDGET_DRAWABLE (widget))
1531 notebook = GTK_NOTEBOOK (widget);
1533 gtk_notebook_paint (widget, &event->area);
1534 if (notebook->show_tabs)
1536 if (notebook->cur_page &&
1537 gtk_widget_intersect (notebook->cur_page->tab_label,
1538 &event->area, &child_area))
1539 gtk_notebook_draw_focus (widget);
1543 if (notebook->cur_page)
1544 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1545 notebook->cur_page->child,
1553 gtk_notebook_show_arrows (GtkNotebook *notebook)
1555 gboolean show_arrow = FALSE;
1558 if (!notebook->scrollable)
1561 children = notebook->children;
1564 GtkNotebookPage *page = children->data;
1566 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1569 children = children->next;
1576 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1577 GdkRectangle *rectangle,
1578 GtkNotebookArrow arrow)
1580 GdkRectangle event_window_pos;
1581 gboolean before = ARROW_IS_BEFORE (arrow);
1582 gboolean left = ARROW_IS_LEFT (arrow);
1584 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1586 rectangle->width = ARROW_SIZE;
1587 rectangle->height = ARROW_SIZE;
1589 switch (notebook->tab_pos)
1593 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1594 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1595 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1597 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1599 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1600 rectangle->y = event_window_pos.y;
1602 rectangle->y += event_window_pos.height - rectangle->height;
1605 case GTK_POS_BOTTOM:
1608 if (left || !notebook->has_before_previous)
1609 rectangle->x = event_window_pos.x;
1611 rectangle->x = event_window_pos.x + rectangle->width;
1615 if (!left || !notebook->has_after_next)
1616 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1618 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1620 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1626 static GtkNotebookArrow
1627 gtk_notebook_get_arrow (GtkNotebook *notebook,
1631 GdkRectangle arrow_rect;
1632 GdkRectangle event_window_pos;
1635 GtkNotebookArrow arrow[4];
1637 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1638 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1639 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1640 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1642 if (gtk_notebook_show_arrows (notebook))
1644 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1645 for (i = 0; i < 4; i++)
1647 if (arrow[i] == ARROW_NONE)
1650 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1652 x0 = x - arrow_rect.x;
1653 y0 = y - arrow_rect.y;
1655 if (y0 >= 0 && y0 < arrow_rect.height &&
1656 x0 >= 0 && x0 < arrow_rect.width)
1665 gtk_notebook_do_arrow (GtkNotebook *notebook,
1666 GtkNotebookArrow arrow)
1668 GtkWidget *widget = GTK_WIDGET (notebook);
1669 GtkDirectionType dir;
1670 gboolean is_rtl, left;
1672 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1673 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1674 (!ARROW_IS_LEFT (arrow) && is_rtl);
1676 if (!notebook->focus_tab ||
1677 gtk_notebook_search_page (notebook, notebook->focus_tab,
1678 left ? STEP_PREV : STEP_NEXT,
1681 if (notebook->tab_pos == GTK_POS_LEFT ||
1682 notebook->tab_pos == GTK_POS_RIGHT)
1683 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1685 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1686 gtk_widget_child_focus (widget, dir);
1691 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1692 GtkNotebookArrow arrow,
1693 GdkEventButton *event)
1695 GtkWidget *widget = GTK_WIDGET (notebook);
1696 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1697 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1698 (!ARROW_IS_LEFT (arrow) && is_rtl);
1700 if (!GTK_WIDGET_HAS_FOCUS (widget))
1701 gtk_widget_grab_focus (widget);
1703 notebook->button = event->button;
1704 notebook->click_child = arrow;
1706 if (event->button == 1)
1708 gtk_notebook_do_arrow (notebook, arrow);
1710 if (!notebook->timer)
1712 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1713 (GSourceFunc) gtk_notebook_timer,
1714 (gpointer) notebook);
1715 notebook->need_timer = TRUE;
1718 else if (event->button == 2)
1719 gtk_notebook_page_select (notebook, TRUE);
1720 else if (event->button == 3)
1721 gtk_notebook_switch_focus_tab (notebook,
1722 gtk_notebook_search_page (notebook,
1724 left ? STEP_NEXT : STEP_PREV,
1726 gtk_notebook_redraw_arrows (notebook);
1732 get_widget_coordinates (GtkWidget *widget,
1737 GdkWindow *window = ((GdkEventAny *)event)->window;
1740 if (!gdk_event_get_coords (event, &tx, &ty))
1743 while (window && window != widget->window)
1745 gint window_x, window_y;
1747 gdk_window_get_position (window, &window_x, &window_y);
1751 window = gdk_window_get_parent (window);
1766 gtk_notebook_scroll (GtkWidget *widget,
1767 GdkEventScroll *event)
1769 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1772 GtkWidget* originator;
1774 if (!notebook->cur_page)
1777 child = notebook->cur_page->child;
1778 originator = gtk_get_event_widget ((GdkEvent *)event);
1780 /* ignore scroll events from the content of the page */
1781 if (!originator || gtk_widget_is_ancestor (originator, child))
1784 switch (event->direction)
1786 case GDK_SCROLL_RIGHT:
1787 case GDK_SCROLL_DOWN:
1788 gtk_notebook_next_page (notebook);
1790 case GDK_SCROLL_LEFT:
1792 gtk_notebook_prev_page (notebook);
1800 gtk_notebook_button_press (GtkWidget *widget,
1801 GdkEventButton *event)
1803 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1804 GtkNotebookPage *page;
1806 GtkNotebookArrow arrow;
1810 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1814 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1817 arrow = gtk_notebook_get_arrow (notebook, x, y);
1819 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1821 if (event->button == 3 && notebook->menu)
1823 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1824 NULL, NULL, 3, event->time);
1828 if (event->button != 1)
1832 children = notebook->children;
1835 page = children->data;
1837 if (GTK_WIDGET_VISIBLE (page->child) &&
1838 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1839 (x >= page->allocation.x) &&
1840 (y >= page->allocation.y) &&
1841 (x <= (page->allocation.x + page->allocation.width)) &&
1842 (y <= (page->allocation.y + page->allocation.height)))
1844 gboolean page_changed = page != notebook->cur_page;
1845 gboolean was_focus = gtk_widget_is_focus (widget);
1847 gtk_notebook_switch_focus_tab (notebook, children);
1848 gtk_widget_grab_focus (widget);
1850 if (page_changed && !was_focus)
1851 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1855 children = children->next;
1863 stop_scrolling (GtkNotebook *notebook)
1865 if (notebook->timer)
1867 g_source_remove (notebook->timer);
1868 notebook->timer = 0;
1869 notebook->need_timer = FALSE;
1871 notebook->click_child = 0;
1872 notebook->button = 0;
1873 gtk_notebook_redraw_arrows (notebook);
1877 gtk_notebook_button_release (GtkWidget *widget,
1878 GdkEventButton *event)
1880 GtkNotebook *notebook;
1882 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1883 g_return_val_if_fail (event != NULL, FALSE);
1885 if (event->type != GDK_BUTTON_RELEASE)
1888 notebook = GTK_NOTEBOOK (widget);
1890 if (event->button == notebook->button)
1892 stop_scrolling (notebook);
1901 gtk_notebook_enter_notify (GtkWidget *widget,
1902 GdkEventCrossing *event)
1904 GtkNotebook *notebook;
1905 GtkNotebookArrow arrow;
1908 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1909 g_return_val_if_fail (event != NULL, FALSE);
1911 notebook = GTK_NOTEBOOK (widget);
1913 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1916 arrow = gtk_notebook_get_arrow (notebook, x, y);
1918 if (arrow != notebook->in_child)
1920 notebook->in_child = arrow;
1921 gtk_notebook_redraw_arrows (notebook);
1930 gtk_notebook_leave_notify (GtkWidget *widget,
1931 GdkEventCrossing *event)
1933 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1934 GtkNotebookArrow arrow;
1937 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1940 arrow = gtk_notebook_get_arrow (notebook, x, y);
1942 if (notebook->in_child)
1944 notebook->in_child = 0;
1945 gtk_notebook_redraw_arrows (notebook);
1952 gtk_notebook_motion_notify (GtkWidget *widget,
1953 GdkEventMotion *event)
1955 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1956 GtkNotebookArrow arrow;
1959 if (notebook->button)
1962 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1965 arrow = gtk_notebook_get_arrow (notebook, x, y);
1967 if (arrow != notebook->in_child)
1969 notebook->in_child = arrow;
1970 gtk_notebook_redraw_arrows (notebook);
1977 gtk_notebook_grab_notify (GtkWidget *widget,
1978 gboolean was_grabbed)
1981 stop_scrolling (GTK_NOTEBOOK (widget));
1985 gtk_notebook_state_changed (GtkWidget *widget,
1986 GtkStateType previous_state)
1988 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1989 stop_scrolling (GTK_NOTEBOOK (widget));
1993 gtk_notebook_focus_in (GtkWidget *widget,
1994 GdkEventFocus *event)
1996 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1998 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2004 gtk_notebook_focus_out (GtkWidget *widget,
2005 GdkEventFocus *event)
2007 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2013 gtk_notebook_draw_focus (GtkWidget *widget)
2015 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2017 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2018 notebook->focus_tab)
2020 GtkNotebookPage *page;
2024 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2026 page = notebook->focus_tab->data;
2028 area.x = page->tab_label->allocation.x - focus_width;
2029 area.y = page->tab_label->allocation.y - focus_width;
2030 area.width = page->tab_label->allocation.width + 2 * focus_width;
2031 area.height = page->tab_label->allocation.height + 2 * focus_width;
2033 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2038 gtk_notebook_style_set (GtkWidget *widget,
2041 GtkNotebook *notebook;
2043 gboolean has_before_previous;
2044 gboolean has_before_next;
2045 gboolean has_after_previous;
2046 gboolean has_after_next;
2048 notebook = GTK_NOTEBOOK (widget);
2050 gtk_widget_style_get (widget,
2051 "has_backward_stepper", &has_before_previous,
2052 "has_secondary_forward_stepper", &has_before_next,
2053 "has_secondary_backward_stepper", &has_after_previous,
2054 "has_forward_stepper", &has_after_next,
2057 notebook->has_before_previous = has_before_previous;
2058 notebook->has_before_next = has_before_next;
2059 notebook->has_after_previous = has_after_previous;
2060 notebook->has_after_next = has_after_next;
2062 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2065 /* Private GtkContainer Methods :
2067 * gtk_notebook_set_child_arg
2068 * gtk_notebook_get_child_arg
2070 * gtk_notebook_remove
2071 * gtk_notebook_focus
2072 * gtk_notebook_set_focus_child
2073 * gtk_notebook_child_type
2074 * gtk_notebook_forall
2077 gtk_notebook_set_child_property (GtkContainer *container,
2080 const GValue *value,
2085 GtkPackType pack_type;
2087 /* not finding child's page is valid for menus or labels */
2088 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2091 switch (property_id)
2093 case CHILD_PROP_TAB_LABEL:
2094 /* a NULL pointer indicates a default_tab setting, otherwise
2095 * we need to set the associated label
2097 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2098 g_value_get_string (value));
2100 case CHILD_PROP_MENU_LABEL:
2101 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2102 g_value_get_string (value));
2104 case CHILD_PROP_POSITION:
2105 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2106 g_value_get_int (value));
2108 case CHILD_PROP_TAB_EXPAND:
2109 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2110 &expand, &fill, &pack_type);
2111 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2112 g_value_get_boolean (value),
2115 case CHILD_PROP_TAB_FILL:
2116 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2117 &expand, &fill, &pack_type);
2118 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2120 g_value_get_boolean (value),
2123 case CHILD_PROP_TAB_PACK:
2124 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2125 &expand, &fill, &pack_type);
2126 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2128 g_value_get_enum (value));
2131 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2137 gtk_notebook_get_child_property (GtkContainer *container,
2144 GtkNotebook *notebook;
2148 GtkPackType pack_type;
2150 notebook = GTK_NOTEBOOK (container);
2152 /* not finding child's page is valid for menus or labels */
2153 list = gtk_notebook_find_child (notebook, child, NULL);
2156 /* nothing to set on labels or menus */
2157 g_param_value_set_default (pspec, value);
2161 switch (property_id)
2163 case CHILD_PROP_TAB_LABEL:
2164 label = gtk_notebook_get_tab_label (notebook, child);
2166 if (label && GTK_IS_LABEL (label))
2167 g_value_set_string (value, GTK_LABEL (label)->label);
2169 g_value_set_string (value, NULL);
2171 case CHILD_PROP_MENU_LABEL:
2172 label = gtk_notebook_get_menu_label (notebook, child);
2174 if (label && GTK_IS_LABEL (label))
2175 g_value_set_string (value, GTK_LABEL (label)->label);
2177 g_value_set_string (value, NULL);
2179 case CHILD_PROP_POSITION:
2180 g_value_set_int (value, g_list_position (notebook->children, list));
2182 case CHILD_PROP_TAB_EXPAND:
2183 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2184 &expand, NULL, NULL);
2185 g_value_set_boolean (value, expand);
2187 case CHILD_PROP_TAB_FILL:
2188 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2190 g_value_set_boolean (value, fill);
2192 case CHILD_PROP_TAB_PACK:
2193 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2194 NULL, NULL, &pack_type);
2195 g_value_set_enum (value, pack_type);
2198 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2204 gtk_notebook_add (GtkContainer *container,
2207 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2209 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2214 gtk_notebook_remove (GtkContainer *container,
2217 GtkNotebook *notebook;
2218 GtkNotebookPage *page;
2221 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2222 g_return_if_fail (widget != NULL);
2224 notebook = GTK_NOTEBOOK (container);
2226 children = notebook->children;
2229 page = children->data;
2230 if (page->child == widget)
2232 gtk_notebook_real_remove (notebook, children, FALSE);
2235 children = children->next;
2240 focus_tabs_in (GtkNotebook *notebook)
2242 if (notebook->show_tabs && notebook->cur_page)
2244 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2246 gtk_notebook_switch_focus_tab (notebook,
2247 g_list_find (notebook->children,
2248 notebook->cur_page));
2257 focus_tabs_move (GtkNotebook *notebook,
2258 GtkDirectionType direction,
2259 gint search_direction)
2263 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2264 search_direction, TRUE);
2266 gtk_notebook_switch_focus_tab (notebook, new_page);
2268 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2274 focus_child_in (GtkNotebook *notebook,
2275 GtkDirectionType direction)
2277 if (notebook->cur_page)
2278 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2283 /* Focus in the notebook can either be on the pages, or on
2287 gtk_notebook_focus (GtkWidget *widget,
2288 GtkDirectionType direction)
2290 GtkWidget *old_focus_child;
2291 GtkNotebook *notebook;
2292 GtkDirectionType effective_direction;
2294 gboolean widget_is_focus;
2295 GtkContainer *container;
2297 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2299 container = GTK_CONTAINER (widget);
2300 notebook = GTK_NOTEBOOK (container);
2302 if (notebook->focus_out)
2304 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2308 widget_is_focus = gtk_widget_is_focus (widget);
2309 old_focus_child = container->focus_child;
2311 effective_direction = get_effective_direction (notebook, direction);
2313 if (old_focus_child) /* Focus on page child */
2315 if (gtk_widget_child_focus (old_focus_child, direction))
2318 switch (effective_direction)
2320 case GTK_DIR_TAB_BACKWARD:
2322 /* Focus onto the tabs */
2323 return focus_tabs_in (notebook);
2325 case GTK_DIR_TAB_FORWARD:
2331 else if (widget_is_focus) /* Focus was on tabs */
2333 switch (effective_direction)
2335 case GTK_DIR_TAB_BACKWARD:
2338 case GTK_DIR_TAB_FORWARD:
2340 /* We use TAB_FORWARD rather than direction so that we focus a more
2341 * predictable widget for the user; users may be using arrow focusing
2342 * in this situation even if they don't usually use arrow focusing.
2344 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2346 return focus_tabs_move (notebook, direction, STEP_PREV);
2348 return focus_tabs_move (notebook, direction, STEP_NEXT);
2351 else /* Focus was not on widget */
2353 switch (effective_direction)
2355 case GTK_DIR_TAB_FORWARD:
2357 if (focus_tabs_in (notebook))
2359 if (focus_child_in (notebook, direction))
2362 case GTK_DIR_TAB_BACKWARD:
2364 if (focus_child_in (notebook, direction))
2366 if (focus_tabs_in (notebook))
2371 return focus_child_in (notebook, direction);
2375 g_assert_not_reached ();
2380 gtk_notebook_set_focus_child (GtkContainer *container,
2383 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2384 GtkWidget *page_child;
2385 GtkWidget *toplevel;
2387 /* If the old focus widget was within a page of the notebook,
2388 * (child may either be NULL or not in this case), record it
2389 * for future use if we switch to the page with a mnemonic.
2392 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2393 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2395 page_child = GTK_WINDOW (toplevel)->focus_widget;
2398 if (page_child->parent == GTK_WIDGET (container))
2400 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2403 GtkNotebookPage *page = list->data;
2405 if (page->last_focus_child)
2406 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2408 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2409 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2415 page_child = page_child->parent;
2421 g_return_if_fail (GTK_IS_WIDGET (child));
2423 notebook->child_has_focus = TRUE;
2424 if (!notebook->focus_tab)
2427 GtkNotebookPage *page;
2429 children = notebook->children;
2432 page = children->data;
2433 if (page->child == child || page->tab_label == child)
2434 gtk_notebook_switch_focus_tab (notebook, children);
2435 children = children->next;
2440 parent_class->set_focus_child (container, child);
2444 gtk_notebook_forall (GtkContainer *container,
2445 gboolean include_internals,
2446 GtkCallback callback,
2447 gpointer callback_data)
2449 GtkNotebook *notebook;
2452 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2453 g_return_if_fail (callback != NULL);
2455 notebook = GTK_NOTEBOOK (container);
2457 children = notebook->children;
2460 GtkNotebookPage *page;
2462 page = children->data;
2463 children = children->next;
2464 (* callback) (page->child, callback_data);
2465 if (include_internals)
2467 if (page->tab_label)
2468 (* callback) (page->tab_label, callback_data);
2474 gtk_notebook_child_type (GtkContainer *container)
2476 return GTK_TYPE_WIDGET;
2479 /* Private GtkNotebook Functions:
2481 * gtk_notebook_redraw_tabs
2482 * gtk_notebook_real_remove
2483 * gtk_notebook_update_labels
2484 * gtk_notebook_timer
2485 * gtk_notebook_page_compare
2486 * gtk_notebook_real_page_position
2487 * gtk_notebook_search_page
2490 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2493 GtkNotebookPage *page;
2494 GdkRectangle redraw_rect;
2496 gint tab_pos = get_effective_tab_pos (notebook);
2498 widget = GTK_WIDGET (notebook);
2499 border = GTK_CONTAINER (notebook)->border_width;
2501 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2504 page = notebook->first_tab->data;
2506 redraw_rect.x = border;
2507 redraw_rect.y = border;
2511 case GTK_POS_BOTTOM:
2512 redraw_rect.y = (widget->allocation.height - border -
2513 page->allocation.height -
2514 widget->style->ythickness);
2515 if (page != notebook->cur_page)
2516 redraw_rect.y -= widget->style->ythickness;
2519 redraw_rect.width = widget->allocation.width - 2 * border;
2520 redraw_rect.height = (page->allocation.height +
2521 widget->style->ythickness);
2522 if (page != notebook->cur_page)
2523 redraw_rect.height += widget->style->ythickness;
2526 redraw_rect.x = (widget->allocation.width - border -
2527 page->allocation.width -
2528 widget->style->xthickness);
2529 if (page != notebook->cur_page)
2530 redraw_rect.x -= widget->style->xthickness;
2533 redraw_rect.width = (page->allocation.width +
2534 widget->style->xthickness);
2535 redraw_rect.height = widget->allocation.height - 2 * border;
2536 if (page != notebook->cur_page)
2537 redraw_rect.width += widget->style->xthickness;
2541 redraw_rect.x += widget->allocation.x;
2542 redraw_rect.y += widget->allocation.y;
2544 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2548 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2550 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2554 GtkNotebookArrow arrow[4];
2556 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2557 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2558 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2559 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2561 for (i = 0; i < 4; i++)
2563 if (arrow[i] == ARROW_NONE)
2566 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2567 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2574 gtk_notebook_timer (GtkNotebook *notebook)
2576 gboolean retval = FALSE;
2578 GDK_THREADS_ENTER ();
2580 if (notebook->timer)
2582 gtk_notebook_do_arrow (notebook, notebook->click_child);
2584 if (notebook->need_timer)
2586 notebook->need_timer = FALSE;
2587 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2588 (GSourceFunc) gtk_notebook_timer,
2589 (gpointer) notebook);
2595 GDK_THREADS_LEAVE ();
2601 gtk_notebook_page_compare (gconstpointer a,
2604 return (((GtkNotebookPage *) a)->child != b);
2608 gtk_notebook_find_child (GtkNotebook *notebook,
2610 const gchar *function)
2612 GList *list = g_list_find_custom (notebook->children, child,
2613 gtk_notebook_page_compare);
2615 #ifndef G_DISABLE_CHECKS
2616 if (!list && function)
2617 g_warning ("%s: unable to find child %p in notebook %p",
2618 function, child, notebook);
2625 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2626 GtkNotebookPage *page)
2628 if (page->tab_label)
2630 if (page->mnemonic_activate_signal)
2631 g_signal_handler_disconnect (page->tab_label,
2632 page->mnemonic_activate_signal);
2633 page->mnemonic_activate_signal = 0;
2635 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2636 gtk_widget_unparent (page->tab_label);
2641 gtk_notebook_real_remove (GtkNotebook *notebook,
2643 gboolean destroying)
2645 GtkNotebookPage *page;
2647 gint need_resize = FALSE;
2649 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2651 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2653 if (notebook->cur_page == list->data)
2655 notebook->cur_page = NULL;
2656 if (next_list && !destroying)
2657 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2660 if (list == notebook->first_tab)
2661 notebook->first_tab = next_list;
2662 if (list == notebook->focus_tab && !destroying)
2663 gtk_notebook_switch_focus_tab (notebook, next_list);
2667 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2670 gtk_widget_unparent (page->child);
2672 gtk_notebook_remove_tab_label (notebook, page);
2676 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2677 page->menu_label->parent);
2678 gtk_widget_queue_resize (notebook->menu);
2680 if (!page->default_menu)
2681 g_object_unref (page->menu_label);
2683 notebook->children = g_list_remove_link (notebook->children, list);
2686 if (page->last_focus_child)
2688 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2689 page->last_focus_child = NULL;
2694 gtk_notebook_update_labels (notebook);
2696 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2700 gtk_notebook_update_labels (GtkNotebook *notebook)
2702 GtkNotebookPage *page;
2707 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2709 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2712 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2713 if (notebook->show_tabs)
2715 if (page->default_tab)
2717 if (!page->tab_label)
2719 page->tab_label = gtk_label_new (string);
2720 gtk_widget_set_parent (page->tab_label,
2721 GTK_WIDGET (notebook));
2724 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2727 if (GTK_WIDGET_VISIBLE (page->child) &&
2728 !GTK_WIDGET_VISIBLE (page->tab_label))
2729 gtk_widget_show (page->tab_label);
2730 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2731 GTK_WIDGET_VISIBLE (page->tab_label))
2732 gtk_widget_hide (page->tab_label);
2734 if (notebook->menu && page->default_menu)
2736 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2737 gtk_label_set_text (GTK_LABEL (page->menu_label),
2738 GTK_LABEL (page->tab_label)->label);
2740 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2746 gtk_notebook_real_page_position (GtkNotebook *notebook,
2752 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2753 g_return_val_if_fail (list != NULL, -1);
2755 for (work = notebook->children, count_start = 0;
2756 work && work != list; work = work->next)
2757 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2763 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2766 return (count_start + g_list_length (list) - 1);
2770 gtk_notebook_search_page (GtkNotebook *notebook,
2773 gboolean find_visible)
2775 GtkNotebookPage *page = NULL;
2776 GList *old_list = NULL;
2779 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2784 flag = GTK_PACK_END;
2788 flag = GTK_PACK_START;
2795 if (!page || page->pack == flag)
2803 list = notebook->children;
2808 if (page->pack == flag &&
2809 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2824 if (page->pack != flag &&
2825 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2833 /* Private GtkNotebook Drawing Functions:
2835 * gtk_notebook_paint
2836 * gtk_notebook_draw_tab
2837 * gtk_notebook_draw_arrow
2840 gtk_notebook_paint (GtkWidget *widget,
2843 GtkNotebook *notebook;
2844 GtkNotebookPage *page;
2849 gint border_width = GTK_CONTAINER (widget)->border_width;
2850 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2854 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2855 g_return_if_fail (area != NULL);
2857 if (!GTK_WIDGET_DRAWABLE (widget))
2860 notebook = GTK_NOTEBOOK (widget);
2861 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2862 tab_pos = get_effective_tab_pos (notebook);
2864 if ((!notebook->show_tabs && !notebook->show_border) ||
2865 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2868 x = widget->allocation.x + border_width;
2869 y = widget->allocation.y + border_width;
2870 width = widget->allocation.width - border_width * 2;
2871 height = widget->allocation.height - border_width * 2;
2873 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2875 gtk_paint_box (widget->style, widget->window,
2876 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2877 area, widget, "notebook",
2878 x, y, width, height);
2883 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2885 page = notebook->first_tab->data;
2890 y += page->allocation.height + widget->style->ythickness;
2891 case GTK_POS_BOTTOM:
2892 height -= page->allocation.height + widget->style->ythickness;
2895 x += page->allocation.width + widget->style->xthickness;
2897 width -= page->allocation.width + widget->style->xthickness;
2900 gtk_paint_box (widget->style, widget->window,
2901 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2902 area, widget, "notebook",
2903 x, y, width, height);
2910 y += notebook->cur_page->allocation.height;
2911 case GTK_POS_BOTTOM:
2912 height -= notebook->cur_page->allocation.height;
2915 x += notebook->cur_page->allocation.width;
2917 width -= notebook->cur_page->allocation.width;
2924 case GTK_POS_BOTTOM:
2925 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2926 gap_width = notebook->cur_page->allocation.width;
2927 step = is_rtl ? STEP_NEXT : STEP_PREV;
2931 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2932 gap_width = notebook->cur_page->allocation.height;
2936 gtk_paint_box_gap (widget->style, widget->window,
2937 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2938 area, widget, "notebook",
2939 x, y, width, height,
2940 tab_pos, gap_x, gap_width);
2944 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2947 page = children->data;
2948 children = gtk_notebook_search_page (notebook, children,
2950 if (!GTK_WIDGET_VISIBLE (page->child))
2952 if (!GTK_WIDGET_MAPPED (page->tab_label))
2954 else if (page != notebook->cur_page)
2955 gtk_notebook_draw_tab (notebook, page, area);
2958 if (showarrow && notebook->scrollable)
2960 if (notebook->has_before_previous)
2961 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2962 if (notebook->has_before_next)
2963 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2964 if (notebook->has_after_previous)
2965 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2966 if (notebook->has_after_next)
2967 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2969 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2973 gtk_notebook_draw_tab (GtkNotebook *notebook,
2974 GtkNotebookPage *page,
2977 GdkRectangle child_area;
2978 GdkRectangle page_area;
2979 GtkStateType state_type;
2980 GtkPositionType gap_side;
2981 gint tab_pos = get_effective_tab_pos (notebook);
2983 g_return_if_fail (notebook != NULL);
2984 g_return_if_fail (page != NULL);
2985 g_return_if_fail (area != NULL);
2987 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2988 (page->allocation.width == 0) || (page->allocation.height == 0))
2991 page_area.x = page->allocation.x;
2992 page_area.y = page->allocation.y;
2993 page_area.width = page->allocation.width;
2994 page_area.height = page->allocation.height;
2996 if (gdk_rectangle_intersect (&page_area, area, &child_area))
3000 widget = GTK_WIDGET (notebook);
3005 gap_side = GTK_POS_BOTTOM;
3007 case GTK_POS_BOTTOM:
3008 gap_side = GTK_POS_TOP;
3011 gap_side = GTK_POS_RIGHT;
3014 gap_side = GTK_POS_LEFT;
3018 if (notebook->cur_page == page)
3019 state_type = GTK_STATE_NORMAL;
3021 state_type = GTK_STATE_ACTIVE;
3022 gtk_paint_extension(widget->style, widget->window,
3023 state_type, GTK_SHADOW_OUT,
3024 area, widget, "tab",
3025 page_area.x, page_area.y,
3026 page_area.width, page_area.height,
3028 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
3029 notebook->focus_tab && (notebook->focus_tab->data == page))
3033 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3035 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3036 area, widget, "tab",
3037 page->tab_label->allocation.x - focus_width,
3038 page->tab_label->allocation.y - focus_width,
3039 page->tab_label->allocation.width + 2 * focus_width,
3040 page->tab_label->allocation.height + 2 * focus_width);
3042 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3043 GTK_WIDGET_DRAWABLE (page->tab_label))
3045 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3047 /* This is a lame hack since all this code needs rewriting anyhow */
3049 expose_event->expose.window = g_object_ref (page->tab_label->window);
3050 expose_event->expose.area = child_area;
3051 expose_event->expose.region = gdk_region_rectangle (&child_area);
3052 expose_event->expose.send_event = TRUE;
3053 expose_event->expose.count = 0;
3055 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3057 gdk_event_free (expose_event);
3063 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3064 GtkNotebookArrow nbarrow)
3066 GtkStateType state_type;
3067 GtkShadowType shadow_type;
3069 GdkRectangle arrow_rect;
3071 gboolean is_rtl, left;
3073 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3075 widget = GTK_WIDGET (notebook);
3077 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3078 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3079 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3081 if (GTK_WIDGET_DRAWABLE (notebook))
3083 if (notebook->in_child == nbarrow)
3085 if (notebook->click_child == nbarrow)
3086 state_type = GTK_STATE_ACTIVE;
3088 state_type = GTK_STATE_PRELIGHT;
3091 state_type = GTK_WIDGET_STATE (widget);
3093 if (notebook->click_child == nbarrow)
3094 shadow_type = GTK_SHADOW_IN;
3096 shadow_type = GTK_SHADOW_OUT;
3098 if (notebook->focus_tab &&
3099 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3100 left? STEP_PREV : STEP_NEXT, TRUE))
3102 shadow_type = GTK_SHADOW_ETCHED_IN;
3103 state_type = GTK_STATE_INSENSITIVE;
3106 if (notebook->tab_pos == GTK_POS_LEFT ||
3107 notebook->tab_pos == GTK_POS_RIGHT)
3108 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3110 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3112 gtk_paint_arrow (widget->style, widget->window, state_type,
3113 shadow_type, NULL, widget, "notebook",
3114 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3115 ARROW_SIZE, ARROW_SIZE);
3119 /* Private GtkNotebook Size Allocate Functions:
3121 * gtk_notebook_pages_allocate
3122 * gtk_notebook_page_allocate
3123 * gtk_notebook_calc_tabs
3126 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3128 GtkWidget *widget = GTK_WIDGET (notebook);
3129 GtkContainer *container = GTK_CONTAINER (notebook);
3130 GtkNotebookPage *page = NULL;
3131 GtkAllocation *allocation = &widget->allocation;
3132 GtkAllocation child_allocation;
3133 GList *children = NULL;
3134 GList *last_child = NULL;
3135 gboolean showarrow = FALSE;
3142 gint tab_pos = get_effective_tab_pos (notebook);
3143 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3144 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3147 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3150 child_allocation.x = widget->allocation.x + container->border_width;
3151 child_allocation.y = widget->allocation.y + container->border_width;
3155 case GTK_POS_BOTTOM:
3156 child_allocation.y = (widget->allocation.y +
3157 allocation->height -
3158 notebook->cur_page->requisition.height -
3159 container->border_width);
3162 child_allocation.height = notebook->cur_page->requisition.height;
3166 child_allocation.x = (widget->allocation.x +
3168 notebook->cur_page->requisition.width -
3169 container->border_width);
3172 child_allocation.width = notebook->cur_page->requisition.width;
3176 if (notebook->scrollable)
3180 children = notebook->children;
3182 if (notebook->focus_tab)
3183 focus_tab = notebook->focus_tab;
3184 else if (notebook->first_tab)
3185 focus_tab = notebook->first_tab;
3187 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3192 case GTK_POS_BOTTOM:
3195 page = children->data;
3196 children = children->next;
3198 if (GTK_WIDGET_VISIBLE (page->child))
3199 tab_space += page->requisition.width;
3202 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3205 page = focus_tab->data;
3207 tab_space = allocation->width - TAB_OVERLAP -
3208 page->requisition.width - 2 * container->border_width;
3209 if (notebook->has_after_previous)
3210 tab_space -= ARROW_SPACING + ARROW_SIZE;
3211 if (notebook->has_after_next)
3212 tab_space -= ARROW_SPACING + ARROW_SIZE;
3213 if (notebook->has_before_previous)
3215 tab_space -= ARROW_SPACING + ARROW_SIZE;
3216 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3218 if (notebook->has_before_next)
3220 tab_space -= ARROW_SPACING + ARROW_SIZE;
3221 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3229 page = children->data;
3230 children = children->next;
3232 if (GTK_WIDGET_VISIBLE (page->child))
3233 tab_space += page->requisition.height;
3236 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3239 page = focus_tab->data;
3240 tab_space = allocation->height
3241 - TAB_OVERLAP - 2 * container->border_width
3242 - page->requisition.height;
3243 if (notebook->has_after_previous || notebook->has_after_next)
3244 tab_space -= ARROW_SPACING + ARROW_SIZE;
3245 if (notebook->has_before_previous || notebook->has_before_next)
3247 tab_space -= ARROW_SPACING + ARROW_SIZE;
3248 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3253 if (showarrow) /* first_tab <- focus_tab */
3257 notebook->first_tab = focus_tab;
3258 last_child = gtk_notebook_search_page (notebook, focus_tab,
3264 if (notebook->first_tab && notebook->first_tab != focus_tab)
3266 /* Is first_tab really predecessor of focus_tab ? */
3267 page = notebook->first_tab->data;
3268 if (GTK_WIDGET_VISIBLE (page->child))
3269 for (children = focus_tab;
3270 children && children != notebook->first_tab;
3271 children = gtk_notebook_search_page (notebook,
3277 notebook->first_tab = focus_tab;
3279 gtk_notebook_calc_tabs (notebook,
3280 gtk_notebook_search_page (notebook,
3284 &(notebook->first_tab), &tab_space,
3289 notebook->first_tab =
3290 gtk_notebook_search_page (notebook, notebook->first_tab,
3292 if (!notebook->first_tab)
3293 notebook->first_tab = focus_tab;
3294 last_child = gtk_notebook_search_page (notebook, focus_tab,
3297 else /* focus_tab -> end */
3299 if (!notebook->first_tab)
3300 notebook->first_tab = gtk_notebook_search_page (notebook,
3305 gtk_notebook_calc_tabs (notebook,
3306 gtk_notebook_search_page (notebook,
3310 &children, &tab_space, STEP_NEXT);
3313 last_child = children;
3314 else /* start <- first_tab */
3318 gtk_notebook_calc_tabs
3320 gtk_notebook_search_page (notebook,
3321 notebook->first_tab,
3324 &children, &tab_space, STEP_PREV);
3325 notebook->first_tab = gtk_notebook_search_page(notebook,
3335 tab_space = -tab_space;
3337 for (children = notebook->first_tab;
3338 children && children != last_child;
3339 children = gtk_notebook_search_page (notebook, children,
3346 /*unmap all non-visible tabs*/
3347 for (children = gtk_notebook_search_page (notebook, NULL,
3349 children && children != notebook->first_tab;
3350 children = gtk_notebook_search_page (notebook, children,
3353 page = children->data;
3354 if (page->tab_label)
3355 gtk_widget_set_child_visible (page->tab_label, FALSE);
3357 for (children = last_child; children;
3358 children = gtk_notebook_search_page (notebook, children,
3361 page = children->data;
3362 if (page->tab_label)
3363 gtk_widget_set_child_visible (page->tab_label, FALSE);
3366 else /* !showarrow */
3368 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3379 children = notebook->children;
3383 case GTK_POS_BOTTOM:
3386 page = children->data;
3387 children = children->next;
3389 if (GTK_WIDGET_VISIBLE (page->child))
3392 tab_space += page->requisition.width;
3397 tab_space -= allocation->width;
3403 page = children->data;
3404 children = children->next;
3406 if (GTK_WIDGET_VISIBLE (page->child))
3409 tab_space += page->requisition.height;
3414 tab_space -= allocation->height;
3416 tab_space += 2 * container->border_width + TAB_OVERLAP;
3418 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3420 if (notebook->homogeneous && n)
3424 children = notebook->first_tab;
3427 memo_x = child_allocation.x;
3428 if (notebook->children && is_rtl)
3430 child_allocation.x = (allocation->x + allocation->width -
3431 container->border_width);
3434 if (notebook->has_after_previous)
3435 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3436 if (notebook->has_after_next)
3437 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3443 if (children == last_child)
3445 /* FIXME double check */
3449 page = children->data;
3450 if (!showarrow && page->pack != GTK_PACK_START)
3452 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3455 if (n && (showarrow || page->expand || notebook->homogeneous))
3457 new_fill = (tab_space * i++) / n;
3458 delta = new_fill - old_fill;
3459 old_fill = new_fill;
3465 case GTK_POS_BOTTOM:
3466 child_allocation.width = (page->requisition.width +
3467 TAB_OVERLAP + delta);
3469 child_allocation.x -= child_allocation.width;
3473 child_allocation.height = (page->requisition.height +
3474 TAB_OVERLAP + delta);
3478 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3483 case GTK_POS_BOTTOM:
3485 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3487 child_allocation.x += TAB_OVERLAP;
3491 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3495 if (page->tab_label)
3496 gtk_widget_set_child_visible (page->tab_label, TRUE);
3501 children = notebook->children;
3506 case GTK_POS_BOTTOM:
3508 child_allocation.x = (allocation->x + allocation->width -
3509 container->border_width);
3511 child_allocation.x = memo_x;
3515 child_allocation.y = (allocation->y + allocation->height -
3516 container->border_width);
3520 while (children != last_child)
3522 page = children->data;
3523 children = children->next;
3525 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3529 if (n && (page->expand || notebook->homogeneous))
3531 new_fill = (tab_space * i++) / n;
3532 delta = new_fill - old_fill;
3533 old_fill = new_fill;
3539 case GTK_POS_BOTTOM:
3540 child_allocation.width = (page->requisition.width +
3541 TAB_OVERLAP + delta);
3543 child_allocation.x -= child_allocation.width;
3547 child_allocation.height = (page->requisition.height +
3548 TAB_OVERLAP + delta);
3549 child_allocation.y -= child_allocation.height;
3553 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3558 case GTK_POS_BOTTOM:
3560 child_allocation.x += TAB_OVERLAP;
3562 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3566 child_allocation.y += TAB_OVERLAP;
3570 if (page->tab_label)
3571 gtk_widget_set_child_visible (page->tab_label, TRUE);
3576 gtk_notebook_redraw_tabs (notebook);
3580 gtk_notebook_page_allocate (GtkNotebook *notebook,
3581 GtkNotebookPage *page,
3582 GtkAllocation *allocation)
3584 GtkWidget *widget = GTK_WIDGET (notebook);
3585 GtkAllocation child_allocation;
3586 GtkRequisition tab_requisition;
3591 gint tab_pos = get_effective_tab_pos (notebook);
3593 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3595 xthickness = widget->style->xthickness;
3596 ythickness = widget->style->ythickness;
3598 page->allocation = *allocation;
3599 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3601 if (notebook->cur_page != page)
3606 page->allocation.y += ythickness;
3607 case GTK_POS_BOTTOM:
3608 if (page->allocation.height > ythickness)
3609 page->allocation.height -= ythickness;
3612 page->allocation.x += xthickness;
3614 if (page->allocation.width > xthickness)
3615 page->allocation.width -= xthickness;
3623 case GTK_POS_BOTTOM:
3624 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3627 child_allocation.x = (xthickness + focus_width +
3628 notebook->tab_hborder);
3629 child_allocation.width = MAX (1, (page->allocation.width -
3630 2 * child_allocation.x));
3631 child_allocation.x += page->allocation.x;
3635 child_allocation.x = (page->allocation.x +
3636 (page->allocation.width -
3637 tab_requisition.width) / 2);
3638 child_allocation.width = tab_requisition.width;
3640 child_allocation.y = (notebook->tab_vborder + focus_width +
3641 page->allocation.y);
3642 if (tab_pos == GTK_POS_TOP)
3643 child_allocation.y += ythickness;
3644 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3645 2 * (notebook->tab_vborder + focus_width)));
3649 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3652 child_allocation.y = ythickness + padding;
3653 child_allocation.height = MAX (1, (page->allocation.height -
3654 2 * child_allocation.y));
3655 child_allocation.y += page->allocation.y;
3659 child_allocation.y = (page->allocation.y + (page->allocation.height -
3660 tab_requisition.height) / 2);
3661 child_allocation.height = tab_requisition.height;
3663 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3664 if (tab_pos == GTK_POS_LEFT)
3665 child_allocation.x += xthickness;
3666 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3667 2 * (notebook->tab_hborder + focus_width)));
3671 if (page->tab_label)
3672 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3676 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3682 GtkNotebookPage *page = NULL;
3684 GList *last_list = NULL;
3686 gint tab_pos = get_effective_tab_pos (notebook);
3692 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3693 if (pack == GTK_PACK_END)
3694 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3701 case GTK_POS_BOTTOM:
3704 page = children->data;
3705 if (GTK_WIDGET_VISIBLE (page->child))
3707 if (page->pack == pack)
3709 *tab_space -= page->requisition.width;
3710 if (*tab_space < 0 || children == *end)
3714 *tab_space = - (*tab_space +
3715 page->requisition.width);
3721 last_list = children;
3723 if (direction == STEP_NEXT)
3724 children = children->next;
3726 children = children->prev;
3733 page = children->data;
3734 if (GTK_WIDGET_VISIBLE (page->child))
3736 if (page->pack == pack)
3738 *tab_space -= page->requisition.height;
3739 if (*tab_space < 0 || children == *end)
3743 *tab_space = - (*tab_space +
3744 page->requisition.height);
3750 last_list = children;
3752 if (direction == STEP_NEXT)
3753 children = children->next;
3755 children = children->prev;
3759 if (direction == STEP_PREV)
3761 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3762 direction = STEP_PREV;
3763 children = last_list;
3768 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3772 for (list = notebook->children; list != NULL; list = list->next)
3774 GtkNotebookPage *page = list->data;
3776 if (page->tab_label)
3778 if (page == notebook->cur_page)
3779 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3781 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3786 /* Private GtkNotebook Page Switch Methods:
3788 * gtk_notebook_real_switch_page
3791 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3792 GtkNotebookPage *page,
3795 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3796 g_return_if_fail (page != NULL);
3798 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3801 if (notebook->cur_page)
3802 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3804 notebook->cur_page = page;
3806 if (!notebook->focus_tab ||
3807 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3808 notebook->focus_tab =
3809 g_list_find (notebook->children, notebook->cur_page);
3811 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3813 /* If the focus was on the previous page, move it to the first
3814 * element on the new page, if possible, or if not, to the
3817 if (notebook->child_has_focus)
3819 if (notebook->cur_page->last_focus_child &&
3820 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3821 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3823 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3824 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3827 gtk_notebook_update_tab_states (notebook);
3828 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3829 g_object_notify (G_OBJECT (notebook), "page");
3832 /* Private GtkNotebook Page Switch Functions:
3834 * gtk_notebook_switch_page
3835 * gtk_notebook_page_select
3836 * gtk_notebook_switch_focus_tab
3837 * gtk_notebook_menu_switch_page
3840 gtk_notebook_switch_page (GtkNotebook *notebook,
3841 GtkNotebookPage *page,
3844 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3845 g_return_if_fail (page != NULL);
3847 if (notebook->cur_page == page)
3851 page_num = g_list_index (notebook->children, page);
3853 g_signal_emit (notebook,
3854 notebook_signals[SWITCH_PAGE],
3861 gtk_notebook_page_select (GtkNotebook *notebook,
3862 gboolean move_focus)
3864 GtkNotebookPage *page;
3865 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3866 gint tab_pos = get_effective_tab_pos (notebook);
3868 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3870 if (!notebook->focus_tab)
3873 page = notebook->focus_tab->data;
3874 gtk_notebook_switch_page (notebook, page, -1);
3883 case GTK_POS_BOTTOM:
3887 dir = GTK_DIR_RIGHT;
3894 if (gtk_widget_child_focus (page->child, dir))
3901 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3905 GtkNotebookPage *old_page = NULL;
3906 GtkNotebookPage *page;
3908 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3910 if (notebook->focus_tab == new_child)
3913 old_child = notebook->focus_tab;
3914 notebook->focus_tab = new_child;
3916 if (notebook->scrollable)
3917 gtk_notebook_redraw_arrows (notebook);
3919 if (!notebook->show_tabs || !notebook->focus_tab)
3923 old_page = old_child->data;
3925 page = notebook->focus_tab->data;
3926 if (GTK_WIDGET_MAPPED (page->tab_label))
3927 gtk_notebook_redraw_tabs (notebook);
3929 gtk_notebook_pages_allocate (notebook);
3931 gtk_notebook_switch_page (notebook, page,
3932 g_list_index (notebook->children, page));
3936 gtk_notebook_menu_switch_page (GtkWidget *widget,
3937 GtkNotebookPage *page)
3939 GtkNotebook *notebook;
3943 g_return_if_fail (widget != NULL);
3944 g_return_if_fail (page != NULL);
3946 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3947 (GTK_MENU (widget->parent)));
3949 if (notebook->cur_page == page)
3953 children = notebook->children;
3954 while (children && children->data != page)
3956 children = children->next;
3960 g_signal_emit (notebook,
3961 notebook_signals[SWITCH_PAGE],
3967 /* Private GtkNotebook Menu Functions:
3969 * gtk_notebook_menu_item_create
3970 * gtk_notebook_menu_label_unparent
3971 * gtk_notebook_menu_detacher
3974 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3977 GtkNotebookPage *page;
3978 GtkWidget *menu_item;
3981 if (page->default_menu)
3983 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3984 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3986 page->menu_label = gtk_label_new ("");
3987 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3990 gtk_widget_show (page->menu_label);
3991 menu_item = gtk_menu_item_new ();
3992 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3993 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3994 gtk_notebook_real_page_position (notebook, list));
3995 g_signal_connect (menu_item, "activate",
3996 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3997 if (GTK_WIDGET_VISIBLE (page->child))
3998 gtk_widget_show (menu_item);
4002 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4005 gtk_widget_unparent (GTK_BIN(widget)->child);
4006 GTK_BIN(widget)->child = NULL;
4010 gtk_notebook_menu_detacher (GtkWidget *widget,
4013 GtkNotebook *notebook;
4015 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4017 notebook = GTK_NOTEBOOK (widget);
4018 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4020 notebook->menu = NULL;
4023 /* Private GtkNotebook Setter Functions:
4025 * gtk_notebook_set_homogeneous_tabs_internal
4026 * gtk_notebook_set_tab_border_internal
4027 * gtk_notebook_set_tab_hborder_internal
4028 * gtk_notebook_set_tab_vborder_internal
4031 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4032 gboolean homogeneous)
4034 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4036 if (homogeneous == notebook->homogeneous)
4039 notebook->homogeneous = homogeneous;
4040 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4042 g_object_notify (G_OBJECT (notebook), "homogeneous");
4046 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4049 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4051 notebook->tab_hborder = border_width;
4052 notebook->tab_vborder = border_width;
4054 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4055 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4057 g_object_freeze_notify (G_OBJECT (notebook));
4058 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4059 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4060 g_object_thaw_notify (G_OBJECT (notebook));
4064 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4067 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4069 if (notebook->tab_hborder == tab_hborder)
4072 notebook->tab_hborder = tab_hborder;
4074 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4075 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4077 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4081 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4084 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4086 if (notebook->tab_vborder == tab_vborder)
4089 notebook->tab_vborder = tab_vborder;
4091 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4092 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4094 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4097 /* Public GtkNotebook Page Insert/Remove Methods :
4099 * gtk_notebook_append_page
4100 * gtk_notebook_append_page_menu
4101 * gtk_notebook_prepend_page
4102 * gtk_notebook_prepend_page_menu
4103 * gtk_notebook_insert_page
4104 * gtk_notebook_insert_page_menu
4105 * gtk_notebook_remove_page
4108 * gtk_notebook_append_page:
4109 * @notebook: a #GtkNotebook
4110 * @child: the #GtkWidget to use as the contents of the page.
4111 * @tab_label: the #GtkWidget to be used as the label for the page,
4112 * or %NULL to use the default label, 'page N'.
4114 * Appends a page to @notebook.
4116 * Return value: the index (starting from 0) of the appended
4117 * page in the notebook, or -1 if function fails
4120 gtk_notebook_append_page (GtkNotebook *notebook,
4122 GtkWidget *tab_label)
4124 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4125 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4126 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4128 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4132 * gtk_notebook_append_page_menu:
4133 * @notebook: a #GtkNotebook
4134 * @child: the #GtkWidget to use as the contents of the page.
4135 * @tab_label: the #GtkWidget to be used as the label for the page,
4136 * or %NULL to use the default label, 'page N'.
4137 * @menu_label: the widget to use as a label for the page-switch
4138 * menu, if that is enabled. If %NULL, and @tab_label
4139 * is a #GtkLabel or %NULL, then the menu label will be
4140 * a newly created label with the same text as @tab_label;
4141 * If @tab_label is not a #GtkLabel, @menu_label must be
4142 * specified if the page-switch menu is to be used.
4144 * Appends a page to @notebook, specifying the widget to use as the
4145 * label in the popup menu.
4147 * Return value: the index (starting from 0) of the appended
4148 * page in the notebook, or -1 if function fails
4151 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4153 GtkWidget *tab_label,
4154 GtkWidget *menu_label)
4156 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4157 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4158 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4159 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4161 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4165 * gtk_notebook_prepend_page:
4166 * @notebook: a #GtkNotebook
4167 * @child: the #GtkWidget to use as the contents of the page.
4168 * @tab_label: the #GtkWidget to be used as the label for the page,
4169 * or %NULL to use the default label, 'page N'.
4171 * Prepends a page to @notebook.
4173 * Return value: the index (starting from 0) of the prepended
4174 * page in the notebook, or -1 if function fails
4177 gtk_notebook_prepend_page (GtkNotebook *notebook,
4179 GtkWidget *tab_label)
4181 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4182 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4183 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4185 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4189 * gtk_notebook_prepend_page_menu:
4190 * @notebook: a #GtkNotebook
4191 * @child: the #GtkWidget to use as the contents of the page.
4192 * @tab_label: the #GtkWidget to be used as the label for the page,
4193 * or %NULL to use the default label, 'page N'.
4194 * @menu_label: the widget to use as a label for the page-switch
4195 * menu, if that is enabled. If %NULL, and @tab_label
4196 * is a #GtkLabel or %NULL, then the menu label will be
4197 * a newly created label with the same text as @tab_label;
4198 * If @tab_label is not a #GtkLabel, @menu_label must be
4199 * specified if the page-switch menu is to be used.
4201 * Prepends a page to @notebook, specifying the widget to use as the
4202 * label in the popup menu.
4204 * Return value: the index (starting from 0) of the prepended
4205 * page in the notebook, or -1 if function fails
4208 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4210 GtkWidget *tab_label,
4211 GtkWidget *menu_label)
4213 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4214 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4215 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4216 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4218 return 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.
4232 * Return value: the index (starting from 0) of the inserted
4233 * page in the notebook, or -1 if function fails
4236 gtk_notebook_insert_page (GtkNotebook *notebook,
4238 GtkWidget *tab_label,
4241 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4242 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4243 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4245 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4250 gtk_notebook_page_compare_tab (gconstpointer a,
4253 return (((GtkNotebookPage *) a)->tab_label != b);
4257 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4261 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4264 list = g_list_find_custom (notebook->children, child,
4265 gtk_notebook_page_compare_tab);
4268 GtkNotebookPage *page = list->data;
4270 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4271 gtk_notebook_switch_page (notebook, page, -1);
4272 focus_tabs_in (notebook);
4279 * gtk_notebook_insert_page_menu:
4280 * @notebook: a #GtkNotebook
4281 * @child: the #GtkWidget to use as the contents of the page.
4282 * @tab_label: the #GtkWidget to be used as the label for the page,
4283 * or %NULL to use the default label, 'page N'.
4284 * @menu_label: the widget to use as a label for the page-switch
4285 * menu, if that is enabled. If %NULL, and @tab_label
4286 * is a #GtkLabel or %NULL, then the menu label will be
4287 * a newly created label with the same text as @tab_label;
4288 * If @tab_label is not a #GtkLabel, @menu_label must be
4289 * specified if the page-switch menu is to be used.
4290 * @position: the index (starting at 0) at which to insert the page,
4291 * or -1 to append the page after all other pages.
4293 * Insert a page into @notebook at the given position, specifying
4294 * the widget to use as the label in the popup menu.
4296 * Return value: the index (starting from 0) of the inserted
4297 * page in the notebook, or -1 if function fails
4300 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4302 GtkWidget *tab_label,
4303 GtkWidget *menu_label,
4306 GtkNotebookPage *page;
4309 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4310 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4311 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4312 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4314 gtk_widget_freeze_child_notify (child);
4316 page = g_new (GtkNotebookPage, 1);
4317 page->child = child;
4318 page->last_focus_child = NULL;
4319 page->requisition.width = 0;
4320 page->requisition.height = 0;
4321 page->allocation.x = 0;
4322 page->allocation.y = 0;
4323 page->allocation.width = 0;
4324 page->allocation.height = 0;
4325 page->default_menu = FALSE;
4326 page->default_tab = FALSE;
4327 page->mnemonic_activate_signal = 0;
4329 nchildren = g_list_length (notebook->children);
4330 if ((position < 0) || (position > nchildren))
4331 position = nchildren;
4333 notebook->children = g_list_insert (notebook->children, page, position);
4337 page->default_tab = TRUE;
4338 if (notebook->show_tabs)
4339 tab_label = gtk_label_new ("");
4341 page->tab_label = tab_label;
4342 page->menu_label = menu_label;
4343 page->expand = FALSE;
4345 page->pack = GTK_PACK_START;
4348 page->default_menu = TRUE;
4351 g_object_ref (page->menu_label);
4352 gtk_object_sink (GTK_OBJECT (page->menu_label));
4356 gtk_notebook_menu_item_create (notebook,
4357 g_list_find (notebook->children, page));
4359 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4361 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4363 gtk_notebook_update_labels (notebook);
4365 if (!notebook->first_tab)
4366 notebook->first_tab = notebook->children;
4368 if (!notebook->cur_page)
4369 gtk_widget_set_child_visible (child, TRUE);
4371 gtk_widget_set_child_visible (child, FALSE);
4375 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4376 gtk_widget_show (tab_label);
4378 gtk_widget_hide (tab_label);
4381 if (!notebook->cur_page)
4383 gtk_notebook_switch_page (notebook, page, 0);
4384 gtk_notebook_switch_focus_tab (notebook, NULL);
4387 gtk_notebook_update_tab_states (notebook);
4390 page->mnemonic_activate_signal =
4391 g_signal_connect (tab_label,
4392 "mnemonic_activate",
4393 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4396 gtk_widget_child_notify (child, "tab_expand");
4397 gtk_widget_child_notify (child, "tab_fill");
4398 gtk_widget_child_notify (child, "tab_pack");
4399 gtk_widget_child_notify (child, "tab_label");
4400 gtk_widget_child_notify (child, "menu_label");
4401 gtk_widget_child_notify (child, "position");
4402 gtk_widget_thaw_child_notify (child);
4408 * gtk_notebook_remove_page:
4409 * @notebook: a #GtkNotebook.
4410 * @page_num: the index of a notebook page, starting
4411 * from 0. If -1, the last page will
4414 * Removes a page from the notebook given its index
4418 gtk_notebook_remove_page (GtkNotebook *notebook,
4423 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4427 list = g_list_nth (notebook->children, page_num);
4429 gtk_notebook_real_remove (notebook, list, FALSE);
4433 list = g_list_last (notebook->children);
4435 gtk_notebook_real_remove (notebook, list, FALSE);
4439 /* Public GtkNotebook Page Switch Methods :
4440 * gtk_notebook_get_current_page
4441 * gtk_notebook_page_num
4442 * gtk_notebook_set_current_page
4443 * gtk_notebook_next_page
4444 * gtk_notebook_prev_page
4447 * gtk_notebook_get_current_page:
4448 * @notebook: a #GtkNotebook
4450 * Returns the page number of the current page.
4452 * Return value: the index (starting from 0) of the current
4453 * page in the notebook. If the notebook has no pages, then
4454 * -1 will be returned.
4457 gtk_notebook_get_current_page (GtkNotebook *notebook)
4459 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4461 if (!notebook->cur_page)
4464 return g_list_index (notebook->children, notebook->cur_page);
4468 * gtk_notebook_get_nth_page:
4469 * @notebook: a #GtkNotebook
4470 * @page_num: the index of a page in the noteobok, or -1
4471 * to get the last page.
4473 * Returns the child widget contained in page number @page_num.
4475 * Return value: the child widget, or %NULL if @page_num is
4479 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4482 GtkNotebookPage *page;
4485 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4488 list = g_list_nth (notebook->children, page_num);
4490 list = g_list_last (notebook->children);
4502 * gtk_notebook_get_n_pages:
4503 * @notebook: a #GtkNotebook
4505 * Gets the number of pages in a notebook.
4507 * Return value: the number of pages in the notebook.
4512 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4514 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4516 return g_list_length (notebook->children);
4520 * gtk_notebook_page_num:
4521 * @notebook: a #GtkNotebook
4522 * @child: a #GtkWidget
4524 * Finds the index of the page which contains the given child
4527 * Return value: the index of the page containing @child, or
4528 * -1 if @child is not in the notebook.
4531 gtk_notebook_page_num (GtkNotebook *notebook,
4537 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4540 children = notebook->children;
4543 GtkNotebookPage *page = children->data;
4545 if (page->child == child)
4548 children = children->next;
4556 * gtk_notebook_set_current_page:
4557 * @notebook: a #GtkNotebook
4558 * @page_num: index of the page to switch to, starting from 0.
4559 * If negative, the last page will be used. If greater
4560 * than the number of pages in the notebook, nothing
4563 * Switches to the page number @page_num.
4566 gtk_notebook_set_current_page (GtkNotebook *notebook,
4571 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4574 list = g_list_nth (notebook->children, page_num);
4576 list = g_list_last (notebook->children);
4578 page_num = g_list_index (notebook->children, list);
4581 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4585 * gtk_notebook_next_page:
4586 * @notebook: a #GtkNotebook
4588 * Switches to the next page. Nothing happens if the current page is
4592 gtk_notebook_next_page (GtkNotebook *notebook)
4596 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4598 list = g_list_find (notebook->children, notebook->cur_page);
4602 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4606 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4610 * gtk_notebook_prev_page:
4611 * @notebook: a #GtkNotebook
4613 * Switches to the previous page. Nothing happens if the current page
4614 * is the first page.
4617 gtk_notebook_prev_page (GtkNotebook *notebook)
4621 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4623 list = g_list_find (notebook->children, notebook->cur_page);
4627 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4631 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4634 /* Public GtkNotebook/Tab Style Functions
4636 * gtk_notebook_set_show_border
4637 * gtk_notebook_set_show_tabs
4638 * gtk_notebook_set_tab_pos
4639 * gtk_notebook_set_homogeneous_tabs
4640 * gtk_notebook_set_tab_border
4641 * gtk_notebook_set_tab_hborder
4642 * gtk_notebook_set_tab_vborder
4643 * gtk_notebook_set_scrollable
4646 * gtk_notebook_set_show_border:
4647 * @notebook: a #GtkNotebook
4648 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4650 * Sets whether a bevel will be drawn around the notebook pages.
4651 * This only has a visual effect when the tabs are not shown.
4652 * See gtk_notebook_set_show_tabs().
4655 gtk_notebook_set_show_border (GtkNotebook *notebook,
4656 gboolean show_border)
4658 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4660 if (notebook->show_border != show_border)
4662 notebook->show_border = show_border;
4664 if (GTK_WIDGET_VISIBLE (notebook))
4665 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4667 g_object_notify (G_OBJECT (notebook), "show_border");
4672 * gtk_notebook_get_show_border:
4673 * @notebook: a #GtkNotebook
4675 * Returns whether a bevel will be drawn around the notebook pages. See
4676 * gtk_notebook_set_show_border().
4678 * Return value: %TRUE if the bevel is drawn
4681 gtk_notebook_get_show_border (GtkNotebook *notebook)
4683 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4685 return notebook->show_border;
4689 * gtk_notebook_set_show_tabs:
4690 * @notebook: a #GtkNotebook
4691 * @show_tabs: %TRUE if the tabs should be shown.
4693 * Sets whether to show the tabs for the notebook or not.
4696 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4699 GtkNotebookPage *page;
4702 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4704 show_tabs = show_tabs != FALSE;
4706 if (notebook->show_tabs == show_tabs)
4709 notebook->show_tabs = show_tabs;
4710 children = notebook->children;
4714 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4718 page = children->data;
4719 children = children->next;
4720 if (page->default_tab)
4722 gtk_widget_destroy (page->tab_label);
4723 page->tab_label = NULL;
4726 gtk_widget_hide (page->tab_label);
4731 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4732 gtk_notebook_update_labels (notebook);
4734 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4736 g_object_notify (G_OBJECT (notebook), "show_tabs");
4740 * gtk_notebook_get_show_tabs:
4741 * @notebook: a #GtkNotebook
4743 * Returns whether the tabs of the notebook are shown. See
4744 * gtk_notebook_set_show_tabs().
4746 * Return value: %TRUE if the tabs are shown
4749 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4751 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4753 return notebook->show_tabs;
4757 * gtk_notebook_set_tab_pos:
4758 * @notebook: a #GtkNotebook.
4759 * @pos: the edge to draw the tabs at.
4761 * Sets the edge at which the tabs for switching pages in the
4762 * notebook are drawn.
4765 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4766 GtkPositionType pos)
4768 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4770 if (notebook->tab_pos != pos)
4772 notebook->tab_pos = pos;
4773 if (GTK_WIDGET_VISIBLE (notebook))
4774 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4777 g_object_notify (G_OBJECT (notebook), "tab_pos");
4781 * gtk_notebook_get_tab_pos:
4782 * @notebook: a #GtkNotebook
4784 * Gets the edge at which the tabs for switching pages in the
4785 * notebook are drawn.
4787 * Return value: the edge at which the tabs are drawn
4790 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4792 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4794 return notebook->tab_pos;
4798 * gtk_notebook_set_homogeneous_tabs:
4799 * @notebook: a #GtkNotebook
4800 * @homogeneous: %TRUE if all tabs should be the same size.
4802 * Sets whether the tabs must have all the same size or not.
4805 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4806 gboolean homogeneous)
4808 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4810 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4814 * gtk_notebook_set_tab_border:
4815 * @notebook: a #GtkNotebook
4816 * @border_width: width of the border around the tab labels.
4818 * Sets the width the border around the tab labels
4819 * in a notebook. This is equivalent to calling
4820 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4821 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4824 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4827 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4829 gtk_notebook_set_tab_border_internal (notebook, border_width);
4833 * gtk_notebook_set_tab_hborder:
4834 * @notebook: a #GtkNotebook
4835 * @tab_hborder: width of the horizontal border of tab labels.
4837 * Sets the width of the horizontal border of tab labels.
4840 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4843 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4845 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4849 * gtk_notebook_set_tab_vborder:
4850 * @notebook: a #GtkNotebook
4851 * @tab_vborder: width of the vertical border of tab labels.
4853 * Sets the width of the vertical border of tab labels.
4856 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4859 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4861 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4865 * gtk_notebook_set_scrollable:
4866 * @notebook: a #GtkNotebook
4867 * @scrollable: %TRUE if scroll arrows should be added
4869 * Sets whether the tab label area will have arrows for scrolling if
4870 * there are too many tabs to fit in the area.
4873 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4874 gboolean scrollable)
4876 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4878 scrollable = (scrollable != FALSE);
4880 if (scrollable != notebook->scrollable)
4882 notebook->scrollable = scrollable;
4884 if (GTK_WIDGET_VISIBLE (notebook))
4885 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4887 g_object_notify (G_OBJECT (notebook), "scrollable");
4892 * gtk_notebook_get_scrollable:
4893 * @notebook: a #GtkNotebook
4895 * Returns whether the tab label area has arrows for scrolling. See
4896 * gtk_notebook_set_scrollable().
4898 * Return value: %TRUE if arrows for scrolling are present
4901 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4903 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4905 return notebook->scrollable;
4908 /* Public GtkNotebook Popup Menu Methods:
4910 * gtk_notebook_popup_enable
4911 * gtk_notebook_popup_disable
4916 * gtk_notebook_popup_enable:
4917 * @notebook: a #GtkNotebook
4919 * Enables the popup menu: if the user clicks with the right mouse button on
4920 * the bookmarks, a menu with all the pages will be popped up.
4923 gtk_notebook_popup_enable (GtkNotebook *notebook)
4927 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4932 notebook->menu = gtk_menu_new ();
4933 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4935 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4936 gtk_notebook_menu_item_create (notebook, list);
4938 gtk_notebook_update_labels (notebook);
4939 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4940 GTK_WIDGET (notebook),
4941 gtk_notebook_menu_detacher);
4943 g_object_notify (G_OBJECT (notebook), "enable_popup");
4947 * gtk_notebook_popup_disable:
4948 * @notebook: a #GtkNotebook
4950 * Disables the popup menu.
4953 gtk_notebook_popup_disable (GtkNotebook *notebook)
4955 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4957 if (!notebook->menu)
4960 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4961 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4962 gtk_widget_destroy (notebook->menu);
4964 g_object_notify (G_OBJECT (notebook), "enable_popup");
4967 /* Public GtkNotebook Page Properties Functions:
4969 * gtk_notebook_get_tab_label
4970 * gtk_notebook_set_tab_label
4971 * gtk_notebook_set_tab_label_text
4972 * gtk_notebook_get_menu_label
4973 * gtk_notebook_set_menu_label
4974 * gtk_notebook_set_menu_label_text
4975 * gtk_notebook_set_tab_label_packing
4976 * gtk_notebook_query_tab_label_packing
4980 * gtk_notebook_get_tab_label:
4981 * @notebook: a #GtkNotebook
4984 * Returns the tab label widget for the page @child. %NULL is returned
4985 * if @child is not in @notebook or if no tab label has specifically
4986 * been set for @child.
4988 * Return value: the tab label
4991 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4996 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4997 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4999 list = CHECK_FIND_CHILD (notebook, child);
5003 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5006 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5010 * gtk_notebook_set_tab_label:
5011 * @notebook: a #GtkNotebook
5013 * @tab_label: the tab label widget to use, or %NULL for default tab
5016 * Changes the tab label for @child. If %NULL is specified
5017 * for @tab_label, then the page will have the label 'page N'.
5020 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5022 GtkWidget *tab_label)
5024 GtkNotebookPage *page;
5027 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5028 g_return_if_fail (GTK_IS_WIDGET (child));
5030 list = CHECK_FIND_CHILD (notebook, child);
5034 /* a NULL pointer indicates a default_tab setting, otherwise
5035 * we need to set the associated label
5039 if (page->tab_label == tab_label)
5043 gtk_notebook_remove_tab_label (notebook, page);
5047 page->default_tab = FALSE;
5048 page->tab_label = tab_label;
5049 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5053 page->default_tab = TRUE;
5054 page->tab_label = NULL;
5056 if (notebook->show_tabs)
5060 g_snprintf (string, sizeof(string), _("Page %u"),
5061 gtk_notebook_real_page_position (notebook, list));
5062 page->tab_label = gtk_label_new (string);
5063 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5067 if (page->tab_label)
5068 page->mnemonic_activate_signal =
5069 g_signal_connect (page->tab_label,
5070 "mnemonic_activate",
5071 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5074 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5076 gtk_widget_show (page->tab_label);
5077 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5080 gtk_notebook_update_tab_states (notebook);
5081 gtk_widget_child_notify (child, "tab_label");
5085 * gtk_notebook_set_tab_label_text:
5086 * @notebook: a #GtkNotebook
5088 * @tab_text: the label text
5090 * Creates a new label and sets it as the tab label for the page
5091 * containing @child.
5094 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5096 const gchar *tab_text)
5098 GtkWidget *tab_label = NULL;
5100 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5103 tab_label = gtk_label_new (tab_text);
5104 gtk_notebook_set_tab_label (notebook, child, tab_label);
5105 gtk_widget_child_notify (child, "tab_label");
5109 * gtk_notebook_get_tab_label_text:
5110 * @notebook: a #GtkNotebook
5111 * @child: a widget contained in a page of @notebook
5113 * Retrieves the text of the tab label for the page containing
5116 * Returns value: the text of the tab label, or %NULL if the
5117 * tab label widget is not a #GtkLabel. The
5118 * string is owned by the widget and must not
5121 G_CONST_RETURN gchar *
5122 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5125 GtkWidget *tab_label;
5127 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5128 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5130 tab_label = gtk_notebook_get_tab_label (notebook, child);
5132 if (tab_label && GTK_IS_LABEL (tab_label))
5133 return gtk_label_get_text (GTK_LABEL (tab_label));
5139 * gtk_notebook_get_menu_label:
5140 * @notebook: a #GtkNotebook
5141 * @child: a widget contained in a page of @notebook
5143 * Retrieves the menu label widget of the page containing @child.
5145 * Return value: the menu label, or %NULL if the
5146 * notebook page does not have a menu label other
5147 * than the default (the tab label).
5150 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5155 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5156 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5158 list = CHECK_FIND_CHILD (notebook, child);
5162 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5165 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5169 * gtk_notebook_set_menu_label:
5170 * @notebook: a #GtkNotebook
5171 * @child: the child widget
5172 * @menu_label: the menu label, or NULL for default
5174 * Changes the menu label for the page containing @child.
5177 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5179 GtkWidget *menu_label)
5181 GtkNotebookPage *page;
5184 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5185 g_return_if_fail (GTK_IS_WIDGET (child));
5187 list = CHECK_FIND_CHILD (notebook, child);
5192 if (page->menu_label)
5195 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5196 page->menu_label->parent);
5198 if (!page->default_menu)
5199 g_object_unref (page->menu_label);
5204 page->menu_label = menu_label;
5205 g_object_ref (page->menu_label);
5206 gtk_object_sink (GTK_OBJECT(page->menu_label));
5207 page->default_menu = FALSE;
5210 page->default_menu = TRUE;
5213 gtk_notebook_menu_item_create (notebook, list);
5214 gtk_widget_child_notify (child, "menu_label");
5218 * gtk_notebook_set_menu_label_text:
5219 * @notebook: a #GtkNotebook
5220 * @child: the child widget
5221 * @menu_text: the label text
5223 * Creates a new label and sets it as the menu label of @child.
5226 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5228 const gchar *menu_text)
5230 GtkWidget *menu_label = NULL;
5232 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5235 menu_label = gtk_label_new (menu_text);
5236 gtk_notebook_set_menu_label (notebook, child, menu_label);
5237 gtk_widget_child_notify (child, "menu_label");
5241 * gtk_notebook_get_menu_label_text:
5242 * @notebook: a #GtkNotebook
5243 * @child: the child widget of a page of the notebook.
5245 * Retrieves the text of the menu label for the page containing
5248 * Returns value: the text of the tab label, or %NULL if the
5249 * widget does not have a menu label other than
5250 * the default menu label, or the menu label widget
5251 * is not a #GtkLabel. The string is owned by
5252 * the widget and must not be freed.
5254 G_CONST_RETURN gchar *
5255 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5258 GtkWidget *menu_label;
5260 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5261 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5263 menu_label = gtk_notebook_get_menu_label (notebook, child);
5265 if (menu_label && GTK_IS_LABEL (menu_label))
5266 return gtk_label_get_text (GTK_LABEL (menu_label));
5271 /* Helper function called when pages are reordered
5274 gtk_notebook_child_reordered (GtkNotebook *notebook,
5275 GtkNotebookPage *page)
5279 GtkWidget *menu_item;
5281 menu_item = page->menu_label->parent;
5282 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5283 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5284 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5287 gtk_notebook_update_tab_states (notebook);
5288 gtk_notebook_update_labels (notebook);
5292 * gtk_notebook_set_tab_label_packing:
5293 * @notebook: a #GtkNotebook
5294 * @child: the child widget
5295 * @expand: whether to expand the bookmark or not
5296 * @fill: whether the bookmark should fill the allocated area or not
5297 * @pack_type: the position of the bookmark
5299 * Sets the packing parameters for the tab label of the page
5300 * containing @child. See gtk_box_pack_start() for the exact meaning
5301 * of the parameters.
5304 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5308 GtkPackType pack_type)
5310 GtkNotebookPage *page;
5313 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5314 g_return_if_fail (GTK_IS_WIDGET (child));
5316 list = CHECK_FIND_CHILD (notebook, child);
5321 expand = expand != FALSE;
5322 fill = fill != FALSE;
5323 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5326 gtk_widget_freeze_child_notify (child);
5327 page->expand = expand;
5328 gtk_widget_child_notify (child, "tab_expand");
5330 gtk_widget_child_notify (child, "tab_fill");
5331 if (page->pack != pack_type)
5333 page->pack = pack_type;
5334 gtk_notebook_child_reordered (notebook, page);
5336 gtk_widget_child_notify (child, "tab_pack");
5337 gtk_widget_child_notify (child, "position");
5338 if (notebook->show_tabs)
5339 gtk_notebook_pages_allocate (notebook);
5340 gtk_widget_thaw_child_notify (child);
5344 * gtk_notebook_query_tab_label_packing:
5345 * @notebook: a #GtkNotebook
5347 * @expand: location to store the expand value (or NULL)
5348 * @fill: location to store the fill value (or NULL)
5349 * @pack_type: location to store the pack_type (or NULL)
5351 * Query the packing attributes for the tab label of the page
5352 * containing @child.
5355 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5359 GtkPackType *pack_type)
5363 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5364 g_return_if_fail (GTK_IS_WIDGET (child));
5366 list = CHECK_FIND_CHILD (notebook, child);
5371 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5373 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5375 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5379 * gtk_notebook_reorder_child:
5380 * @notebook: a #GtkNotebook
5381 * @child: the child to move
5382 * @position: the new position, or -1 to move to the end
5384 * Reorders the page containing @child, so that it appears in position
5385 * @position. If @position is greater than or equal to the number of
5386 * children in the list or negative, @child will be moved to the end
5390 gtk_notebook_reorder_child (GtkNotebook *notebook,
5394 GList *list, *new_list;
5395 GtkNotebookPage *page;
5399 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5400 g_return_if_fail (GTK_IS_WIDGET (child));
5402 list = CHECK_FIND_CHILD (notebook, child);
5406 max_pos = g_list_length (notebook->children) - 1;
5407 if (position < 0 || position > max_pos)
5410 old_pos = g_list_position (notebook->children, list);
5412 if (old_pos == position)
5416 notebook->children = g_list_delete_link (notebook->children, list);
5418 notebook->children = g_list_insert (notebook->children, page, position);
5419 new_list = g_list_nth (notebook->children, position);
5421 /* Fix up GList references in GtkNotebook structure */
5422 if (notebook->first_tab == list)
5423 notebook->first_tab = new_list;
5424 if (notebook->focus_tab == list)
5425 notebook->focus_tab = new_list;
5427 gtk_widget_freeze_child_notify (child);
5429 /* Move around the menu items if necessary */
5430 gtk_notebook_child_reordered (notebook, page);
5431 gtk_widget_child_notify (child, "tab_pack");
5432 gtk_widget_child_notify (child, "position");
5434 if (notebook->show_tabs)
5435 gtk_notebook_pages_allocate (notebook);
5437 gtk_widget_thaw_child_notify (child);