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/.
28 #include "gtknotebook.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
36 #include "gtkmarshalers.h"
37 #include "gtkbindings.h"
41 #define TAB_CURVATURE 1
43 #define ARROW_SPACING 0
44 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
45 #define NOTEBOOK_SCROLL_DELAY (100)
71 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
72 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
91 CHILD_PROP_MENU_LABEL,
93 CHILD_PROP_TAB_EXPAND,
98 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
100 struct _GtkNotebookPage
103 GtkWidget *tab_label;
104 GtkWidget *menu_label;
105 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
107 guint default_menu : 1; /* If true, we create the menu label ourself */
108 guint default_tab : 1; /* If true, we create the tab label ourself */
113 GtkRequisition requisition;
114 GtkAllocation allocation;
116 guint mnemonic_activate_signal;
119 #ifdef G_DISABLE_CHECKS
120 #define CHECK_FIND_CHILD(notebook, child) \
121 gtk_notebook_find_child (notebook, child, G_STRLOC)
123 #define CHECK_FIND_CHILD(notebook, child) \
124 gtk_notebook_find_child (notebook, child, NULL)
127 /*** GtkNotebook Methods ***/
128 static void gtk_notebook_class_init (GtkNotebookClass *klass);
129 static void gtk_notebook_init (GtkNotebook *notebook);
131 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
132 gboolean move_focus);
133 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
134 GtkNotebookTab type);
135 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
137 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
138 GtkDirectionType direction_type);
140 /*** GtkObject Methods ***/
141 static void gtk_notebook_destroy (GtkObject *object);
142 static void gtk_notebook_set_property (GObject *object,
146 static void gtk_notebook_get_property (GObject *object,
151 /*** GtkWidget Methods ***/
152 static void gtk_notebook_map (GtkWidget *widget);
153 static void gtk_notebook_unmap (GtkWidget *widget);
154 static void gtk_notebook_realize (GtkWidget *widget);
155 static void gtk_notebook_unrealize (GtkWidget *widget);
156 static void gtk_notebook_size_request (GtkWidget *widget,
157 GtkRequisition *requisition);
158 static void gtk_notebook_size_allocate (GtkWidget *widget,
159 GtkAllocation *allocation);
160 static gint gtk_notebook_expose (GtkWidget *widget,
161 GdkEventExpose *event);
162 static gboolean gtk_notebook_scroll (GtkWidget *widget,
163 GdkEventScroll *event);
164 static gint gtk_notebook_button_press (GtkWidget *widget,
165 GdkEventButton *event);
166 static gint gtk_notebook_button_release (GtkWidget *widget,
167 GdkEventButton *event);
168 static gint gtk_notebook_enter_notify (GtkWidget *widget,
169 GdkEventCrossing *event);
170 static gint gtk_notebook_leave_notify (GtkWidget *widget,
171 GdkEventCrossing *event);
172 static gint gtk_notebook_motion_notify (GtkWidget *widget,
173 GdkEventMotion *event);
174 static gint gtk_notebook_focus_in (GtkWidget *widget,
175 GdkEventFocus *event);
176 static gint gtk_notebook_focus_out (GtkWidget *widget,
177 GdkEventFocus *event);
178 static void gtk_notebook_grab_notify (GtkWidget *widget,
179 gboolean was_grabbed);
180 static void gtk_notebook_state_changed (GtkWidget *widget,
181 GtkStateType previous_state);
182 static void gtk_notebook_draw_focus (GtkWidget *widget);
183 static gint gtk_notebook_focus (GtkWidget *widget,
184 GtkDirectionType direction);
185 static void gtk_notebook_style_set (GtkWidget *widget,
188 /*** GtkContainer Methods ***/
189 static void gtk_notebook_set_child_property (GtkContainer *container,
194 static void gtk_notebook_get_child_property (GtkContainer *container,
199 static void gtk_notebook_add (GtkContainer *container,
201 static void gtk_notebook_remove (GtkContainer *container,
203 static void gtk_notebook_set_focus_child (GtkContainer *container,
205 static GType gtk_notebook_child_type (GtkContainer *container);
206 static void gtk_notebook_forall (GtkContainer *container,
207 gboolean include_internals,
208 GtkCallback callback,
209 gpointer callback_data);
211 /*** GtkNotebook Private Functions ***/
212 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
213 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
214 static void gtk_notebook_real_remove (GtkNotebook *notebook,
216 gboolean destroying);
217 static void gtk_notebook_update_labels (GtkNotebook *notebook);
218 static gint gtk_notebook_timer (GtkNotebook *notebook);
219 static gint gtk_notebook_page_compare (gconstpointer a,
221 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
223 const gchar *function);
224 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
226 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
229 gboolean find_visible);
231 /*** GtkNotebook Drawing Functions ***/
232 static void gtk_notebook_paint (GtkWidget *widget,
234 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
235 GtkNotebookPage *page,
237 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
238 GtkNotebookArrow arrow);
240 /*** GtkNotebook Size Allocate Functions ***/
241 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
242 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
243 GtkNotebookPage *page,
244 GtkAllocation *allocation);
245 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
251 /*** GtkNotebook Page Switch Methods ***/
252 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
253 GtkNotebookPage *page,
256 /*** GtkNotebook Page Switch Functions ***/
257 static void gtk_notebook_switch_page (GtkNotebook *notebook,
258 GtkNotebookPage *page,
260 static gint gtk_notebook_page_select (GtkNotebook *notebook,
261 gboolean move_focus);
262 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
264 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
265 GtkNotebookPage *page);
267 /*** GtkNotebook Menu Functions ***/
268 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
270 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
272 static void gtk_notebook_menu_detacher (GtkWidget *widget,
275 /*** GtkNotebook Private Setters ***/
276 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
277 gboolean homogeneous);
278 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
280 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
282 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
285 static gboolean focus_tabs_in (GtkNotebook *notebook);
286 static gboolean focus_child_in (GtkNotebook *notebook,
287 GtkDirectionType direction);
289 static GtkContainerClass *parent_class = NULL;
290 static guint notebook_signals[LAST_SIGNAL] = { 0 };
293 gtk_notebook_get_type (void)
295 static GType notebook_type = 0;
299 static const GTypeInfo notebook_info =
301 sizeof (GtkNotebookClass),
302 NULL, /* base_init */
303 NULL, /* base_finalize */
304 (GClassInitFunc) gtk_notebook_class_init,
305 NULL, /* class_finalize */
306 NULL, /* class_data */
307 sizeof (GtkNotebook),
309 (GInstanceInitFunc) gtk_notebook_init,
312 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
316 return notebook_type;
320 add_tab_bindings (GtkBindingSet *binding_set,
321 GdkModifierType modifiers,
322 GtkDirectionType direction)
324 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
326 GTK_TYPE_DIRECTION_TYPE, direction);
327 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
329 GTK_TYPE_DIRECTION_TYPE, direction);
333 add_arrow_bindings (GtkBindingSet *binding_set,
335 GtkDirectionType direction)
337 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
339 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
344 GTK_TYPE_DIRECTION_TYPE, direction);
348 gtk_notebook_class_init (GtkNotebookClass *class)
350 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
351 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
352 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
353 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
354 GtkBindingSet *binding_set;
356 parent_class = g_type_class_peek_parent (class);
358 gobject_class->set_property = gtk_notebook_set_property;
359 gobject_class->get_property = gtk_notebook_get_property;
360 object_class->destroy = gtk_notebook_destroy;
362 widget_class->map = gtk_notebook_map;
363 widget_class->unmap = gtk_notebook_unmap;
364 widget_class->realize = gtk_notebook_realize;
365 widget_class->unrealize = gtk_notebook_unrealize;
366 widget_class->size_request = gtk_notebook_size_request;
367 widget_class->size_allocate = gtk_notebook_size_allocate;
368 widget_class->expose_event = gtk_notebook_expose;
369 widget_class->scroll_event = gtk_notebook_scroll;
370 widget_class->button_press_event = gtk_notebook_button_press;
371 widget_class->button_release_event = gtk_notebook_button_release;
372 widget_class->enter_notify_event = gtk_notebook_enter_notify;
373 widget_class->leave_notify_event = gtk_notebook_leave_notify;
374 widget_class->motion_notify_event = gtk_notebook_motion_notify;
375 widget_class->grab_notify = gtk_notebook_grab_notify;
376 widget_class->state_changed = gtk_notebook_state_changed;
377 widget_class->focus_in_event = gtk_notebook_focus_in;
378 widget_class->focus_out_event = gtk_notebook_focus_out;
379 widget_class->focus = gtk_notebook_focus;
380 widget_class->style_set = gtk_notebook_style_set;
382 container_class->add = gtk_notebook_add;
383 container_class->remove = gtk_notebook_remove;
384 container_class->forall = gtk_notebook_forall;
385 container_class->set_focus_child = gtk_notebook_set_focus_child;
386 container_class->get_child_property = gtk_notebook_get_child_property;
387 container_class->set_child_property = gtk_notebook_set_child_property;
388 container_class->child_type = gtk_notebook_child_type;
390 class->switch_page = gtk_notebook_real_switch_page;
392 class->focus_tab = gtk_notebook_focus_tab;
393 class->select_page = gtk_notebook_select_page;
394 class->change_current_page = gtk_notebook_change_current_page;
395 class->move_focus_out = gtk_notebook_move_focus_out;
397 g_object_class_install_property (gobject_class,
399 g_param_spec_int ("page",
401 P_("The index of the current page"),
406 g_object_class_install_property (gobject_class,
408 g_param_spec_enum ("tab_pos",
410 P_("Which side of the notebook holds the tabs"),
411 GTK_TYPE_POSITION_TYPE,
414 g_object_class_install_property (gobject_class,
416 g_param_spec_uint ("tab_border",
418 P_("Width of the border around the tab labels"),
423 g_object_class_install_property (gobject_class,
425 g_param_spec_uint ("tab_hborder",
426 P_("Horizontal Tab Border"),
427 P_("Width of the horizontal border of tab labels"),
432 g_object_class_install_property (gobject_class,
434 g_param_spec_uint ("tab_vborder",
435 P_("Vertical Tab Border"),
436 P_("Width of the vertical border of tab labels"),
441 g_object_class_install_property (gobject_class,
443 g_param_spec_boolean ("show_tabs",
445 P_("Whether tabs should be shown or not"),
448 g_object_class_install_property (gobject_class,
450 g_param_spec_boolean ("show_border",
452 P_("Whether the border should be shown or not"),
455 g_object_class_install_property (gobject_class,
457 g_param_spec_boolean ("scrollable",
459 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
462 g_object_class_install_property (gobject_class,
464 g_param_spec_boolean ("enable_popup",
466 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
469 g_object_class_install_property (gobject_class,
471 g_param_spec_boolean ("homogeneous",
473 P_("Whether tabs should have homogeneous sizes"),
477 gtk_container_class_install_child_property (container_class,
478 CHILD_PROP_TAB_LABEL,
479 g_param_spec_string ("tab_label",
481 P_("The string displayed on the child's tab label"),
484 gtk_container_class_install_child_property (container_class,
485 CHILD_PROP_MENU_LABEL,
486 g_param_spec_string ("menu_label",
488 P_("The string displayed in the child's menu entry"),
491 gtk_container_class_install_child_property (container_class,
493 g_param_spec_int ("position",
495 P_("The index of the child in the parent"),
498 gtk_container_class_install_child_property (container_class,
499 CHILD_PROP_TAB_EXPAND,
500 g_param_spec_boolean ("tab_expand",
502 P_("Whether to expand the child's tab or not"),
505 gtk_container_class_install_child_property (container_class,
507 g_param_spec_boolean ("tab_fill",
509 P_("Whether the child's tab should fill the allocated area or not"),
512 gtk_container_class_install_child_property (container_class,
514 g_param_spec_enum ("tab_pack",
516 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
517 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
521 * GtkNotebook:has-secondary-backward-stepper:
523 * The "has-secondary-backward-stepper" property determines whether
524 * a second backward arrow button is displayed on the opposite end
529 gtk_widget_class_install_style_property (widget_class,
530 g_param_spec_boolean ("has_secondary backward_stepper",
531 P_("Secondary backward stepper"),
532 P_("Display a second backward arrow button on the opposite end of the tab area"),
538 * GtkNotebook:has-secondary-forward-stepper:
540 * The "has-secondary-forward-stepper" property determines whether
541 * a second forward arrow button is displayed on the opposite end
546 gtk_widget_class_install_style_property (widget_class,
547 g_param_spec_boolean ("has_secondary_forward_stepper",
548 P_("Secondary forward stepper"),
549 P_("Display a second forward arrow button on the opposite end of the tab area"),
555 * GtkNotebook:has-backward-stepper:
557 * The "has-backward-stepper" property determines whether
558 * the standard backward arrow button is displayed.
562 gtk_widget_class_install_style_property (widget_class,
563 g_param_spec_boolean ("has_backward_stepper",
564 P_("Backward stepper"),
565 P_("Display the standard backward arrow button"),
571 * GtkNotebook:has-forward-stepper:
573 * The "has-forward-stepper" property determines whether
574 * the standard forward arrow button is displayed.
578 gtk_widget_class_install_style_property (widget_class,
579 g_param_spec_boolean ("has_forward_stepper",
580 P_("Forward stepper"),
581 P_("Display the standard forward arrow button"),
586 notebook_signals[SWITCH_PAGE] =
587 g_signal_new ("switch_page",
588 G_TYPE_FROM_CLASS (gobject_class),
590 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
592 _gtk_marshal_VOID__POINTER_UINT,
596 notebook_signals[FOCUS_TAB] =
597 g_signal_new ("focus_tab",
598 G_TYPE_FROM_CLASS (gobject_class),
599 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
600 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
602 _gtk_marshal_BOOLEAN__ENUM,
604 GTK_TYPE_NOTEBOOK_TAB);
605 notebook_signals[SELECT_PAGE] =
606 g_signal_new ("select_page",
607 G_TYPE_FROM_CLASS (gobject_class),
608 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
609 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
611 _gtk_marshal_BOOLEAN__BOOLEAN,
614 notebook_signals[CHANGE_CURRENT_PAGE] =
615 g_signal_new ("change_current_page",
616 G_TYPE_FROM_CLASS (gobject_class),
617 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
618 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
620 _gtk_marshal_VOID__INT,
623 notebook_signals[MOVE_FOCUS_OUT] =
624 g_signal_new ("move_focus_out",
625 G_TYPE_FROM_CLASS (gobject_class),
626 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
627 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
629 _gtk_marshal_VOID__ENUM,
631 GTK_TYPE_DIRECTION_TYPE);
634 binding_set = gtk_binding_set_by_class (class);
635 gtk_binding_entry_add_signal (binding_set,
638 G_TYPE_BOOLEAN, FALSE);
639 gtk_binding_entry_add_signal (binding_set,
642 G_TYPE_BOOLEAN, FALSE);
644 gtk_binding_entry_add_signal (binding_set,
647 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
648 gtk_binding_entry_add_signal (binding_set,
651 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
652 gtk_binding_entry_add_signal (binding_set,
655 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
656 gtk_binding_entry_add_signal (binding_set,
659 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
661 gtk_binding_entry_add_signal (binding_set,
662 GDK_Page_Up, GDK_CONTROL_MASK,
663 "change_current_page", 1,
665 gtk_binding_entry_add_signal (binding_set,
666 GDK_Page_Down, GDK_CONTROL_MASK,
667 "change_current_page", 1,
670 gtk_binding_entry_add_signal (binding_set,
671 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
672 "change_current_page", 1,
674 gtk_binding_entry_add_signal (binding_set,
675 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
676 "change_current_page", 1,
679 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
680 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
681 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
682 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
684 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
685 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
689 gtk_notebook_init (GtkNotebook *notebook)
691 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
692 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
694 notebook->cur_page = NULL;
695 notebook->children = NULL;
696 notebook->first_tab = NULL;
697 notebook->focus_tab = NULL;
698 notebook->event_window = NULL;
699 notebook->menu = NULL;
701 notebook->tab_hborder = 2;
702 notebook->tab_vborder = 2;
704 notebook->show_tabs = TRUE;
705 notebook->show_border = TRUE;
706 notebook->tab_pos = GTK_POS_TOP;
707 notebook->scrollable = FALSE;
708 notebook->in_child = 0;
709 notebook->click_child = 0;
710 notebook->button = 0;
711 notebook->need_timer = 0;
712 notebook->child_has_focus = FALSE;
713 notebook->have_visible_child = FALSE;
714 notebook->focus_out = FALSE;
716 notebook->has_before_previous = 1;
717 notebook->has_before_next = 0;
718 notebook->has_after_previous = 0;
719 notebook->has_after_next = 1;
723 gtk_notebook_select_page (GtkNotebook *notebook,
726 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
728 gtk_notebook_page_select (notebook, move_focus);
736 gtk_notebook_focus_tab (GtkNotebook *notebook,
741 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
745 case GTK_NOTEBOOK_TAB_FIRST:
746 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
748 gtk_notebook_switch_focus_tab (notebook, list);
750 case GTK_NOTEBOOK_TAB_LAST:
751 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
753 gtk_notebook_switch_focus_tab (notebook, list);
764 gtk_notebook_change_current_page (GtkNotebook *notebook,
767 GList *current = NULL;
769 if (notebook->cur_page)
770 current = g_list_find (notebook->children, notebook->cur_page);
774 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
775 offset += offset < 0 ? 1 : -1;
779 gtk_notebook_switch_page (notebook, current->data, -1);
781 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
784 static GtkDirectionType
785 get_effective_direction (GtkNotebook *notebook,
786 GtkDirectionType direction)
788 /* Remap the directions into the effective direction it would be for a
789 * GTK_POS_TOP notebook
792 #define D(rest) GTK_DIR_##rest
794 static const GtkDirectionType translate_direction[2][4][6] = {
795 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
796 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
797 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
798 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
799 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
800 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
801 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
802 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
807 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
809 return translate_direction[text_dir][notebook->tab_pos][direction];
813 get_effective_tab_pos (GtkNotebook *notebook)
815 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
817 switch (notebook->tab_pos)
820 return GTK_POS_RIGHT;
827 return notebook->tab_pos;
831 gtk_notebook_move_focus_out (GtkNotebook *notebook,
832 GtkDirectionType direction_type)
834 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
837 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
838 if (focus_tabs_in (notebook))
840 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
841 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
844 /* At this point, we know we should be focusing out of the notebook entirely. We
845 * do this by setting a flag, then propagating the focus motion to the notebook.
847 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
848 if (!GTK_WIDGET_TOPLEVEL (toplevel))
851 g_object_ref (notebook);
853 notebook->focus_out = TRUE;
854 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
855 notebook->focus_out = FALSE;
857 g_object_unref (notebook);
864 * Creates a new #GtkNotebook widget with no pages.
866 * Return value: the newly created #GtkNotebook
869 gtk_notebook_new (void)
871 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
874 /* Private GtkObject Methods :
876 * gtk_notebook_destroy
877 * gtk_notebook_set_arg
878 * gtk_notebook_get_arg
881 gtk_notebook_destroy (GtkObject *object)
884 GtkNotebook *notebook = GTK_NOTEBOOK (object);
887 gtk_notebook_popup_disable (notebook);
889 children = notebook->children;
892 GList *child = children;
893 children = child->next;
895 gtk_notebook_real_remove (notebook, child, TRUE);
898 GTK_OBJECT_CLASS (parent_class)->destroy (object);
902 gtk_notebook_set_property (GObject *object,
907 GtkNotebook *notebook;
909 notebook = GTK_NOTEBOOK (object);
914 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
916 case PROP_SHOW_BORDER:
917 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
919 case PROP_SCROLLABLE:
920 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
922 case PROP_ENABLE_POPUP:
923 if (g_value_get_boolean (value))
924 gtk_notebook_popup_enable (notebook);
926 gtk_notebook_popup_disable (notebook);
928 case PROP_HOMOGENEOUS:
929 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
932 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
935 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
937 case PROP_TAB_BORDER:
938 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
940 case PROP_TAB_HBORDER:
941 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
943 case PROP_TAB_VBORDER:
944 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
952 gtk_notebook_get_property (GObject *object,
957 GtkNotebook *notebook;
959 notebook = GTK_NOTEBOOK (object);
964 g_value_set_boolean (value, notebook->show_tabs);
966 case PROP_SHOW_BORDER:
967 g_value_set_boolean (value, notebook->show_border);
969 case PROP_SCROLLABLE:
970 g_value_set_boolean (value, notebook->scrollable);
972 case PROP_ENABLE_POPUP:
973 g_value_set_boolean (value, notebook->menu != NULL);
975 case PROP_HOMOGENEOUS:
976 g_value_set_boolean (value, notebook->homogeneous);
979 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
982 g_value_set_enum (value, notebook->tab_pos);
984 case PROP_TAB_HBORDER:
985 g_value_set_uint (value, notebook->tab_hborder);
987 case PROP_TAB_VBORDER:
988 g_value_set_uint (value, notebook->tab_vborder);
991 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
996 /* Private GtkWidget Methods :
1000 * gtk_notebook_realize
1001 * gtk_notebook_size_request
1002 * gtk_notebook_size_allocate
1003 * gtk_notebook_expose
1004 * gtk_notebook_scroll
1005 * gtk_notebook_button_press
1006 * gtk_notebook_button_release
1007 * gtk_notebook_enter_notify
1008 * gtk_notebook_leave_notify
1009 * gtk_notebook_motion_notify
1010 * gtk_notebook_focus_in
1011 * gtk_notebook_focus_out
1012 * gtk_notebook_draw_focus
1013 * gtk_notebook_style_set
1016 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1017 GdkRectangle *rectangle)
1019 GtkWidget *widget = GTK_WIDGET (notebook);
1020 gint border_width = GTK_CONTAINER (notebook)->border_width;
1021 GtkNotebookPage *visible_page = NULL;
1023 gint tab_pos = get_effective_tab_pos (notebook);
1025 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1027 GtkNotebookPage *page = tmp_list->data;
1028 if (GTK_WIDGET_VISIBLE (page->child))
1030 visible_page = page;
1035 if (notebook->show_tabs && visible_page)
1039 rectangle->x = widget->allocation.x + border_width;
1040 rectangle->y = widget->allocation.y + border_width;
1045 case GTK_POS_BOTTOM:
1046 rectangle->width = widget->allocation.width - 2 * border_width;
1047 rectangle->height = visible_page->requisition.height;
1048 if (tab_pos == GTK_POS_BOTTOM)
1049 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1053 rectangle->width = visible_page->requisition.width;
1054 rectangle->height = widget->allocation.height - 2 * border_width;
1055 if (tab_pos == GTK_POS_RIGHT)
1056 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1067 rectangle->x = rectangle->y = 0;
1068 rectangle->width = rectangle->height = 10;
1076 gtk_notebook_map (GtkWidget *widget)
1078 GtkNotebook *notebook;
1079 GtkNotebookPage *page;
1082 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1084 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1086 notebook = GTK_NOTEBOOK (widget);
1088 if (notebook->cur_page &&
1089 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1090 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1091 gtk_widget_map (notebook->cur_page->child);
1093 if (notebook->scrollable)
1094 gtk_notebook_pages_allocate (notebook);
1097 children = notebook->children;
1101 page = children->data;
1102 children = children->next;
1104 if (page->tab_label &&
1105 GTK_WIDGET_VISIBLE (page->tab_label) &&
1106 !GTK_WIDGET_MAPPED (page->tab_label))
1107 gtk_widget_map (page->tab_label);
1111 if (gtk_notebook_get_event_window_position (notebook, NULL))
1112 gdk_window_show_unraised (notebook->event_window);
1116 gtk_notebook_unmap (GtkWidget *widget)
1118 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1120 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1122 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1124 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1128 gtk_notebook_realize (GtkWidget *widget)
1130 GtkNotebook *notebook;
1131 GdkWindowAttr attributes;
1132 gint attributes_mask;
1133 GdkRectangle event_window_pos;
1135 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1137 notebook = GTK_NOTEBOOK (widget);
1138 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1140 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1142 widget->window = gtk_widget_get_parent_window (widget);
1143 g_object_ref (widget->window);
1145 attributes.window_type = GDK_WINDOW_CHILD;
1146 attributes.x = event_window_pos.x;
1147 attributes.y = event_window_pos.y;
1148 attributes.width = event_window_pos.width;
1149 attributes.height = event_window_pos.height;
1150 attributes.wclass = GDK_INPUT_ONLY;
1151 attributes.event_mask = gtk_widget_get_events (widget);
1152 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1153 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1155 attributes_mask = GDK_WA_X | GDK_WA_Y;
1157 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1158 &attributes, attributes_mask);
1159 gdk_window_set_user_data (notebook->event_window, notebook);
1161 widget->style = gtk_style_attach (widget->style, widget->window);
1165 gtk_notebook_unrealize (GtkWidget *widget)
1167 GtkNotebook *notebook;
1169 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1171 notebook = GTK_NOTEBOOK (widget);
1173 gdk_window_set_user_data (notebook->event_window, NULL);
1174 gdk_window_destroy (notebook->event_window);
1175 notebook->event_window = NULL;
1177 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1178 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1182 gtk_notebook_size_request (GtkWidget *widget,
1183 GtkRequisition *requisition)
1185 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1186 GtkNotebookPage *page;
1188 GtkRequisition child_requisition;
1189 gboolean switch_page = FALSE;
1193 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1195 widget->requisition.width = 0;
1196 widget->requisition.height = 0;
1198 for (children = notebook->children, vis_pages = 0; children;
1199 children = children->next)
1201 page = children->data;
1203 if (GTK_WIDGET_VISIBLE (page->child))
1206 gtk_widget_size_request (page->child, &child_requisition);
1208 widget->requisition.width = MAX (widget->requisition.width,
1209 child_requisition.width);
1210 widget->requisition.height = MAX (widget->requisition.height,
1211 child_requisition.height);
1213 if (notebook->menu && page->menu_label->parent &&
1214 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1215 gtk_widget_show (page->menu_label->parent);
1219 if (page == notebook->cur_page)
1221 if (notebook->menu && page->menu_label->parent &&
1222 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1223 gtk_widget_hide (page->menu_label->parent);
1227 if (notebook->show_border || notebook->show_tabs)
1229 widget->requisition.width += widget->style->xthickness * 2;
1230 widget->requisition.height += widget->style->ythickness * 2;
1232 if (notebook->show_tabs)
1235 gint tab_height = 0;
1239 for (children = notebook->children; children;
1240 children = children->next)
1242 page = children->data;
1244 if (GTK_WIDGET_VISIBLE (page->child))
1246 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1247 gtk_widget_show (page->tab_label);
1249 gtk_widget_size_request (page->tab_label,
1250 &child_requisition);
1252 page->requisition.width =
1253 child_requisition.width +
1254 2 * widget->style->xthickness;
1255 page->requisition.height =
1256 child_requisition.height +
1257 2 * widget->style->ythickness;
1259 switch (notebook->tab_pos)
1262 case GTK_POS_BOTTOM:
1263 page->requisition.height += 2 * (notebook->tab_vborder +
1265 tab_height = MAX (tab_height, page->requisition.height);
1266 tab_max = MAX (tab_max, page->requisition.width);
1270 page->requisition.width += 2 * (notebook->tab_hborder +
1272 tab_width = MAX (tab_width, page->requisition.width);
1273 tab_max = MAX (tab_max, page->requisition.height);
1277 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1278 gtk_widget_hide (page->tab_label);
1281 children = notebook->children;
1285 switch (notebook->tab_pos)
1288 case GTK_POS_BOTTOM:
1289 if (tab_height == 0)
1292 if (notebook->scrollable && vis_pages > 1 &&
1293 widget->requisition.width < tab_width)
1294 tab_height = MAX (tab_height, ARROW_SIZE);
1296 padding = 2 * (TAB_CURVATURE + focus_width +
1297 notebook->tab_hborder) - TAB_OVERLAP;
1301 page = children->data;
1302 children = children->next;
1304 if (!GTK_WIDGET_VISIBLE (page->child))
1307 if (notebook->homogeneous)
1308 page->requisition.width = tab_max;
1310 page->requisition.width += padding;
1312 tab_width += page->requisition.width;
1313 page->requisition.height = tab_height;
1316 if (notebook->scrollable && vis_pages > 1 &&
1317 widget->requisition.width < tab_width)
1318 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1320 if (notebook->homogeneous && !notebook->scrollable)
1321 widget->requisition.width = MAX (widget->requisition.width,
1322 vis_pages * tab_max +
1325 widget->requisition.width = MAX (widget->requisition.width,
1326 tab_width + TAB_OVERLAP);
1328 widget->requisition.height += tab_height;
1335 if (notebook->scrollable && vis_pages > 1 &&
1336 widget->requisition.height < tab_height)
1337 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1339 padding = 2 * (TAB_CURVATURE + focus_width +
1340 notebook->tab_vborder) - TAB_OVERLAP;
1345 page = children->data;
1346 children = children->next;
1348 if (!GTK_WIDGET_VISIBLE (page->child))
1351 page->requisition.width = tab_width;
1353 if (notebook->homogeneous)
1354 page->requisition.height = tab_max;
1356 page->requisition.height += padding;
1358 tab_height += page->requisition.height;
1361 if (notebook->scrollable && vis_pages > 1 &&
1362 widget->requisition.height < tab_height)
1363 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1365 widget->requisition.width += tab_width;
1367 if (notebook->homogeneous && !notebook->scrollable)
1368 widget->requisition.height =
1369 MAX (widget->requisition.height,
1370 vis_pages * tab_max + TAB_OVERLAP);
1372 widget->requisition.height =
1373 MAX (widget->requisition.height,
1374 tab_height + TAB_OVERLAP);
1376 if (!notebook->homogeneous || notebook->scrollable)
1378 widget->requisition.height = MAX (widget->requisition.height,
1379 vis_pages * tab_max +
1387 for (children = notebook->children; children;
1388 children = children->next)
1390 page = children->data;
1392 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1393 gtk_widget_hide (page->tab_label);
1398 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1399 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1405 for (children = notebook->children; children;
1406 children = children->next)
1408 page = children->data;
1409 if (GTK_WIDGET_VISIBLE (page->child))
1411 gtk_notebook_switch_page (notebook, page, -1);
1416 else if (GTK_WIDGET_VISIBLE (widget))
1418 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1419 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1422 if (vis_pages && !notebook->cur_page)
1424 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1427 notebook->first_tab = children;
1428 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1434 gtk_notebook_size_allocate (GtkWidget *widget,
1435 GtkAllocation *allocation)
1437 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1439 gint tab_pos = get_effective_tab_pos (notebook);
1441 widget->allocation = *allocation;
1442 if (GTK_WIDGET_REALIZED (widget))
1444 GdkRectangle position;
1446 if (gtk_notebook_get_event_window_position (notebook, &position))
1448 gdk_window_move_resize (notebook->event_window,
1449 position.x, position.y,
1450 position.width, position.height);
1451 if (GTK_WIDGET_MAPPED (notebook))
1452 gdk_window_show_unraised (notebook->event_window);
1455 gdk_window_hide (notebook->event_window);
1458 if (notebook->children)
1460 gint border_width = GTK_CONTAINER (widget)->border_width;
1461 GtkNotebookPage *page;
1462 GtkAllocation child_allocation;
1465 child_allocation.x = widget->allocation.x + border_width;
1466 child_allocation.y = widget->allocation.y + border_width;
1467 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1468 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1470 if (notebook->show_tabs || notebook->show_border)
1472 child_allocation.x += widget->style->xthickness;
1473 child_allocation.y += widget->style->ythickness;
1474 child_allocation.width = MAX (1, child_allocation.width -
1475 widget->style->xthickness * 2);
1476 child_allocation.height = MAX (1, child_allocation.height -
1477 widget->style->ythickness * 2);
1479 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1484 child_allocation.y += notebook->cur_page->requisition.height;
1485 case GTK_POS_BOTTOM:
1486 child_allocation.height =
1487 MAX (1, child_allocation.height -
1488 notebook->cur_page->requisition.height);
1491 child_allocation.x += notebook->cur_page->requisition.width;
1493 child_allocation.width =
1494 MAX (1, child_allocation.width -
1495 notebook->cur_page->requisition.width);
1501 children = notebook->children;
1504 page = children->data;
1505 children = children->next;
1507 if (GTK_WIDGET_VISIBLE (page->child))
1509 gtk_widget_size_allocate (page->child, &child_allocation);
1514 gtk_notebook_pages_allocate (notebook);
1519 gtk_notebook_expose (GtkWidget *widget,
1520 GdkEventExpose *event)
1522 GtkNotebook *notebook;
1523 GdkRectangle child_area;
1525 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1526 g_return_val_if_fail (event != NULL, FALSE);
1528 if (GTK_WIDGET_DRAWABLE (widget))
1530 notebook = GTK_NOTEBOOK (widget);
1532 gtk_notebook_paint (widget, &event->area);
1533 if (notebook->show_tabs)
1535 if (notebook->cur_page &&
1536 gtk_widget_intersect (notebook->cur_page->tab_label,
1537 &event->area, &child_area))
1538 gtk_notebook_draw_focus (widget);
1542 if (notebook->cur_page)
1543 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1544 notebook->cur_page->child,
1552 gtk_notebook_show_arrows (GtkNotebook *notebook)
1554 gboolean show_arrow = FALSE;
1557 if (!notebook->scrollable)
1560 children = notebook->children;
1563 GtkNotebookPage *page = children->data;
1565 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1568 children = children->next;
1575 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1576 GdkRectangle *rectangle,
1577 GtkNotebookArrow arrow)
1579 GdkRectangle event_window_pos;
1580 gboolean before = ARROW_IS_BEFORE (arrow);
1581 gboolean left = ARROW_IS_LEFT (arrow);
1583 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1585 rectangle->width = ARROW_SIZE;
1586 rectangle->height = ARROW_SIZE;
1588 switch (notebook->tab_pos)
1592 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1593 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1594 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1596 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1598 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1599 rectangle->y = event_window_pos.y;
1601 rectangle->y += event_window_pos.height - rectangle->height;
1604 case GTK_POS_BOTTOM:
1607 if (left || !notebook->has_before_previous)
1608 rectangle->x = event_window_pos.x;
1610 rectangle->x = event_window_pos.x + rectangle->width;
1614 if (!left || !notebook->has_after_next)
1615 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1617 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1619 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1625 static GtkNotebookArrow
1626 gtk_notebook_get_arrow (GtkNotebook *notebook,
1630 GdkRectangle arrow_rect;
1631 GdkRectangle event_window_pos;
1634 GtkNotebookArrow arrow[4];
1636 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1637 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1638 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1639 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1641 if (gtk_notebook_show_arrows (notebook))
1643 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1644 for (i = 0; i < 4; i++)
1646 if (arrow[i] == ARROW_NONE)
1649 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1651 x0 = x - arrow_rect.x;
1652 y0 = y - arrow_rect.y;
1654 if (y0 >= 0 && y0 < arrow_rect.height &&
1655 x0 >= 0 && x0 < arrow_rect.width)
1664 gtk_notebook_do_arrow (GtkNotebook *notebook,
1665 GtkNotebookArrow arrow)
1667 GtkWidget *widget = GTK_WIDGET (notebook);
1668 GtkDirectionType dir;
1669 gboolean is_rtl, left;
1671 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1672 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1673 (!ARROW_IS_LEFT (arrow) && is_rtl);
1675 if (!notebook->focus_tab ||
1676 gtk_notebook_search_page (notebook, notebook->focus_tab,
1677 left ? STEP_PREV : STEP_NEXT,
1680 if (notebook->tab_pos == GTK_POS_LEFT ||
1681 notebook->tab_pos == GTK_POS_RIGHT)
1682 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1684 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1685 gtk_widget_child_focus (widget, dir);
1690 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1691 GtkNotebookArrow arrow,
1692 GdkEventButton *event)
1694 GtkWidget *widget = GTK_WIDGET (notebook);
1695 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1696 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1697 (!ARROW_IS_LEFT (arrow) && is_rtl);
1699 if (!GTK_WIDGET_HAS_FOCUS (widget))
1700 gtk_widget_grab_focus (widget);
1702 notebook->button = event->button;
1703 notebook->click_child = arrow;
1705 if (event->button == 1)
1707 gtk_notebook_do_arrow (notebook, arrow);
1709 if (!notebook->timer)
1711 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1712 (GSourceFunc) gtk_notebook_timer,
1713 (gpointer) notebook);
1714 notebook->need_timer = TRUE;
1717 else if (event->button == 2)
1718 gtk_notebook_page_select (notebook, TRUE);
1719 else if (event->button == 3)
1720 gtk_notebook_switch_focus_tab (notebook,
1721 gtk_notebook_search_page (notebook,
1723 left ? STEP_NEXT : STEP_PREV,
1725 gtk_notebook_redraw_arrows (notebook);
1731 get_widget_coordinates (GtkWidget *widget,
1736 GdkWindow *window = ((GdkEventAny *)event)->window;
1739 if (!gdk_event_get_coords (event, &tx, &ty))
1742 while (window && window != widget->window)
1744 gint window_x, window_y;
1746 gdk_window_get_position (window, &window_x, &window_y);
1750 window = gdk_window_get_parent (window);
1765 gtk_notebook_scroll (GtkWidget *widget,
1766 GdkEventScroll *event)
1768 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1771 GtkWidget* originator;
1773 if (!notebook->cur_page)
1776 child = notebook->cur_page->child;
1777 originator = gtk_get_event_widget ((GdkEvent *)event);
1779 /* ignore scroll events from the content of the page */
1780 if (!originator || gtk_widget_is_ancestor (originator, child))
1783 switch (event->direction)
1785 case GDK_SCROLL_RIGHT:
1786 case GDK_SCROLL_DOWN:
1787 gtk_notebook_next_page (notebook);
1789 case GDK_SCROLL_LEFT:
1791 gtk_notebook_prev_page (notebook);
1799 gtk_notebook_button_press (GtkWidget *widget,
1800 GdkEventButton *event)
1802 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1803 GtkNotebookPage *page;
1805 GtkNotebookArrow arrow;
1809 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1813 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1816 arrow = gtk_notebook_get_arrow (notebook, x, y);
1818 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1820 if (event->button == 3 && notebook->menu)
1822 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1823 NULL, NULL, 3, event->time);
1827 if (event->button != 1)
1831 children = notebook->children;
1834 page = children->data;
1836 if (GTK_WIDGET_VISIBLE (page->child) &&
1837 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1838 (x >= page->allocation.x) &&
1839 (y >= page->allocation.y) &&
1840 (x <= (page->allocation.x + page->allocation.width)) &&
1841 (y <= (page->allocation.y + page->allocation.height)))
1843 gboolean page_changed = page != notebook->cur_page;
1844 gboolean was_focus = gtk_widget_is_focus (widget);
1846 gtk_notebook_switch_focus_tab (notebook, children);
1847 gtk_widget_grab_focus (widget);
1849 if (page_changed && !was_focus)
1850 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1854 children = children->next;
1862 stop_scrolling (GtkNotebook *notebook)
1864 if (notebook->timer)
1866 g_source_remove (notebook->timer);
1867 notebook->timer = 0;
1868 notebook->need_timer = FALSE;
1870 notebook->click_child = 0;
1871 notebook->button = 0;
1872 gtk_notebook_redraw_arrows (notebook);
1876 gtk_notebook_button_release (GtkWidget *widget,
1877 GdkEventButton *event)
1879 GtkNotebook *notebook;
1881 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1882 g_return_val_if_fail (event != NULL, FALSE);
1884 if (event->type != GDK_BUTTON_RELEASE)
1887 notebook = GTK_NOTEBOOK (widget);
1889 if (event->button == notebook->button)
1891 stop_scrolling (notebook);
1900 gtk_notebook_enter_notify (GtkWidget *widget,
1901 GdkEventCrossing *event)
1903 GtkNotebook *notebook;
1904 GtkNotebookArrow arrow;
1907 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1908 g_return_val_if_fail (event != NULL, FALSE);
1910 notebook = GTK_NOTEBOOK (widget);
1912 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1915 arrow = gtk_notebook_get_arrow (notebook, x, y);
1917 if (arrow != notebook->in_child)
1919 notebook->in_child = arrow;
1920 gtk_notebook_redraw_arrows (notebook);
1929 gtk_notebook_leave_notify (GtkWidget *widget,
1930 GdkEventCrossing *event)
1932 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1933 GtkNotebookArrow arrow;
1936 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1939 arrow = gtk_notebook_get_arrow (notebook, x, y);
1941 if (notebook->in_child)
1943 notebook->in_child = 0;
1944 gtk_notebook_redraw_arrows (notebook);
1951 gtk_notebook_motion_notify (GtkWidget *widget,
1952 GdkEventMotion *event)
1954 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1955 GtkNotebookArrow arrow;
1958 if (notebook->button)
1961 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1964 arrow = gtk_notebook_get_arrow (notebook, x, y);
1966 if (arrow != notebook->in_child)
1968 notebook->in_child = arrow;
1969 gtk_notebook_redraw_arrows (notebook);
1976 gtk_notebook_grab_notify (GtkWidget *widget,
1977 gboolean was_grabbed)
1980 stop_scrolling (GTK_NOTEBOOK (widget));
1984 gtk_notebook_state_changed (GtkWidget *widget,
1985 GtkStateType previous_state)
1987 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1988 stop_scrolling (GTK_NOTEBOOK (widget));
1992 gtk_notebook_focus_in (GtkWidget *widget,
1993 GdkEventFocus *event)
1995 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1997 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2003 gtk_notebook_focus_out (GtkWidget *widget,
2004 GdkEventFocus *event)
2006 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2012 gtk_notebook_draw_focus (GtkWidget *widget)
2014 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2016 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2017 notebook->focus_tab)
2019 GtkNotebookPage *page;
2023 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2025 page = notebook->focus_tab->data;
2027 area.x = page->tab_label->allocation.x - focus_width;
2028 area.y = page->tab_label->allocation.y - focus_width;
2029 area.width = page->tab_label->allocation.width + 2 * focus_width;
2030 area.height = page->tab_label->allocation.height + 2 * focus_width;
2032 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2037 gtk_notebook_style_set (GtkWidget *widget,
2040 GtkNotebook *notebook;
2042 gboolean has_before_previous;
2043 gboolean has_before_next;
2044 gboolean has_after_previous;
2045 gboolean has_after_next;
2047 notebook = GTK_NOTEBOOK (widget);
2049 gtk_widget_style_get (widget,
2050 "has_backward_stepper", &has_before_previous,
2051 "has_secondary_forward_stepper", &has_before_next,
2052 "has_secondary_backward_stepper", &has_after_previous,
2053 "has_forward_stepper", &has_after_next,
2056 notebook->has_before_previous = has_before_previous;
2057 notebook->has_before_next = has_before_next;
2058 notebook->has_after_previous = has_after_previous;
2059 notebook->has_after_next = has_after_next;
2061 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2064 /* Private GtkContainer Methods :
2066 * gtk_notebook_set_child_arg
2067 * gtk_notebook_get_child_arg
2069 * gtk_notebook_remove
2070 * gtk_notebook_focus
2071 * gtk_notebook_set_focus_child
2072 * gtk_notebook_child_type
2073 * gtk_notebook_forall
2076 gtk_notebook_set_child_property (GtkContainer *container,
2079 const GValue *value,
2084 GtkPackType pack_type;
2086 /* not finding child's page is valid for menus or labels */
2087 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2090 switch (property_id)
2092 case CHILD_PROP_TAB_LABEL:
2093 /* a NULL pointer indicates a default_tab setting, otherwise
2094 * we need to set the associated label
2096 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2097 g_value_get_string (value));
2099 case CHILD_PROP_MENU_LABEL:
2100 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2101 g_value_get_string (value));
2103 case CHILD_PROP_POSITION:
2104 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2105 g_value_get_int (value));
2107 case CHILD_PROP_TAB_EXPAND:
2108 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2109 &expand, &fill, &pack_type);
2110 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2111 g_value_get_boolean (value),
2114 case CHILD_PROP_TAB_FILL:
2115 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2116 &expand, &fill, &pack_type);
2117 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2119 g_value_get_boolean (value),
2122 case CHILD_PROP_TAB_PACK:
2123 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2124 &expand, &fill, &pack_type);
2125 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2127 g_value_get_enum (value));
2130 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2136 gtk_notebook_get_child_property (GtkContainer *container,
2143 GtkNotebook *notebook;
2147 GtkPackType pack_type;
2149 notebook = GTK_NOTEBOOK (container);
2151 /* not finding child's page is valid for menus or labels */
2152 list = gtk_notebook_find_child (notebook, child, NULL);
2155 /* nothing to set on labels or menus */
2156 g_param_value_set_default (pspec, value);
2160 switch (property_id)
2162 case CHILD_PROP_TAB_LABEL:
2163 label = gtk_notebook_get_tab_label (notebook, child);
2165 if (label && GTK_IS_LABEL (label))
2166 g_value_set_string (value, GTK_LABEL (label)->label);
2168 g_value_set_string (value, NULL);
2170 case CHILD_PROP_MENU_LABEL:
2171 label = gtk_notebook_get_menu_label (notebook, child);
2173 if (label && GTK_IS_LABEL (label))
2174 g_value_set_string (value, GTK_LABEL (label)->label);
2176 g_value_set_string (value, NULL);
2178 case CHILD_PROP_POSITION:
2179 g_value_set_int (value, g_list_position (notebook->children, list));
2181 case CHILD_PROP_TAB_EXPAND:
2182 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2183 &expand, NULL, NULL);
2184 g_value_set_boolean (value, expand);
2186 case CHILD_PROP_TAB_FILL:
2187 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2189 g_value_set_boolean (value, fill);
2191 case CHILD_PROP_TAB_PACK:
2192 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2193 NULL, NULL, &pack_type);
2194 g_value_set_enum (value, pack_type);
2197 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2203 gtk_notebook_add (GtkContainer *container,
2206 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2208 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2213 gtk_notebook_remove (GtkContainer *container,
2216 GtkNotebook *notebook;
2217 GtkNotebookPage *page;
2220 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2221 g_return_if_fail (widget != NULL);
2223 notebook = GTK_NOTEBOOK (container);
2225 children = notebook->children;
2228 page = children->data;
2229 if (page->child == widget)
2231 gtk_notebook_real_remove (notebook, children, FALSE);
2234 children = children->next;
2239 focus_tabs_in (GtkNotebook *notebook)
2241 if (notebook->show_tabs && notebook->cur_page)
2243 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2245 gtk_notebook_switch_focus_tab (notebook,
2246 g_list_find (notebook->children,
2247 notebook->cur_page));
2256 focus_tabs_move (GtkNotebook *notebook,
2257 GtkDirectionType direction,
2258 gint search_direction)
2262 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2263 search_direction, TRUE);
2265 gtk_notebook_switch_focus_tab (notebook, new_page);
2267 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2273 focus_child_in (GtkNotebook *notebook,
2274 GtkDirectionType direction)
2276 if (notebook->cur_page)
2277 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2282 /* Focus in the notebook can either be on the pages, or on
2286 gtk_notebook_focus (GtkWidget *widget,
2287 GtkDirectionType direction)
2289 GtkWidget *old_focus_child;
2290 GtkNotebook *notebook;
2291 GtkDirectionType effective_direction;
2293 gboolean widget_is_focus;
2294 GtkContainer *container;
2296 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2298 container = GTK_CONTAINER (widget);
2299 notebook = GTK_NOTEBOOK (container);
2301 if (notebook->focus_out)
2303 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2307 widget_is_focus = gtk_widget_is_focus (widget);
2308 old_focus_child = container->focus_child;
2310 effective_direction = get_effective_direction (notebook, direction);
2312 if (old_focus_child) /* Focus on page child */
2314 if (gtk_widget_child_focus (old_focus_child, direction))
2317 switch (effective_direction)
2319 case GTK_DIR_TAB_BACKWARD:
2321 /* Focus onto the tabs */
2322 return focus_tabs_in (notebook);
2324 case GTK_DIR_TAB_FORWARD:
2330 else if (widget_is_focus) /* Focus was on tabs */
2332 switch (effective_direction)
2334 case GTK_DIR_TAB_BACKWARD:
2337 case GTK_DIR_TAB_FORWARD:
2339 /* We use TAB_FORWARD rather than direction so that we focus a more
2340 * predictable widget for the user; users may be using arrow focusing
2341 * in this situation even if they don't usually use arrow focusing.
2343 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2345 return focus_tabs_move (notebook, direction, STEP_PREV);
2347 return focus_tabs_move (notebook, direction, STEP_NEXT);
2350 else /* Focus was not on widget */
2352 switch (effective_direction)
2354 case GTK_DIR_TAB_FORWARD:
2356 if (focus_tabs_in (notebook))
2358 if (focus_child_in (notebook, direction))
2361 case GTK_DIR_TAB_BACKWARD:
2363 if (focus_child_in (notebook, direction))
2365 if (focus_tabs_in (notebook))
2370 return focus_child_in (notebook, direction);
2374 g_assert_not_reached ();
2379 gtk_notebook_set_focus_child (GtkContainer *container,
2382 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2383 GtkWidget *page_child;
2384 GtkWidget *toplevel;
2386 /* If the old focus widget was within a page of the notebook,
2387 * (child may either be NULL or not in this case), record it
2388 * for future use if we switch to the page with a mnemonic.
2391 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2392 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2394 page_child = GTK_WINDOW (toplevel)->focus_widget;
2397 if (page_child->parent == GTK_WIDGET (container))
2399 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2402 GtkNotebookPage *page = list->data;
2404 if (page->last_focus_child)
2405 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2407 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2408 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2414 page_child = page_child->parent;
2420 g_return_if_fail (GTK_IS_WIDGET (child));
2422 notebook->child_has_focus = TRUE;
2423 if (!notebook->focus_tab)
2426 GtkNotebookPage *page;
2428 children = notebook->children;
2431 page = children->data;
2432 if (page->child == child || page->tab_label == child)
2433 gtk_notebook_switch_focus_tab (notebook, children);
2434 children = children->next;
2439 parent_class->set_focus_child (container, child);
2443 gtk_notebook_forall (GtkContainer *container,
2444 gboolean include_internals,
2445 GtkCallback callback,
2446 gpointer callback_data)
2448 GtkNotebook *notebook;
2451 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2452 g_return_if_fail (callback != NULL);
2454 notebook = GTK_NOTEBOOK (container);
2456 children = notebook->children;
2459 GtkNotebookPage *page;
2461 page = children->data;
2462 children = children->next;
2463 (* callback) (page->child, callback_data);
2464 if (include_internals)
2466 if (page->tab_label)
2467 (* callback) (page->tab_label, callback_data);
2473 gtk_notebook_child_type (GtkContainer *container)
2475 return GTK_TYPE_WIDGET;
2478 /* Private GtkNotebook Functions:
2480 * gtk_notebook_redraw_tabs
2481 * gtk_notebook_real_remove
2482 * gtk_notebook_update_labels
2483 * gtk_notebook_timer
2484 * gtk_notebook_page_compare
2485 * gtk_notebook_real_page_position
2486 * gtk_notebook_search_page
2489 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2492 GtkNotebookPage *page;
2493 GdkRectangle redraw_rect;
2495 gint tab_pos = get_effective_tab_pos (notebook);
2497 widget = GTK_WIDGET (notebook);
2498 border = GTK_CONTAINER (notebook)->border_width;
2500 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2503 page = notebook->first_tab->data;
2505 redraw_rect.x = border;
2506 redraw_rect.y = border;
2510 case GTK_POS_BOTTOM:
2511 redraw_rect.y = (widget->allocation.height - border -
2512 page->allocation.height -
2513 widget->style->ythickness);
2514 if (page != notebook->cur_page)
2515 redraw_rect.y -= widget->style->ythickness;
2518 redraw_rect.width = widget->allocation.width - 2 * border;
2519 redraw_rect.height = (page->allocation.height +
2520 widget->style->ythickness);
2521 if (page != notebook->cur_page)
2522 redraw_rect.height += widget->style->ythickness;
2525 redraw_rect.x = (widget->allocation.width - border -
2526 page->allocation.width -
2527 widget->style->xthickness);
2528 if (page != notebook->cur_page)
2529 redraw_rect.x -= widget->style->xthickness;
2532 redraw_rect.width = (page->allocation.width +
2533 widget->style->xthickness);
2534 redraw_rect.height = widget->allocation.height - 2 * border;
2535 if (page != notebook->cur_page)
2536 redraw_rect.width += widget->style->xthickness;
2540 redraw_rect.x += widget->allocation.x;
2541 redraw_rect.y += widget->allocation.y;
2543 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2547 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2549 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2553 GtkNotebookArrow arrow[4];
2555 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2556 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2557 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2558 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2560 for (i = 0; i < 4; i++)
2562 if (arrow[i] == ARROW_NONE)
2565 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2566 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2573 gtk_notebook_timer (GtkNotebook *notebook)
2575 gboolean retval = FALSE;
2577 GDK_THREADS_ENTER ();
2579 if (notebook->timer)
2581 gtk_notebook_do_arrow (notebook, notebook->click_child);
2583 if (notebook->need_timer)
2585 notebook->need_timer = FALSE;
2586 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2587 (GSourceFunc) gtk_notebook_timer,
2588 (gpointer) notebook);
2594 GDK_THREADS_LEAVE ();
2600 gtk_notebook_page_compare (gconstpointer a,
2603 return (((GtkNotebookPage *) a)->child != b);
2607 gtk_notebook_find_child (GtkNotebook *notebook,
2609 const gchar *function)
2611 GList *list = g_list_find_custom (notebook->children, child,
2612 gtk_notebook_page_compare);
2614 #ifndef G_DISABLE_CHECKS
2615 if (!list && function)
2616 g_warning ("%s: unable to find child %p in notebook %p",
2617 function, child, notebook);
2624 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2625 GtkNotebookPage *page)
2627 if (page->tab_label)
2629 if (page->mnemonic_activate_signal)
2630 g_signal_handler_disconnect (page->tab_label,
2631 page->mnemonic_activate_signal);
2632 page->mnemonic_activate_signal = 0;
2634 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2635 gtk_widget_unparent (page->tab_label);
2640 gtk_notebook_real_remove (GtkNotebook *notebook,
2642 gboolean destroying)
2644 GtkNotebookPage *page;
2646 gint need_resize = FALSE;
2648 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2650 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2652 if (notebook->cur_page == list->data)
2654 notebook->cur_page = NULL;
2655 if (next_list && !destroying)
2656 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2659 if (list == notebook->first_tab)
2660 notebook->first_tab = next_list;
2661 if (list == notebook->focus_tab && !destroying)
2662 gtk_notebook_switch_focus_tab (notebook, next_list);
2666 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2669 gtk_widget_unparent (page->child);
2671 gtk_notebook_remove_tab_label (notebook, page);
2675 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2676 page->menu_label->parent);
2677 gtk_widget_queue_resize (notebook->menu);
2679 if (!page->default_menu)
2680 g_object_unref (page->menu_label);
2682 notebook->children = g_list_remove_link (notebook->children, list);
2685 if (page->last_focus_child)
2687 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2688 page->last_focus_child = NULL;
2693 gtk_notebook_update_labels (notebook);
2695 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2699 gtk_notebook_update_labels (GtkNotebook *notebook)
2701 GtkNotebookPage *page;
2706 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2708 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2711 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2712 if (notebook->show_tabs)
2714 if (page->default_tab)
2716 if (!page->tab_label)
2718 page->tab_label = gtk_label_new (string);
2719 gtk_widget_set_parent (page->tab_label,
2720 GTK_WIDGET (notebook));
2723 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2726 if (GTK_WIDGET_VISIBLE (page->child) &&
2727 !GTK_WIDGET_VISIBLE (page->tab_label))
2728 gtk_widget_show (page->tab_label);
2729 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2730 GTK_WIDGET_VISIBLE (page->tab_label))
2731 gtk_widget_hide (page->tab_label);
2733 if (notebook->menu && page->default_menu)
2735 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2736 gtk_label_set_text (GTK_LABEL (page->menu_label),
2737 GTK_LABEL (page->tab_label)->label);
2739 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2745 gtk_notebook_real_page_position (GtkNotebook *notebook,
2751 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2752 g_return_val_if_fail (list != NULL, -1);
2754 for (work = notebook->children, count_start = 0;
2755 work && work != list; work = work->next)
2756 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2762 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2765 return (count_start + g_list_length (list) - 1);
2769 gtk_notebook_search_page (GtkNotebook *notebook,
2772 gboolean find_visible)
2774 GtkNotebookPage *page = NULL;
2775 GList *old_list = NULL;
2778 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2783 flag = GTK_PACK_END;
2787 flag = GTK_PACK_START;
2794 if (!page || page->pack == flag)
2802 list = notebook->children;
2807 if (page->pack == flag &&
2808 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2823 if (page->pack != flag &&
2824 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2832 /* Private GtkNotebook Drawing Functions:
2834 * gtk_notebook_paint
2835 * gtk_notebook_draw_tab
2836 * gtk_notebook_draw_arrow
2839 gtk_notebook_paint (GtkWidget *widget,
2842 GtkNotebook *notebook;
2843 GtkNotebookPage *page;
2848 gint border_width = GTK_CONTAINER (widget)->border_width;
2849 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2853 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2854 g_return_if_fail (area != NULL);
2856 if (!GTK_WIDGET_DRAWABLE (widget))
2859 notebook = GTK_NOTEBOOK (widget);
2860 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2861 tab_pos = get_effective_tab_pos (notebook);
2863 if ((!notebook->show_tabs && !notebook->show_border) ||
2864 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2867 x = widget->allocation.x + border_width;
2868 y = widget->allocation.y + border_width;
2869 width = widget->allocation.width - border_width * 2;
2870 height = widget->allocation.height - border_width * 2;
2872 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2874 gtk_paint_box (widget->style, widget->window,
2875 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2876 area, widget, "notebook",
2877 x, y, width, height);
2882 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2884 page = notebook->first_tab->data;
2889 y += page->allocation.height + widget->style->ythickness;
2890 case GTK_POS_BOTTOM:
2891 height -= page->allocation.height + widget->style->ythickness;
2894 x += page->allocation.width + widget->style->xthickness;
2896 width -= page->allocation.width + widget->style->xthickness;
2899 gtk_paint_box (widget->style, widget->window,
2900 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2901 area, widget, "notebook",
2902 x, y, width, height);
2909 y += notebook->cur_page->allocation.height;
2910 case GTK_POS_BOTTOM:
2911 height -= notebook->cur_page->allocation.height;
2914 x += notebook->cur_page->allocation.width;
2916 width -= notebook->cur_page->allocation.width;
2923 case GTK_POS_BOTTOM:
2924 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2925 gap_width = notebook->cur_page->allocation.width;
2926 step = is_rtl ? STEP_NEXT : STEP_PREV;
2930 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2931 gap_width = notebook->cur_page->allocation.height;
2935 gtk_paint_box_gap (widget->style, widget->window,
2936 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2937 area, widget, "notebook",
2938 x, y, width, height,
2939 tab_pos, gap_x, gap_width);
2943 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2946 page = children->data;
2947 children = gtk_notebook_search_page (notebook, children,
2949 if (!GTK_WIDGET_VISIBLE (page->child))
2951 if (!GTK_WIDGET_MAPPED (page->tab_label))
2953 else if (page != notebook->cur_page)
2954 gtk_notebook_draw_tab (notebook, page, area);
2957 if (showarrow && notebook->scrollable)
2959 if (notebook->has_before_previous)
2960 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2961 if (notebook->has_before_next)
2962 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2963 if (notebook->has_after_previous)
2964 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2965 if (notebook->has_after_next)
2966 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2968 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2972 gtk_notebook_draw_tab (GtkNotebook *notebook,
2973 GtkNotebookPage *page,
2976 GdkRectangle child_area;
2977 GdkRectangle page_area;
2978 GtkStateType state_type;
2979 GtkPositionType gap_side;
2980 gint tab_pos = get_effective_tab_pos (notebook);
2982 g_return_if_fail (notebook != NULL);
2983 g_return_if_fail (page != NULL);
2984 g_return_if_fail (area != NULL);
2986 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2987 (page->allocation.width == 0) || (page->allocation.height == 0))
2990 page_area.x = page->allocation.x;
2991 page_area.y = page->allocation.y;
2992 page_area.width = page->allocation.width;
2993 page_area.height = page->allocation.height;
2995 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2999 widget = GTK_WIDGET (notebook);
3004 gap_side = GTK_POS_BOTTOM;
3006 case GTK_POS_BOTTOM:
3007 gap_side = GTK_POS_TOP;
3010 gap_side = GTK_POS_RIGHT;
3013 gap_side = GTK_POS_LEFT;
3017 if (notebook->cur_page == page)
3018 state_type = GTK_STATE_NORMAL;
3020 state_type = GTK_STATE_ACTIVE;
3021 gtk_paint_extension(widget->style, widget->window,
3022 state_type, GTK_SHADOW_OUT,
3023 area, widget, "tab",
3024 page_area.x, page_area.y,
3025 page_area.width, page_area.height,
3027 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
3028 notebook->focus_tab && (notebook->focus_tab->data == page))
3032 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3034 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3035 area, widget, "tab",
3036 page->tab_label->allocation.x - focus_width,
3037 page->tab_label->allocation.y - focus_width,
3038 page->tab_label->allocation.width + 2 * focus_width,
3039 page->tab_label->allocation.height + 2 * focus_width);
3041 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3042 GTK_WIDGET_DRAWABLE (page->tab_label))
3044 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3046 /* This is a lame hack since all this code needs rewriting anyhow */
3048 expose_event->expose.window = g_object_ref (page->tab_label->window);
3049 expose_event->expose.area = child_area;
3050 expose_event->expose.region = gdk_region_rectangle (&child_area);
3051 expose_event->expose.send_event = TRUE;
3052 expose_event->expose.count = 0;
3054 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3056 gdk_event_free (expose_event);
3062 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3063 GtkNotebookArrow nbarrow)
3065 GtkStateType state_type;
3066 GtkShadowType shadow_type;
3068 GdkRectangle arrow_rect;
3070 gboolean is_rtl, left;
3072 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3074 widget = GTK_WIDGET (notebook);
3076 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3077 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3078 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3080 if (GTK_WIDGET_DRAWABLE (notebook))
3082 if (notebook->in_child == nbarrow)
3084 if (notebook->click_child == nbarrow)
3085 state_type = GTK_STATE_ACTIVE;
3087 state_type = GTK_STATE_PRELIGHT;
3090 state_type = GTK_WIDGET_STATE (widget);
3092 if (notebook->click_child == nbarrow)
3093 shadow_type = GTK_SHADOW_IN;
3095 shadow_type = GTK_SHADOW_OUT;
3097 if (notebook->focus_tab &&
3098 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3099 left? STEP_PREV : STEP_NEXT, TRUE))
3101 shadow_type = GTK_SHADOW_ETCHED_IN;
3102 state_type = GTK_STATE_INSENSITIVE;
3105 if (notebook->tab_pos == GTK_POS_LEFT ||
3106 notebook->tab_pos == GTK_POS_RIGHT)
3107 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3109 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3111 gtk_paint_arrow (widget->style, widget->window, state_type,
3112 shadow_type, NULL, widget, "notebook",
3113 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3114 ARROW_SIZE, ARROW_SIZE);
3118 /* Private GtkNotebook Size Allocate Functions:
3120 * gtk_notebook_pages_allocate
3121 * gtk_notebook_page_allocate
3122 * gtk_notebook_calc_tabs
3125 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3127 GtkWidget *widget = GTK_WIDGET (notebook);
3128 GtkContainer *container = GTK_CONTAINER (notebook);
3129 GtkNotebookPage *page = NULL;
3130 GtkAllocation *allocation = &widget->allocation;
3131 GtkAllocation child_allocation;
3132 GList *children = NULL;
3133 GList *last_child = NULL;
3134 gboolean showarrow = FALSE;
3141 gint tab_pos = get_effective_tab_pos (notebook);
3142 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3143 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3146 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3149 child_allocation.x = widget->allocation.x + container->border_width;
3150 child_allocation.y = widget->allocation.y + container->border_width;
3154 case GTK_POS_BOTTOM:
3155 child_allocation.y = (widget->allocation.y +
3156 allocation->height -
3157 notebook->cur_page->requisition.height -
3158 container->border_width);
3161 child_allocation.height = notebook->cur_page->requisition.height;
3165 child_allocation.x = (widget->allocation.x +
3167 notebook->cur_page->requisition.width -
3168 container->border_width);
3171 child_allocation.width = notebook->cur_page->requisition.width;
3175 if (notebook->scrollable)
3179 children = notebook->children;
3181 if (notebook->focus_tab)
3182 focus_tab = notebook->focus_tab;
3183 else if (notebook->first_tab)
3184 focus_tab = notebook->first_tab;
3186 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3191 case GTK_POS_BOTTOM:
3194 page = children->data;
3195 children = children->next;
3197 if (GTK_WIDGET_VISIBLE (page->child))
3198 tab_space += page->requisition.width;
3201 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3204 page = focus_tab->data;
3206 tab_space = allocation->width - TAB_OVERLAP -
3207 page->requisition.width - 2 * container->border_width;
3208 if (notebook->has_after_previous)
3209 tab_space -= ARROW_SPACING + ARROW_SIZE;
3210 if (notebook->has_after_next)
3211 tab_space -= ARROW_SPACING + ARROW_SIZE;
3212 if (notebook->has_before_previous)
3214 tab_space -= ARROW_SPACING + ARROW_SIZE;
3215 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3217 if (notebook->has_before_next)
3219 tab_space -= ARROW_SPACING + ARROW_SIZE;
3220 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3228 page = children->data;
3229 children = children->next;
3231 if (GTK_WIDGET_VISIBLE (page->child))
3232 tab_space += page->requisition.height;
3235 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3238 page = focus_tab->data;
3239 tab_space = allocation->height
3240 - TAB_OVERLAP - 2 * container->border_width
3241 - page->requisition.height;
3242 if (notebook->has_after_previous || notebook->has_after_next)
3243 tab_space -= ARROW_SPACING + ARROW_SIZE;
3244 if (notebook->has_before_previous || notebook->has_before_next)
3246 tab_space -= ARROW_SPACING + ARROW_SIZE;
3247 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3252 if (showarrow) /* first_tab <- focus_tab */
3256 notebook->first_tab = focus_tab;
3257 last_child = gtk_notebook_search_page (notebook, focus_tab,
3263 if (notebook->first_tab && notebook->first_tab != focus_tab)
3265 /* Is first_tab really predecessor of focus_tab ? */
3266 page = notebook->first_tab->data;
3267 if (GTK_WIDGET_VISIBLE (page->child))
3268 for (children = focus_tab;
3269 children && children != notebook->first_tab;
3270 children = gtk_notebook_search_page (notebook,
3276 notebook->first_tab = focus_tab;
3278 gtk_notebook_calc_tabs (notebook,
3279 gtk_notebook_search_page (notebook,
3283 &(notebook->first_tab), &tab_space,
3288 notebook->first_tab =
3289 gtk_notebook_search_page (notebook, notebook->first_tab,
3291 if (!notebook->first_tab)
3292 notebook->first_tab = focus_tab;
3293 last_child = gtk_notebook_search_page (notebook, focus_tab,
3296 else /* focus_tab -> end */
3298 if (!notebook->first_tab)
3299 notebook->first_tab = gtk_notebook_search_page (notebook,
3304 gtk_notebook_calc_tabs (notebook,
3305 gtk_notebook_search_page (notebook,
3309 &children, &tab_space, STEP_NEXT);
3312 last_child = children;
3313 else /* start <- first_tab */
3317 gtk_notebook_calc_tabs
3319 gtk_notebook_search_page (notebook,
3320 notebook->first_tab,
3323 &children, &tab_space, STEP_PREV);
3324 notebook->first_tab = gtk_notebook_search_page(notebook,
3334 tab_space = -tab_space;
3336 for (children = notebook->first_tab;
3337 children && children != last_child;
3338 children = gtk_notebook_search_page (notebook, children,
3345 /*unmap all non-visible tabs*/
3346 for (children = gtk_notebook_search_page (notebook, NULL,
3348 children && children != notebook->first_tab;
3349 children = gtk_notebook_search_page (notebook, children,
3352 page = children->data;
3353 if (page->tab_label)
3354 gtk_widget_set_child_visible (page->tab_label, FALSE);
3356 for (children = last_child; children;
3357 children = gtk_notebook_search_page (notebook, children,
3360 page = children->data;
3361 if (page->tab_label)
3362 gtk_widget_set_child_visible (page->tab_label, FALSE);
3365 else /* !showarrow */
3367 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3378 children = notebook->children;
3382 case GTK_POS_BOTTOM:
3385 page = children->data;
3386 children = children->next;
3388 if (GTK_WIDGET_VISIBLE (page->child))
3391 tab_space += page->requisition.width;
3396 tab_space -= allocation->width;
3402 page = children->data;
3403 children = children->next;
3405 if (GTK_WIDGET_VISIBLE (page->child))
3408 tab_space += page->requisition.height;
3413 tab_space -= allocation->height;
3415 tab_space += 2 * container->border_width + TAB_OVERLAP;
3417 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3419 if (notebook->homogeneous && n)
3423 children = notebook->first_tab;
3426 memo_x = child_allocation.x;
3427 if (notebook->children && is_rtl)
3429 child_allocation.x = (allocation->x + allocation->width -
3430 container->border_width);
3433 if (notebook->has_after_previous)
3434 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3435 if (notebook->has_after_next)
3436 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3442 if (children == last_child)
3444 /* FIXME double check */
3448 page = children->data;
3449 if (!showarrow && page->pack != GTK_PACK_START)
3451 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3454 if (n && (showarrow || page->expand || notebook->homogeneous))
3456 new_fill = (tab_space * i++) / n;
3457 delta = new_fill - old_fill;
3458 old_fill = new_fill;
3464 case GTK_POS_BOTTOM:
3465 child_allocation.width = (page->requisition.width +
3466 TAB_OVERLAP + delta);
3468 child_allocation.x -= child_allocation.width;
3472 child_allocation.height = (page->requisition.height +
3473 TAB_OVERLAP + delta);
3477 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3482 case GTK_POS_BOTTOM:
3484 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3486 child_allocation.x += TAB_OVERLAP;
3490 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3494 if (page->tab_label)
3495 gtk_widget_set_child_visible (page->tab_label, TRUE);
3500 children = notebook->children;
3505 case GTK_POS_BOTTOM:
3507 child_allocation.x = (allocation->x + allocation->width -
3508 container->border_width);
3510 child_allocation.x = memo_x;
3514 child_allocation.y = (allocation->y + allocation->height -
3515 container->border_width);
3519 while (children != last_child)
3521 page = children->data;
3522 children = children->next;
3524 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3528 if (n && (page->expand || notebook->homogeneous))
3530 new_fill = (tab_space * i++) / n;
3531 delta = new_fill - old_fill;
3532 old_fill = new_fill;
3538 case GTK_POS_BOTTOM:
3539 child_allocation.width = (page->requisition.width +
3540 TAB_OVERLAP + delta);
3542 child_allocation.x -= child_allocation.width;
3546 child_allocation.height = (page->requisition.height +
3547 TAB_OVERLAP + delta);
3548 child_allocation.y -= child_allocation.height;
3552 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3557 case GTK_POS_BOTTOM:
3559 child_allocation.x += TAB_OVERLAP;
3561 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3565 child_allocation.y += TAB_OVERLAP;
3569 if (page->tab_label)
3570 gtk_widget_set_child_visible (page->tab_label, TRUE);
3575 gtk_notebook_redraw_tabs (notebook);
3579 gtk_notebook_page_allocate (GtkNotebook *notebook,
3580 GtkNotebookPage *page,
3581 GtkAllocation *allocation)
3583 GtkWidget *widget = GTK_WIDGET (notebook);
3584 GtkAllocation child_allocation;
3585 GtkRequisition tab_requisition;
3590 gint tab_pos = get_effective_tab_pos (notebook);
3592 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3594 xthickness = widget->style->xthickness;
3595 ythickness = widget->style->ythickness;
3597 page->allocation = *allocation;
3598 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3600 if (notebook->cur_page != page)
3605 page->allocation.y += ythickness;
3606 case GTK_POS_BOTTOM:
3607 if (page->allocation.height > ythickness)
3608 page->allocation.height -= ythickness;
3611 page->allocation.x += xthickness;
3613 if (page->allocation.width > xthickness)
3614 page->allocation.width -= xthickness;
3622 case GTK_POS_BOTTOM:
3623 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3626 child_allocation.x = (xthickness + focus_width +
3627 notebook->tab_hborder);
3628 child_allocation.width = MAX (1, (page->allocation.width -
3629 2 * child_allocation.x));
3630 child_allocation.x += page->allocation.x;
3634 child_allocation.x = (page->allocation.x +
3635 (page->allocation.width -
3636 tab_requisition.width) / 2);
3637 child_allocation.width = tab_requisition.width;
3639 child_allocation.y = (notebook->tab_vborder + focus_width +
3640 page->allocation.y);
3641 if (tab_pos == GTK_POS_TOP)
3642 child_allocation.y += ythickness;
3643 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3644 2 * (notebook->tab_vborder + focus_width)));
3648 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3651 child_allocation.y = ythickness + padding;
3652 child_allocation.height = MAX (1, (page->allocation.height -
3653 2 * child_allocation.y));
3654 child_allocation.y += page->allocation.y;
3658 child_allocation.y = (page->allocation.y + (page->allocation.height -
3659 tab_requisition.height) / 2);
3660 child_allocation.height = tab_requisition.height;
3662 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3663 if (tab_pos == GTK_POS_LEFT)
3664 child_allocation.x += xthickness;
3665 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3666 2 * (notebook->tab_hborder + focus_width)));
3670 if (page->tab_label)
3671 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3675 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3681 GtkNotebookPage *page = NULL;
3683 GList *last_list = NULL;
3685 gint tab_pos = get_effective_tab_pos (notebook);
3691 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3692 if (pack == GTK_PACK_END)
3693 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3700 case GTK_POS_BOTTOM:
3703 page = children->data;
3704 if (GTK_WIDGET_VISIBLE (page->child))
3706 if (page->pack == pack)
3708 *tab_space -= page->requisition.width;
3709 if (*tab_space < 0 || children == *end)
3713 *tab_space = - (*tab_space +
3714 page->requisition.width);
3720 last_list = children;
3722 if (direction == STEP_NEXT)
3723 children = children->next;
3725 children = children->prev;
3732 page = children->data;
3733 if (GTK_WIDGET_VISIBLE (page->child))
3735 if (page->pack == pack)
3737 *tab_space -= page->requisition.height;
3738 if (*tab_space < 0 || children == *end)
3742 *tab_space = - (*tab_space +
3743 page->requisition.height);
3749 last_list = children;
3751 if (direction == STEP_NEXT)
3752 children = children->next;
3754 children = children->prev;
3758 if (direction == STEP_PREV)
3760 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3761 direction = STEP_PREV;
3762 children = last_list;
3767 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3771 for (list = notebook->children; list != NULL; list = list->next)
3773 GtkNotebookPage *page = list->data;
3775 if (page->tab_label)
3777 if (page == notebook->cur_page)
3778 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3780 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3785 /* Private GtkNotebook Page Switch Methods:
3787 * gtk_notebook_real_switch_page
3790 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3791 GtkNotebookPage *page,
3794 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3795 g_return_if_fail (page != NULL);
3797 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3800 if (notebook->cur_page)
3801 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3803 notebook->cur_page = page;
3805 if (!notebook->focus_tab ||
3806 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3807 notebook->focus_tab =
3808 g_list_find (notebook->children, notebook->cur_page);
3810 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3812 /* If the focus was on the previous page, move it to the first
3813 * element on the new page, if possible, or if not, to the
3816 if (notebook->child_has_focus)
3818 if (notebook->cur_page->last_focus_child &&
3819 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3820 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3822 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3823 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3826 gtk_notebook_update_tab_states (notebook);
3827 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3828 g_object_notify (G_OBJECT (notebook), "page");
3831 /* Private GtkNotebook Page Switch Functions:
3833 * gtk_notebook_switch_page
3834 * gtk_notebook_page_select
3835 * gtk_notebook_switch_focus_tab
3836 * gtk_notebook_menu_switch_page
3839 gtk_notebook_switch_page (GtkNotebook *notebook,
3840 GtkNotebookPage *page,
3843 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3844 g_return_if_fail (page != NULL);
3846 if (notebook->cur_page == page)
3850 page_num = g_list_index (notebook->children, page);
3852 g_signal_emit (notebook,
3853 notebook_signals[SWITCH_PAGE],
3860 gtk_notebook_page_select (GtkNotebook *notebook,
3861 gboolean move_focus)
3863 GtkNotebookPage *page;
3864 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3865 gint tab_pos = get_effective_tab_pos (notebook);
3867 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3869 if (!notebook->focus_tab)
3872 page = notebook->focus_tab->data;
3873 gtk_notebook_switch_page (notebook, page, -1);
3882 case GTK_POS_BOTTOM:
3886 dir = GTK_DIR_RIGHT;
3893 if (gtk_widget_child_focus (page->child, dir))
3900 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3904 GtkNotebookPage *old_page = NULL;
3905 GtkNotebookPage *page;
3907 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3909 if (notebook->focus_tab == new_child)
3912 old_child = notebook->focus_tab;
3913 notebook->focus_tab = new_child;
3915 if (notebook->scrollable)
3916 gtk_notebook_redraw_arrows (notebook);
3918 if (!notebook->show_tabs || !notebook->focus_tab)
3922 old_page = old_child->data;
3924 page = notebook->focus_tab->data;
3925 if (GTK_WIDGET_MAPPED (page->tab_label))
3926 gtk_notebook_redraw_tabs (notebook);
3928 gtk_notebook_pages_allocate (notebook);
3930 gtk_notebook_switch_page (notebook, page,
3931 g_list_index (notebook->children, page));
3935 gtk_notebook_menu_switch_page (GtkWidget *widget,
3936 GtkNotebookPage *page)
3938 GtkNotebook *notebook;
3942 g_return_if_fail (widget != NULL);
3943 g_return_if_fail (page != NULL);
3945 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3946 (GTK_MENU (widget->parent)));
3948 if (notebook->cur_page == page)
3952 children = notebook->children;
3953 while (children && children->data != page)
3955 children = children->next;
3959 g_signal_emit (notebook,
3960 notebook_signals[SWITCH_PAGE],
3966 /* Private GtkNotebook Menu Functions:
3968 * gtk_notebook_menu_item_create
3969 * gtk_notebook_menu_label_unparent
3970 * gtk_notebook_menu_detacher
3973 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3976 GtkNotebookPage *page;
3977 GtkWidget *menu_item;
3980 if (page->default_menu)
3982 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3983 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3985 page->menu_label = gtk_label_new ("");
3986 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3989 gtk_widget_show (page->menu_label);
3990 menu_item = gtk_menu_item_new ();
3991 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3992 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3993 gtk_notebook_real_page_position (notebook, list));
3994 g_signal_connect (menu_item, "activate",
3995 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3996 if (GTK_WIDGET_VISIBLE (page->child))
3997 gtk_widget_show (menu_item);
4001 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4004 gtk_widget_unparent (GTK_BIN(widget)->child);
4005 GTK_BIN(widget)->child = NULL;
4009 gtk_notebook_menu_detacher (GtkWidget *widget,
4012 GtkNotebook *notebook;
4014 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4016 notebook = GTK_NOTEBOOK (widget);
4017 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4019 notebook->menu = NULL;
4022 /* Private GtkNotebook Setter Functions:
4024 * gtk_notebook_set_homogeneous_tabs_internal
4025 * gtk_notebook_set_tab_border_internal
4026 * gtk_notebook_set_tab_hborder_internal
4027 * gtk_notebook_set_tab_vborder_internal
4030 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4031 gboolean homogeneous)
4033 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4035 if (homogeneous == notebook->homogeneous)
4038 notebook->homogeneous = homogeneous;
4039 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4041 g_object_notify (G_OBJECT (notebook), "homogeneous");
4045 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4048 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4050 notebook->tab_hborder = border_width;
4051 notebook->tab_vborder = border_width;
4053 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4054 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4056 g_object_freeze_notify (G_OBJECT (notebook));
4057 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4058 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4059 g_object_thaw_notify (G_OBJECT (notebook));
4063 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4066 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4068 if (notebook->tab_hborder == tab_hborder)
4071 notebook->tab_hborder = tab_hborder;
4073 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4074 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4076 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4080 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4083 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4085 if (notebook->tab_vborder == tab_vborder)
4088 notebook->tab_vborder = tab_vborder;
4090 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4091 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4093 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4096 /* Public GtkNotebook Page Insert/Remove Methods :
4098 * gtk_notebook_append_page
4099 * gtk_notebook_append_page_menu
4100 * gtk_notebook_prepend_page
4101 * gtk_notebook_prepend_page_menu
4102 * gtk_notebook_insert_page
4103 * gtk_notebook_insert_page_menu
4104 * gtk_notebook_remove_page
4107 * gtk_notebook_append_page:
4108 * @notebook: a #GtkNotebook
4109 * @child: the #GtkWidget to use as the contents of the page.
4110 * @tab_label: the #GtkWidget to be used as the label for the page,
4111 * or %NULL to use the default label, 'page N'.
4113 * Appends a page to @notebook.
4115 * Return value: the index (starting from 0) of the appended
4116 * page in the notebook, or -1 if function fails
4119 gtk_notebook_append_page (GtkNotebook *notebook,
4121 GtkWidget *tab_label)
4123 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4124 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4125 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4127 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4131 * gtk_notebook_append_page_menu:
4132 * @notebook: a #GtkNotebook
4133 * @child: the #GtkWidget to use as the contents of the page.
4134 * @tab_label: the #GtkWidget to be used as the label for the page,
4135 * or %NULL to use the default label, 'page N'.
4136 * @menu_label: the widget to use as a label for the page-switch
4137 * menu, if that is enabled. If %NULL, and @tab_label
4138 * is a #GtkLabel or %NULL, then the menu label will be
4139 * a newly created label with the same text as @tab_label;
4140 * If @tab_label is not a #GtkLabel, @menu_label must be
4141 * specified if the page-switch menu is to be used.
4143 * Appends a page to @notebook, specifying the widget to use as the
4144 * label in the popup menu.
4146 * Return value: the index (starting from 0) of the appended
4147 * page in the notebook, or -1 if function fails
4150 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4152 GtkWidget *tab_label,
4153 GtkWidget *menu_label)
4155 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4156 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4157 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4158 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4160 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4164 * gtk_notebook_prepend_page:
4165 * @notebook: a #GtkNotebook
4166 * @child: the #GtkWidget to use as the contents of the page.
4167 * @tab_label: the #GtkWidget to be used as the label for the page,
4168 * or %NULL to use the default label, 'page N'.
4170 * Prepends a page to @notebook.
4172 * Return value: the index (starting from 0) of the prepended
4173 * page in the notebook, or -1 if function fails
4176 gtk_notebook_prepend_page (GtkNotebook *notebook,
4178 GtkWidget *tab_label)
4180 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4181 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4182 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4184 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4188 * gtk_notebook_prepend_page_menu:
4189 * @notebook: a #GtkNotebook
4190 * @child: the #GtkWidget to use as the contents of the page.
4191 * @tab_label: the #GtkWidget to be used as the label for the page,
4192 * or %NULL to use the default label, 'page N'.
4193 * @menu_label: the widget to use as a label for the page-switch
4194 * menu, if that is enabled. If %NULL, and @tab_label
4195 * is a #GtkLabel or %NULL, then the menu label will be
4196 * a newly created label with the same text as @tab_label;
4197 * If @tab_label is not a #GtkLabel, @menu_label must be
4198 * specified if the page-switch menu is to be used.
4200 * Prepends a page to @notebook, specifying the widget to use as the
4201 * label in the popup menu.
4203 * Return value: the index (starting from 0) of the prepended
4204 * page in the notebook, or -1 if function fails
4207 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4209 GtkWidget *tab_label,
4210 GtkWidget *menu_label)
4212 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4213 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4214 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4215 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4217 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4221 * gtk_notebook_insert_page:
4222 * @notebook: a #GtkNotebook
4223 * @child: the #GtkWidget to use as the contents of the page.
4224 * @tab_label: the #GtkWidget to be used as the label for the page,
4225 * or %NULL to use the default label, 'page N'.
4226 * @position: the index (starting at 0) at which to insert the page,
4227 * or -1 to append the page after all other pages.
4229 * Insert a page into @notebook at the given position.
4231 * Return value: the index (starting from 0) of the inserted
4232 * page in the notebook, or -1 if function fails
4235 gtk_notebook_insert_page (GtkNotebook *notebook,
4237 GtkWidget *tab_label,
4240 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4241 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4242 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4244 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4249 gtk_notebook_page_compare_tab (gconstpointer a,
4252 return (((GtkNotebookPage *) a)->tab_label != b);
4256 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4260 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4263 list = g_list_find_custom (notebook->children, child,
4264 gtk_notebook_page_compare_tab);
4267 GtkNotebookPage *page = list->data;
4269 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4270 gtk_notebook_switch_page (notebook, page, -1);
4271 focus_tabs_in (notebook);
4278 * gtk_notebook_insert_page_menu:
4279 * @notebook: a #GtkNotebook
4280 * @child: the #GtkWidget to use as the contents of the page.
4281 * @tab_label: the #GtkWidget to be used as the label for the page,
4282 * or %NULL to use the default label, 'page N'.
4283 * @menu_label: the widget to use as a label for the page-switch
4284 * menu, if that is enabled. If %NULL, and @tab_label
4285 * is a #GtkLabel or %NULL, then the menu label will be
4286 * a newly created label with the same text as @tab_label;
4287 * If @tab_label is not a #GtkLabel, @menu_label must be
4288 * specified if the page-switch menu is to be used.
4289 * @position: the index (starting at 0) at which to insert the page,
4290 * or -1 to append the page after all other pages.
4292 * Insert a page into @notebook at the given position, specifying
4293 * the widget to use as the label in the popup menu.
4295 * Return value: the index (starting from 0) of the inserted
4296 * page in the notebook, or -1 if function fails
4299 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4301 GtkWidget *tab_label,
4302 GtkWidget *menu_label,
4305 GtkNotebookPage *page;
4308 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4309 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4310 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4311 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4313 gtk_widget_freeze_child_notify (child);
4315 page = g_new (GtkNotebookPage, 1);
4316 page->child = child;
4317 page->last_focus_child = NULL;
4318 page->requisition.width = 0;
4319 page->requisition.height = 0;
4320 page->allocation.x = 0;
4321 page->allocation.y = 0;
4322 page->allocation.width = 0;
4323 page->allocation.height = 0;
4324 page->default_menu = FALSE;
4325 page->default_tab = FALSE;
4326 page->mnemonic_activate_signal = 0;
4328 nchildren = g_list_length (notebook->children);
4329 if ((position < 0) || (position > nchildren))
4330 position = nchildren;
4332 notebook->children = g_list_insert (notebook->children, page, position);
4336 page->default_tab = TRUE;
4337 if (notebook->show_tabs)
4338 tab_label = gtk_label_new ("");
4340 page->tab_label = tab_label;
4341 page->menu_label = menu_label;
4342 page->expand = FALSE;
4344 page->pack = GTK_PACK_START;
4347 page->default_menu = TRUE;
4350 g_object_ref (page->menu_label);
4351 gtk_object_sink (GTK_OBJECT (page->menu_label));
4355 gtk_notebook_menu_item_create (notebook,
4356 g_list_find (notebook->children, page));
4358 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4360 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4362 gtk_notebook_update_labels (notebook);
4364 if (!notebook->first_tab)
4365 notebook->first_tab = notebook->children;
4367 if (!notebook->cur_page)
4368 gtk_widget_set_child_visible (child, TRUE);
4370 gtk_widget_set_child_visible (child, FALSE);
4374 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4375 gtk_widget_show (tab_label);
4377 gtk_widget_hide (tab_label);
4380 if (!notebook->cur_page)
4382 gtk_notebook_switch_page (notebook, page, 0);
4383 gtk_notebook_switch_focus_tab (notebook, NULL);
4386 gtk_notebook_update_tab_states (notebook);
4389 page->mnemonic_activate_signal =
4390 g_signal_connect (tab_label,
4391 "mnemonic_activate",
4392 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4395 gtk_widget_child_notify (child, "tab_expand");
4396 gtk_widget_child_notify (child, "tab_fill");
4397 gtk_widget_child_notify (child, "tab_pack");
4398 gtk_widget_child_notify (child, "tab_label");
4399 gtk_widget_child_notify (child, "menu_label");
4400 gtk_widget_child_notify (child, "position");
4401 gtk_widget_thaw_child_notify (child);
4407 * gtk_notebook_remove_page:
4408 * @notebook: a #GtkNotebook.
4409 * @page_num: the index of a notebook page, starting
4410 * from 0. If -1, the last page will
4413 * Removes a page from the notebook given its index
4417 gtk_notebook_remove_page (GtkNotebook *notebook,
4422 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4426 list = g_list_nth (notebook->children, page_num);
4428 gtk_notebook_real_remove (notebook, list, FALSE);
4432 list = g_list_last (notebook->children);
4434 gtk_notebook_real_remove (notebook, list, FALSE);
4438 /* Public GtkNotebook Page Switch Methods :
4439 * gtk_notebook_get_current_page
4440 * gtk_notebook_page_num
4441 * gtk_notebook_set_current_page
4442 * gtk_notebook_next_page
4443 * gtk_notebook_prev_page
4446 * gtk_notebook_get_current_page:
4447 * @notebook: a #GtkNotebook
4449 * Returns the page number of the current page.
4451 * Return value: the index (starting from 0) of the current
4452 * page in the notebook. If the notebook has no pages, then
4453 * -1 will be returned.
4456 gtk_notebook_get_current_page (GtkNotebook *notebook)
4458 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4460 if (!notebook->cur_page)
4463 return g_list_index (notebook->children, notebook->cur_page);
4467 * gtk_notebook_get_nth_page:
4468 * @notebook: a #GtkNotebook
4469 * @page_num: the index of a page in the noteobok, or -1
4470 * to get the last page.
4472 * Returns the child widget contained in page number @page_num.
4474 * Return value: the child widget, or %NULL if @page_num is
4478 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4481 GtkNotebookPage *page;
4484 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4487 list = g_list_nth (notebook->children, page_num);
4489 list = g_list_last (notebook->children);
4501 * gtk_notebook_get_n_pages:
4502 * @notebook: a #GtkNotebook
4504 * Gets the number of pages in a notebook.
4506 * Return value: the number of pages in the notebook.
4511 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4513 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4515 return g_list_length (notebook->children);
4519 * gtk_notebook_page_num:
4520 * @notebook: a #GtkNotebook
4521 * @child: a #GtkWidget
4523 * Finds the index of the page which contains the given child
4526 * Return value: the index of the page containing @child, or
4527 * -1 if @child is not in the notebook.
4530 gtk_notebook_page_num (GtkNotebook *notebook,
4536 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4539 children = notebook->children;
4542 GtkNotebookPage *page = children->data;
4544 if (page->child == child)
4547 children = children->next;
4555 * gtk_notebook_set_current_page:
4556 * @notebook: a #GtkNotebook
4557 * @page_num: index of the page to switch to, starting from 0.
4558 * If negative, the last page will be used. If greater
4559 * than the number of pages in the notebook, nothing
4562 * Switches to the page number @page_num.
4565 gtk_notebook_set_current_page (GtkNotebook *notebook,
4570 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4573 list = g_list_nth (notebook->children, page_num);
4575 list = g_list_last (notebook->children);
4577 page_num = g_list_index (notebook->children, list);
4580 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4584 * gtk_notebook_next_page:
4585 * @notebook: a #GtkNotebook
4587 * Switches to the next page. Nothing happens if the current page is
4591 gtk_notebook_next_page (GtkNotebook *notebook)
4595 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4597 list = g_list_find (notebook->children, notebook->cur_page);
4601 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4605 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4609 * gtk_notebook_prev_page:
4610 * @notebook: a #GtkNotebook
4612 * Switches to the previous page. Nothing happens if the current page
4613 * is the first page.
4616 gtk_notebook_prev_page (GtkNotebook *notebook)
4620 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4622 list = g_list_find (notebook->children, notebook->cur_page);
4626 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4630 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4633 /* Public GtkNotebook/Tab Style Functions
4635 * gtk_notebook_set_show_border
4636 * gtk_notebook_set_show_tabs
4637 * gtk_notebook_set_tab_pos
4638 * gtk_notebook_set_homogeneous_tabs
4639 * gtk_notebook_set_tab_border
4640 * gtk_notebook_set_tab_hborder
4641 * gtk_notebook_set_tab_vborder
4642 * gtk_notebook_set_scrollable
4645 * gtk_notebook_set_show_border:
4646 * @notebook: a #GtkNotebook
4647 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4649 * Sets whether a bevel will be drawn around the notebook pages.
4650 * This only has a visual effect when the tabs are not shown.
4651 * See gtk_notebook_set_show_tabs().
4654 gtk_notebook_set_show_border (GtkNotebook *notebook,
4655 gboolean show_border)
4657 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4659 if (notebook->show_border != show_border)
4661 notebook->show_border = show_border;
4663 if (GTK_WIDGET_VISIBLE (notebook))
4664 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4666 g_object_notify (G_OBJECT (notebook), "show_border");
4671 * gtk_notebook_get_show_border:
4672 * @notebook: a #GtkNotebook
4674 * Returns whether a bevel will be drawn around the notebook pages. See
4675 * gtk_notebook_set_show_border().
4677 * Return value: %TRUE if the bevel is drawn
4680 gtk_notebook_get_show_border (GtkNotebook *notebook)
4682 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4684 return notebook->show_border;
4688 * gtk_notebook_set_show_tabs:
4689 * @notebook: a #GtkNotebook
4690 * @show_tabs: %TRUE if the tabs should be shown.
4692 * Sets whether to show the tabs for the notebook or not.
4695 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4698 GtkNotebookPage *page;
4701 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4703 show_tabs = show_tabs != FALSE;
4705 if (notebook->show_tabs == show_tabs)
4708 notebook->show_tabs = show_tabs;
4709 children = notebook->children;
4713 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4717 page = children->data;
4718 children = children->next;
4719 if (page->default_tab)
4721 gtk_widget_destroy (page->tab_label);
4722 page->tab_label = NULL;
4725 gtk_widget_hide (page->tab_label);
4730 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4731 gtk_notebook_update_labels (notebook);
4733 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4735 g_object_notify (G_OBJECT (notebook), "show_tabs");
4739 * gtk_notebook_get_show_tabs:
4740 * @notebook: a #GtkNotebook
4742 * Returns whether the tabs of the notebook are shown. See
4743 * gtk_notebook_set_show_tabs().
4745 * Return value: %TRUE if the tabs are shown
4748 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4750 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4752 return notebook->show_tabs;
4756 * gtk_notebook_set_tab_pos:
4757 * @notebook: a #GtkNotebook.
4758 * @pos: the edge to draw the tabs at.
4760 * Sets the edge at which the tabs for switching pages in the
4761 * notebook are drawn.
4764 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4765 GtkPositionType pos)
4767 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4769 if (notebook->tab_pos != pos)
4771 notebook->tab_pos = pos;
4772 if (GTK_WIDGET_VISIBLE (notebook))
4773 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4776 g_object_notify (G_OBJECT (notebook), "tab_pos");
4780 * gtk_notebook_get_tab_pos:
4781 * @notebook: a #GtkNotebook
4783 * Gets the edge at which the tabs for switching pages in the
4784 * notebook are drawn.
4786 * Return value: the edge at which the tabs are drawn
4789 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4791 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4793 return notebook->tab_pos;
4797 * gtk_notebook_set_homogeneous_tabs:
4798 * @notebook: a #GtkNotebook
4799 * @homogeneous: %TRUE if all tabs should be the same size.
4801 * Sets whether the tabs must have all the same size or not.
4804 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4805 gboolean homogeneous)
4807 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4809 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4813 * gtk_notebook_set_tab_border:
4814 * @notebook: a #GtkNotebook
4815 * @border_width: width of the border around the tab labels.
4817 * Sets the width the border around the tab labels
4818 * in a notebook. This is equivalent to calling
4819 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4820 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4823 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4826 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4828 gtk_notebook_set_tab_border_internal (notebook, border_width);
4832 * gtk_notebook_set_tab_hborder:
4833 * @notebook: a #GtkNotebook
4834 * @tab_hborder: width of the horizontal border of tab labels.
4836 * Sets the width of the horizontal border of tab labels.
4839 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4842 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4844 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4848 * gtk_notebook_set_tab_vborder:
4849 * @notebook: a #GtkNotebook
4850 * @tab_vborder: width of the vertical border of tab labels.
4852 * Sets the width of the vertical border of tab labels.
4855 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4858 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4860 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4864 * gtk_notebook_set_scrollable:
4865 * @notebook: a #GtkNotebook
4866 * @scrollable: %TRUE if scroll arrows should be added
4868 * Sets whether the tab label area will have arrows for scrolling if
4869 * there are too many tabs to fit in the area.
4872 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4873 gboolean scrollable)
4875 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4877 scrollable = (scrollable != FALSE);
4879 if (scrollable != notebook->scrollable)
4881 notebook->scrollable = scrollable;
4883 if (GTK_WIDGET_VISIBLE (notebook))
4884 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4886 g_object_notify (G_OBJECT (notebook), "scrollable");
4891 * gtk_notebook_get_scrollable:
4892 * @notebook: a #GtkNotebook
4894 * Returns whether the tab label area has arrows for scrolling. See
4895 * gtk_notebook_set_scrollable().
4897 * Return value: %TRUE if arrows for scrolling are present
4900 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4902 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4904 return notebook->scrollable;
4907 /* Public GtkNotebook Popup Menu Methods:
4909 * gtk_notebook_popup_enable
4910 * gtk_notebook_popup_disable
4915 * gtk_notebook_popup_enable:
4916 * @notebook: a #GtkNotebook
4918 * Enables the popup menu: if the user clicks with the right mouse button on
4919 * the bookmarks, a menu with all the pages will be popped up.
4922 gtk_notebook_popup_enable (GtkNotebook *notebook)
4926 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4931 notebook->menu = gtk_menu_new ();
4932 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4934 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4935 gtk_notebook_menu_item_create (notebook, list);
4937 gtk_notebook_update_labels (notebook);
4938 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4939 GTK_WIDGET (notebook),
4940 gtk_notebook_menu_detacher);
4942 g_object_notify (G_OBJECT (notebook), "enable_popup");
4946 * gtk_notebook_popup_disable:
4947 * @notebook: a #GtkNotebook
4949 * Disables the popup menu.
4952 gtk_notebook_popup_disable (GtkNotebook *notebook)
4954 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4956 if (!notebook->menu)
4959 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4960 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4961 gtk_widget_destroy (notebook->menu);
4963 g_object_notify (G_OBJECT (notebook), "enable_popup");
4966 /* Public GtkNotebook Page Properties Functions:
4968 * gtk_notebook_get_tab_label
4969 * gtk_notebook_set_tab_label
4970 * gtk_notebook_set_tab_label_text
4971 * gtk_notebook_get_menu_label
4972 * gtk_notebook_set_menu_label
4973 * gtk_notebook_set_menu_label_text
4974 * gtk_notebook_set_tab_label_packing
4975 * gtk_notebook_query_tab_label_packing
4979 * gtk_notebook_get_tab_label:
4980 * @notebook: a #GtkNotebook
4983 * Returns the tab label widget for the page @child. %NULL is returned
4984 * if @child is not in @notebook or if no tab label has specifically
4985 * been set for @child.
4987 * Return value: the tab label
4990 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4995 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4996 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4998 list = CHECK_FIND_CHILD (notebook, child);
5002 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5005 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5009 * gtk_notebook_set_tab_label:
5010 * @notebook: a #GtkNotebook
5012 * @tab_label: the tab label widget to use, or %NULL for default tab
5015 * Changes the tab label for @child. If %NULL is specified
5016 * for @tab_label, then the page will have the label 'page N'.
5019 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5021 GtkWidget *tab_label)
5023 GtkNotebookPage *page;
5026 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5027 g_return_if_fail (GTK_IS_WIDGET (child));
5029 list = CHECK_FIND_CHILD (notebook, child);
5033 /* a NULL pointer indicates a default_tab setting, otherwise
5034 * we need to set the associated label
5038 if (page->tab_label == tab_label)
5042 gtk_notebook_remove_tab_label (notebook, page);
5046 page->default_tab = FALSE;
5047 page->tab_label = tab_label;
5048 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5052 page->default_tab = TRUE;
5053 page->tab_label = NULL;
5055 if (notebook->show_tabs)
5059 g_snprintf (string, sizeof(string), _("Page %u"),
5060 gtk_notebook_real_page_position (notebook, list));
5061 page->tab_label = gtk_label_new (string);
5062 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5066 if (page->tab_label)
5067 page->mnemonic_activate_signal =
5068 g_signal_connect (page->tab_label,
5069 "mnemonic_activate",
5070 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5073 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5075 gtk_widget_show (page->tab_label);
5076 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5079 gtk_notebook_update_tab_states (notebook);
5080 gtk_widget_child_notify (child, "tab_label");
5084 * gtk_notebook_set_tab_label_text:
5085 * @notebook: a #GtkNotebook
5087 * @tab_text: the label text
5089 * Creates a new label and sets it as the tab label for the page
5090 * containing @child.
5093 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5095 const gchar *tab_text)
5097 GtkWidget *tab_label = NULL;
5099 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5102 tab_label = gtk_label_new (tab_text);
5103 gtk_notebook_set_tab_label (notebook, child, tab_label);
5104 gtk_widget_child_notify (child, "tab_label");
5108 * gtk_notebook_get_tab_label_text:
5109 * @notebook: a #GtkNotebook
5110 * @child: a widget contained in a page of @notebook
5112 * Retrieves the text of the tab label for the page containing
5115 * Returns value: the text of the tab label, or %NULL if the
5116 * tab label widget is not a #GtkLabel. The
5117 * string is owned by the widget and must not
5120 G_CONST_RETURN gchar *
5121 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5124 GtkWidget *tab_label;
5126 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5127 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5129 tab_label = gtk_notebook_get_tab_label (notebook, child);
5131 if (tab_label && GTK_IS_LABEL (tab_label))
5132 return gtk_label_get_text (GTK_LABEL (tab_label));
5138 * gtk_notebook_get_menu_label:
5139 * @notebook: a #GtkNotebook
5140 * @child: a widget contained in a page of @notebook
5142 * Retrieves the menu label widget of the page containing @child.
5144 * Return value: the menu label, or %NULL if the
5145 * notebook page does not have a menu label other
5146 * than the default (the tab label).
5149 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5154 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5155 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5157 list = CHECK_FIND_CHILD (notebook, child);
5161 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5164 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5168 * gtk_notebook_set_menu_label:
5169 * @notebook: a #GtkNotebook
5170 * @child: the child widget
5171 * @menu_label: the menu label, or NULL for default
5173 * Changes the menu label for the page containing @child.
5176 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5178 GtkWidget *menu_label)
5180 GtkNotebookPage *page;
5183 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5184 g_return_if_fail (GTK_IS_WIDGET (child));
5186 list = CHECK_FIND_CHILD (notebook, child);
5191 if (page->menu_label)
5194 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5195 page->menu_label->parent);
5197 if (!page->default_menu)
5198 g_object_unref (page->menu_label);
5203 page->menu_label = menu_label;
5204 g_object_ref (page->menu_label);
5205 gtk_object_sink (GTK_OBJECT(page->menu_label));
5206 page->default_menu = FALSE;
5209 page->default_menu = TRUE;
5212 gtk_notebook_menu_item_create (notebook, list);
5213 gtk_widget_child_notify (child, "menu_label");
5217 * gtk_notebook_set_menu_label_text:
5218 * @notebook: a #GtkNotebook
5219 * @child: the child widget
5220 * @menu_text: the label text
5222 * Creates a new label and sets it as the menu label of @child.
5225 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5227 const gchar *menu_text)
5229 GtkWidget *menu_label = NULL;
5231 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5234 menu_label = gtk_label_new (menu_text);
5235 gtk_notebook_set_menu_label (notebook, child, menu_label);
5236 gtk_widget_child_notify (child, "menu_label");
5240 * gtk_notebook_get_menu_label_text:
5241 * @notebook: a #GtkNotebook
5242 * @child: the child widget of a page of the notebook.
5244 * Retrieves the text of the menu label for the page containing
5247 * Returns value: the text of the tab label, or %NULL if the
5248 * widget does not have a menu label other than
5249 * the default menu label, or the menu label widget
5250 * is not a #GtkLabel. The string is owned by
5251 * the widget and must not be freed.
5253 G_CONST_RETURN gchar *
5254 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5257 GtkWidget *menu_label;
5259 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5260 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5262 menu_label = gtk_notebook_get_menu_label (notebook, child);
5264 if (menu_label && GTK_IS_LABEL (menu_label))
5265 return gtk_label_get_text (GTK_LABEL (menu_label));
5270 /* Helper function called when pages are reordered
5273 gtk_notebook_child_reordered (GtkNotebook *notebook,
5274 GtkNotebookPage *page)
5278 GtkWidget *menu_item;
5280 menu_item = page->menu_label->parent;
5281 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5282 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5283 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5286 gtk_notebook_update_tab_states (notebook);
5287 gtk_notebook_update_labels (notebook);
5291 * gtk_notebook_set_tab_label_packing:
5292 * @notebook: a #GtkNotebook
5293 * @child: the child widget
5294 * @expand: whether to expand the bookmark or not
5295 * @fill: whether the bookmark should fill the allocated area or not
5296 * @pack_type: the position of the bookmark
5298 * Sets the packing parameters for the tab label of the page
5299 * containing @child. See gtk_box_pack_start() for the exact meaning
5300 * of the parameters.
5303 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5307 GtkPackType pack_type)
5309 GtkNotebookPage *page;
5312 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5313 g_return_if_fail (GTK_IS_WIDGET (child));
5315 list = CHECK_FIND_CHILD (notebook, child);
5320 expand = expand != FALSE;
5321 fill = fill != FALSE;
5322 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5325 gtk_widget_freeze_child_notify (child);
5326 page->expand = expand;
5327 gtk_widget_child_notify (child, "tab_expand");
5329 gtk_widget_child_notify (child, "tab_fill");
5330 if (page->pack != pack_type)
5332 page->pack = pack_type;
5333 gtk_notebook_child_reordered (notebook, page);
5335 gtk_widget_child_notify (child, "tab_pack");
5336 gtk_widget_child_notify (child, "position");
5337 if (notebook->show_tabs)
5338 gtk_notebook_pages_allocate (notebook);
5339 gtk_widget_thaw_child_notify (child);
5343 * gtk_notebook_query_tab_label_packing:
5344 * @notebook: a #GtkNotebook
5346 * @expand: location to store the expand value (or NULL)
5347 * @fill: location to store the fill value (or NULL)
5348 * @pack_type: location to store the pack_type (or NULL)
5350 * Query the packing attributes for the tab label of the page
5351 * containing @child.
5354 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5358 GtkPackType *pack_type)
5362 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5363 g_return_if_fail (GTK_IS_WIDGET (child));
5365 list = CHECK_FIND_CHILD (notebook, child);
5370 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5372 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5374 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5378 * gtk_notebook_reorder_child:
5379 * @notebook: a #GtkNotebook
5380 * @child: the child to move
5381 * @position: the new position, or -1 to move to the end
5383 * Reorders the page containing @child, so that it appears in position
5384 * @position. If @position is greater than or equal to the number of
5385 * children in the list or negative, @child will be moved to the end
5389 gtk_notebook_reorder_child (GtkNotebook *notebook,
5393 GList *list, *new_list;
5394 GtkNotebookPage *page;
5398 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5399 g_return_if_fail (GTK_IS_WIDGET (child));
5401 list = CHECK_FIND_CHILD (notebook, child);
5405 max_pos = g_list_length (notebook->children) - 1;
5406 if (position < 0 || position > max_pos)
5409 old_pos = g_list_position (notebook->children, list);
5411 if (old_pos == position)
5415 notebook->children = g_list_delete_link (notebook->children, list);
5417 notebook->children = g_list_insert (notebook->children, page, position);
5418 new_list = g_list_nth (notebook->children, position);
5420 /* Fix up GList references in GtkNotebook structure */
5421 if (notebook->first_tab == list)
5422 notebook->first_tab = new_list;
5423 if (notebook->focus_tab == list)
5424 notebook->focus_tab = new_list;
5426 gtk_widget_freeze_child_notify (child);
5428 /* Move around the menu items if necessary */
5429 gtk_notebook_child_reordered (notebook, page);
5430 gtk_widget_child_notify (child, "tab_pack");
5431 gtk_widget_child_notify (child, "position");
5433 if (notebook->show_tabs)
5434 gtk_notebook_pages_allocate (notebook);
5436 gtk_widget_thaw_child_notify (child);