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 gint gtk_notebook_button_press (GtkWidget *widget,
163 GdkEventButton *event);
164 static gint gtk_notebook_button_release (GtkWidget *widget,
165 GdkEventButton *event);
166 static gint gtk_notebook_enter_notify (GtkWidget *widget,
167 GdkEventCrossing *event);
168 static gint gtk_notebook_leave_notify (GtkWidget *widget,
169 GdkEventCrossing *event);
170 static gint gtk_notebook_motion_notify (GtkWidget *widget,
171 GdkEventMotion *event);
172 static gint gtk_notebook_focus_in (GtkWidget *widget,
173 GdkEventFocus *event);
174 static gint gtk_notebook_focus_out (GtkWidget *widget,
175 GdkEventFocus *event);
176 static void gtk_notebook_grab_notify (GtkWidget *widget,
177 gboolean was_grabbed);
178 static void gtk_notebook_state_changed (GtkWidget *widget,
179 GtkStateType previous_state);
180 static void gtk_notebook_draw_focus (GtkWidget *widget);
181 static gint gtk_notebook_focus (GtkWidget *widget,
182 GtkDirectionType direction);
183 static void gtk_notebook_style_set (GtkWidget *widget,
186 /*** GtkContainer Methods ***/
187 static void gtk_notebook_set_child_property (GtkContainer *container,
192 static void gtk_notebook_get_child_property (GtkContainer *container,
197 static void gtk_notebook_add (GtkContainer *container,
199 static void gtk_notebook_remove (GtkContainer *container,
201 static void gtk_notebook_set_focus_child (GtkContainer *container,
203 static GType gtk_notebook_child_type (GtkContainer *container);
204 static void gtk_notebook_forall (GtkContainer *container,
205 gboolean include_internals,
206 GtkCallback callback,
207 gpointer callback_data);
209 /*** GtkNotebook Private Functions ***/
210 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
211 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
212 static void gtk_notebook_real_remove (GtkNotebook *notebook,
214 gboolean destroying);
215 static void gtk_notebook_update_labels (GtkNotebook *notebook);
216 static gint gtk_notebook_timer (GtkNotebook *notebook);
217 static gint gtk_notebook_page_compare (gconstpointer a,
219 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
221 const gchar *function);
222 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
224 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
227 gboolean find_visible);
229 /*** GtkNotebook Drawing Functions ***/
230 static void gtk_notebook_paint (GtkWidget *widget,
232 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
233 GtkNotebookPage *page,
235 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
236 GtkNotebookArrow arrow);
238 /*** GtkNotebook Size Allocate Functions ***/
239 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
240 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
241 GtkNotebookPage *page,
242 GtkAllocation *allocation);
243 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
249 /*** GtkNotebook Page Switch Methods ***/
250 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
251 GtkNotebookPage *page,
254 /*** GtkNotebook Page Switch Functions ***/
255 static void gtk_notebook_switch_page (GtkNotebook *notebook,
256 GtkNotebookPage *page,
258 static gint gtk_notebook_page_select (GtkNotebook *notebook,
259 gboolean move_focus);
260 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
262 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
263 GtkNotebookPage *page);
265 /*** GtkNotebook Menu Functions ***/
266 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
268 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
270 static void gtk_notebook_menu_detacher (GtkWidget *widget,
273 /*** GtkNotebook Private Setters ***/
274 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
275 gboolean homogeneous);
276 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
278 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
280 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
283 static gboolean focus_tabs_in (GtkNotebook *notebook);
284 static gboolean focus_child_in (GtkNotebook *notebook,
285 GtkDirectionType direction);
287 static GtkContainerClass *parent_class = NULL;
288 static guint notebook_signals[LAST_SIGNAL] = { 0 };
291 gtk_notebook_get_type (void)
293 static GType notebook_type = 0;
297 static const GTypeInfo notebook_info =
299 sizeof (GtkNotebookClass),
300 NULL, /* base_init */
301 NULL, /* base_finalize */
302 (GClassInitFunc) gtk_notebook_class_init,
303 NULL, /* class_finalize */
304 NULL, /* class_data */
305 sizeof (GtkNotebook),
307 (GInstanceInitFunc) gtk_notebook_init,
310 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
314 return notebook_type;
318 add_tab_bindings (GtkBindingSet *binding_set,
319 GdkModifierType modifiers,
320 GtkDirectionType direction)
322 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
324 GTK_TYPE_DIRECTION_TYPE, direction);
325 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
327 GTK_TYPE_DIRECTION_TYPE, direction);
331 add_arrow_bindings (GtkBindingSet *binding_set,
333 GtkDirectionType direction)
335 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
337 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
339 GTK_TYPE_DIRECTION_TYPE, direction);
340 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
342 GTK_TYPE_DIRECTION_TYPE, direction);
346 gtk_notebook_class_init (GtkNotebookClass *class)
348 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
349 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
350 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
351 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
352 GtkBindingSet *binding_set;
354 parent_class = g_type_class_peek_parent (class);
356 gobject_class->set_property = gtk_notebook_set_property;
357 gobject_class->get_property = gtk_notebook_get_property;
358 object_class->destroy = gtk_notebook_destroy;
360 widget_class->map = gtk_notebook_map;
361 widget_class->unmap = gtk_notebook_unmap;
362 widget_class->realize = gtk_notebook_realize;
363 widget_class->unrealize = gtk_notebook_unrealize;
364 widget_class->size_request = gtk_notebook_size_request;
365 widget_class->size_allocate = gtk_notebook_size_allocate;
366 widget_class->expose_event = gtk_notebook_expose;
367 widget_class->button_press_event = gtk_notebook_button_press;
368 widget_class->button_release_event = gtk_notebook_button_release;
369 widget_class->enter_notify_event = gtk_notebook_enter_notify;
370 widget_class->leave_notify_event = gtk_notebook_leave_notify;
371 widget_class->motion_notify_event = gtk_notebook_motion_notify;
372 widget_class->grab_notify = gtk_notebook_grab_notify;
373 widget_class->state_changed = gtk_notebook_state_changed;
374 widget_class->focus_in_event = gtk_notebook_focus_in;
375 widget_class->focus_out_event = gtk_notebook_focus_out;
376 widget_class->focus = gtk_notebook_focus;
377 widget_class->style_set = gtk_notebook_style_set;
379 container_class->add = gtk_notebook_add;
380 container_class->remove = gtk_notebook_remove;
381 container_class->forall = gtk_notebook_forall;
382 container_class->set_focus_child = gtk_notebook_set_focus_child;
383 container_class->get_child_property = gtk_notebook_get_child_property;
384 container_class->set_child_property = gtk_notebook_set_child_property;
385 container_class->child_type = gtk_notebook_child_type;
387 class->switch_page = gtk_notebook_real_switch_page;
389 class->focus_tab = gtk_notebook_focus_tab;
390 class->select_page = gtk_notebook_select_page;
391 class->change_current_page = gtk_notebook_change_current_page;
392 class->move_focus_out = gtk_notebook_move_focus_out;
394 g_object_class_install_property (gobject_class,
396 g_param_spec_int ("page",
398 P_("The index of the current page"),
403 g_object_class_install_property (gobject_class,
405 g_param_spec_enum ("tab_pos",
407 P_("Which side of the notebook holds the tabs"),
408 GTK_TYPE_POSITION_TYPE,
411 g_object_class_install_property (gobject_class,
413 g_param_spec_uint ("tab_border",
415 P_("Width of the border around the tab labels"),
420 g_object_class_install_property (gobject_class,
422 g_param_spec_uint ("tab_hborder",
423 P_("Horizontal Tab Border"),
424 P_("Width of the horizontal border of tab labels"),
429 g_object_class_install_property (gobject_class,
431 g_param_spec_uint ("tab_vborder",
432 P_("Vertical Tab Border"),
433 P_("Width of the vertical border of tab labels"),
438 g_object_class_install_property (gobject_class,
440 g_param_spec_boolean ("show_tabs",
442 P_("Whether tabs should be shown or not"),
445 g_object_class_install_property (gobject_class,
447 g_param_spec_boolean ("show_border",
449 P_("Whether the border should be shown or not"),
452 g_object_class_install_property (gobject_class,
454 g_param_spec_boolean ("scrollable",
456 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
459 g_object_class_install_property (gobject_class,
461 g_param_spec_boolean ("enable_popup",
463 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
466 g_object_class_install_property (gobject_class,
468 g_param_spec_boolean ("homogeneous",
470 P_("Whether tabs should have homogeneous sizes"),
474 gtk_container_class_install_child_property (container_class,
475 CHILD_PROP_TAB_LABEL,
476 g_param_spec_string ("tab_label",
478 P_("The string displayed on the childs tab label"),
481 gtk_container_class_install_child_property (container_class,
482 CHILD_PROP_MENU_LABEL,
483 g_param_spec_string ("menu_label",
485 P_("The string displayed in the childs menu entry"),
488 gtk_container_class_install_child_property (container_class,
490 g_param_spec_int ("position",
492 P_("The index of the child in the parent"),
495 gtk_container_class_install_child_property (container_class,
496 CHILD_PROP_TAB_EXPAND,
497 g_param_spec_boolean ("tab_expand",
499 P_("Whether to expand the childs tab or not"),
502 gtk_container_class_install_child_property (container_class,
504 g_param_spec_boolean ("tab_fill",
506 P_("Whether the childs tab should fill the allocated area or not"),
509 gtk_container_class_install_child_property (container_class,
511 g_param_spec_enum ("tab_pack",
513 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
514 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
518 * GtkNotebook:has-secondary-backward-stepper:
520 * The "has-secondary-backward-stepper" property determines whether
521 * a second backward arrow button is displayed on the opposite end
526 gtk_widget_class_install_style_property (widget_class,
527 g_param_spec_boolean ("has_secondary backward_stepper",
528 P_("Secondary backward stepper"),
529 P_("Display a second backward arrow button on the opposite end of the tab area"),
535 * GtkNotebook:has-secondary-forward-stepper:
537 * The "has-secondary-forward-stepper" property determines whether
538 * a second forward arrow button is displayed on the opposite end
543 gtk_widget_class_install_style_property (widget_class,
544 g_param_spec_boolean ("has_secondary_forward_stepper",
545 P_("Secondary forward stepper"),
546 P_("Display a second forward arrow button on the opposite end of the tab area"),
552 * GtkNotebook:has-backward-stepper:
554 * The "has-backward-stepper" property determines whether
555 * the standard backward arrow button is displayed.
559 gtk_widget_class_install_style_property (widget_class,
560 g_param_spec_boolean ("has_backward_stepper",
561 P_("Backward stepper"),
562 P_("Display the standard backward arrow button"),
568 * GtkNotebook:has-forward-stepper:
570 * The "has-forward-stepper" property determines whether
571 * the standard forward arrow button is displayed.
575 gtk_widget_class_install_style_property (widget_class,
576 g_param_spec_boolean ("has_forward_stepper",
577 P_("Forward stepper"),
578 P_("Display the standard forward arrow button"),
583 notebook_signals[SWITCH_PAGE] =
584 g_signal_new ("switch_page",
585 G_TYPE_FROM_CLASS (gobject_class),
587 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
589 _gtk_marshal_VOID__POINTER_UINT,
593 notebook_signals[FOCUS_TAB] =
594 g_signal_new ("focus_tab",
595 G_TYPE_FROM_CLASS (gobject_class),
596 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
597 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
599 _gtk_marshal_BOOLEAN__ENUM,
601 GTK_TYPE_NOTEBOOK_TAB);
602 notebook_signals[SELECT_PAGE] =
603 g_signal_new ("select_page",
604 G_TYPE_FROM_CLASS (gobject_class),
605 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
606 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
608 _gtk_marshal_BOOLEAN__BOOLEAN,
611 notebook_signals[CHANGE_CURRENT_PAGE] =
612 g_signal_new ("change_current_page",
613 G_TYPE_FROM_CLASS (gobject_class),
614 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
615 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
617 _gtk_marshal_VOID__INT,
620 notebook_signals[MOVE_FOCUS_OUT] =
621 g_signal_new ("move_focus_out",
622 G_TYPE_FROM_CLASS (gobject_class),
623 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
624 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
626 _gtk_marshal_VOID__ENUM,
628 GTK_TYPE_DIRECTION_TYPE);
631 binding_set = gtk_binding_set_by_class (class);
632 gtk_binding_entry_add_signal (binding_set,
635 G_TYPE_BOOLEAN, FALSE);
636 gtk_binding_entry_add_signal (binding_set,
639 G_TYPE_BOOLEAN, FALSE);
641 gtk_binding_entry_add_signal (binding_set,
644 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
645 gtk_binding_entry_add_signal (binding_set,
648 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
649 gtk_binding_entry_add_signal (binding_set,
652 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
653 gtk_binding_entry_add_signal (binding_set,
656 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
658 gtk_binding_entry_add_signal (binding_set,
659 GDK_Page_Up, GDK_CONTROL_MASK,
660 "change_current_page", 1,
662 gtk_binding_entry_add_signal (binding_set,
663 GDK_Page_Down, GDK_CONTROL_MASK,
664 "change_current_page", 1,
667 gtk_binding_entry_add_signal (binding_set,
668 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
669 "change_current_page", 1,
671 gtk_binding_entry_add_signal (binding_set,
672 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
673 "change_current_page", 1,
676 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
677 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
678 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
679 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
681 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
682 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
686 gtk_notebook_init (GtkNotebook *notebook)
688 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
689 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
691 notebook->cur_page = NULL;
692 notebook->children = NULL;
693 notebook->first_tab = NULL;
694 notebook->focus_tab = NULL;
695 notebook->event_window = NULL;
696 notebook->menu = NULL;
698 notebook->tab_hborder = 2;
699 notebook->tab_vborder = 2;
701 notebook->show_tabs = TRUE;
702 notebook->show_border = TRUE;
703 notebook->tab_pos = GTK_POS_TOP;
704 notebook->scrollable = FALSE;
705 notebook->in_child = 0;
706 notebook->click_child = 0;
707 notebook->button = 0;
708 notebook->need_timer = 0;
709 notebook->child_has_focus = FALSE;
710 notebook->have_visible_child = FALSE;
711 notebook->focus_out = FALSE;
713 notebook->has_before_previous = 1;
714 notebook->has_before_next = 0;
715 notebook->has_after_previous = 0;
716 notebook->has_after_next = 1;
720 gtk_notebook_select_page (GtkNotebook *notebook,
723 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
725 gtk_notebook_page_select (notebook, move_focus);
733 gtk_notebook_focus_tab (GtkNotebook *notebook,
738 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
742 case GTK_NOTEBOOK_TAB_FIRST:
743 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
745 gtk_notebook_switch_focus_tab (notebook, list);
747 case GTK_NOTEBOOK_TAB_LAST:
748 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
750 gtk_notebook_switch_focus_tab (notebook, list);
761 gtk_notebook_change_current_page (GtkNotebook *notebook,
764 GList *current = NULL;
766 if (notebook->cur_page)
767 current = g_list_find (notebook->children, notebook->cur_page);
771 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
772 offset += offset < 0 ? 1 : -1;
776 gtk_notebook_switch_page (notebook, current->data, -1);
778 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
781 static GtkDirectionType
782 get_effective_direction (GtkNotebook *notebook,
783 GtkDirectionType direction)
785 /* Remap the directions into the effective direction it would be for a
786 * GTK_POS_TOP notebook
789 #define D(rest) GTK_DIR_##rest
791 static const GtkDirectionType translate_direction[2][4][6] = {
792 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
793 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
794 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
795 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
796 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
797 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
798 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
799 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
804 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
806 return translate_direction[text_dir][notebook->tab_pos][direction];
810 get_effective_tab_pos (GtkNotebook *notebook)
812 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
814 switch (notebook->tab_pos)
817 return GTK_POS_RIGHT;
824 return notebook->tab_pos;
828 gtk_notebook_move_focus_out (GtkNotebook *notebook,
829 GtkDirectionType direction_type)
831 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
834 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
835 if (focus_tabs_in (notebook))
837 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
838 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
841 /* At this point, we know we should be focusing out of the notebook entirely. We
842 * do this by setting a flag, then propagating the focus motion to the notebook.
844 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
845 if (!GTK_WIDGET_TOPLEVEL (toplevel))
848 g_object_ref (notebook);
850 notebook->focus_out = TRUE;
851 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
852 notebook->focus_out = FALSE;
854 g_object_unref (notebook);
861 * Creates a new #GtkNotebook widget with no pages.
863 * Return value: the newly created #GtkNotebook
866 gtk_notebook_new (void)
868 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
871 /* Private GtkObject Methods :
873 * gtk_notebook_destroy
874 * gtk_notebook_set_arg
875 * gtk_notebook_get_arg
878 gtk_notebook_destroy (GtkObject *object)
881 GtkNotebook *notebook = GTK_NOTEBOOK (object);
884 gtk_notebook_popup_disable (notebook);
886 children = notebook->children;
889 GList *child = children;
890 children = child->next;
892 gtk_notebook_real_remove (notebook, child, TRUE);
895 GTK_OBJECT_CLASS (parent_class)->destroy (object);
899 gtk_notebook_set_property (GObject *object,
904 GtkNotebook *notebook;
906 notebook = GTK_NOTEBOOK (object);
911 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
913 case PROP_SHOW_BORDER:
914 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
916 case PROP_SCROLLABLE:
917 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
919 case PROP_ENABLE_POPUP:
920 if (g_value_get_boolean (value))
921 gtk_notebook_popup_enable (notebook);
923 gtk_notebook_popup_disable (notebook);
925 case PROP_HOMOGENEOUS:
926 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
929 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
932 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
934 case PROP_TAB_BORDER:
935 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
937 case PROP_TAB_HBORDER:
938 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
940 case PROP_TAB_VBORDER:
941 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
949 gtk_notebook_get_property (GObject *object,
954 GtkNotebook *notebook;
956 notebook = GTK_NOTEBOOK (object);
961 g_value_set_boolean (value, notebook->show_tabs);
963 case PROP_SHOW_BORDER:
964 g_value_set_boolean (value, notebook->show_border);
966 case PROP_SCROLLABLE:
967 g_value_set_boolean (value, notebook->scrollable);
969 case PROP_ENABLE_POPUP:
970 g_value_set_boolean (value, notebook->menu != NULL);
972 case PROP_HOMOGENEOUS:
973 g_value_set_boolean (value, notebook->homogeneous);
976 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
979 g_value_set_enum (value, notebook->tab_pos);
981 case PROP_TAB_HBORDER:
982 g_value_set_uint (value, notebook->tab_hborder);
984 case PROP_TAB_VBORDER:
985 g_value_set_uint (value, notebook->tab_vborder);
988 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
993 /* Private GtkWidget Methods :
997 * gtk_notebook_realize
998 * gtk_notebook_size_request
999 * gtk_notebook_size_allocate
1000 * gtk_notebook_expose
1001 * gtk_notebook_button_press
1002 * gtk_notebook_button_release
1003 * gtk_notebook_enter_notify
1004 * gtk_notebook_leave_notify
1005 * gtk_notebook_motion_notify
1006 * gtk_notebook_focus_in
1007 * gtk_notebook_focus_out
1008 * gtk_notebook_draw_focus
1009 * gtk_notebook_style_set
1012 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1013 GdkRectangle *rectangle)
1015 GtkWidget *widget = GTK_WIDGET (notebook);
1016 gint border_width = GTK_CONTAINER (notebook)->border_width;
1017 GtkNotebookPage *visible_page = NULL;
1019 gint tab_pos = get_effective_tab_pos (notebook);
1021 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1023 GtkNotebookPage *page = tmp_list->data;
1024 if (GTK_WIDGET_VISIBLE (page->child))
1026 visible_page = page;
1031 if (notebook->show_tabs && visible_page)
1035 rectangle->x = widget->allocation.x + border_width;
1036 rectangle->y = widget->allocation.y + border_width;
1041 case GTK_POS_BOTTOM:
1042 rectangle->width = widget->allocation.width - 2 * border_width;
1043 rectangle->height = visible_page->requisition.height;
1044 if (tab_pos == GTK_POS_BOTTOM)
1045 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1049 rectangle->width = visible_page->requisition.width;
1050 rectangle->height = widget->allocation.height - 2 * border_width;
1051 if (tab_pos == GTK_POS_RIGHT)
1052 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1063 rectangle->x = rectangle->y = 0;
1064 rectangle->width = rectangle->height = 10;
1072 gtk_notebook_map (GtkWidget *widget)
1074 GtkNotebook *notebook;
1075 GtkNotebookPage *page;
1078 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1080 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1082 notebook = GTK_NOTEBOOK (widget);
1084 if (notebook->cur_page &&
1085 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1086 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1087 gtk_widget_map (notebook->cur_page->child);
1089 if (notebook->scrollable)
1090 gtk_notebook_pages_allocate (notebook);
1093 children = notebook->children;
1097 page = children->data;
1098 children = children->next;
1100 if (page->tab_label &&
1101 GTK_WIDGET_VISIBLE (page->tab_label) &&
1102 !GTK_WIDGET_MAPPED (page->tab_label))
1103 gtk_widget_map (page->tab_label);
1107 if (gtk_notebook_get_event_window_position (notebook, NULL))
1108 gdk_window_show_unraised (notebook->event_window);
1112 gtk_notebook_unmap (GtkWidget *widget)
1114 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1116 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1118 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1120 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1124 gtk_notebook_realize (GtkWidget *widget)
1126 GtkNotebook *notebook;
1127 GdkWindowAttr attributes;
1128 gint attributes_mask;
1129 GdkRectangle event_window_pos;
1131 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1133 notebook = GTK_NOTEBOOK (widget);
1134 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1136 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1138 widget->window = gtk_widget_get_parent_window (widget);
1139 g_object_ref (widget->window);
1141 attributes.window_type = GDK_WINDOW_CHILD;
1142 attributes.x = event_window_pos.x;
1143 attributes.y = event_window_pos.y;
1144 attributes.width = event_window_pos.width;
1145 attributes.height = event_window_pos.height;
1146 attributes.wclass = GDK_INPUT_ONLY;
1147 attributes.event_mask = gtk_widget_get_events (widget);
1148 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1149 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1151 attributes_mask = GDK_WA_X | GDK_WA_Y;
1153 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1154 &attributes, attributes_mask);
1155 gdk_window_set_user_data (notebook->event_window, notebook);
1157 widget->style = gtk_style_attach (widget->style, widget->window);
1161 gtk_notebook_unrealize (GtkWidget *widget)
1163 GtkNotebook *notebook;
1165 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1167 notebook = GTK_NOTEBOOK (widget);
1169 gdk_window_set_user_data (notebook->event_window, NULL);
1170 gdk_window_destroy (notebook->event_window);
1171 notebook->event_window = NULL;
1173 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1174 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1178 gtk_notebook_size_request (GtkWidget *widget,
1179 GtkRequisition *requisition)
1181 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1182 GtkNotebookPage *page;
1184 GtkRequisition child_requisition;
1185 gboolean switch_page = FALSE;
1189 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1191 widget->requisition.width = 0;
1192 widget->requisition.height = 0;
1194 for (children = notebook->children, vis_pages = 0; children;
1195 children = children->next)
1197 page = children->data;
1199 if (GTK_WIDGET_VISIBLE (page->child))
1202 gtk_widget_size_request (page->child, &child_requisition);
1204 widget->requisition.width = MAX (widget->requisition.width,
1205 child_requisition.width);
1206 widget->requisition.height = MAX (widget->requisition.height,
1207 child_requisition.height);
1209 if (notebook->menu && page->menu_label->parent &&
1210 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1211 gtk_widget_show (page->menu_label->parent);
1215 if (page == notebook->cur_page)
1217 if (notebook->menu && page->menu_label->parent &&
1218 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1219 gtk_widget_hide (page->menu_label->parent);
1223 if (notebook->show_border || notebook->show_tabs)
1225 widget->requisition.width += widget->style->xthickness * 2;
1226 widget->requisition.height += widget->style->ythickness * 2;
1228 if (notebook->show_tabs)
1231 gint tab_height = 0;
1235 for (children = notebook->children; children;
1236 children = children->next)
1238 page = children->data;
1240 if (GTK_WIDGET_VISIBLE (page->child))
1242 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1243 gtk_widget_show (page->tab_label);
1245 gtk_widget_size_request (page->tab_label,
1246 &child_requisition);
1248 page->requisition.width =
1249 child_requisition.width +
1250 2 * widget->style->xthickness;
1251 page->requisition.height =
1252 child_requisition.height +
1253 2 * widget->style->ythickness;
1255 switch (notebook->tab_pos)
1258 case GTK_POS_BOTTOM:
1259 page->requisition.height += 2 * (notebook->tab_vborder +
1261 tab_height = MAX (tab_height, page->requisition.height);
1262 tab_max = MAX (tab_max, page->requisition.width);
1266 page->requisition.width += 2 * (notebook->tab_hborder +
1268 tab_width = MAX (tab_width, page->requisition.width);
1269 tab_max = MAX (tab_max, page->requisition.height);
1273 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1274 gtk_widget_hide (page->tab_label);
1277 children = notebook->children;
1281 switch (notebook->tab_pos)
1284 case GTK_POS_BOTTOM:
1285 if (tab_height == 0)
1288 if (notebook->scrollable && vis_pages > 1 &&
1289 widget->requisition.width < tab_width)
1290 tab_height = MAX (tab_height, ARROW_SIZE);
1292 padding = 2 * (TAB_CURVATURE + focus_width +
1293 notebook->tab_hborder) - TAB_OVERLAP;
1297 page = children->data;
1298 children = children->next;
1300 if (!GTK_WIDGET_VISIBLE (page->child))
1303 if (notebook->homogeneous)
1304 page->requisition.width = tab_max;
1306 page->requisition.width += padding;
1308 tab_width += page->requisition.width;
1309 page->requisition.height = tab_height;
1312 if (notebook->scrollable && vis_pages > 1 &&
1313 widget->requisition.width < tab_width)
1314 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1316 if (notebook->homogeneous && !notebook->scrollable)
1317 widget->requisition.width = MAX (widget->requisition.width,
1318 vis_pages * tab_max +
1321 widget->requisition.width = MAX (widget->requisition.width,
1322 tab_width + TAB_OVERLAP);
1324 widget->requisition.height += tab_height;
1331 if (notebook->scrollable && vis_pages > 1 &&
1332 widget->requisition.height < tab_height)
1333 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1335 padding = 2 * (TAB_CURVATURE + focus_width +
1336 notebook->tab_vborder) - TAB_OVERLAP;
1341 page = children->data;
1342 children = children->next;
1344 if (!GTK_WIDGET_VISIBLE (page->child))
1347 page->requisition.width = tab_width;
1349 if (notebook->homogeneous)
1350 page->requisition.height = tab_max;
1352 page->requisition.height += padding;
1354 tab_height += page->requisition.height;
1357 if (notebook->scrollable && vis_pages > 1 &&
1358 widget->requisition.height < tab_height)
1359 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1361 widget->requisition.width += tab_width;
1363 if (notebook->homogeneous && !notebook->scrollable)
1364 widget->requisition.height =
1365 MAX (widget->requisition.height,
1366 vis_pages * tab_max + TAB_OVERLAP);
1368 widget->requisition.height =
1369 MAX (widget->requisition.height,
1370 tab_height + TAB_OVERLAP);
1372 if (!notebook->homogeneous || notebook->scrollable)
1374 widget->requisition.height = MAX (widget->requisition.height,
1375 vis_pages * tab_max +
1383 for (children = notebook->children; children;
1384 children = children->next)
1386 page = children->data;
1388 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1389 gtk_widget_hide (page->tab_label);
1394 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1395 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1401 for (children = notebook->children; children;
1402 children = children->next)
1404 page = children->data;
1405 if (GTK_WIDGET_VISIBLE (page->child))
1407 gtk_notebook_switch_page (notebook, page, -1);
1412 else if (GTK_WIDGET_VISIBLE (widget))
1414 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1415 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1418 if (vis_pages && !notebook->cur_page)
1420 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1423 notebook->first_tab = children;
1424 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1430 gtk_notebook_size_allocate (GtkWidget *widget,
1431 GtkAllocation *allocation)
1433 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1435 gint tab_pos = get_effective_tab_pos (notebook);
1437 widget->allocation = *allocation;
1438 if (GTK_WIDGET_REALIZED (widget))
1440 GdkRectangle position;
1442 if (gtk_notebook_get_event_window_position (notebook, &position))
1444 gdk_window_move_resize (notebook->event_window,
1445 position.x, position.y,
1446 position.width, position.height);
1447 if (GTK_WIDGET_MAPPED (notebook))
1448 gdk_window_show_unraised (notebook->event_window);
1451 gdk_window_hide (notebook->event_window);
1454 if (notebook->children)
1456 gint border_width = GTK_CONTAINER (widget)->border_width;
1457 GtkNotebookPage *page;
1458 GtkAllocation child_allocation;
1461 child_allocation.x = widget->allocation.x + border_width;
1462 child_allocation.y = widget->allocation.y + border_width;
1463 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1464 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1466 if (notebook->show_tabs || notebook->show_border)
1468 child_allocation.x += widget->style->xthickness;
1469 child_allocation.y += widget->style->ythickness;
1470 child_allocation.width = MAX (1, child_allocation.width -
1471 widget->style->xthickness * 2);
1472 child_allocation.height = MAX (1, child_allocation.height -
1473 widget->style->ythickness * 2);
1475 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1480 child_allocation.y += notebook->cur_page->requisition.height;
1481 case GTK_POS_BOTTOM:
1482 child_allocation.height =
1483 MAX (1, child_allocation.height -
1484 notebook->cur_page->requisition.height);
1487 child_allocation.x += notebook->cur_page->requisition.width;
1489 child_allocation.width =
1490 MAX (1, child_allocation.width -
1491 notebook->cur_page->requisition.width);
1497 children = notebook->children;
1500 page = children->data;
1501 children = children->next;
1503 if (GTK_WIDGET_VISIBLE (page->child))
1505 gtk_widget_size_allocate (page->child, &child_allocation);
1510 gtk_notebook_pages_allocate (notebook);
1513 if ((vis_pages != 0) != notebook->have_visible_child)
1515 notebook->have_visible_child = (vis_pages != 0);
1516 if (notebook->show_tabs)
1517 gtk_widget_queue_draw (widget);
1522 gtk_notebook_expose (GtkWidget *widget,
1523 GdkEventExpose *event)
1525 GtkNotebook *notebook;
1526 GdkRectangle child_area;
1528 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1529 g_return_val_if_fail (event != NULL, FALSE);
1531 if (GTK_WIDGET_DRAWABLE (widget))
1533 notebook = GTK_NOTEBOOK (widget);
1535 gtk_notebook_paint (widget, &event->area);
1536 if (notebook->show_tabs)
1538 if (notebook->cur_page &&
1539 gtk_widget_intersect (notebook->cur_page->tab_label,
1540 &event->area, &child_area))
1541 gtk_notebook_draw_focus (widget);
1545 if (notebook->cur_page)
1546 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1547 notebook->cur_page->child,
1555 gtk_notebook_show_arrows (GtkNotebook *notebook)
1557 gboolean show_arrow = FALSE;
1560 if (!notebook->scrollable)
1563 children = notebook->children;
1566 GtkNotebookPage *page = children->data;
1568 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1571 children = children->next;
1578 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1579 GdkRectangle *rectangle,
1580 GtkNotebookArrow arrow)
1582 GdkRectangle event_window_pos;
1583 gboolean before = ARROW_IS_BEFORE (arrow);
1584 gboolean left = ARROW_IS_LEFT (arrow);
1586 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1588 rectangle->width = ARROW_SIZE;
1589 rectangle->height = ARROW_SIZE;
1591 switch (notebook->tab_pos)
1595 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1596 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1597 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1599 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1601 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1602 rectangle->y = event_window_pos.y;
1604 rectangle->y += event_window_pos.height - rectangle->height;
1607 case GTK_POS_BOTTOM:
1610 if (left || !notebook->has_before_previous)
1611 rectangle->x = event_window_pos.x;
1613 rectangle->x = event_window_pos.x + rectangle->width;
1617 if (!left || !notebook->has_after_next)
1618 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1620 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1622 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1628 static GtkNotebookArrow
1629 gtk_notebook_get_arrow (GtkNotebook *notebook,
1633 GdkRectangle arrow_rect;
1634 GdkRectangle event_window_pos;
1637 GtkNotebookArrow arrow[4];
1639 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1640 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1641 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1642 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1644 if (gtk_notebook_show_arrows (notebook))
1646 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1647 for (i = 0; i < 4; i++)
1649 if (arrow[i] == ARROW_NONE)
1652 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1654 x0 = x - arrow_rect.x;
1655 y0 = y - arrow_rect.y;
1657 if (y0 >= 0 && y0 < arrow_rect.height &&
1658 x0 >= 0 && x0 < arrow_rect.width)
1667 gtk_notebook_do_arrow (GtkNotebook *notebook,
1668 GtkNotebookArrow arrow)
1670 GtkWidget *widget = GTK_WIDGET (notebook);
1671 GtkDirectionType dir;
1672 gboolean is_rtl, left;
1674 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1675 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1676 (!ARROW_IS_LEFT (arrow) && is_rtl);
1678 if (!notebook->focus_tab ||
1679 gtk_notebook_search_page (notebook, notebook->focus_tab,
1680 left ? STEP_PREV : STEP_NEXT,
1683 if (notebook->tab_pos == GTK_POS_LEFT ||
1684 notebook->tab_pos == GTK_POS_RIGHT)
1685 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1687 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1688 gtk_widget_child_focus (widget, dir);
1693 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1694 GtkNotebookArrow arrow,
1695 GdkEventButton *event)
1697 GtkWidget *widget = GTK_WIDGET (notebook);
1698 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1699 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1700 (!ARROW_IS_LEFT (arrow) && is_rtl);
1702 if (!GTK_WIDGET_HAS_FOCUS (widget))
1703 gtk_widget_grab_focus (widget);
1705 notebook->button = event->button;
1706 notebook->click_child = arrow;
1708 if (event->button == 1)
1710 gtk_notebook_do_arrow (notebook, arrow);
1712 if (!notebook->timer)
1714 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1715 (GSourceFunc) gtk_notebook_timer,
1716 (gpointer) notebook);
1717 notebook->need_timer = TRUE;
1720 else if (event->button == 2)
1721 gtk_notebook_page_select (notebook, TRUE);
1722 else if (event->button == 3)
1723 gtk_notebook_switch_focus_tab (notebook,
1724 gtk_notebook_search_page (notebook,
1726 left ? STEP_NEXT : STEP_PREV,
1728 gtk_notebook_redraw_arrows (notebook);
1734 get_widget_coordinates (GtkWidget *widget,
1739 GdkWindow *window = ((GdkEventAny *)event)->window;
1742 if (!gdk_event_get_coords (event, &tx, &ty))
1745 while (window && window != widget->window)
1747 gint window_x, window_y;
1749 gdk_window_get_position (window, &window_x, &window_y);
1753 window = gdk_window_get_parent (window);
1768 gtk_notebook_button_press (GtkWidget *widget,
1769 GdkEventButton *event)
1771 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1772 GtkNotebookPage *page;
1774 GtkNotebookArrow arrow;
1778 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1782 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1785 arrow = gtk_notebook_get_arrow (notebook, x, y);
1787 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1789 if (event->button == 3 && notebook->menu)
1791 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1792 NULL, NULL, 3, event->time);
1796 if (event->button != 1)
1800 children = notebook->children;
1803 page = children->data;
1805 if (GTK_WIDGET_VISIBLE (page->child) &&
1806 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1807 (x >= page->allocation.x) &&
1808 (y >= page->allocation.y) &&
1809 (x <= (page->allocation.x + page->allocation.width)) &&
1810 (y <= (page->allocation.y + page->allocation.height)))
1812 gboolean page_changed = page != notebook->cur_page;
1813 gboolean was_focus = gtk_widget_is_focus (widget);
1815 gtk_notebook_switch_focus_tab (notebook, children);
1816 gtk_widget_grab_focus (widget);
1818 if (page_changed && !was_focus)
1819 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1823 children = children->next;
1831 stop_scrolling (GtkNotebook *notebook)
1833 if (notebook->timer)
1835 g_source_remove (notebook->timer);
1836 notebook->timer = 0;
1837 notebook->need_timer = FALSE;
1839 notebook->click_child = 0;
1840 notebook->button = 0;
1841 gtk_notebook_redraw_arrows (notebook);
1845 gtk_notebook_button_release (GtkWidget *widget,
1846 GdkEventButton *event)
1848 GtkNotebook *notebook;
1850 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1851 g_return_val_if_fail (event != NULL, FALSE);
1853 if (event->type != GDK_BUTTON_RELEASE)
1856 notebook = GTK_NOTEBOOK (widget);
1858 if (event->button == notebook->button)
1860 stop_scrolling (notebook);
1869 gtk_notebook_enter_notify (GtkWidget *widget,
1870 GdkEventCrossing *event)
1872 GtkNotebook *notebook;
1873 GtkNotebookArrow arrow;
1876 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1877 g_return_val_if_fail (event != NULL, FALSE);
1879 notebook = GTK_NOTEBOOK (widget);
1881 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1884 arrow = gtk_notebook_get_arrow (notebook, x, y);
1886 if (arrow != notebook->in_child)
1888 notebook->in_child = arrow;
1889 gtk_notebook_redraw_arrows (notebook);
1898 gtk_notebook_leave_notify (GtkWidget *widget,
1899 GdkEventCrossing *event)
1901 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1902 GtkNotebookArrow arrow;
1905 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1908 arrow = gtk_notebook_get_arrow (notebook, x, y);
1910 if (notebook->in_child)
1912 notebook->in_child = 0;
1913 gtk_notebook_redraw_arrows (notebook);
1920 gtk_notebook_motion_notify (GtkWidget *widget,
1921 GdkEventMotion *event)
1923 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1924 GtkNotebookArrow arrow;
1927 if (notebook->button)
1930 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1933 arrow = gtk_notebook_get_arrow (notebook, x, y);
1935 if (arrow != notebook->in_child)
1937 notebook->in_child = arrow;
1938 gtk_notebook_redraw_arrows (notebook);
1945 gtk_notebook_grab_notify (GtkWidget *widget,
1946 gboolean was_grabbed)
1949 stop_scrolling (GTK_NOTEBOOK (widget));
1953 gtk_notebook_state_changed (GtkWidget *widget,
1954 GtkStateType previous_state)
1956 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1957 stop_scrolling (GTK_NOTEBOOK (widget));
1961 gtk_notebook_focus_in (GtkWidget *widget,
1962 GdkEventFocus *event)
1964 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1966 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
1972 gtk_notebook_focus_out (GtkWidget *widget,
1973 GdkEventFocus *event)
1975 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
1981 gtk_notebook_draw_focus (GtkWidget *widget)
1983 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1985 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1986 notebook->focus_tab)
1988 GtkNotebookPage *page;
1992 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1994 page = notebook->focus_tab->data;
1996 area.x = page->tab_label->allocation.x - focus_width;
1997 area.y = page->tab_label->allocation.y - focus_width;
1998 area.width = page->tab_label->allocation.width + 2 * focus_width;
1999 area.height = page->tab_label->allocation.height + 2 * focus_width;
2001 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2006 gtk_notebook_style_set (GtkWidget *widget,
2009 GtkNotebook *notebook;
2011 gboolean has_before_previous;
2012 gboolean has_before_next;
2013 gboolean has_after_previous;
2014 gboolean has_after_next;
2016 notebook = GTK_NOTEBOOK (widget);
2018 gtk_widget_style_get (widget,
2019 "has_backward_stepper", &has_before_previous,
2020 "has_secondary_forward_stepper", &has_before_next,
2021 "has_secondary_backward_stepper", &has_after_previous,
2022 "has_forward_stepper", &has_after_next,
2025 notebook->has_before_previous = has_before_previous;
2026 notebook->has_before_next = has_before_next;
2027 notebook->has_after_previous = has_after_previous;
2028 notebook->has_after_next = has_after_next;
2030 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2033 /* Private GtkContainer Methods :
2035 * gtk_notebook_set_child_arg
2036 * gtk_notebook_get_child_arg
2038 * gtk_notebook_remove
2039 * gtk_notebook_focus
2040 * gtk_notebook_set_focus_child
2041 * gtk_notebook_child_type
2042 * gtk_notebook_forall
2045 gtk_notebook_set_child_property (GtkContainer *container,
2048 const GValue *value,
2053 GtkPackType pack_type;
2055 /* not finding child's page is valid for menus or labels */
2056 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2059 switch (property_id)
2061 case CHILD_PROP_TAB_LABEL:
2062 /* a NULL pointer indicates a default_tab setting, otherwise
2063 * we need to set the associated label
2065 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2066 g_value_get_string (value));
2068 case CHILD_PROP_MENU_LABEL:
2069 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2070 g_value_get_string (value));
2072 case CHILD_PROP_POSITION:
2073 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2074 g_value_get_int (value));
2076 case CHILD_PROP_TAB_EXPAND:
2077 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2078 &expand, &fill, &pack_type);
2079 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2080 g_value_get_boolean (value),
2083 case CHILD_PROP_TAB_FILL:
2084 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2085 &expand, &fill, &pack_type);
2086 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2088 g_value_get_boolean (value),
2091 case CHILD_PROP_TAB_PACK:
2092 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2093 &expand, &fill, &pack_type);
2094 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2096 g_value_get_enum (value));
2099 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2105 gtk_notebook_get_child_property (GtkContainer *container,
2112 GtkNotebook *notebook;
2116 GtkPackType pack_type;
2118 notebook = GTK_NOTEBOOK (container);
2120 /* not finding child's page is valid for menus or labels */
2121 list = gtk_notebook_find_child (notebook, child, NULL);
2124 /* nothing to set on labels or menus */
2125 g_param_value_set_default (pspec, value);
2129 switch (property_id)
2131 case CHILD_PROP_TAB_LABEL:
2132 label = gtk_notebook_get_tab_label (notebook, child);
2134 if (label && GTK_IS_LABEL (label))
2135 g_value_set_string (value, GTK_LABEL (label)->label);
2137 g_value_set_string (value, NULL);
2139 case CHILD_PROP_MENU_LABEL:
2140 label = gtk_notebook_get_menu_label (notebook, child);
2142 if (label && GTK_IS_LABEL (label))
2143 g_value_set_string (value, GTK_LABEL (label)->label);
2145 g_value_set_string (value, NULL);
2147 case CHILD_PROP_POSITION:
2148 g_value_set_int (value, g_list_position (notebook->children, list));
2150 case CHILD_PROP_TAB_EXPAND:
2151 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2152 &expand, NULL, NULL);
2153 g_value_set_boolean (value, expand);
2155 case CHILD_PROP_TAB_FILL:
2156 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2158 g_value_set_boolean (value, fill);
2160 case CHILD_PROP_TAB_PACK:
2161 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2162 NULL, NULL, &pack_type);
2163 g_value_set_enum (value, pack_type);
2166 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2172 gtk_notebook_add (GtkContainer *container,
2175 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2177 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2182 gtk_notebook_remove (GtkContainer *container,
2185 GtkNotebook *notebook;
2186 GtkNotebookPage *page;
2189 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2190 g_return_if_fail (widget != NULL);
2192 notebook = GTK_NOTEBOOK (container);
2194 children = notebook->children;
2197 page = children->data;
2198 if (page->child == widget)
2200 gtk_notebook_real_remove (notebook, children, FALSE);
2203 children = children->next;
2208 focus_tabs_in (GtkNotebook *notebook)
2210 if (notebook->show_tabs && notebook->cur_page)
2212 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2214 gtk_notebook_switch_focus_tab (notebook,
2215 g_list_find (notebook->children,
2216 notebook->cur_page));
2225 focus_tabs_move (GtkNotebook *notebook,
2226 GtkDirectionType direction,
2227 gint search_direction)
2231 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2232 search_direction, TRUE);
2234 gtk_notebook_switch_focus_tab (notebook, new_page);
2236 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2242 focus_child_in (GtkNotebook *notebook,
2243 GtkDirectionType direction)
2245 if (notebook->cur_page)
2246 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2251 /* Focus in the notebook can either be on the pages, or on
2255 gtk_notebook_focus (GtkWidget *widget,
2256 GtkDirectionType direction)
2258 GtkWidget *old_focus_child;
2259 GtkNotebook *notebook;
2260 GtkDirectionType effective_direction;
2262 gboolean widget_is_focus;
2263 GtkContainer *container;
2265 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2267 container = GTK_CONTAINER (widget);
2268 notebook = GTK_NOTEBOOK (container);
2270 if (notebook->focus_out)
2272 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2276 widget_is_focus = gtk_widget_is_focus (widget);
2277 old_focus_child = container->focus_child;
2279 effective_direction = get_effective_direction (notebook, direction);
2281 if (old_focus_child) /* Focus on page child */
2283 if (gtk_widget_child_focus (old_focus_child, direction))
2286 switch (effective_direction)
2288 case GTK_DIR_TAB_BACKWARD:
2290 /* Focus onto the tabs */
2291 return focus_tabs_in (notebook);
2293 case GTK_DIR_TAB_FORWARD:
2299 else if (widget_is_focus) /* Focus was on tabs */
2301 switch (effective_direction)
2303 case GTK_DIR_TAB_BACKWARD:
2306 case GTK_DIR_TAB_FORWARD:
2308 /* We use TAB_FORWARD rather than direction so that we focus a more
2309 * predictable widget for the user; users may be using arrow focusing
2310 * in this situation even if they don't usually use arrow focusing.
2312 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2314 return focus_tabs_move (notebook, direction, STEP_PREV);
2316 return focus_tabs_move (notebook, direction, STEP_NEXT);
2319 else /* Focus was not on widget */
2321 switch (effective_direction)
2323 case GTK_DIR_TAB_FORWARD:
2325 if (focus_tabs_in (notebook))
2327 if (focus_child_in (notebook, direction))
2330 case GTK_DIR_TAB_BACKWARD:
2332 if (focus_child_in (notebook, direction))
2334 if (focus_tabs_in (notebook))
2339 return focus_child_in (notebook, direction);
2343 g_assert_not_reached ();
2348 gtk_notebook_set_focus_child (GtkContainer *container,
2351 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2352 GtkWidget *page_child;
2353 GtkWidget *toplevel;
2355 /* If the old focus widget was within a page of the notebook,
2356 * (child may either be NULL or not in this case), record it
2357 * for future use if we switch to the page with a mnemonic.
2360 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2361 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2363 page_child = GTK_WINDOW (toplevel)->focus_widget;
2366 if (page_child->parent == GTK_WIDGET (container))
2368 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2371 GtkNotebookPage *page = list->data;
2373 if (page->last_focus_child)
2374 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2376 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2377 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2383 page_child = page_child->parent;
2389 g_return_if_fail (GTK_IS_WIDGET (child));
2391 notebook->child_has_focus = TRUE;
2392 if (!notebook->focus_tab)
2395 GtkNotebookPage *page;
2397 children = notebook->children;
2400 page = children->data;
2401 if (page->child == child || page->tab_label == child)
2402 gtk_notebook_switch_focus_tab (notebook, children);
2403 children = children->next;
2408 parent_class->set_focus_child (container, child);
2412 gtk_notebook_forall (GtkContainer *container,
2413 gboolean include_internals,
2414 GtkCallback callback,
2415 gpointer callback_data)
2417 GtkNotebook *notebook;
2420 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2421 g_return_if_fail (callback != NULL);
2423 notebook = GTK_NOTEBOOK (container);
2425 children = notebook->children;
2428 GtkNotebookPage *page;
2430 page = children->data;
2431 children = children->next;
2432 (* callback) (page->child, callback_data);
2433 if (include_internals)
2435 if (page->tab_label)
2436 (* callback) (page->tab_label, callback_data);
2442 gtk_notebook_child_type (GtkContainer *container)
2444 return GTK_TYPE_WIDGET;
2447 /* Private GtkNotebook Functions:
2449 * gtk_notebook_redraw_tabs
2450 * gtk_notebook_real_remove
2451 * gtk_notebook_update_labels
2452 * gtk_notebook_timer
2453 * gtk_notebook_page_compare
2454 * gtk_notebook_real_page_position
2455 * gtk_notebook_search_page
2458 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2461 GtkNotebookPage *page;
2462 GdkRectangle redraw_rect;
2464 gint tab_pos = get_effective_tab_pos (notebook);
2466 widget = GTK_WIDGET (notebook);
2467 border = GTK_CONTAINER (notebook)->border_width;
2469 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2472 page = notebook->first_tab->data;
2474 redraw_rect.x = border;
2475 redraw_rect.y = border;
2479 case GTK_POS_BOTTOM:
2480 redraw_rect.y = (widget->allocation.height - border -
2481 page->allocation.height -
2482 widget->style->ythickness);
2483 if (page != notebook->cur_page)
2484 redraw_rect.y -= widget->style->ythickness;
2487 redraw_rect.width = widget->allocation.width - 2 * border;
2488 redraw_rect.height = (page->allocation.height +
2489 widget->style->ythickness);
2490 if (page != notebook->cur_page)
2491 redraw_rect.height += widget->style->ythickness;
2494 redraw_rect.x = (widget->allocation.width - border -
2495 page->allocation.width -
2496 widget->style->xthickness);
2497 if (page != notebook->cur_page)
2498 redraw_rect.x -= widget->style->xthickness;
2501 redraw_rect.width = (page->allocation.width +
2502 widget->style->xthickness);
2503 redraw_rect.height = widget->allocation.height - 2 * border;
2504 if (page != notebook->cur_page)
2505 redraw_rect.width += widget->style->xthickness;
2509 redraw_rect.x += widget->allocation.x;
2510 redraw_rect.y += widget->allocation.y;
2512 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2516 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2518 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2522 GtkNotebookArrow arrow[4];
2524 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2525 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2526 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2527 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2529 for (i = 0; i < 4; i++)
2531 if (arrow[i] == ARROW_NONE)
2534 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2535 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2542 gtk_notebook_timer (GtkNotebook *notebook)
2544 gboolean retval = FALSE;
2546 GDK_THREADS_ENTER ();
2548 if (notebook->timer)
2550 gtk_notebook_do_arrow (notebook, notebook->click_child);
2552 if (notebook->need_timer)
2554 notebook->need_timer = FALSE;
2555 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2556 (GSourceFunc) gtk_notebook_timer,
2557 (gpointer) notebook);
2563 GDK_THREADS_LEAVE ();
2569 gtk_notebook_page_compare (gconstpointer a,
2572 return (((GtkNotebookPage *) a)->child != b);
2576 gtk_notebook_find_child (GtkNotebook *notebook,
2578 const gchar *function)
2580 GList *list = g_list_find_custom (notebook->children, child,
2581 gtk_notebook_page_compare);
2583 #ifndef G_DISABLE_CHECKS
2584 if (!list && function)
2585 g_warning ("%s: unable to find child %p in notebook %p",
2586 function, child, notebook);
2593 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2594 GtkNotebookPage *page)
2596 if (page->tab_label)
2598 if (page->mnemonic_activate_signal)
2599 g_signal_handler_disconnect (page->tab_label,
2600 page->mnemonic_activate_signal);
2601 page->mnemonic_activate_signal = 0;
2603 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2604 gtk_widget_unparent (page->tab_label);
2609 gtk_notebook_real_remove (GtkNotebook *notebook,
2611 gboolean destroying)
2613 GtkNotebookPage *page;
2615 gint need_resize = FALSE;
2617 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2619 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2621 if (notebook->cur_page == list->data)
2623 notebook->cur_page = NULL;
2624 if (next_list && !destroying)
2625 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2628 if (list == notebook->first_tab)
2629 notebook->first_tab = next_list;
2630 if (list == notebook->focus_tab && !destroying)
2631 gtk_notebook_switch_focus_tab (notebook, next_list);
2635 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2638 gtk_widget_unparent (page->child);
2640 gtk_notebook_remove_tab_label (notebook, page);
2644 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2645 page->menu_label->parent);
2646 gtk_widget_queue_resize (notebook->menu);
2648 if (!page->default_menu)
2649 g_object_unref (page->menu_label);
2651 notebook->children = g_list_remove_link (notebook->children, list);
2654 if (page->last_focus_child)
2656 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2657 page->last_focus_child = NULL;
2662 gtk_notebook_update_labels (notebook);
2664 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2668 gtk_notebook_update_labels (GtkNotebook *notebook)
2670 GtkNotebookPage *page;
2675 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2677 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2680 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2681 if (notebook->show_tabs)
2683 if (page->default_tab)
2685 if (!page->tab_label)
2687 page->tab_label = gtk_label_new (string);
2688 gtk_widget_set_parent (page->tab_label,
2689 GTK_WIDGET (notebook));
2692 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2695 if (GTK_WIDGET_VISIBLE (page->child) &&
2696 !GTK_WIDGET_VISIBLE (page->tab_label))
2697 gtk_widget_show (page->tab_label);
2698 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2699 GTK_WIDGET_VISIBLE (page->tab_label))
2700 gtk_widget_hide (page->tab_label);
2702 if (notebook->menu && page->default_menu)
2704 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2705 gtk_label_set_text (GTK_LABEL (page->menu_label),
2706 GTK_LABEL (page->tab_label)->label);
2708 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2714 gtk_notebook_real_page_position (GtkNotebook *notebook,
2720 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2721 g_return_val_if_fail (list != NULL, -1);
2723 for (work = notebook->children, count_start = 0;
2724 work && work != list; work = work->next)
2725 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2731 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2734 return (count_start + g_list_length (list) - 1);
2738 gtk_notebook_search_page (GtkNotebook *notebook,
2741 gboolean find_visible)
2743 GtkNotebookPage *page = NULL;
2744 GList *old_list = NULL;
2747 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2752 flag = GTK_PACK_END;
2756 flag = GTK_PACK_START;
2763 if (!page || page->pack == flag)
2771 list = notebook->children;
2776 if (page->pack == flag &&
2777 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2792 if (page->pack != flag &&
2793 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2801 /* Private GtkNotebook Drawing Functions:
2803 * gtk_notebook_paint
2804 * gtk_notebook_draw_tab
2805 * gtk_notebook_draw_arrow
2808 gtk_notebook_paint (GtkWidget *widget,
2811 GtkNotebook *notebook;
2812 GtkNotebookPage *page;
2817 gint border_width = GTK_CONTAINER (widget)->border_width;
2818 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2822 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2823 g_return_if_fail (area != NULL);
2825 if (!GTK_WIDGET_DRAWABLE (widget))
2828 notebook = GTK_NOTEBOOK (widget);
2829 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2830 tab_pos = get_effective_tab_pos (notebook);
2832 if ((!notebook->show_tabs && !notebook->show_border) ||
2833 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2836 x = widget->allocation.x + border_width;
2837 y = widget->allocation.y + border_width;
2838 width = widget->allocation.width - border_width * 2;
2839 height = widget->allocation.height - border_width * 2;
2841 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2843 gtk_paint_box (widget->style, widget->window,
2844 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2845 area, widget, "notebook",
2846 x, y, width, height);
2851 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2853 page = notebook->first_tab->data;
2858 y += page->allocation.height + widget->style->ythickness;
2859 case GTK_POS_BOTTOM:
2860 height -= page->allocation.height + widget->style->ythickness;
2863 x += page->allocation.width + widget->style->xthickness;
2865 width -= page->allocation.width + widget->style->xthickness;
2868 gtk_paint_box (widget->style, widget->window,
2869 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2870 area, widget, "notebook",
2871 x, y, width, height);
2878 y += notebook->cur_page->allocation.height;
2879 case GTK_POS_BOTTOM:
2880 height -= notebook->cur_page->allocation.height;
2883 x += notebook->cur_page->allocation.width;
2885 width -= notebook->cur_page->allocation.width;
2892 case GTK_POS_BOTTOM:
2893 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2894 gap_width = notebook->cur_page->allocation.width;
2895 step = is_rtl ? STEP_NEXT : STEP_PREV;
2899 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2900 gap_width = notebook->cur_page->allocation.height;
2904 gtk_paint_box_gap (widget->style, widget->window,
2905 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2906 area, widget, "notebook",
2907 x, y, width, height,
2908 tab_pos, gap_x, gap_width);
2912 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2915 page = children->data;
2916 children = gtk_notebook_search_page (notebook, children,
2918 if (!GTK_WIDGET_VISIBLE (page->child))
2920 if (!GTK_WIDGET_MAPPED (page->tab_label))
2922 else if (page != notebook->cur_page)
2923 gtk_notebook_draw_tab (notebook, page, area);
2926 if (showarrow && notebook->scrollable)
2928 if (notebook->has_before_previous)
2929 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2930 if (notebook->has_before_next)
2931 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2932 if (notebook->has_after_previous)
2933 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2934 if (notebook->has_after_next)
2935 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2937 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2941 gtk_notebook_draw_tab (GtkNotebook *notebook,
2942 GtkNotebookPage *page,
2945 GdkRectangle child_area;
2946 GdkRectangle page_area;
2947 GtkStateType state_type;
2948 GtkPositionType gap_side;
2949 gint tab_pos = get_effective_tab_pos (notebook);
2951 g_return_if_fail (notebook != NULL);
2952 g_return_if_fail (page != NULL);
2953 g_return_if_fail (area != NULL);
2955 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2956 (page->allocation.width == 0) || (page->allocation.height == 0))
2959 page_area.x = page->allocation.x;
2960 page_area.y = page->allocation.y;
2961 page_area.width = page->allocation.width;
2962 page_area.height = page->allocation.height;
2964 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2968 widget = GTK_WIDGET (notebook);
2973 gap_side = GTK_POS_BOTTOM;
2975 case GTK_POS_BOTTOM:
2976 gap_side = GTK_POS_TOP;
2979 gap_side = GTK_POS_RIGHT;
2982 gap_side = GTK_POS_LEFT;
2986 if (notebook->cur_page == page)
2987 state_type = GTK_STATE_NORMAL;
2989 state_type = GTK_STATE_ACTIVE;
2990 gtk_paint_extension(widget->style, widget->window,
2991 state_type, GTK_SHADOW_OUT,
2992 area, widget, "tab",
2993 page_area.x, page_area.y,
2994 page_area.width, page_area.height,
2996 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2997 notebook->focus_tab && (notebook->focus_tab->data == page))
3001 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3003 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3004 area, widget, "tab",
3005 page->tab_label->allocation.x - focus_width,
3006 page->tab_label->allocation.y - focus_width,
3007 page->tab_label->allocation.width + 2 * focus_width,
3008 page->tab_label->allocation.height + 2 * focus_width);
3010 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3011 GTK_WIDGET_DRAWABLE (page->tab_label))
3013 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3015 /* This is a lame hack since all this code needs rewriting anyhow */
3017 expose_event->expose.window = g_object_ref (page->tab_label->window);
3018 expose_event->expose.area = child_area;
3019 expose_event->expose.region = gdk_region_rectangle (&child_area);
3020 expose_event->expose.send_event = TRUE;
3021 expose_event->expose.count = 0;
3023 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3025 gdk_event_free (expose_event);
3031 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3032 GtkNotebookArrow nbarrow)
3034 GtkStateType state_type;
3035 GtkShadowType shadow_type;
3037 GdkRectangle arrow_rect;
3039 gboolean is_rtl, left;
3041 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3043 widget = GTK_WIDGET (notebook);
3045 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3046 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3047 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3049 if (GTK_WIDGET_DRAWABLE (notebook))
3051 if (notebook->in_child == nbarrow)
3053 if (notebook->click_child == nbarrow)
3054 state_type = GTK_STATE_ACTIVE;
3056 state_type = GTK_STATE_PRELIGHT;
3059 state_type = GTK_WIDGET_STATE (widget);
3061 if (notebook->click_child == nbarrow)
3062 shadow_type = GTK_SHADOW_IN;
3064 shadow_type = GTK_SHADOW_OUT;
3066 if (notebook->focus_tab &&
3067 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3068 left? STEP_PREV : STEP_NEXT, TRUE))
3070 shadow_type = GTK_SHADOW_ETCHED_IN;
3071 state_type = GTK_STATE_INSENSITIVE;
3074 if (notebook->tab_pos == GTK_POS_LEFT ||
3075 notebook->tab_pos == GTK_POS_RIGHT)
3076 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3078 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3080 gtk_paint_arrow (widget->style, widget->window, state_type,
3081 shadow_type, NULL, widget, "notebook",
3082 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3083 ARROW_SIZE, ARROW_SIZE);
3087 /* Private GtkNotebook Size Allocate Functions:
3089 * gtk_notebook_pages_allocate
3090 * gtk_notebook_page_allocate
3091 * gtk_notebook_calc_tabs
3094 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3096 GtkWidget *widget = GTK_WIDGET (notebook);
3097 GtkContainer *container = GTK_CONTAINER (notebook);
3098 GtkNotebookPage *page = NULL;
3099 GtkAllocation *allocation = &widget->allocation;
3100 GtkAllocation child_allocation;
3101 GList *children = NULL;
3102 GList *last_child = NULL;
3103 gboolean showarrow = FALSE;
3110 gint tab_pos = get_effective_tab_pos (notebook);
3111 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3112 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3115 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3118 child_allocation.x = widget->allocation.x + container->border_width;
3119 child_allocation.y = widget->allocation.y + container->border_width;
3123 case GTK_POS_BOTTOM:
3124 child_allocation.y = (widget->allocation.y +
3125 allocation->height -
3126 notebook->cur_page->requisition.height -
3127 container->border_width);
3130 child_allocation.height = notebook->cur_page->requisition.height;
3134 child_allocation.x = (widget->allocation.x +
3136 notebook->cur_page->requisition.width -
3137 container->border_width);
3140 child_allocation.width = notebook->cur_page->requisition.width;
3144 if (notebook->scrollable)
3148 children = notebook->children;
3150 if (notebook->focus_tab)
3151 focus_tab = notebook->focus_tab;
3152 else if (notebook->first_tab)
3153 focus_tab = notebook->first_tab;
3155 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3160 case GTK_POS_BOTTOM:
3163 page = children->data;
3164 children = children->next;
3166 if (GTK_WIDGET_VISIBLE (page->child))
3167 tab_space += page->requisition.width;
3170 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3173 page = focus_tab->data;
3175 tab_space = allocation->width - TAB_OVERLAP -
3176 page->requisition.width - 2 * container->border_width;
3177 if (notebook->has_after_previous)
3178 tab_space -= ARROW_SPACING + ARROW_SIZE;
3179 if (notebook->has_after_next)
3180 tab_space -= ARROW_SPACING + ARROW_SIZE;
3181 if (notebook->has_before_previous)
3183 tab_space -= ARROW_SPACING + ARROW_SIZE;
3184 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3186 if (notebook->has_before_next)
3188 tab_space -= ARROW_SPACING + ARROW_SIZE;
3189 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3197 page = children->data;
3198 children = children->next;
3200 if (GTK_WIDGET_VISIBLE (page->child))
3201 tab_space += page->requisition.height;
3204 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3207 page = focus_tab->data;
3208 tab_space = allocation->height
3209 - TAB_OVERLAP - 2 * container->border_width
3210 - page->requisition.height;
3211 if (notebook->has_after_previous || notebook->has_after_next)
3212 tab_space -= ARROW_SPACING + ARROW_SIZE;
3213 if (notebook->has_before_previous || notebook->has_before_next)
3215 tab_space -= ARROW_SPACING + ARROW_SIZE;
3216 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3221 if (showarrow) /* first_tab <- focus_tab */
3225 notebook->first_tab = focus_tab;
3226 last_child = gtk_notebook_search_page (notebook, focus_tab,
3232 if (notebook->first_tab && notebook->first_tab != focus_tab)
3234 /* Is first_tab really predecessor of focus_tab ? */
3235 page = notebook->first_tab->data;
3236 if (GTK_WIDGET_VISIBLE (page->child))
3237 for (children = focus_tab;
3238 children && children != notebook->first_tab;
3239 children = gtk_notebook_search_page (notebook,
3245 notebook->first_tab = focus_tab;
3247 gtk_notebook_calc_tabs (notebook,
3248 gtk_notebook_search_page (notebook,
3252 &(notebook->first_tab), &tab_space,
3257 notebook->first_tab =
3258 gtk_notebook_search_page (notebook, notebook->first_tab,
3260 if (!notebook->first_tab)
3261 notebook->first_tab = focus_tab;
3262 last_child = gtk_notebook_search_page (notebook, focus_tab,
3265 else /* focus_tab -> end */
3267 if (!notebook->first_tab)
3268 notebook->first_tab = gtk_notebook_search_page (notebook,
3273 gtk_notebook_calc_tabs (notebook,
3274 gtk_notebook_search_page (notebook,
3278 &children, &tab_space, STEP_NEXT);
3281 last_child = children;
3282 else /* start <- first_tab */
3286 gtk_notebook_calc_tabs
3288 gtk_notebook_search_page (notebook,
3289 notebook->first_tab,
3292 &children, &tab_space, STEP_PREV);
3293 notebook->first_tab = gtk_notebook_search_page(notebook,
3303 tab_space = -tab_space;
3305 for (children = notebook->first_tab;
3306 children && children != last_child;
3307 children = gtk_notebook_search_page (notebook, children,
3314 /*unmap all non-visible tabs*/
3315 for (children = gtk_notebook_search_page (notebook, NULL,
3317 children && children != notebook->first_tab;
3318 children = gtk_notebook_search_page (notebook, children,
3321 page = children->data;
3322 if (page->tab_label)
3323 gtk_widget_set_child_visible (page->tab_label, FALSE);
3325 for (children = last_child; children;
3326 children = gtk_notebook_search_page (notebook, children,
3329 page = children->data;
3330 if (page->tab_label)
3331 gtk_widget_set_child_visible (page->tab_label, FALSE);
3334 else /* !showarrow */
3336 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3347 children = notebook->children;
3351 case GTK_POS_BOTTOM:
3354 page = children->data;
3355 children = children->next;
3357 if (GTK_WIDGET_VISIBLE (page->child))
3360 tab_space += page->requisition.width;
3365 tab_space -= allocation->width;
3371 page = children->data;
3372 children = children->next;
3374 if (GTK_WIDGET_VISIBLE (page->child))
3377 tab_space += page->requisition.height;
3382 tab_space -= allocation->height;
3384 tab_space += 2 * container->border_width + TAB_OVERLAP;
3386 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3388 if (notebook->homogeneous && n)
3392 children = notebook->first_tab;
3395 memo_x = child_allocation.x;
3396 if (notebook->children && is_rtl)
3398 child_allocation.x = (allocation->x + allocation->width -
3399 container->border_width);
3402 if (notebook->has_after_previous)
3403 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3404 if (notebook->has_after_next)
3405 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3411 if (children == last_child)
3413 /* FIXME double check */
3417 page = children->data;
3418 if (!showarrow && page->pack != GTK_PACK_START)
3420 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3423 if (n && (showarrow || page->expand || notebook->homogeneous))
3425 new_fill = (tab_space * i++) / n;
3426 delta = new_fill - old_fill;
3427 old_fill = new_fill;
3433 case GTK_POS_BOTTOM:
3434 child_allocation.width = (page->requisition.width +
3435 TAB_OVERLAP + delta);
3437 child_allocation.x -= child_allocation.width;
3441 child_allocation.height = (page->requisition.height +
3442 TAB_OVERLAP + delta);
3446 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3451 case GTK_POS_BOTTOM:
3453 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3455 child_allocation.x += TAB_OVERLAP;
3459 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3463 if (page->tab_label)
3464 gtk_widget_set_child_visible (page->tab_label, TRUE);
3469 children = notebook->children;
3474 case GTK_POS_BOTTOM:
3476 child_allocation.x = (allocation->x + allocation->width -
3477 container->border_width);
3479 child_allocation.x = memo_x;
3483 child_allocation.y = (allocation->y + allocation->height -
3484 container->border_width);
3488 while (children != last_child)
3490 page = children->data;
3491 children = children->next;
3493 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3497 if (n && (page->expand || notebook->homogeneous))
3499 new_fill = (tab_space * i++) / n;
3500 delta = new_fill - old_fill;
3501 old_fill = new_fill;
3507 case GTK_POS_BOTTOM:
3508 child_allocation.width = (page->requisition.width +
3509 TAB_OVERLAP + delta);
3511 child_allocation.x -= child_allocation.width;
3515 child_allocation.height = (page->requisition.height +
3516 TAB_OVERLAP + delta);
3517 child_allocation.y -= child_allocation.height;
3521 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3526 case GTK_POS_BOTTOM:
3528 child_allocation.x += TAB_OVERLAP;
3530 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3534 child_allocation.y += TAB_OVERLAP;
3538 if (page->tab_label)
3539 gtk_widget_set_child_visible (page->tab_label, TRUE);
3544 gtk_notebook_redraw_tabs (notebook);
3548 gtk_notebook_page_allocate (GtkNotebook *notebook,
3549 GtkNotebookPage *page,
3550 GtkAllocation *allocation)
3552 GtkWidget *widget = GTK_WIDGET (notebook);
3553 GtkAllocation child_allocation;
3554 GtkRequisition tab_requisition;
3559 gint tab_pos = get_effective_tab_pos (notebook);
3561 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3563 xthickness = widget->style->xthickness;
3564 ythickness = widget->style->ythickness;
3566 /* If the size of the notebook tabs change, we need to queue
3567 * a redraw on the tab area
3569 if ((allocation->width != page->allocation.width) ||
3570 (allocation->height != page->allocation.height))
3572 gint x, y, width, height, border_width;
3574 border_width = GTK_CONTAINER (notebook)->border_width;
3579 width = widget->allocation.width;
3580 height = MAX (page->allocation.height, allocation->height) + ythickness;
3585 case GTK_POS_BOTTOM:
3586 width = widget->allocation.width + xthickness;
3587 height = MAX (page->allocation.height, allocation->height) + ythickness;
3589 y = widget->allocation.height - height - border_width;
3593 width = MAX (page->allocation.width, allocation->width) + xthickness;
3594 height = widget->allocation.height;
3600 default: /* quiet gcc */
3601 width = MAX (page->allocation.width, allocation->width) + xthickness;
3602 height = widget->allocation.height;
3603 x = widget->allocation.width - width - border_width;
3608 gtk_widget_queue_draw_area (widget, x, y, width, height);
3611 page->allocation = *allocation;
3612 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3614 if (notebook->cur_page != page)
3619 page->allocation.y += ythickness;
3620 case GTK_POS_BOTTOM:
3621 if (page->allocation.height > ythickness)
3622 page->allocation.height -= ythickness;
3625 page->allocation.x += xthickness;
3627 if (page->allocation.width > xthickness)
3628 page->allocation.width -= xthickness;
3636 case GTK_POS_BOTTOM:
3637 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3640 child_allocation.x = (xthickness + focus_width +
3641 notebook->tab_hborder);
3642 child_allocation.width = MAX (1, (page->allocation.width -
3643 2 * child_allocation.x));
3644 child_allocation.x += page->allocation.x;
3648 child_allocation.x = (page->allocation.x +
3649 (page->allocation.width -
3650 tab_requisition.width) / 2);
3651 child_allocation.width = tab_requisition.width;
3653 child_allocation.y = (notebook->tab_vborder + focus_width +
3654 page->allocation.y);
3655 if (tab_pos == GTK_POS_TOP)
3656 child_allocation.y += ythickness;
3657 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3658 2 * (notebook->tab_vborder + focus_width)));
3662 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3665 child_allocation.y = ythickness + padding;
3666 child_allocation.height = MAX (1, (page->allocation.height -
3667 2 * child_allocation.y));
3668 child_allocation.y += page->allocation.y;
3672 child_allocation.y = (page->allocation.y + (page->allocation.height -
3673 tab_requisition.height) / 2);
3674 child_allocation.height = tab_requisition.height;
3676 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3677 if (tab_pos == GTK_POS_LEFT)
3678 child_allocation.x += xthickness;
3679 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3680 2 * (notebook->tab_hborder + focus_width)));
3684 if (page->tab_label)
3685 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3689 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3695 GtkNotebookPage *page = NULL;
3697 GList *last_list = NULL;
3699 gint tab_pos = get_effective_tab_pos (notebook);
3705 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3706 if (pack == GTK_PACK_END)
3707 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3714 case GTK_POS_BOTTOM:
3717 page = children->data;
3718 if (GTK_WIDGET_VISIBLE (page->child))
3720 if (page->pack == pack)
3722 *tab_space -= page->requisition.width;
3723 if (*tab_space < 0 || children == *end)
3727 *tab_space = - (*tab_space +
3728 page->requisition.width);
3734 last_list = children;
3736 if (direction == STEP_NEXT)
3737 children = children->next;
3739 children = children->prev;
3746 page = children->data;
3747 if (GTK_WIDGET_VISIBLE (page->child))
3749 if (page->pack == pack)
3751 *tab_space -= page->requisition.height;
3752 if (*tab_space < 0 || children == *end)
3756 *tab_space = - (*tab_space +
3757 page->requisition.height);
3763 last_list = children;
3765 if (direction == STEP_NEXT)
3766 children = children->next;
3768 children = children->prev;
3772 if (direction == STEP_PREV)
3774 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3775 direction = STEP_PREV;
3776 children = last_list;
3781 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3785 for (list = notebook->children; list != NULL; list = list->next)
3787 GtkNotebookPage *page = list->data;
3789 if (page->tab_label)
3791 if (page == notebook->cur_page)
3792 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3794 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3799 /* Private GtkNotebook Page Switch Methods:
3801 * gtk_notebook_real_switch_page
3804 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3805 GtkNotebookPage *page,
3808 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3809 g_return_if_fail (page != NULL);
3811 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3814 if (notebook->cur_page)
3815 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3817 notebook->cur_page = page;
3819 if (!notebook->focus_tab ||
3820 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3821 notebook->focus_tab =
3822 g_list_find (notebook->children, notebook->cur_page);
3824 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3826 /* If the focus was on the previous page, move it to the first
3827 * element on the new page, if possible, or if not, to the
3830 if (notebook->child_has_focus)
3832 if (notebook->cur_page->last_focus_child &&
3833 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3834 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3836 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3837 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3840 gtk_notebook_update_tab_states (notebook);
3841 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3842 g_object_notify (G_OBJECT (notebook), "page");
3845 /* Private GtkNotebook Page Switch Functions:
3847 * gtk_notebook_switch_page
3848 * gtk_notebook_page_select
3849 * gtk_notebook_switch_focus_tab
3850 * gtk_notebook_menu_switch_page
3853 gtk_notebook_switch_page (GtkNotebook *notebook,
3854 GtkNotebookPage *page,
3857 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3858 g_return_if_fail (page != NULL);
3860 if (notebook->cur_page == page)
3864 page_num = g_list_index (notebook->children, page);
3866 g_signal_emit (notebook,
3867 notebook_signals[SWITCH_PAGE],
3874 gtk_notebook_page_select (GtkNotebook *notebook,
3875 gboolean move_focus)
3877 GtkNotebookPage *page;
3878 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3879 gint tab_pos = get_effective_tab_pos (notebook);
3881 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3883 if (!notebook->focus_tab)
3886 page = notebook->focus_tab->data;
3887 gtk_notebook_switch_page (notebook, page, -1);
3896 case GTK_POS_BOTTOM:
3900 dir = GTK_DIR_RIGHT;
3907 if (gtk_widget_child_focus (page->child, dir))
3914 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3918 GtkNotebookPage *old_page = NULL;
3919 GtkNotebookPage *page;
3921 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3923 if (notebook->focus_tab == new_child)
3926 old_child = notebook->focus_tab;
3927 notebook->focus_tab = new_child;
3929 if (notebook->scrollable)
3930 gtk_notebook_redraw_arrows (notebook);
3932 if (!notebook->show_tabs || !notebook->focus_tab)
3936 old_page = old_child->data;
3938 page = notebook->focus_tab->data;
3939 if (GTK_WIDGET_MAPPED (page->tab_label))
3940 gtk_notebook_redraw_tabs (notebook);
3942 gtk_notebook_pages_allocate (notebook);
3944 gtk_notebook_switch_page (notebook, page,
3945 g_list_index (notebook->children, page));
3949 gtk_notebook_menu_switch_page (GtkWidget *widget,
3950 GtkNotebookPage *page)
3952 GtkNotebook *notebook;
3956 g_return_if_fail (widget != NULL);
3957 g_return_if_fail (page != NULL);
3959 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3960 (GTK_MENU (widget->parent)));
3962 if (notebook->cur_page == page)
3966 children = notebook->children;
3967 while (children && children->data != page)
3969 children = children->next;
3973 g_signal_emit (notebook,
3974 notebook_signals[SWITCH_PAGE],
3980 /* Private GtkNotebook Menu Functions:
3982 * gtk_notebook_menu_item_create
3983 * gtk_notebook_menu_label_unparent
3984 * gtk_notebook_menu_detacher
3987 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3990 GtkNotebookPage *page;
3991 GtkWidget *menu_item;
3994 if (page->default_menu)
3996 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3997 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3999 page->menu_label = gtk_label_new ("");
4000 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
4003 gtk_widget_show (page->menu_label);
4004 menu_item = gtk_menu_item_new ();
4005 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
4006 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
4007 gtk_notebook_real_page_position (notebook, list));
4008 g_signal_connect (menu_item, "activate",
4009 G_CALLBACK (gtk_notebook_menu_switch_page), page);
4010 if (GTK_WIDGET_VISIBLE (page->child))
4011 gtk_widget_show (menu_item);
4015 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4018 gtk_widget_unparent (GTK_BIN(widget)->child);
4019 GTK_BIN(widget)->child = NULL;
4023 gtk_notebook_menu_detacher (GtkWidget *widget,
4026 GtkNotebook *notebook;
4028 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4030 notebook = GTK_NOTEBOOK (widget);
4031 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4033 notebook->menu = NULL;
4036 /* Private GtkNotebook Setter Functions:
4038 * gtk_notebook_set_homogeneous_tabs_internal
4039 * gtk_notebook_set_tab_border_internal
4040 * gtk_notebook_set_tab_hborder_internal
4041 * gtk_notebook_set_tab_vborder_internal
4044 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4045 gboolean homogeneous)
4047 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4049 if (homogeneous == notebook->homogeneous)
4052 notebook->homogeneous = homogeneous;
4053 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4055 g_object_notify (G_OBJECT (notebook), "homogeneous");
4059 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4062 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4064 notebook->tab_hborder = border_width;
4065 notebook->tab_vborder = border_width;
4067 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4068 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4070 g_object_freeze_notify (G_OBJECT (notebook));
4071 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4072 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4073 g_object_thaw_notify (G_OBJECT (notebook));
4077 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4080 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4082 if (notebook->tab_hborder == tab_hborder)
4085 notebook->tab_hborder = tab_hborder;
4087 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4088 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4090 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4094 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4097 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4099 if (notebook->tab_vborder == tab_vborder)
4102 notebook->tab_vborder = tab_vborder;
4104 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4105 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4107 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4110 /* Public GtkNotebook Page Insert/Remove Methods :
4112 * gtk_notebook_append_page
4113 * gtk_notebook_append_page_menu
4114 * gtk_notebook_prepend_page
4115 * gtk_notebook_prepend_page_menu
4116 * gtk_notebook_insert_page
4117 * gtk_notebook_insert_page_menu
4118 * gtk_notebook_remove_page
4121 * gtk_notebook_append_page:
4122 * @notebook: a #GtkNotebook
4123 * @child: the #GtkWidget to use as the contents of the page.
4124 * @tab_label: the #GtkWidget to be used as the label for the page,
4125 * or %NULL to use the default label, 'page N'.
4127 * Appends a page to @notebook.
4129 * Return value: the index (starting from 0) of the appended
4130 * page in the notebook, or -1 if function fails
4133 gtk_notebook_append_page (GtkNotebook *notebook,
4135 GtkWidget *tab_label)
4137 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4138 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4139 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4141 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4145 * gtk_notebook_append_page_menu:
4146 * @notebook: a #GtkNotebook
4147 * @child: the #GtkWidget to use as the contents of the page.
4148 * @tab_label: the #GtkWidget to be used as the label for the page,
4149 * or %NULL to use the default label, 'page N'.
4150 * @menu_label: the widget to use as a label for the page-switch
4151 * menu, if that is enabled. If %NULL, and @tab_label
4152 * is a #GtkLabel or %NULL, then the menu label will be
4153 * a newly created label with the same text as @tab_label;
4154 * If @tab_label is not a #GtkLabel, @menu_label must be
4155 * specified if the page-switch menu is to be used.
4157 * Appends a page to @notebook, specifying the widget to use as the
4158 * label in the popup menu.
4160 * Return value: the index (starting from 0) of the appended
4161 * page in the notebook, or -1 if function fails
4164 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4166 GtkWidget *tab_label,
4167 GtkWidget *menu_label)
4169 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4170 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4171 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4172 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4174 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4178 * gtk_notebook_prepend_page:
4179 * @notebook: a #GtkNotebook
4180 * @child: the #GtkWidget to use as the contents of the page.
4181 * @tab_label: the #GtkWidget to be used as the label for the page,
4182 * or %NULL to use the default label, 'page N'.
4184 * Prepends a page to @notebook.
4186 * Return value: the index (starting from 0) of the prepended
4187 * page in the notebook, or -1 if function fails
4190 gtk_notebook_prepend_page (GtkNotebook *notebook,
4192 GtkWidget *tab_label)
4194 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4195 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4196 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4198 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4202 * gtk_notebook_prepend_page_menu:
4203 * @notebook: a #GtkNotebook
4204 * @child: the #GtkWidget to use as the contents of the page.
4205 * @tab_label: the #GtkWidget to be used as the label for the page,
4206 * or %NULL to use the default label, 'page N'.
4207 * @menu_label: the widget to use as a label for the page-switch
4208 * menu, if that is enabled. If %NULL, and @tab_label
4209 * is a #GtkLabel or %NULL, then the menu label will be
4210 * a newly created label with the same text as @tab_label;
4211 * If @tab_label is not a #GtkLabel, @menu_label must be
4212 * specified if the page-switch menu is to be used.
4214 * Prepends a page to @notebook, specifying the widget to use as the
4215 * label in the popup menu.
4217 * Return value: the index (starting from 0) of the prepended
4218 * page in the notebook, or -1 if function fails
4221 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4223 GtkWidget *tab_label,
4224 GtkWidget *menu_label)
4226 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4227 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4228 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4229 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4231 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4235 * gtk_notebook_insert_page:
4236 * @notebook: a #GtkNotebook
4237 * @child: the #GtkWidget to use as the contents of the page.
4238 * @tab_label: the #GtkWidget to be used as the label for the page,
4239 * or %NULL to use the default label, 'page N'.
4240 * @position: the index (starting at 0) at which to insert the page,
4241 * or -1 to append the page after all other pages.
4243 * Insert a page into @notebook at the given position.
4245 * Return value: the index (starting from 0) of the inserted
4246 * page in the notebook, or -1 if function fails
4249 gtk_notebook_insert_page (GtkNotebook *notebook,
4251 GtkWidget *tab_label,
4254 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4255 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4256 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4258 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4263 gtk_notebook_page_compare_tab (gconstpointer a,
4266 return (((GtkNotebookPage *) a)->tab_label != b);
4270 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4274 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4277 list = g_list_find_custom (notebook->children, child,
4278 gtk_notebook_page_compare_tab);
4281 GtkNotebookPage *page = list->data;
4283 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4284 gtk_notebook_switch_page (notebook, page, -1);
4285 focus_tabs_in (notebook);
4292 * gtk_notebook_insert_page_menu:
4293 * @notebook: a #GtkNotebook
4294 * @child: the #GtkWidget to use as the contents of the page.
4295 * @tab_label: the #GtkWidget to be used as the label for the page,
4296 * or %NULL to use the default label, 'page N'.
4297 * @menu_label: the widget to use as a label for the page-switch
4298 * menu, if that is enabled. If %NULL, and @tab_label
4299 * is a #GtkLabel or %NULL, then the menu label will be
4300 * a newly created label with the same text as @tab_label;
4301 * If @tab_label is not a #GtkLabel, @menu_label must be
4302 * specified if the page-switch menu is to be used.
4303 * @position: the index (starting at 0) at which to insert the page,
4304 * or -1 to append the page after all other pages.
4306 * Insert a page into @notebook at the given position, specifying
4307 * the widget to use as the label in the popup menu.
4309 * Return value: the index (starting from 0) of the inserted
4310 * page in the notebook, or -1 if function fails
4313 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4315 GtkWidget *tab_label,
4316 GtkWidget *menu_label,
4319 GtkNotebookPage *page;
4322 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4323 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4324 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4325 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4327 gtk_widget_freeze_child_notify (child);
4329 page = g_new (GtkNotebookPage, 1);
4330 page->child = child;
4331 page->last_focus_child = NULL;
4332 page->requisition.width = 0;
4333 page->requisition.height = 0;
4334 page->allocation.x = 0;
4335 page->allocation.y = 0;
4336 page->allocation.width = 0;
4337 page->allocation.height = 0;
4338 page->default_menu = FALSE;
4339 page->default_tab = FALSE;
4340 page->mnemonic_activate_signal = 0;
4342 nchildren = g_list_length (notebook->children);
4343 if ((position < 0) || (position > nchildren))
4344 position = nchildren;
4346 notebook->children = g_list_insert (notebook->children, page, position);
4350 page->default_tab = TRUE;
4351 if (notebook->show_tabs)
4352 tab_label = gtk_label_new ("");
4354 page->tab_label = tab_label;
4355 page->menu_label = menu_label;
4356 page->expand = FALSE;
4358 page->pack = GTK_PACK_START;
4361 page->default_menu = TRUE;
4364 g_object_ref (page->menu_label);
4365 gtk_object_sink (GTK_OBJECT (page->menu_label));
4369 gtk_notebook_menu_item_create (notebook,
4370 g_list_find (notebook->children, page));
4372 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4374 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4376 gtk_notebook_update_labels (notebook);
4378 if (!notebook->first_tab)
4379 notebook->first_tab = notebook->children;
4381 if (!notebook->cur_page)
4382 gtk_widget_set_child_visible (child, TRUE);
4384 gtk_widget_set_child_visible (child, FALSE);
4388 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4389 gtk_widget_show (tab_label);
4391 gtk_widget_hide (tab_label);
4394 if (!notebook->cur_page)
4396 gtk_notebook_switch_page (notebook, page, 0);
4397 gtk_notebook_switch_focus_tab (notebook, NULL);
4400 gtk_notebook_update_tab_states (notebook);
4403 page->mnemonic_activate_signal =
4404 g_signal_connect (tab_label,
4405 "mnemonic_activate",
4406 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4409 gtk_widget_child_notify (child, "tab_expand");
4410 gtk_widget_child_notify (child, "tab_fill");
4411 gtk_widget_child_notify (child, "tab_pack");
4412 gtk_widget_child_notify (child, "tab_label");
4413 gtk_widget_child_notify (child, "menu_label");
4414 gtk_widget_child_notify (child, "position");
4415 gtk_widget_thaw_child_notify (child);
4421 * gtk_notebook_remove_page:
4422 * @notebook: a #GtkNotebook.
4423 * @page_num: the index of a notebook page, starting
4424 * from 0. If -1, the last page will
4427 * Removes a page from the notebook given its index
4431 gtk_notebook_remove_page (GtkNotebook *notebook,
4436 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4440 list = g_list_nth (notebook->children, page_num);
4442 gtk_notebook_real_remove (notebook, list, FALSE);
4446 list = g_list_last (notebook->children);
4448 gtk_notebook_real_remove (notebook, list, FALSE);
4452 /* Public GtkNotebook Page Switch Methods :
4453 * gtk_notebook_get_current_page
4454 * gtk_notebook_page_num
4455 * gtk_notebook_set_current_page
4456 * gtk_notebook_next_page
4457 * gtk_notebook_prev_page
4460 * gtk_notebook_get_current_page:
4461 * @notebook: a #GtkNotebook
4463 * Returns the page number of the current page.
4465 * Return value: the index (starting from 0) of the current
4466 * page in the notebook. If the notebook has no pages, then
4467 * -1 will be returned.
4470 gtk_notebook_get_current_page (GtkNotebook *notebook)
4472 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4474 if (!notebook->cur_page)
4477 return g_list_index (notebook->children, notebook->cur_page);
4481 * gtk_notebook_get_nth_page:
4482 * @notebook: a #GtkNotebook
4483 * @page_num: the index of a page in the noteobok, or -1
4484 * to get the last page.
4486 * Returns the child widget contained in page number @page_num.
4488 * Return value: the child widget, or %NULL if @page_num is
4492 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4495 GtkNotebookPage *page;
4498 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4501 list = g_list_nth (notebook->children, page_num);
4503 list = g_list_last (notebook->children);
4515 * gtk_notebook_get_n_pages:
4516 * @notebook: a #GtkNotebook
4518 * Gets the number of pages in a notebook.
4520 * Return value: the number of pages in the notebook.
4525 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4527 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4529 return g_list_length (notebook->children);
4533 * gtk_notebook_page_num:
4534 * @notebook: a #GtkNotebook
4535 * @child: a #GtkWidget
4537 * Finds the index of the page which contains the given child
4540 * Return value: the index of the page containing @child, or
4541 * -1 if @child is not in the notebook.
4544 gtk_notebook_page_num (GtkNotebook *notebook,
4550 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4553 children = notebook->children;
4556 GtkNotebookPage *page = children->data;
4558 if (page->child == child)
4561 children = children->next;
4569 * gtk_notebook_set_current_page:
4570 * @notebook: a #GtkNotebook
4571 * @page_num: index of the page to switch to, starting from 0.
4572 * If negative, the last page will be used. If greater
4573 * than the number of pages in the notebook, nothing
4576 * Switches to the page number @page_num.
4579 gtk_notebook_set_current_page (GtkNotebook *notebook,
4584 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4587 list = g_list_nth (notebook->children, page_num);
4589 list = g_list_last (notebook->children);
4591 page_num = g_list_index (notebook->children, list);
4594 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4598 * gtk_notebook_next_page:
4599 * @notebook: a #GtkNotebook
4601 * Switches to the next page. Nothing happens if the current page is
4605 gtk_notebook_next_page (GtkNotebook *notebook)
4609 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4611 list = g_list_find (notebook->children, notebook->cur_page);
4615 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4619 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4623 * gtk_notebook_prev_page:
4624 * @notebook: a #GtkNotebook
4626 * Switches to the previous page. Nothing happens if the current page
4627 * is the first page.
4630 gtk_notebook_prev_page (GtkNotebook *notebook)
4634 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4636 list = g_list_find (notebook->children, notebook->cur_page);
4640 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4644 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4647 /* Public GtkNotebook/Tab Style Functions
4649 * gtk_notebook_set_show_border
4650 * gtk_notebook_set_show_tabs
4651 * gtk_notebook_set_tab_pos
4652 * gtk_notebook_set_homogeneous_tabs
4653 * gtk_notebook_set_tab_border
4654 * gtk_notebook_set_tab_hborder
4655 * gtk_notebook_set_tab_vborder
4656 * gtk_notebook_set_scrollable
4659 * gtk_notebook_set_show_border:
4660 * @notebook: a #GtkNotebook
4661 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4663 * Sets whether a bevel will be drawn around the notebook pages.
4664 * This only has a visual effect when the tabs are not shown.
4665 * See gtk_notebook_set_show_tabs().
4668 gtk_notebook_set_show_border (GtkNotebook *notebook,
4669 gboolean show_border)
4671 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4673 if (notebook->show_border != show_border)
4675 notebook->show_border = show_border;
4677 if (GTK_WIDGET_VISIBLE (notebook))
4678 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4680 g_object_notify (G_OBJECT (notebook), "show_border");
4685 * gtk_notebook_get_show_border:
4686 * @notebook: a #GtkNotebook
4688 * Returns whether a bevel will be drawn around the notebook pages. See
4689 * gtk_notebook_set_show_border().
4691 * Return value: %TRUE if the bevel is drawn
4694 gtk_notebook_get_show_border (GtkNotebook *notebook)
4696 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4698 return notebook->show_border;
4702 * gtk_notebook_set_show_tabs:
4703 * @notebook: a #GtkNotebook
4704 * @show_tabs: %TRUE if the tabs should be shown.
4706 * Sets whether to show the tabs for the notebook or not.
4709 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4712 GtkNotebookPage *page;
4715 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4717 show_tabs = show_tabs != FALSE;
4719 if (notebook->show_tabs == show_tabs)
4722 notebook->show_tabs = show_tabs;
4723 children = notebook->children;
4727 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4731 page = children->data;
4732 children = children->next;
4733 if (page->default_tab)
4735 gtk_widget_destroy (page->tab_label);
4736 page->tab_label = NULL;
4739 gtk_widget_hide (page->tab_label);
4744 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4745 gtk_notebook_update_labels (notebook);
4747 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4749 g_object_notify (G_OBJECT (notebook), "show_tabs");
4753 * gtk_notebook_get_show_tabs:
4754 * @notebook: a #GtkNotebook
4756 * Returns whether the tabs of the notebook are shown. See
4757 * gtk_notebook_set_show_tabs().
4759 * Return value: %TRUE if the tabs are shown
4762 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4764 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4766 return notebook->show_tabs;
4770 * gtk_notebook_set_tab_pos:
4771 * @notebook: a #GtkNotebook.
4772 * @pos: the edge to draw the tabs at.
4774 * Sets the edge at which the tabs for switching pages in the
4775 * notebook are drawn.
4778 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4779 GtkPositionType pos)
4781 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4783 if (notebook->tab_pos != pos)
4785 notebook->tab_pos = pos;
4786 if (GTK_WIDGET_VISIBLE (notebook))
4787 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4790 g_object_notify (G_OBJECT (notebook), "tab_pos");
4794 * gtk_notebook_get_tab_pos:
4795 * @notebook: a #GtkNotebook
4797 * Gets the edge at which the tabs for switching pages in the
4798 * notebook are drawn.
4800 * Return value: the edge at which the tabs are drawn
4803 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4805 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4807 return notebook->tab_pos;
4811 * gtk_notebook_set_homogeneous_tabs:
4812 * @notebook: a #GtkNotebook
4813 * @homogeneous: %TRUE if all tabs should be the same size.
4815 * Sets whether the tabs must have all the same size or not.
4818 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4819 gboolean homogeneous)
4821 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4823 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4827 * gtk_notebook_set_tab_border:
4828 * @notebook: a #GtkNotebook
4829 * @border_width: width of the border around the tab labels.
4831 * Sets the width the border around the tab labels
4832 * in a notebook. This is equivalent to calling
4833 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4834 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4837 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4840 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4842 gtk_notebook_set_tab_border_internal (notebook, border_width);
4846 * gtk_notebook_set_tab_hborder:
4847 * @notebook: a #GtkNotebook
4848 * @tab_hborder: width of the horizontal border of tab labels.
4850 * Sets the width of the horizontal border of tab labels.
4853 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4856 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4858 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4862 * gtk_notebook_set_tab_vborder:
4863 * @notebook: a #GtkNotebook
4864 * @tab_vborder: width of the vertical border of tab labels.
4866 * Sets the width of the vertical border of tab labels.
4869 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4872 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4874 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4878 * gtk_notebook_set_scrollable:
4879 * @notebook: a #GtkNotebook
4880 * @scrollable: %TRUE if scroll arrows should be added
4882 * Sets whether the tab label area will have arrows for scrolling if
4883 * there are too many tabs to fit in the area.
4886 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4887 gboolean scrollable)
4889 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4891 scrollable = (scrollable != FALSE);
4893 if (scrollable != notebook->scrollable)
4895 notebook->scrollable = scrollable;
4897 if (GTK_WIDGET_VISIBLE (notebook))
4898 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4900 g_object_notify (G_OBJECT (notebook), "scrollable");
4905 * gtk_notebook_get_scrollable:
4906 * @notebook: a #GtkNotebook
4908 * Returns whether the tab label area has arrows for scrolling. See
4909 * gtk_notebook_set_scrollable().
4911 * Return value: %TRUE if arrows for scrolling are present
4914 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4916 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4918 return notebook->scrollable;
4921 /* Public GtkNotebook Popup Menu Methods:
4923 * gtk_notebook_popup_enable
4924 * gtk_notebook_popup_disable
4929 * gtk_notebook_popup_enable:
4930 * @notebook: a #GtkNotebook
4932 * Enables the popup menu: if the user clicks with the right mouse button on
4933 * the bookmarks, a menu with all the pages will be popped up.
4936 gtk_notebook_popup_enable (GtkNotebook *notebook)
4940 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4945 notebook->menu = gtk_menu_new ();
4946 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4948 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4949 gtk_notebook_menu_item_create (notebook, list);
4951 gtk_notebook_update_labels (notebook);
4952 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4953 GTK_WIDGET (notebook),
4954 gtk_notebook_menu_detacher);
4956 g_object_notify (G_OBJECT (notebook), "enable_popup");
4960 * gtk_notebook_popup_disable:
4961 * @notebook: a #GtkNotebook
4963 * Disables the popup menu.
4966 gtk_notebook_popup_disable (GtkNotebook *notebook)
4968 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4970 if (!notebook->menu)
4973 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4974 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4975 gtk_widget_destroy (notebook->menu);
4977 g_object_notify (G_OBJECT (notebook), "enable_popup");
4980 /* Public GtkNotebook Page Properties Functions:
4982 * gtk_notebook_get_tab_label
4983 * gtk_notebook_set_tab_label
4984 * gtk_notebook_set_tab_label_text
4985 * gtk_notebook_get_menu_label
4986 * gtk_notebook_set_menu_label
4987 * gtk_notebook_set_menu_label_text
4988 * gtk_notebook_set_tab_label_packing
4989 * gtk_notebook_query_tab_label_packing
4993 * gtk_notebook_get_tab_label:
4994 * @notebook: a #GtkNotebook
4997 * Returns the tab label widget for the page @child. %NULL is returned
4998 * if @child is not in @notebook or if no tab label has specifically
4999 * been set for @child.
5001 * Return value: the tab label
5004 gtk_notebook_get_tab_label (GtkNotebook *notebook,
5009 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5010 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5012 list = CHECK_FIND_CHILD (notebook, child);
5016 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5019 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5023 * gtk_notebook_set_tab_label:
5024 * @notebook: a #GtkNotebook
5026 * @tab_label: the tab label widget to use, or %NULL for default tab
5029 * Changes the tab label for @child. If %NULL is specified
5030 * for @tab_label, then the page will have the label 'page N'.
5033 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5035 GtkWidget *tab_label)
5037 GtkNotebookPage *page;
5040 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5041 g_return_if_fail (GTK_IS_WIDGET (child));
5043 list = CHECK_FIND_CHILD (notebook, child);
5047 /* a NULL pointer indicates a default_tab setting, otherwise
5048 * we need to set the associated label
5052 if (page->tab_label == tab_label)
5056 gtk_notebook_remove_tab_label (notebook, page);
5060 page->default_tab = FALSE;
5061 page->tab_label = tab_label;
5062 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5066 page->default_tab = TRUE;
5067 page->tab_label = NULL;
5069 if (notebook->show_tabs)
5073 g_snprintf (string, sizeof(string), _("Page %u"),
5074 gtk_notebook_real_page_position (notebook, list));
5075 page->tab_label = gtk_label_new (string);
5076 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5080 if (page->tab_label)
5081 page->mnemonic_activate_signal =
5082 g_signal_connect (page->tab_label,
5083 "mnemonic_activate",
5084 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5087 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5089 gtk_widget_show (page->tab_label);
5090 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5093 gtk_notebook_update_tab_states (notebook);
5094 gtk_widget_child_notify (child, "tab_label");
5098 * gtk_notebook_set_tab_label_text:
5099 * @notebook: a #GtkNotebook
5101 * @tab_text: the label text
5103 * Creates a new label and sets it as the tab label for the page
5104 * containing @child.
5107 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5109 const gchar *tab_text)
5111 GtkWidget *tab_label = NULL;
5113 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5116 tab_label = gtk_label_new (tab_text);
5117 gtk_notebook_set_tab_label (notebook, child, tab_label);
5118 gtk_widget_child_notify (child, "tab_label");
5122 * gtk_notebook_get_tab_label_text:
5123 * @notebook: a #GtkNotebook
5124 * @child: a widget contained in a page of @notebook
5126 * Retrieves the text of the tab label for the page containing
5129 * Returns value: the text of the tab label, or %NULL if the
5130 * tab label widget is not a #GtkLabel. The
5131 * string is owned by the widget and must not
5134 G_CONST_RETURN gchar *
5135 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5138 GtkWidget *tab_label;
5140 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5141 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5143 tab_label = gtk_notebook_get_tab_label (notebook, child);
5145 if (tab_label && GTK_IS_LABEL (tab_label))
5146 return gtk_label_get_text (GTK_LABEL (tab_label));
5152 * gtk_notebook_get_menu_label:
5153 * @notebook: a #GtkNotebook
5154 * @child: a widget contained in a page of @notebook
5156 * Retrieves the menu label widget of the page containing @child.
5158 * Return value: the menu label, or %NULL if the
5159 * notebook page does not have a menu label other
5160 * than the default (the tab label).
5163 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5168 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5169 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5171 list = CHECK_FIND_CHILD (notebook, child);
5175 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5178 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5182 * gtk_notebook_set_menu_label:
5183 * @notebook: a #GtkNotebook
5184 * @child: the child widget
5185 * @menu_label: the menu label, or NULL for default
5187 * Changes the menu label for the page containing @child.
5190 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5192 GtkWidget *menu_label)
5194 GtkNotebookPage *page;
5197 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5198 g_return_if_fail (GTK_IS_WIDGET (child));
5200 list = CHECK_FIND_CHILD (notebook, child);
5205 if (page->menu_label)
5208 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5209 page->menu_label->parent);
5211 if (!page->default_menu)
5212 g_object_unref (page->menu_label);
5217 page->menu_label = menu_label;
5218 g_object_ref (page->menu_label);
5219 gtk_object_sink (GTK_OBJECT(page->menu_label));
5220 page->default_menu = FALSE;
5223 page->default_menu = TRUE;
5226 gtk_notebook_menu_item_create (notebook, list);
5227 gtk_widget_child_notify (child, "menu_label");
5231 * gtk_notebook_set_menu_label_text:
5232 * @notebook: a #GtkNotebook
5233 * @child: the child widget
5234 * @menu_text: the label text
5236 * Creates a new label and sets it as the menu label of @child.
5239 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5241 const gchar *menu_text)
5243 GtkWidget *menu_label = NULL;
5245 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5248 menu_label = gtk_label_new (menu_text);
5249 gtk_notebook_set_menu_label (notebook, child, menu_label);
5250 gtk_widget_child_notify (child, "menu_label");
5254 * gtk_notebook_get_menu_label_text:
5255 * @notebook: a #GtkNotebook
5256 * @child: the child widget of a page of the notebook.
5258 * Retrieves the text of the menu label for the page containing
5261 * Returns value: the text of the tab label, or %NULL if the
5262 * widget does not have a menu label other than
5263 * the default menu label, or the menu label widget
5264 * is not a #GtkLabel. The string is owned by
5265 * the widget and must not be freed.
5267 G_CONST_RETURN gchar *
5268 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5271 GtkWidget *menu_label;
5273 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5274 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5276 menu_label = gtk_notebook_get_menu_label (notebook, child);
5278 if (menu_label && GTK_IS_LABEL (menu_label))
5279 return gtk_label_get_text (GTK_LABEL (menu_label));
5284 /* Helper function called when pages are reordered
5287 gtk_notebook_child_reordered (GtkNotebook *notebook,
5288 GtkNotebookPage *page)
5292 GtkWidget *menu_item;
5294 menu_item = page->menu_label->parent;
5295 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5296 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5297 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5300 gtk_notebook_update_tab_states (notebook);
5301 gtk_notebook_update_labels (notebook);
5305 * gtk_notebook_set_tab_label_packing:
5306 * @notebook: a #GtkNotebook
5307 * @child: the child widget
5308 * @expand: whether to expand the bookmark or not
5309 * @fill: whether the bookmark should fill the allocated area or not
5310 * @pack_type: the position of the bookmark
5312 * Sets the packing parameters for the tab label of the page
5313 * containing @child. See gtk_box_pack_start() for the exact meaning
5314 * of the parameters.
5317 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5321 GtkPackType pack_type)
5323 GtkNotebookPage *page;
5326 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5327 g_return_if_fail (GTK_IS_WIDGET (child));
5329 list = CHECK_FIND_CHILD (notebook, child);
5334 expand = expand != FALSE;
5335 fill = fill != FALSE;
5336 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5339 gtk_widget_freeze_child_notify (child);
5340 page->expand = expand;
5341 gtk_widget_child_notify (child, "tab_expand");
5343 gtk_widget_child_notify (child, "tab_fill");
5344 if (page->pack != pack_type)
5346 page->pack = pack_type;
5347 gtk_notebook_child_reordered (notebook, page);
5349 gtk_widget_child_notify (child, "tab_pack");
5350 gtk_widget_child_notify (child, "position");
5351 if (notebook->show_tabs)
5352 gtk_notebook_pages_allocate (notebook);
5353 gtk_widget_thaw_child_notify (child);
5357 * gtk_notebook_query_tab_label_packing:
5358 * @notebook: a #GtkNotebook
5360 * @expand: location to store the expand value (or NULL)
5361 * @fill: location to store the fill value (or NULL)
5362 * @pack_type: location to store the pack_type (or NULL)
5364 * Query the packing attributes for the tab label of the page
5365 * containing @child.
5368 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5372 GtkPackType *pack_type)
5376 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5377 g_return_if_fail (GTK_IS_WIDGET (child));
5379 list = CHECK_FIND_CHILD (notebook, child);
5384 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5386 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5388 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5392 * gtk_notebook_reorder_child:
5393 * @notebook: a #GtkNotebook
5394 * @child: the child to move
5395 * @position: the new position, or -1 to move to the end
5397 * Reorders the page containing @child, so that it appears in position
5398 * @position. If @position is greater than or equal to the number of
5399 * children in the list or negative, @child will be moved to the end
5403 gtk_notebook_reorder_child (GtkNotebook *notebook,
5407 GList *list, *new_list;
5408 GtkNotebookPage *page;
5412 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5413 g_return_if_fail (GTK_IS_WIDGET (child));
5415 list = CHECK_FIND_CHILD (notebook, child);
5419 max_pos = g_list_length (notebook->children) - 1;
5420 if (position < 0 || position > max_pos)
5423 old_pos = g_list_position (notebook->children, list);
5425 if (old_pos == position)
5429 notebook->children = g_list_delete_link (notebook->children, list);
5431 notebook->children = g_list_insert (notebook->children, page, position);
5432 new_list = g_list_nth (notebook->children, position);
5434 /* Fix up GList references in GtkNotebook structure */
5435 if (notebook->first_tab == list)
5436 notebook->first_tab = new_list;
5437 if (notebook->focus_tab == list)
5438 notebook->focus_tab = new_list;
5440 gtk_widget_freeze_child_notify (child);
5442 /* Move around the menu items if necessary */
5443 gtk_notebook_child_reordered (notebook, page);
5444 gtk_widget_child_notify (child, "tab_pack");
5445 gtk_widget_child_notify (child, "position");
5447 if (notebook->show_tabs)
5448 gtk_notebook_pages_allocate (notebook);
5450 gtk_widget_thaw_child_notify (child);