1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gtknotebook.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
36 #include "gtkmarshalers.h"
37 #include "gtkbindings.h"
41 #define TAB_CURVATURE 1
43 #define ARROW_SPACING 0
44 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
45 #define NOTEBOOK_SCROLL_DELAY (100)
71 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
72 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
91 CHILD_PROP_MENU_LABEL,
93 CHILD_PROP_TAB_EXPAND,
98 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
100 struct _GtkNotebookPage
103 GtkWidget *tab_label;
104 GtkWidget *menu_label;
105 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
107 guint default_menu : 1; /* If true, we create the menu label ourself */
108 guint default_tab : 1; /* If true, we create the tab label ourself */
113 GtkRequisition requisition;
114 GtkAllocation allocation;
116 guint mnemonic_activate_signal;
119 #ifdef G_DISABLE_CHECKS
120 #define CHECK_FIND_CHILD(notebook, child) \
121 gtk_notebook_find_child (notebook, child, G_STRLOC)
123 #define CHECK_FIND_CHILD(notebook, child) \
124 gtk_notebook_find_child (notebook, child, NULL)
127 /*** GtkNotebook Methods ***/
128 static void gtk_notebook_class_init (GtkNotebookClass *klass);
129 static void gtk_notebook_init (GtkNotebook *notebook);
131 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
132 gboolean move_focus);
133 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
134 GtkNotebookTab type);
135 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
137 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
138 GtkDirectionType direction_type);
140 /*** GtkObject Methods ***/
141 static void gtk_notebook_destroy (GtkObject *object);
142 static void gtk_notebook_set_property (GObject *object,
146 static void gtk_notebook_get_property (GObject *object,
151 /*** GtkWidget Methods ***/
152 static void gtk_notebook_map (GtkWidget *widget);
153 static void gtk_notebook_unmap (GtkWidget *widget);
154 static void gtk_notebook_realize (GtkWidget *widget);
155 static void gtk_notebook_unrealize (GtkWidget *widget);
156 static void gtk_notebook_size_request (GtkWidget *widget,
157 GtkRequisition *requisition);
158 static void gtk_notebook_size_allocate (GtkWidget *widget,
159 GtkAllocation *allocation);
160 static gint gtk_notebook_expose (GtkWidget *widget,
161 GdkEventExpose *event);
162 static gboolean gtk_notebook_scroll (GtkWidget *widget,
163 GdkEventScroll *event);
164 static gint gtk_notebook_button_press (GtkWidget *widget,
165 GdkEventButton *event);
166 static gint gtk_notebook_button_release (GtkWidget *widget,
167 GdkEventButton *event);
168 static gint gtk_notebook_enter_notify (GtkWidget *widget,
169 GdkEventCrossing *event);
170 static gint gtk_notebook_leave_notify (GtkWidget *widget,
171 GdkEventCrossing *event);
172 static gint gtk_notebook_motion_notify (GtkWidget *widget,
173 GdkEventMotion *event);
174 static gint gtk_notebook_focus_in (GtkWidget *widget,
175 GdkEventFocus *event);
176 static gint gtk_notebook_focus_out (GtkWidget *widget,
177 GdkEventFocus *event);
178 static void gtk_notebook_grab_notify (GtkWidget *widget,
179 gboolean was_grabbed);
180 static void gtk_notebook_state_changed (GtkWidget *widget,
181 GtkStateType previous_state);
182 static void gtk_notebook_draw_focus (GtkWidget *widget);
183 static gint gtk_notebook_focus (GtkWidget *widget,
184 GtkDirectionType direction);
185 static void gtk_notebook_style_set (GtkWidget *widget,
188 /*** GtkContainer Methods ***/
189 static void gtk_notebook_set_child_property (GtkContainer *container,
194 static void gtk_notebook_get_child_property (GtkContainer *container,
199 static void gtk_notebook_add (GtkContainer *container,
201 static void gtk_notebook_remove (GtkContainer *container,
203 static void gtk_notebook_set_focus_child (GtkContainer *container,
205 static GType gtk_notebook_child_type (GtkContainer *container);
206 static void gtk_notebook_forall (GtkContainer *container,
207 gboolean include_internals,
208 GtkCallback callback,
209 gpointer callback_data);
211 /*** GtkNotebook Private Functions ***/
212 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
213 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
214 static void gtk_notebook_real_remove (GtkNotebook *notebook,
216 gboolean destroying);
217 static void gtk_notebook_update_labels (GtkNotebook *notebook);
218 static gint gtk_notebook_timer (GtkNotebook *notebook);
219 static gint gtk_notebook_page_compare (gconstpointer a,
221 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
223 const gchar *function);
224 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
226 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
229 gboolean find_visible);
231 /*** GtkNotebook Drawing Functions ***/
232 static void gtk_notebook_paint (GtkWidget *widget,
234 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
235 GtkNotebookPage *page,
237 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
238 GtkNotebookArrow arrow);
240 /*** GtkNotebook Size Allocate Functions ***/
241 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
242 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
243 GtkNotebookPage *page,
244 GtkAllocation *allocation);
245 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
251 /*** GtkNotebook Page Switch Methods ***/
252 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
253 GtkNotebookPage *page,
256 /*** GtkNotebook Page Switch Functions ***/
257 static void gtk_notebook_switch_page (GtkNotebook *notebook,
258 GtkNotebookPage *page,
260 static gint gtk_notebook_page_select (GtkNotebook *notebook,
261 gboolean move_focus);
262 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
264 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
265 GtkNotebookPage *page);
267 /*** GtkNotebook Menu Functions ***/
268 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
270 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
272 static void gtk_notebook_menu_detacher (GtkWidget *widget,
275 /*** GtkNotebook Private Setters ***/
276 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
277 gboolean homogeneous);
278 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
280 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
282 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
285 static gboolean focus_tabs_in (GtkNotebook *notebook);
286 static gboolean focus_child_in (GtkNotebook *notebook,
287 GtkDirectionType direction);
289 static GtkContainerClass *parent_class = NULL;
290 static guint notebook_signals[LAST_SIGNAL] = { 0 };
293 gtk_notebook_get_type (void)
295 static GType notebook_type = 0;
299 static const GTypeInfo notebook_info =
301 sizeof (GtkNotebookClass),
302 NULL, /* base_init */
303 NULL, /* base_finalize */
304 (GClassInitFunc) gtk_notebook_class_init,
305 NULL, /* class_finalize */
306 NULL, /* class_data */
307 sizeof (GtkNotebook),
309 (GInstanceInitFunc) gtk_notebook_init,
312 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
316 return notebook_type;
320 add_tab_bindings (GtkBindingSet *binding_set,
321 GdkModifierType modifiers,
322 GtkDirectionType direction)
324 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
326 GTK_TYPE_DIRECTION_TYPE, direction);
327 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
329 GTK_TYPE_DIRECTION_TYPE, direction);
333 add_arrow_bindings (GtkBindingSet *binding_set,
335 GtkDirectionType direction)
337 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
339 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
341 GTK_TYPE_DIRECTION_TYPE, direction);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
344 GTK_TYPE_DIRECTION_TYPE, direction);
348 gtk_notebook_class_init (GtkNotebookClass *class)
350 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
351 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
352 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
353 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
354 GtkBindingSet *binding_set;
356 parent_class = g_type_class_peek_parent (class);
358 gobject_class->set_property = gtk_notebook_set_property;
359 gobject_class->get_property = gtk_notebook_get_property;
360 object_class->destroy = gtk_notebook_destroy;
362 widget_class->map = gtk_notebook_map;
363 widget_class->unmap = gtk_notebook_unmap;
364 widget_class->realize = gtk_notebook_realize;
365 widget_class->unrealize = gtk_notebook_unrealize;
366 widget_class->size_request = gtk_notebook_size_request;
367 widget_class->size_allocate = gtk_notebook_size_allocate;
368 widget_class->expose_event = gtk_notebook_expose;
369 widget_class->scroll_event = gtk_notebook_scroll;
370 widget_class->button_press_event = gtk_notebook_button_press;
371 widget_class->button_release_event = gtk_notebook_button_release;
372 widget_class->enter_notify_event = gtk_notebook_enter_notify;
373 widget_class->leave_notify_event = gtk_notebook_leave_notify;
374 widget_class->motion_notify_event = gtk_notebook_motion_notify;
375 widget_class->grab_notify = gtk_notebook_grab_notify;
376 widget_class->state_changed = gtk_notebook_state_changed;
377 widget_class->focus_in_event = gtk_notebook_focus_in;
378 widget_class->focus_out_event = gtk_notebook_focus_out;
379 widget_class->focus = gtk_notebook_focus;
380 widget_class->style_set = gtk_notebook_style_set;
382 container_class->add = gtk_notebook_add;
383 container_class->remove = gtk_notebook_remove;
384 container_class->forall = gtk_notebook_forall;
385 container_class->set_focus_child = gtk_notebook_set_focus_child;
386 container_class->get_child_property = gtk_notebook_get_child_property;
387 container_class->set_child_property = gtk_notebook_set_child_property;
388 container_class->child_type = gtk_notebook_child_type;
390 class->switch_page = gtk_notebook_real_switch_page;
392 class->focus_tab = gtk_notebook_focus_tab;
393 class->select_page = gtk_notebook_select_page;
394 class->change_current_page = gtk_notebook_change_current_page;
395 class->move_focus_out = gtk_notebook_move_focus_out;
397 g_object_class_install_property (gobject_class,
399 g_param_spec_int ("page",
401 P_("The index of the current page"),
406 g_object_class_install_property (gobject_class,
408 g_param_spec_enum ("tab_pos",
410 P_("Which side of the notebook holds the tabs"),
411 GTK_TYPE_POSITION_TYPE,
414 g_object_class_install_property (gobject_class,
416 g_param_spec_uint ("tab_border",
418 P_("Width of the border around the tab labels"),
423 g_object_class_install_property (gobject_class,
425 g_param_spec_uint ("tab_hborder",
426 P_("Horizontal Tab Border"),
427 P_("Width of the horizontal border of tab labels"),
432 g_object_class_install_property (gobject_class,
434 g_param_spec_uint ("tab_vborder",
435 P_("Vertical Tab Border"),
436 P_("Width of the vertical border of tab labels"),
441 g_object_class_install_property (gobject_class,
443 g_param_spec_boolean ("show_tabs",
445 P_("Whether tabs should be shown or not"),
448 g_object_class_install_property (gobject_class,
450 g_param_spec_boolean ("show_border",
452 P_("Whether the border should be shown or not"),
455 g_object_class_install_property (gobject_class,
457 g_param_spec_boolean ("scrollable",
459 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
462 g_object_class_install_property (gobject_class,
464 g_param_spec_boolean ("enable_popup",
466 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
469 g_object_class_install_property (gobject_class,
471 g_param_spec_boolean ("homogeneous",
473 P_("Whether tabs should have homogeneous sizes"),
477 gtk_container_class_install_child_property (container_class,
478 CHILD_PROP_TAB_LABEL,
479 g_param_spec_string ("tab_label",
481 P_("The string displayed on the childs tab label"),
484 gtk_container_class_install_child_property (container_class,
485 CHILD_PROP_MENU_LABEL,
486 g_param_spec_string ("menu_label",
488 P_("The string displayed in the childs menu entry"),
491 gtk_container_class_install_child_property (container_class,
493 g_param_spec_int ("position",
495 P_("The index of the child in the parent"),
498 gtk_container_class_install_child_property (container_class,
499 CHILD_PROP_TAB_EXPAND,
500 g_param_spec_boolean ("tab_expand",
502 P_("Whether to expand the childs tab or not"),
505 gtk_container_class_install_child_property (container_class,
507 g_param_spec_boolean ("tab_fill",
509 P_("Whether the childs tab should fill the allocated area or not"),
512 gtk_container_class_install_child_property (container_class,
514 g_param_spec_enum ("tab_pack",
516 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
517 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
521 * GtkNotebook:has-secondary-backward-stepper:
523 * The "has-secondary-backward-stepper" property determines whether
524 * a second backward arrow button is displayed on the opposite end
529 gtk_widget_class_install_style_property (widget_class,
530 g_param_spec_boolean ("has_secondary backward_stepper",
531 P_("Secondary backward stepper"),
532 P_("Display a second backward arrow button on the opposite end of the tab area"),
538 * GtkNotebook:has-secondary-forward-stepper:
540 * The "has-secondary-forward-stepper" property determines whether
541 * a second forward arrow button is displayed on the opposite end
546 gtk_widget_class_install_style_property (widget_class,
547 g_param_spec_boolean ("has_secondary_forward_stepper",
548 P_("Secondary forward stepper"),
549 P_("Display a second forward arrow button on the opposite end of the tab area"),
555 * GtkNotebook:has-backward-stepper:
557 * The "has-backward-stepper" property determines whether
558 * the standard backward arrow button is displayed.
562 gtk_widget_class_install_style_property (widget_class,
563 g_param_spec_boolean ("has_backward_stepper",
564 P_("Backward stepper"),
565 P_("Display the standard backward arrow button"),
571 * GtkNotebook:has-forward-stepper:
573 * The "has-forward-stepper" property determines whether
574 * the standard forward arrow button is displayed.
578 gtk_widget_class_install_style_property (widget_class,
579 g_param_spec_boolean ("has_forward_stepper",
580 P_("Forward stepper"),
581 P_("Display the standard forward arrow button"),
586 notebook_signals[SWITCH_PAGE] =
587 g_signal_new ("switch_page",
588 G_TYPE_FROM_CLASS (gobject_class),
590 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
592 _gtk_marshal_VOID__POINTER_UINT,
596 notebook_signals[FOCUS_TAB] =
597 g_signal_new ("focus_tab",
598 G_TYPE_FROM_CLASS (gobject_class),
599 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
600 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
602 _gtk_marshal_BOOLEAN__ENUM,
604 GTK_TYPE_NOTEBOOK_TAB);
605 notebook_signals[SELECT_PAGE] =
606 g_signal_new ("select_page",
607 G_TYPE_FROM_CLASS (gobject_class),
608 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
609 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
611 _gtk_marshal_BOOLEAN__BOOLEAN,
614 notebook_signals[CHANGE_CURRENT_PAGE] =
615 g_signal_new ("change_current_page",
616 G_TYPE_FROM_CLASS (gobject_class),
617 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
618 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
620 _gtk_marshal_VOID__INT,
623 notebook_signals[MOVE_FOCUS_OUT] =
624 g_signal_new ("move_focus_out",
625 G_TYPE_FROM_CLASS (gobject_class),
626 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
627 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
629 _gtk_marshal_VOID__ENUM,
631 GTK_TYPE_DIRECTION_TYPE);
634 binding_set = gtk_binding_set_by_class (class);
635 gtk_binding_entry_add_signal (binding_set,
638 G_TYPE_BOOLEAN, FALSE);
639 gtk_binding_entry_add_signal (binding_set,
642 G_TYPE_BOOLEAN, FALSE);
644 gtk_binding_entry_add_signal (binding_set,
647 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
648 gtk_binding_entry_add_signal (binding_set,
651 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
652 gtk_binding_entry_add_signal (binding_set,
655 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
656 gtk_binding_entry_add_signal (binding_set,
659 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
661 gtk_binding_entry_add_signal (binding_set,
662 GDK_Page_Up, GDK_CONTROL_MASK,
663 "change_current_page", 1,
665 gtk_binding_entry_add_signal (binding_set,
666 GDK_Page_Down, GDK_CONTROL_MASK,
667 "change_current_page", 1,
670 gtk_binding_entry_add_signal (binding_set,
671 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
672 "change_current_page", 1,
674 gtk_binding_entry_add_signal (binding_set,
675 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
676 "change_current_page", 1,
679 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
680 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
681 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
682 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
684 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
685 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
689 gtk_notebook_init (GtkNotebook *notebook)
691 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
692 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
694 notebook->cur_page = NULL;
695 notebook->children = NULL;
696 notebook->first_tab = NULL;
697 notebook->focus_tab = NULL;
698 notebook->event_window = NULL;
699 notebook->menu = NULL;
701 notebook->tab_hborder = 2;
702 notebook->tab_vborder = 2;
704 notebook->show_tabs = TRUE;
705 notebook->show_border = TRUE;
706 notebook->tab_pos = GTK_POS_TOP;
707 notebook->scrollable = FALSE;
708 notebook->in_child = 0;
709 notebook->click_child = 0;
710 notebook->button = 0;
711 notebook->need_timer = 0;
712 notebook->child_has_focus = FALSE;
713 notebook->have_visible_child = FALSE;
714 notebook->focus_out = FALSE;
716 notebook->has_before_previous = 1;
717 notebook->has_before_next = 0;
718 notebook->has_after_previous = 0;
719 notebook->has_after_next = 1;
723 gtk_notebook_select_page (GtkNotebook *notebook,
726 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
728 gtk_notebook_page_select (notebook, move_focus);
736 gtk_notebook_focus_tab (GtkNotebook *notebook,
741 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
745 case GTK_NOTEBOOK_TAB_FIRST:
746 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
748 gtk_notebook_switch_focus_tab (notebook, list);
750 case GTK_NOTEBOOK_TAB_LAST:
751 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
753 gtk_notebook_switch_focus_tab (notebook, list);
764 gtk_notebook_change_current_page (GtkNotebook *notebook,
767 GList *current = NULL;
769 if (notebook->cur_page)
770 current = g_list_find (notebook->children, notebook->cur_page);
774 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
775 offset += offset < 0 ? 1 : -1;
779 gtk_notebook_switch_page (notebook, current->data, -1);
781 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
784 static GtkDirectionType
785 get_effective_direction (GtkNotebook *notebook,
786 GtkDirectionType direction)
788 /* Remap the directions into the effective direction it would be for a
789 * GTK_POS_TOP notebook
792 #define D(rest) GTK_DIR_##rest
794 static const GtkDirectionType translate_direction[2][4][6] = {
795 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
796 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
797 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
798 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
799 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
800 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
801 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
802 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
807 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
809 return translate_direction[text_dir][notebook->tab_pos][direction];
813 get_effective_tab_pos (GtkNotebook *notebook)
815 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
817 switch (notebook->tab_pos)
820 return GTK_POS_RIGHT;
827 return notebook->tab_pos;
831 gtk_notebook_move_focus_out (GtkNotebook *notebook,
832 GtkDirectionType direction_type)
834 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
837 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
838 if (focus_tabs_in (notebook))
840 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
841 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
844 /* At this point, we know we should be focusing out of the notebook entirely. We
845 * do this by setting a flag, then propagating the focus motion to the notebook.
847 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
848 if (!GTK_WIDGET_TOPLEVEL (toplevel))
851 g_object_ref (notebook);
853 notebook->focus_out = TRUE;
854 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
855 notebook->focus_out = FALSE;
857 g_object_unref (notebook);
864 * Creates a new #GtkNotebook widget with no pages.
866 * Return value: the newly created #GtkNotebook
869 gtk_notebook_new (void)
871 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
874 /* Private GtkObject Methods :
876 * gtk_notebook_destroy
877 * gtk_notebook_set_arg
878 * gtk_notebook_get_arg
881 gtk_notebook_destroy (GtkObject *object)
884 GtkNotebook *notebook = GTK_NOTEBOOK (object);
887 gtk_notebook_popup_disable (notebook);
889 children = notebook->children;
892 GList *child = children;
893 children = child->next;
895 gtk_notebook_real_remove (notebook, child, TRUE);
898 GTK_OBJECT_CLASS (parent_class)->destroy (object);
902 gtk_notebook_set_property (GObject *object,
907 GtkNotebook *notebook;
909 notebook = GTK_NOTEBOOK (object);
914 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
916 case PROP_SHOW_BORDER:
917 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
919 case PROP_SCROLLABLE:
920 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
922 case PROP_ENABLE_POPUP:
923 if (g_value_get_boolean (value))
924 gtk_notebook_popup_enable (notebook);
926 gtk_notebook_popup_disable (notebook);
928 case PROP_HOMOGENEOUS:
929 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
932 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
935 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
937 case PROP_TAB_BORDER:
938 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
940 case PROP_TAB_HBORDER:
941 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
943 case PROP_TAB_VBORDER:
944 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
952 gtk_notebook_get_property (GObject *object,
957 GtkNotebook *notebook;
959 notebook = GTK_NOTEBOOK (object);
964 g_value_set_boolean (value, notebook->show_tabs);
966 case PROP_SHOW_BORDER:
967 g_value_set_boolean (value, notebook->show_border);
969 case PROP_SCROLLABLE:
970 g_value_set_boolean (value, notebook->scrollable);
972 case PROP_ENABLE_POPUP:
973 g_value_set_boolean (value, notebook->menu != NULL);
975 case PROP_HOMOGENEOUS:
976 g_value_set_boolean (value, notebook->homogeneous);
979 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
982 g_value_set_enum (value, notebook->tab_pos);
984 case PROP_TAB_HBORDER:
985 g_value_set_uint (value, notebook->tab_hborder);
987 case PROP_TAB_VBORDER:
988 g_value_set_uint (value, notebook->tab_vborder);
991 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
996 /* Private GtkWidget Methods :
1000 * gtk_notebook_realize
1001 * gtk_notebook_size_request
1002 * gtk_notebook_size_allocate
1003 * gtk_notebook_expose
1004 * gtk_notebook_scroll
1005 * gtk_notebook_button_press
1006 * gtk_notebook_button_release
1007 * gtk_notebook_enter_notify
1008 * gtk_notebook_leave_notify
1009 * gtk_notebook_motion_notify
1010 * gtk_notebook_focus_in
1011 * gtk_notebook_focus_out
1012 * gtk_notebook_draw_focus
1013 * gtk_notebook_style_set
1016 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1017 GdkRectangle *rectangle)
1019 GtkWidget *widget = GTK_WIDGET (notebook);
1020 gint border_width = GTK_CONTAINER (notebook)->border_width;
1021 GtkNotebookPage *visible_page = NULL;
1023 gint tab_pos = get_effective_tab_pos (notebook);
1025 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1027 GtkNotebookPage *page = tmp_list->data;
1028 if (GTK_WIDGET_VISIBLE (page->child))
1030 visible_page = page;
1035 if (notebook->show_tabs && visible_page)
1039 rectangle->x = widget->allocation.x + border_width;
1040 rectangle->y = widget->allocation.y + border_width;
1045 case GTK_POS_BOTTOM:
1046 rectangle->width = widget->allocation.width - 2 * border_width;
1047 rectangle->height = visible_page->requisition.height;
1048 if (tab_pos == GTK_POS_BOTTOM)
1049 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1053 rectangle->width = visible_page->requisition.width;
1054 rectangle->height = widget->allocation.height - 2 * border_width;
1055 if (tab_pos == GTK_POS_RIGHT)
1056 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1067 rectangle->x = rectangle->y = 0;
1068 rectangle->width = rectangle->height = 10;
1076 gtk_notebook_map (GtkWidget *widget)
1078 GtkNotebook *notebook;
1079 GtkNotebookPage *page;
1082 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1084 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1086 notebook = GTK_NOTEBOOK (widget);
1088 if (notebook->cur_page &&
1089 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1090 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1091 gtk_widget_map (notebook->cur_page->child);
1093 if (notebook->scrollable)
1094 gtk_notebook_pages_allocate (notebook);
1097 children = notebook->children;
1101 page = children->data;
1102 children = children->next;
1104 if (page->tab_label &&
1105 GTK_WIDGET_VISIBLE (page->tab_label) &&
1106 !GTK_WIDGET_MAPPED (page->tab_label))
1107 gtk_widget_map (page->tab_label);
1111 if (gtk_notebook_get_event_window_position (notebook, NULL))
1112 gdk_window_show_unraised (notebook->event_window);
1116 gtk_notebook_unmap (GtkWidget *widget)
1118 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1120 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1122 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1124 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1128 gtk_notebook_realize (GtkWidget *widget)
1130 GtkNotebook *notebook;
1131 GdkWindowAttr attributes;
1132 gint attributes_mask;
1133 GdkRectangle event_window_pos;
1135 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1137 notebook = GTK_NOTEBOOK (widget);
1138 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1140 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1142 widget->window = gtk_widget_get_parent_window (widget);
1143 g_object_ref (widget->window);
1145 attributes.window_type = GDK_WINDOW_CHILD;
1146 attributes.x = event_window_pos.x;
1147 attributes.y = event_window_pos.y;
1148 attributes.width = event_window_pos.width;
1149 attributes.height = event_window_pos.height;
1150 attributes.wclass = GDK_INPUT_ONLY;
1151 attributes.event_mask = gtk_widget_get_events (widget);
1152 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1153 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1155 attributes_mask = GDK_WA_X | GDK_WA_Y;
1157 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1158 &attributes, attributes_mask);
1159 gdk_window_set_user_data (notebook->event_window, notebook);
1161 widget->style = gtk_style_attach (widget->style, widget->window);
1165 gtk_notebook_unrealize (GtkWidget *widget)
1167 GtkNotebook *notebook;
1169 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1171 notebook = GTK_NOTEBOOK (widget);
1173 gdk_window_set_user_data (notebook->event_window, NULL);
1174 gdk_window_destroy (notebook->event_window);
1175 notebook->event_window = NULL;
1177 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1178 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1182 gtk_notebook_size_request (GtkWidget *widget,
1183 GtkRequisition *requisition)
1185 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1186 GtkNotebookPage *page;
1188 GtkRequisition child_requisition;
1189 gboolean switch_page = FALSE;
1193 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1195 widget->requisition.width = 0;
1196 widget->requisition.height = 0;
1198 for (children = notebook->children, vis_pages = 0; children;
1199 children = children->next)
1201 page = children->data;
1203 if (GTK_WIDGET_VISIBLE (page->child))
1206 gtk_widget_size_request (page->child, &child_requisition);
1208 widget->requisition.width = MAX (widget->requisition.width,
1209 child_requisition.width);
1210 widget->requisition.height = MAX (widget->requisition.height,
1211 child_requisition.height);
1213 if (notebook->menu && page->menu_label->parent &&
1214 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1215 gtk_widget_show (page->menu_label->parent);
1219 if (page == notebook->cur_page)
1221 if (notebook->menu && page->menu_label->parent &&
1222 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1223 gtk_widget_hide (page->menu_label->parent);
1227 if (notebook->show_border || notebook->show_tabs)
1229 widget->requisition.width += widget->style->xthickness * 2;
1230 widget->requisition.height += widget->style->ythickness * 2;
1232 if (notebook->show_tabs)
1235 gint tab_height = 0;
1239 for (children = notebook->children; children;
1240 children = children->next)
1242 page = children->data;
1244 if (GTK_WIDGET_VISIBLE (page->child))
1246 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1247 gtk_widget_show (page->tab_label);
1249 gtk_widget_size_request (page->tab_label,
1250 &child_requisition);
1252 page->requisition.width =
1253 child_requisition.width +
1254 2 * widget->style->xthickness;
1255 page->requisition.height =
1256 child_requisition.height +
1257 2 * widget->style->ythickness;
1259 switch (notebook->tab_pos)
1262 case GTK_POS_BOTTOM:
1263 page->requisition.height += 2 * (notebook->tab_vborder +
1265 tab_height = MAX (tab_height, page->requisition.height);
1266 tab_max = MAX (tab_max, page->requisition.width);
1270 page->requisition.width += 2 * (notebook->tab_hborder +
1272 tab_width = MAX (tab_width, page->requisition.width);
1273 tab_max = MAX (tab_max, page->requisition.height);
1277 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1278 gtk_widget_hide (page->tab_label);
1281 children = notebook->children;
1285 switch (notebook->tab_pos)
1288 case GTK_POS_BOTTOM:
1289 if (tab_height == 0)
1292 if (notebook->scrollable && vis_pages > 1 &&
1293 widget->requisition.width < tab_width)
1294 tab_height = MAX (tab_height, ARROW_SIZE);
1296 padding = 2 * (TAB_CURVATURE + focus_width +
1297 notebook->tab_hborder) - TAB_OVERLAP;
1301 page = children->data;
1302 children = children->next;
1304 if (!GTK_WIDGET_VISIBLE (page->child))
1307 if (notebook->homogeneous)
1308 page->requisition.width = tab_max;
1310 page->requisition.width += padding;
1312 tab_width += page->requisition.width;
1313 page->requisition.height = tab_height;
1316 if (notebook->scrollable && vis_pages > 1 &&
1317 widget->requisition.width < tab_width)
1318 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1320 if (notebook->homogeneous && !notebook->scrollable)
1321 widget->requisition.width = MAX (widget->requisition.width,
1322 vis_pages * tab_max +
1325 widget->requisition.width = MAX (widget->requisition.width,
1326 tab_width + TAB_OVERLAP);
1328 widget->requisition.height += tab_height;
1335 if (notebook->scrollable && vis_pages > 1 &&
1336 widget->requisition.height < tab_height)
1337 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1339 padding = 2 * (TAB_CURVATURE + focus_width +
1340 notebook->tab_vborder) - TAB_OVERLAP;
1345 page = children->data;
1346 children = children->next;
1348 if (!GTK_WIDGET_VISIBLE (page->child))
1351 page->requisition.width = tab_width;
1353 if (notebook->homogeneous)
1354 page->requisition.height = tab_max;
1356 page->requisition.height += padding;
1358 tab_height += page->requisition.height;
1361 if (notebook->scrollable && vis_pages > 1 &&
1362 widget->requisition.height < tab_height)
1363 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1365 widget->requisition.width += tab_width;
1367 if (notebook->homogeneous && !notebook->scrollable)
1368 widget->requisition.height =
1369 MAX (widget->requisition.height,
1370 vis_pages * tab_max + TAB_OVERLAP);
1372 widget->requisition.height =
1373 MAX (widget->requisition.height,
1374 tab_height + TAB_OVERLAP);
1376 if (!notebook->homogeneous || notebook->scrollable)
1378 widget->requisition.height = MAX (widget->requisition.height,
1379 vis_pages * tab_max +
1387 for (children = notebook->children; children;
1388 children = children->next)
1390 page = children->data;
1392 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1393 gtk_widget_hide (page->tab_label);
1398 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1399 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1405 for (children = notebook->children; children;
1406 children = children->next)
1408 page = children->data;
1409 if (GTK_WIDGET_VISIBLE (page->child))
1411 gtk_notebook_switch_page (notebook, page, -1);
1416 else if (GTK_WIDGET_VISIBLE (widget))
1418 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1419 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1422 if (vis_pages && !notebook->cur_page)
1424 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1427 notebook->first_tab = children;
1428 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1434 gtk_notebook_size_allocate (GtkWidget *widget,
1435 GtkAllocation *allocation)
1437 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1439 gint tab_pos = get_effective_tab_pos (notebook);
1441 widget->allocation = *allocation;
1442 if (GTK_WIDGET_REALIZED (widget))
1444 GdkRectangle position;
1446 if (gtk_notebook_get_event_window_position (notebook, &position))
1448 gdk_window_move_resize (notebook->event_window,
1449 position.x, position.y,
1450 position.width, position.height);
1451 if (GTK_WIDGET_MAPPED (notebook))
1452 gdk_window_show_unraised (notebook->event_window);
1455 gdk_window_hide (notebook->event_window);
1458 if (notebook->children)
1460 gint border_width = GTK_CONTAINER (widget)->border_width;
1461 GtkNotebookPage *page;
1462 GtkAllocation child_allocation;
1465 child_allocation.x = widget->allocation.x + border_width;
1466 child_allocation.y = widget->allocation.y + border_width;
1467 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1468 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1470 if (notebook->show_tabs || notebook->show_border)
1472 child_allocation.x += widget->style->xthickness;
1473 child_allocation.y += widget->style->ythickness;
1474 child_allocation.width = MAX (1, child_allocation.width -
1475 widget->style->xthickness * 2);
1476 child_allocation.height = MAX (1, child_allocation.height -
1477 widget->style->ythickness * 2);
1479 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1484 child_allocation.y += notebook->cur_page->requisition.height;
1485 case GTK_POS_BOTTOM:
1486 child_allocation.height =
1487 MAX (1, child_allocation.height -
1488 notebook->cur_page->requisition.height);
1491 child_allocation.x += notebook->cur_page->requisition.width;
1493 child_allocation.width =
1494 MAX (1, child_allocation.width -
1495 notebook->cur_page->requisition.width);
1501 children = notebook->children;
1504 page = children->data;
1505 children = children->next;
1507 if (GTK_WIDGET_VISIBLE (page->child))
1509 gtk_widget_size_allocate (page->child, &child_allocation);
1514 gtk_notebook_pages_allocate (notebook);
1517 if ((vis_pages != 0) != notebook->have_visible_child)
1519 notebook->have_visible_child = (vis_pages != 0);
1520 if (notebook->show_tabs)
1521 gtk_widget_queue_draw (widget);
1526 gtk_notebook_expose (GtkWidget *widget,
1527 GdkEventExpose *event)
1529 GtkNotebook *notebook;
1530 GdkRectangle child_area;
1532 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1533 g_return_val_if_fail (event != NULL, FALSE);
1535 if (GTK_WIDGET_DRAWABLE (widget))
1537 notebook = GTK_NOTEBOOK (widget);
1539 gtk_notebook_paint (widget, &event->area);
1540 if (notebook->show_tabs)
1542 if (notebook->cur_page &&
1543 gtk_widget_intersect (notebook->cur_page->tab_label,
1544 &event->area, &child_area))
1545 gtk_notebook_draw_focus (widget);
1549 if (notebook->cur_page)
1550 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1551 notebook->cur_page->child,
1559 gtk_notebook_show_arrows (GtkNotebook *notebook)
1561 gboolean show_arrow = FALSE;
1564 if (!notebook->scrollable)
1567 children = notebook->children;
1570 GtkNotebookPage *page = children->data;
1572 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1575 children = children->next;
1582 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1583 GdkRectangle *rectangle,
1584 GtkNotebookArrow arrow)
1586 GdkRectangle event_window_pos;
1587 gboolean before = ARROW_IS_BEFORE (arrow);
1588 gboolean left = ARROW_IS_LEFT (arrow);
1590 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1592 rectangle->width = ARROW_SIZE;
1593 rectangle->height = ARROW_SIZE;
1595 switch (notebook->tab_pos)
1599 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1600 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1601 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1603 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1605 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1606 rectangle->y = event_window_pos.y;
1608 rectangle->y += event_window_pos.height - rectangle->height;
1611 case GTK_POS_BOTTOM:
1614 if (left || !notebook->has_before_previous)
1615 rectangle->x = event_window_pos.x;
1617 rectangle->x = event_window_pos.x + rectangle->width;
1621 if (!left || !notebook->has_after_next)
1622 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1624 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1626 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1632 static GtkNotebookArrow
1633 gtk_notebook_get_arrow (GtkNotebook *notebook,
1637 GdkRectangle arrow_rect;
1638 GdkRectangle event_window_pos;
1641 GtkNotebookArrow arrow[4];
1643 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1644 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1645 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1646 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1648 if (gtk_notebook_show_arrows (notebook))
1650 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1651 for (i = 0; i < 4; i++)
1653 if (arrow[i] == ARROW_NONE)
1656 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1658 x0 = x - arrow_rect.x;
1659 y0 = y - arrow_rect.y;
1661 if (y0 >= 0 && y0 < arrow_rect.height &&
1662 x0 >= 0 && x0 < arrow_rect.width)
1671 gtk_notebook_do_arrow (GtkNotebook *notebook,
1672 GtkNotebookArrow arrow)
1674 GtkWidget *widget = GTK_WIDGET (notebook);
1675 GtkDirectionType dir;
1676 gboolean is_rtl, left;
1678 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1679 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1680 (!ARROW_IS_LEFT (arrow) && is_rtl);
1682 if (!notebook->focus_tab ||
1683 gtk_notebook_search_page (notebook, notebook->focus_tab,
1684 left ? STEP_PREV : STEP_NEXT,
1687 if (notebook->tab_pos == GTK_POS_LEFT ||
1688 notebook->tab_pos == GTK_POS_RIGHT)
1689 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1691 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1692 gtk_widget_child_focus (widget, dir);
1697 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1698 GtkNotebookArrow arrow,
1699 GdkEventButton *event)
1701 GtkWidget *widget = GTK_WIDGET (notebook);
1702 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1703 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1704 (!ARROW_IS_LEFT (arrow) && is_rtl);
1706 if (!GTK_WIDGET_HAS_FOCUS (widget))
1707 gtk_widget_grab_focus (widget);
1709 notebook->button = event->button;
1710 notebook->click_child = arrow;
1712 if (event->button == 1)
1714 gtk_notebook_do_arrow (notebook, arrow);
1716 if (!notebook->timer)
1718 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1719 (GSourceFunc) gtk_notebook_timer,
1720 (gpointer) notebook);
1721 notebook->need_timer = TRUE;
1724 else if (event->button == 2)
1725 gtk_notebook_page_select (notebook, TRUE);
1726 else if (event->button == 3)
1727 gtk_notebook_switch_focus_tab (notebook,
1728 gtk_notebook_search_page (notebook,
1730 left ? STEP_NEXT : STEP_PREV,
1732 gtk_notebook_redraw_arrows (notebook);
1738 get_widget_coordinates (GtkWidget *widget,
1743 GdkWindow *window = ((GdkEventAny *)event)->window;
1746 if (!gdk_event_get_coords (event, &tx, &ty))
1749 while (window && window != widget->window)
1751 gint window_x, window_y;
1753 gdk_window_get_position (window, &window_x, &window_y);
1757 window = gdk_window_get_parent (window);
1772 gtk_notebook_scroll (GtkWidget *widget,
1773 GdkEventScroll *event)
1775 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1777 switch (event->direction)
1779 case GDK_SCROLL_RIGHT:
1780 case GDK_SCROLL_DOWN:
1781 gtk_notebook_next_page (notebook);
1783 case GDK_SCROLL_LEFT:
1785 gtk_notebook_prev_page (notebook);
1793 gtk_notebook_button_press (GtkWidget *widget,
1794 GdkEventButton *event)
1796 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1797 GtkNotebookPage *page;
1799 GtkNotebookArrow arrow;
1803 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1807 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1810 arrow = gtk_notebook_get_arrow (notebook, x, y);
1812 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1814 if (event->button == 3 && notebook->menu)
1816 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1817 NULL, NULL, 3, event->time);
1821 if (event->button != 1)
1825 children = notebook->children;
1828 page = children->data;
1830 if (GTK_WIDGET_VISIBLE (page->child) &&
1831 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1832 (x >= page->allocation.x) &&
1833 (y >= page->allocation.y) &&
1834 (x <= (page->allocation.x + page->allocation.width)) &&
1835 (y <= (page->allocation.y + page->allocation.height)))
1837 gboolean page_changed = page != notebook->cur_page;
1838 gboolean was_focus = gtk_widget_is_focus (widget);
1840 gtk_notebook_switch_focus_tab (notebook, children);
1841 gtk_widget_grab_focus (widget);
1843 if (page_changed && !was_focus)
1844 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1848 children = children->next;
1856 stop_scrolling (GtkNotebook *notebook)
1858 if (notebook->timer)
1860 g_source_remove (notebook->timer);
1861 notebook->timer = 0;
1862 notebook->need_timer = FALSE;
1864 notebook->click_child = 0;
1865 notebook->button = 0;
1866 gtk_notebook_redraw_arrows (notebook);
1870 gtk_notebook_button_release (GtkWidget *widget,
1871 GdkEventButton *event)
1873 GtkNotebook *notebook;
1875 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1876 g_return_val_if_fail (event != NULL, FALSE);
1878 if (event->type != GDK_BUTTON_RELEASE)
1881 notebook = GTK_NOTEBOOK (widget);
1883 if (event->button == notebook->button)
1885 stop_scrolling (notebook);
1894 gtk_notebook_enter_notify (GtkWidget *widget,
1895 GdkEventCrossing *event)
1897 GtkNotebook *notebook;
1898 GtkNotebookArrow arrow;
1901 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1902 g_return_val_if_fail (event != NULL, FALSE);
1904 notebook = GTK_NOTEBOOK (widget);
1906 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1909 arrow = gtk_notebook_get_arrow (notebook, x, y);
1911 if (arrow != notebook->in_child)
1913 notebook->in_child = arrow;
1914 gtk_notebook_redraw_arrows (notebook);
1923 gtk_notebook_leave_notify (GtkWidget *widget,
1924 GdkEventCrossing *event)
1926 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1927 GtkNotebookArrow arrow;
1930 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1933 arrow = gtk_notebook_get_arrow (notebook, x, y);
1935 if (notebook->in_child)
1937 notebook->in_child = 0;
1938 gtk_notebook_redraw_arrows (notebook);
1945 gtk_notebook_motion_notify (GtkWidget *widget,
1946 GdkEventMotion *event)
1948 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1949 GtkNotebookArrow arrow;
1952 if (notebook->button)
1955 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1958 arrow = gtk_notebook_get_arrow (notebook, x, y);
1960 if (arrow != notebook->in_child)
1962 notebook->in_child = arrow;
1963 gtk_notebook_redraw_arrows (notebook);
1970 gtk_notebook_grab_notify (GtkWidget *widget,
1971 gboolean was_grabbed)
1974 stop_scrolling (GTK_NOTEBOOK (widget));
1978 gtk_notebook_state_changed (GtkWidget *widget,
1979 GtkStateType previous_state)
1981 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1982 stop_scrolling (GTK_NOTEBOOK (widget));
1986 gtk_notebook_focus_in (GtkWidget *widget,
1987 GdkEventFocus *event)
1989 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1991 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
1997 gtk_notebook_focus_out (GtkWidget *widget,
1998 GdkEventFocus *event)
2000 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2006 gtk_notebook_draw_focus (GtkWidget *widget)
2008 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2010 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2011 notebook->focus_tab)
2013 GtkNotebookPage *page;
2017 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2019 page = notebook->focus_tab->data;
2021 area.x = page->tab_label->allocation.x - focus_width;
2022 area.y = page->tab_label->allocation.y - focus_width;
2023 area.width = page->tab_label->allocation.width + 2 * focus_width;
2024 area.height = page->tab_label->allocation.height + 2 * focus_width;
2026 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2031 gtk_notebook_style_set (GtkWidget *widget,
2034 GtkNotebook *notebook;
2036 gboolean has_before_previous;
2037 gboolean has_before_next;
2038 gboolean has_after_previous;
2039 gboolean has_after_next;
2041 notebook = GTK_NOTEBOOK (widget);
2043 gtk_widget_style_get (widget,
2044 "has_backward_stepper", &has_before_previous,
2045 "has_secondary_forward_stepper", &has_before_next,
2046 "has_secondary_backward_stepper", &has_after_previous,
2047 "has_forward_stepper", &has_after_next,
2050 notebook->has_before_previous = has_before_previous;
2051 notebook->has_before_next = has_before_next;
2052 notebook->has_after_previous = has_after_previous;
2053 notebook->has_after_next = has_after_next;
2055 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2058 /* Private GtkContainer Methods :
2060 * gtk_notebook_set_child_arg
2061 * gtk_notebook_get_child_arg
2063 * gtk_notebook_remove
2064 * gtk_notebook_focus
2065 * gtk_notebook_set_focus_child
2066 * gtk_notebook_child_type
2067 * gtk_notebook_forall
2070 gtk_notebook_set_child_property (GtkContainer *container,
2073 const GValue *value,
2078 GtkPackType pack_type;
2080 /* not finding child's page is valid for menus or labels */
2081 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2084 switch (property_id)
2086 case CHILD_PROP_TAB_LABEL:
2087 /* a NULL pointer indicates a default_tab setting, otherwise
2088 * we need to set the associated label
2090 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2091 g_value_get_string (value));
2093 case CHILD_PROP_MENU_LABEL:
2094 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2095 g_value_get_string (value));
2097 case CHILD_PROP_POSITION:
2098 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2099 g_value_get_int (value));
2101 case CHILD_PROP_TAB_EXPAND:
2102 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2103 &expand, &fill, &pack_type);
2104 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2105 g_value_get_boolean (value),
2108 case CHILD_PROP_TAB_FILL:
2109 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2110 &expand, &fill, &pack_type);
2111 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2113 g_value_get_boolean (value),
2116 case CHILD_PROP_TAB_PACK:
2117 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2118 &expand, &fill, &pack_type);
2119 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2121 g_value_get_enum (value));
2124 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2130 gtk_notebook_get_child_property (GtkContainer *container,
2137 GtkNotebook *notebook;
2141 GtkPackType pack_type;
2143 notebook = GTK_NOTEBOOK (container);
2145 /* not finding child's page is valid for menus or labels */
2146 list = gtk_notebook_find_child (notebook, child, NULL);
2149 /* nothing to set on labels or menus */
2150 g_param_value_set_default (pspec, value);
2154 switch (property_id)
2156 case CHILD_PROP_TAB_LABEL:
2157 label = gtk_notebook_get_tab_label (notebook, child);
2159 if (label && GTK_IS_LABEL (label))
2160 g_value_set_string (value, GTK_LABEL (label)->label);
2162 g_value_set_string (value, NULL);
2164 case CHILD_PROP_MENU_LABEL:
2165 label = gtk_notebook_get_menu_label (notebook, child);
2167 if (label && GTK_IS_LABEL (label))
2168 g_value_set_string (value, GTK_LABEL (label)->label);
2170 g_value_set_string (value, NULL);
2172 case CHILD_PROP_POSITION:
2173 g_value_set_int (value, g_list_position (notebook->children, list));
2175 case CHILD_PROP_TAB_EXPAND:
2176 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2177 &expand, NULL, NULL);
2178 g_value_set_boolean (value, expand);
2180 case CHILD_PROP_TAB_FILL:
2181 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2183 g_value_set_boolean (value, fill);
2185 case CHILD_PROP_TAB_PACK:
2186 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2187 NULL, NULL, &pack_type);
2188 g_value_set_enum (value, pack_type);
2191 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2197 gtk_notebook_add (GtkContainer *container,
2200 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2202 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2207 gtk_notebook_remove (GtkContainer *container,
2210 GtkNotebook *notebook;
2211 GtkNotebookPage *page;
2214 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2215 g_return_if_fail (widget != NULL);
2217 notebook = GTK_NOTEBOOK (container);
2219 children = notebook->children;
2222 page = children->data;
2223 if (page->child == widget)
2225 gtk_notebook_real_remove (notebook, children, FALSE);
2228 children = children->next;
2233 focus_tabs_in (GtkNotebook *notebook)
2235 if (notebook->show_tabs && notebook->cur_page)
2237 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2239 gtk_notebook_switch_focus_tab (notebook,
2240 g_list_find (notebook->children,
2241 notebook->cur_page));
2250 focus_tabs_move (GtkNotebook *notebook,
2251 GtkDirectionType direction,
2252 gint search_direction)
2256 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2257 search_direction, TRUE);
2259 gtk_notebook_switch_focus_tab (notebook, new_page);
2261 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2267 focus_child_in (GtkNotebook *notebook,
2268 GtkDirectionType direction)
2270 if (notebook->cur_page)
2271 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2276 /* Focus in the notebook can either be on the pages, or on
2280 gtk_notebook_focus (GtkWidget *widget,
2281 GtkDirectionType direction)
2283 GtkWidget *old_focus_child;
2284 GtkNotebook *notebook;
2285 GtkDirectionType effective_direction;
2287 gboolean widget_is_focus;
2288 GtkContainer *container;
2290 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2292 container = GTK_CONTAINER (widget);
2293 notebook = GTK_NOTEBOOK (container);
2295 if (notebook->focus_out)
2297 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2301 widget_is_focus = gtk_widget_is_focus (widget);
2302 old_focus_child = container->focus_child;
2304 effective_direction = get_effective_direction (notebook, direction);
2306 if (old_focus_child) /* Focus on page child */
2308 if (gtk_widget_child_focus (old_focus_child, direction))
2311 switch (effective_direction)
2313 case GTK_DIR_TAB_BACKWARD:
2315 /* Focus onto the tabs */
2316 return focus_tabs_in (notebook);
2318 case GTK_DIR_TAB_FORWARD:
2324 else if (widget_is_focus) /* Focus was on tabs */
2326 switch (effective_direction)
2328 case GTK_DIR_TAB_BACKWARD:
2331 case GTK_DIR_TAB_FORWARD:
2333 /* We use TAB_FORWARD rather than direction so that we focus a more
2334 * predictable widget for the user; users may be using arrow focusing
2335 * in this situation even if they don't usually use arrow focusing.
2337 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2339 return focus_tabs_move (notebook, direction, STEP_PREV);
2341 return focus_tabs_move (notebook, direction, STEP_NEXT);
2344 else /* Focus was not on widget */
2346 switch (effective_direction)
2348 case GTK_DIR_TAB_FORWARD:
2350 if (focus_tabs_in (notebook))
2352 if (focus_child_in (notebook, direction))
2355 case GTK_DIR_TAB_BACKWARD:
2357 if (focus_child_in (notebook, direction))
2359 if (focus_tabs_in (notebook))
2364 return focus_child_in (notebook, direction);
2368 g_assert_not_reached ();
2373 gtk_notebook_set_focus_child (GtkContainer *container,
2376 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2377 GtkWidget *page_child;
2378 GtkWidget *toplevel;
2380 /* If the old focus widget was within a page of the notebook,
2381 * (child may either be NULL or not in this case), record it
2382 * for future use if we switch to the page with a mnemonic.
2385 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2386 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2388 page_child = GTK_WINDOW (toplevel)->focus_widget;
2391 if (page_child->parent == GTK_WIDGET (container))
2393 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2396 GtkNotebookPage *page = list->data;
2398 if (page->last_focus_child)
2399 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2401 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2402 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2408 page_child = page_child->parent;
2414 g_return_if_fail (GTK_IS_WIDGET (child));
2416 notebook->child_has_focus = TRUE;
2417 if (!notebook->focus_tab)
2420 GtkNotebookPage *page;
2422 children = notebook->children;
2425 page = children->data;
2426 if (page->child == child || page->tab_label == child)
2427 gtk_notebook_switch_focus_tab (notebook, children);
2428 children = children->next;
2433 parent_class->set_focus_child (container, child);
2437 gtk_notebook_forall (GtkContainer *container,
2438 gboolean include_internals,
2439 GtkCallback callback,
2440 gpointer callback_data)
2442 GtkNotebook *notebook;
2445 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2446 g_return_if_fail (callback != NULL);
2448 notebook = GTK_NOTEBOOK (container);
2450 children = notebook->children;
2453 GtkNotebookPage *page;
2455 page = children->data;
2456 children = children->next;
2457 (* callback) (page->child, callback_data);
2458 if (include_internals)
2460 if (page->tab_label)
2461 (* callback) (page->tab_label, callback_data);
2467 gtk_notebook_child_type (GtkContainer *container)
2469 return GTK_TYPE_WIDGET;
2472 /* Private GtkNotebook Functions:
2474 * gtk_notebook_redraw_tabs
2475 * gtk_notebook_real_remove
2476 * gtk_notebook_update_labels
2477 * gtk_notebook_timer
2478 * gtk_notebook_page_compare
2479 * gtk_notebook_real_page_position
2480 * gtk_notebook_search_page
2483 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2486 GtkNotebookPage *page;
2487 GdkRectangle redraw_rect;
2489 gint tab_pos = get_effective_tab_pos (notebook);
2491 widget = GTK_WIDGET (notebook);
2492 border = GTK_CONTAINER (notebook)->border_width;
2494 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2497 page = notebook->first_tab->data;
2499 redraw_rect.x = border;
2500 redraw_rect.y = border;
2504 case GTK_POS_BOTTOM:
2505 redraw_rect.y = (widget->allocation.height - border -
2506 page->allocation.height -
2507 widget->style->ythickness);
2508 if (page != notebook->cur_page)
2509 redraw_rect.y -= widget->style->ythickness;
2512 redraw_rect.width = widget->allocation.width - 2 * border;
2513 redraw_rect.height = (page->allocation.height +
2514 widget->style->ythickness);
2515 if (page != notebook->cur_page)
2516 redraw_rect.height += widget->style->ythickness;
2519 redraw_rect.x = (widget->allocation.width - border -
2520 page->allocation.width -
2521 widget->style->xthickness);
2522 if (page != notebook->cur_page)
2523 redraw_rect.x -= widget->style->xthickness;
2526 redraw_rect.width = (page->allocation.width +
2527 widget->style->xthickness);
2528 redraw_rect.height = widget->allocation.height - 2 * border;
2529 if (page != notebook->cur_page)
2530 redraw_rect.width += widget->style->xthickness;
2534 redraw_rect.x += widget->allocation.x;
2535 redraw_rect.y += widget->allocation.y;
2537 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2541 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2543 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2547 GtkNotebookArrow arrow[4];
2549 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2550 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2551 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2552 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2554 for (i = 0; i < 4; i++)
2556 if (arrow[i] == ARROW_NONE)
2559 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2560 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2567 gtk_notebook_timer (GtkNotebook *notebook)
2569 gboolean retval = FALSE;
2571 GDK_THREADS_ENTER ();
2573 if (notebook->timer)
2575 gtk_notebook_do_arrow (notebook, notebook->click_child);
2577 if (notebook->need_timer)
2579 notebook->need_timer = FALSE;
2580 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2581 (GSourceFunc) gtk_notebook_timer,
2582 (gpointer) notebook);
2588 GDK_THREADS_LEAVE ();
2594 gtk_notebook_page_compare (gconstpointer a,
2597 return (((GtkNotebookPage *) a)->child != b);
2601 gtk_notebook_find_child (GtkNotebook *notebook,
2603 const gchar *function)
2605 GList *list = g_list_find_custom (notebook->children, child,
2606 gtk_notebook_page_compare);
2608 #ifndef G_DISABLE_CHECKS
2609 if (!list && function)
2610 g_warning ("%s: unable to find child %p in notebook %p",
2611 function, child, notebook);
2618 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2619 GtkNotebookPage *page)
2621 if (page->tab_label)
2623 if (page->mnemonic_activate_signal)
2624 g_signal_handler_disconnect (page->tab_label,
2625 page->mnemonic_activate_signal);
2626 page->mnemonic_activate_signal = 0;
2628 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2629 gtk_widget_unparent (page->tab_label);
2634 gtk_notebook_real_remove (GtkNotebook *notebook,
2636 gboolean destroying)
2638 GtkNotebookPage *page;
2640 gint need_resize = FALSE;
2642 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2644 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2646 if (notebook->cur_page == list->data)
2648 notebook->cur_page = NULL;
2649 if (next_list && !destroying)
2650 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2653 if (list == notebook->first_tab)
2654 notebook->first_tab = next_list;
2655 if (list == notebook->focus_tab && !destroying)
2656 gtk_notebook_switch_focus_tab (notebook, next_list);
2660 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2663 gtk_widget_unparent (page->child);
2665 gtk_notebook_remove_tab_label (notebook, page);
2669 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2670 page->menu_label->parent);
2671 gtk_widget_queue_resize (notebook->menu);
2673 if (!page->default_menu)
2674 g_object_unref (page->menu_label);
2676 notebook->children = g_list_remove_link (notebook->children, list);
2679 if (page->last_focus_child)
2681 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2682 page->last_focus_child = NULL;
2687 gtk_notebook_update_labels (notebook);
2689 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2693 gtk_notebook_update_labels (GtkNotebook *notebook)
2695 GtkNotebookPage *page;
2700 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2702 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2705 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2706 if (notebook->show_tabs)
2708 if (page->default_tab)
2710 if (!page->tab_label)
2712 page->tab_label = gtk_label_new (string);
2713 gtk_widget_set_parent (page->tab_label,
2714 GTK_WIDGET (notebook));
2717 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2720 if (GTK_WIDGET_VISIBLE (page->child) &&
2721 !GTK_WIDGET_VISIBLE (page->tab_label))
2722 gtk_widget_show (page->tab_label);
2723 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2724 GTK_WIDGET_VISIBLE (page->tab_label))
2725 gtk_widget_hide (page->tab_label);
2727 if (notebook->menu && page->default_menu)
2729 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2730 gtk_label_set_text (GTK_LABEL (page->menu_label),
2731 GTK_LABEL (page->tab_label)->label);
2733 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2739 gtk_notebook_real_page_position (GtkNotebook *notebook,
2745 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2746 g_return_val_if_fail (list != NULL, -1);
2748 for (work = notebook->children, count_start = 0;
2749 work && work != list; work = work->next)
2750 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2756 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2759 return (count_start + g_list_length (list) - 1);
2763 gtk_notebook_search_page (GtkNotebook *notebook,
2766 gboolean find_visible)
2768 GtkNotebookPage *page = NULL;
2769 GList *old_list = NULL;
2772 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2777 flag = GTK_PACK_END;
2781 flag = GTK_PACK_START;
2788 if (!page || page->pack == flag)
2796 list = notebook->children;
2801 if (page->pack == flag &&
2802 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2817 if (page->pack != flag &&
2818 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2826 /* Private GtkNotebook Drawing Functions:
2828 * gtk_notebook_paint
2829 * gtk_notebook_draw_tab
2830 * gtk_notebook_draw_arrow
2833 gtk_notebook_paint (GtkWidget *widget,
2836 GtkNotebook *notebook;
2837 GtkNotebookPage *page;
2842 gint border_width = GTK_CONTAINER (widget)->border_width;
2843 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2847 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2848 g_return_if_fail (area != NULL);
2850 if (!GTK_WIDGET_DRAWABLE (widget))
2853 notebook = GTK_NOTEBOOK (widget);
2854 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2855 tab_pos = get_effective_tab_pos (notebook);
2857 if ((!notebook->show_tabs && !notebook->show_border) ||
2858 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2861 x = widget->allocation.x + border_width;
2862 y = widget->allocation.y + border_width;
2863 width = widget->allocation.width - border_width * 2;
2864 height = widget->allocation.height - border_width * 2;
2866 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2868 gtk_paint_box (widget->style, widget->window,
2869 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2870 area, widget, "notebook",
2871 x, y, width, height);
2876 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2878 page = notebook->first_tab->data;
2883 y += page->allocation.height + widget->style->ythickness;
2884 case GTK_POS_BOTTOM:
2885 height -= page->allocation.height + widget->style->ythickness;
2888 x += page->allocation.width + widget->style->xthickness;
2890 width -= page->allocation.width + widget->style->xthickness;
2893 gtk_paint_box (widget->style, widget->window,
2894 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2895 area, widget, "notebook",
2896 x, y, width, height);
2903 y += notebook->cur_page->allocation.height;
2904 case GTK_POS_BOTTOM:
2905 height -= notebook->cur_page->allocation.height;
2908 x += notebook->cur_page->allocation.width;
2910 width -= notebook->cur_page->allocation.width;
2917 case GTK_POS_BOTTOM:
2918 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2919 gap_width = notebook->cur_page->allocation.width;
2920 step = is_rtl ? STEP_NEXT : STEP_PREV;
2924 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2925 gap_width = notebook->cur_page->allocation.height;
2929 gtk_paint_box_gap (widget->style, widget->window,
2930 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2931 area, widget, "notebook",
2932 x, y, width, height,
2933 tab_pos, gap_x, gap_width);
2937 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2940 page = children->data;
2941 children = gtk_notebook_search_page (notebook, children,
2943 if (!GTK_WIDGET_VISIBLE (page->child))
2945 if (!GTK_WIDGET_MAPPED (page->tab_label))
2947 else if (page != notebook->cur_page)
2948 gtk_notebook_draw_tab (notebook, page, area);
2951 if (showarrow && notebook->scrollable)
2953 if (notebook->has_before_previous)
2954 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2955 if (notebook->has_before_next)
2956 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2957 if (notebook->has_after_previous)
2958 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2959 if (notebook->has_after_next)
2960 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2962 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2966 gtk_notebook_draw_tab (GtkNotebook *notebook,
2967 GtkNotebookPage *page,
2970 GdkRectangle child_area;
2971 GdkRectangle page_area;
2972 GtkStateType state_type;
2973 GtkPositionType gap_side;
2974 gint tab_pos = get_effective_tab_pos (notebook);
2976 g_return_if_fail (notebook != NULL);
2977 g_return_if_fail (page != NULL);
2978 g_return_if_fail (area != NULL);
2980 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2981 (page->allocation.width == 0) || (page->allocation.height == 0))
2984 page_area.x = page->allocation.x;
2985 page_area.y = page->allocation.y;
2986 page_area.width = page->allocation.width;
2987 page_area.height = page->allocation.height;
2989 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2993 widget = GTK_WIDGET (notebook);
2998 gap_side = GTK_POS_BOTTOM;
3000 case GTK_POS_BOTTOM:
3001 gap_side = GTK_POS_TOP;
3004 gap_side = GTK_POS_RIGHT;
3007 gap_side = GTK_POS_LEFT;
3011 if (notebook->cur_page == page)
3012 state_type = GTK_STATE_NORMAL;
3014 state_type = GTK_STATE_ACTIVE;
3015 gtk_paint_extension(widget->style, widget->window,
3016 state_type, GTK_SHADOW_OUT,
3017 area, widget, "tab",
3018 page_area.x, page_area.y,
3019 page_area.width, page_area.height,
3021 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
3022 notebook->focus_tab && (notebook->focus_tab->data == page))
3026 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3028 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3029 area, widget, "tab",
3030 page->tab_label->allocation.x - focus_width,
3031 page->tab_label->allocation.y - focus_width,
3032 page->tab_label->allocation.width + 2 * focus_width,
3033 page->tab_label->allocation.height + 2 * focus_width);
3035 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3036 GTK_WIDGET_DRAWABLE (page->tab_label))
3038 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3040 /* This is a lame hack since all this code needs rewriting anyhow */
3042 expose_event->expose.window = g_object_ref (page->tab_label->window);
3043 expose_event->expose.area = child_area;
3044 expose_event->expose.region = gdk_region_rectangle (&child_area);
3045 expose_event->expose.send_event = TRUE;
3046 expose_event->expose.count = 0;
3048 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3050 gdk_event_free (expose_event);
3056 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3057 GtkNotebookArrow nbarrow)
3059 GtkStateType state_type;
3060 GtkShadowType shadow_type;
3062 GdkRectangle arrow_rect;
3064 gboolean is_rtl, left;
3066 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3068 widget = GTK_WIDGET (notebook);
3070 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3071 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3072 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3074 if (GTK_WIDGET_DRAWABLE (notebook))
3076 if (notebook->in_child == nbarrow)
3078 if (notebook->click_child == nbarrow)
3079 state_type = GTK_STATE_ACTIVE;
3081 state_type = GTK_STATE_PRELIGHT;
3084 state_type = GTK_WIDGET_STATE (widget);
3086 if (notebook->click_child == nbarrow)
3087 shadow_type = GTK_SHADOW_IN;
3089 shadow_type = GTK_SHADOW_OUT;
3091 if (notebook->focus_tab &&
3092 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3093 left? STEP_PREV : STEP_NEXT, TRUE))
3095 shadow_type = GTK_SHADOW_ETCHED_IN;
3096 state_type = GTK_STATE_INSENSITIVE;
3099 if (notebook->tab_pos == GTK_POS_LEFT ||
3100 notebook->tab_pos == GTK_POS_RIGHT)
3101 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3103 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3105 gtk_paint_arrow (widget->style, widget->window, state_type,
3106 shadow_type, NULL, widget, "notebook",
3107 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3108 ARROW_SIZE, ARROW_SIZE);
3112 /* Private GtkNotebook Size Allocate Functions:
3114 * gtk_notebook_pages_allocate
3115 * gtk_notebook_page_allocate
3116 * gtk_notebook_calc_tabs
3119 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3121 GtkWidget *widget = GTK_WIDGET (notebook);
3122 GtkContainer *container = GTK_CONTAINER (notebook);
3123 GtkNotebookPage *page = NULL;
3124 GtkAllocation *allocation = &widget->allocation;
3125 GtkAllocation child_allocation;
3126 GList *children = NULL;
3127 GList *last_child = NULL;
3128 gboolean showarrow = FALSE;
3135 gint tab_pos = get_effective_tab_pos (notebook);
3136 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3137 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3140 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3143 child_allocation.x = widget->allocation.x + container->border_width;
3144 child_allocation.y = widget->allocation.y + container->border_width;
3148 case GTK_POS_BOTTOM:
3149 child_allocation.y = (widget->allocation.y +
3150 allocation->height -
3151 notebook->cur_page->requisition.height -
3152 container->border_width);
3155 child_allocation.height = notebook->cur_page->requisition.height;
3159 child_allocation.x = (widget->allocation.x +
3161 notebook->cur_page->requisition.width -
3162 container->border_width);
3165 child_allocation.width = notebook->cur_page->requisition.width;
3169 if (notebook->scrollable)
3173 children = notebook->children;
3175 if (notebook->focus_tab)
3176 focus_tab = notebook->focus_tab;
3177 else if (notebook->first_tab)
3178 focus_tab = notebook->first_tab;
3180 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3185 case GTK_POS_BOTTOM:
3188 page = children->data;
3189 children = children->next;
3191 if (GTK_WIDGET_VISIBLE (page->child))
3192 tab_space += page->requisition.width;
3195 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3198 page = focus_tab->data;
3200 tab_space = allocation->width - TAB_OVERLAP -
3201 page->requisition.width - 2 * container->border_width;
3202 if (notebook->has_after_previous)
3203 tab_space -= ARROW_SPACING + ARROW_SIZE;
3204 if (notebook->has_after_next)
3205 tab_space -= ARROW_SPACING + ARROW_SIZE;
3206 if (notebook->has_before_previous)
3208 tab_space -= ARROW_SPACING + ARROW_SIZE;
3209 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3211 if (notebook->has_before_next)
3213 tab_space -= ARROW_SPACING + ARROW_SIZE;
3214 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3222 page = children->data;
3223 children = children->next;
3225 if (GTK_WIDGET_VISIBLE (page->child))
3226 tab_space += page->requisition.height;
3229 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3232 page = focus_tab->data;
3233 tab_space = allocation->height
3234 - TAB_OVERLAP - 2 * container->border_width
3235 - page->requisition.height;
3236 if (notebook->has_after_previous || notebook->has_after_next)
3237 tab_space -= ARROW_SPACING + ARROW_SIZE;
3238 if (notebook->has_before_previous || notebook->has_before_next)
3240 tab_space -= ARROW_SPACING + ARROW_SIZE;
3241 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3246 if (showarrow) /* first_tab <- focus_tab */
3250 notebook->first_tab = focus_tab;
3251 last_child = gtk_notebook_search_page (notebook, focus_tab,
3257 if (notebook->first_tab && notebook->first_tab != focus_tab)
3259 /* Is first_tab really predecessor of focus_tab ? */
3260 page = notebook->first_tab->data;
3261 if (GTK_WIDGET_VISIBLE (page->child))
3262 for (children = focus_tab;
3263 children && children != notebook->first_tab;
3264 children = gtk_notebook_search_page (notebook,
3270 notebook->first_tab = focus_tab;
3272 gtk_notebook_calc_tabs (notebook,
3273 gtk_notebook_search_page (notebook,
3277 &(notebook->first_tab), &tab_space,
3282 notebook->first_tab =
3283 gtk_notebook_search_page (notebook, notebook->first_tab,
3285 if (!notebook->first_tab)
3286 notebook->first_tab = focus_tab;
3287 last_child = gtk_notebook_search_page (notebook, focus_tab,
3290 else /* focus_tab -> end */
3292 if (!notebook->first_tab)
3293 notebook->first_tab = gtk_notebook_search_page (notebook,
3298 gtk_notebook_calc_tabs (notebook,
3299 gtk_notebook_search_page (notebook,
3303 &children, &tab_space, STEP_NEXT);
3306 last_child = children;
3307 else /* start <- first_tab */
3311 gtk_notebook_calc_tabs
3313 gtk_notebook_search_page (notebook,
3314 notebook->first_tab,
3317 &children, &tab_space, STEP_PREV);
3318 notebook->first_tab = gtk_notebook_search_page(notebook,
3328 tab_space = -tab_space;
3330 for (children = notebook->first_tab;
3331 children && children != last_child;
3332 children = gtk_notebook_search_page (notebook, children,
3339 /*unmap all non-visible tabs*/
3340 for (children = gtk_notebook_search_page (notebook, NULL,
3342 children && children != notebook->first_tab;
3343 children = gtk_notebook_search_page (notebook, children,
3346 page = children->data;
3347 if (page->tab_label)
3348 gtk_widget_set_child_visible (page->tab_label, FALSE);
3350 for (children = last_child; children;
3351 children = gtk_notebook_search_page (notebook, children,
3354 page = children->data;
3355 if (page->tab_label)
3356 gtk_widget_set_child_visible (page->tab_label, FALSE);
3359 else /* !showarrow */
3361 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3372 children = notebook->children;
3376 case GTK_POS_BOTTOM:
3379 page = children->data;
3380 children = children->next;
3382 if (GTK_WIDGET_VISIBLE (page->child))
3385 tab_space += page->requisition.width;
3390 tab_space -= allocation->width;
3396 page = children->data;
3397 children = children->next;
3399 if (GTK_WIDGET_VISIBLE (page->child))
3402 tab_space += page->requisition.height;
3407 tab_space -= allocation->height;
3409 tab_space += 2 * container->border_width + TAB_OVERLAP;
3411 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3413 if (notebook->homogeneous && n)
3417 children = notebook->first_tab;
3420 memo_x = child_allocation.x;
3421 if (notebook->children && is_rtl)
3423 child_allocation.x = (allocation->x + allocation->width -
3424 container->border_width);
3427 if (notebook->has_after_previous)
3428 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3429 if (notebook->has_after_next)
3430 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3436 if (children == last_child)
3438 /* FIXME double check */
3442 page = children->data;
3443 if (!showarrow && page->pack != GTK_PACK_START)
3445 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3448 if (n && (showarrow || page->expand || notebook->homogeneous))
3450 new_fill = (tab_space * i++) / n;
3451 delta = new_fill - old_fill;
3452 old_fill = new_fill;
3458 case GTK_POS_BOTTOM:
3459 child_allocation.width = (page->requisition.width +
3460 TAB_OVERLAP + delta);
3462 child_allocation.x -= child_allocation.width;
3466 child_allocation.height = (page->requisition.height +
3467 TAB_OVERLAP + delta);
3471 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3476 case GTK_POS_BOTTOM:
3478 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3480 child_allocation.x += TAB_OVERLAP;
3484 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3488 if (page->tab_label)
3489 gtk_widget_set_child_visible (page->tab_label, TRUE);
3494 children = notebook->children;
3499 case GTK_POS_BOTTOM:
3501 child_allocation.x = (allocation->x + allocation->width -
3502 container->border_width);
3504 child_allocation.x = memo_x;
3508 child_allocation.y = (allocation->y + allocation->height -
3509 container->border_width);
3513 while (children != last_child)
3515 page = children->data;
3516 children = children->next;
3518 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3522 if (n && (page->expand || notebook->homogeneous))
3524 new_fill = (tab_space * i++) / n;
3525 delta = new_fill - old_fill;
3526 old_fill = new_fill;
3532 case GTK_POS_BOTTOM:
3533 child_allocation.width = (page->requisition.width +
3534 TAB_OVERLAP + delta);
3536 child_allocation.x -= child_allocation.width;
3540 child_allocation.height = (page->requisition.height +
3541 TAB_OVERLAP + delta);
3542 child_allocation.y -= child_allocation.height;
3546 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3551 case GTK_POS_BOTTOM:
3553 child_allocation.x += TAB_OVERLAP;
3555 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3559 child_allocation.y += TAB_OVERLAP;
3563 if (page->tab_label)
3564 gtk_widget_set_child_visible (page->tab_label, TRUE);
3569 gtk_notebook_redraw_tabs (notebook);
3573 gtk_notebook_page_allocate (GtkNotebook *notebook,
3574 GtkNotebookPage *page,
3575 GtkAllocation *allocation)
3577 GtkWidget *widget = GTK_WIDGET (notebook);
3578 GtkAllocation child_allocation;
3579 GtkRequisition tab_requisition;
3584 gint tab_pos = get_effective_tab_pos (notebook);
3586 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3588 xthickness = widget->style->xthickness;
3589 ythickness = widget->style->ythickness;
3591 /* If the size of the notebook tabs change, we need to queue
3592 * a redraw on the tab area
3594 if ((allocation->width != page->allocation.width) ||
3595 (allocation->height != page->allocation.height))
3597 gint x, y, width, height, border_width;
3599 border_width = GTK_CONTAINER (notebook)->border_width;
3604 width = widget->allocation.width;
3605 height = MAX (page->allocation.height, allocation->height) + ythickness;
3610 case GTK_POS_BOTTOM:
3611 width = widget->allocation.width + xthickness;
3612 height = MAX (page->allocation.height, allocation->height) + ythickness;
3614 y = widget->allocation.height - height - border_width;
3618 width = MAX (page->allocation.width, allocation->width) + xthickness;
3619 height = widget->allocation.height;
3625 default: /* quiet gcc */
3626 width = MAX (page->allocation.width, allocation->width) + xthickness;
3627 height = widget->allocation.height;
3628 x = widget->allocation.width - width - border_width;
3633 gtk_widget_queue_draw_area (widget, x, y, width, height);
3636 page->allocation = *allocation;
3637 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3639 if (notebook->cur_page != page)
3644 page->allocation.y += ythickness;
3645 case GTK_POS_BOTTOM:
3646 if (page->allocation.height > ythickness)
3647 page->allocation.height -= ythickness;
3650 page->allocation.x += xthickness;
3652 if (page->allocation.width > xthickness)
3653 page->allocation.width -= xthickness;
3661 case GTK_POS_BOTTOM:
3662 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3665 child_allocation.x = (xthickness + focus_width +
3666 notebook->tab_hborder);
3667 child_allocation.width = MAX (1, (page->allocation.width -
3668 2 * child_allocation.x));
3669 child_allocation.x += page->allocation.x;
3673 child_allocation.x = (page->allocation.x +
3674 (page->allocation.width -
3675 tab_requisition.width) / 2);
3676 child_allocation.width = tab_requisition.width;
3678 child_allocation.y = (notebook->tab_vborder + focus_width +
3679 page->allocation.y);
3680 if (tab_pos == GTK_POS_TOP)
3681 child_allocation.y += ythickness;
3682 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3683 2 * (notebook->tab_vborder + focus_width)));
3687 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3690 child_allocation.y = ythickness + padding;
3691 child_allocation.height = MAX (1, (page->allocation.height -
3692 2 * child_allocation.y));
3693 child_allocation.y += page->allocation.y;
3697 child_allocation.y = (page->allocation.y + (page->allocation.height -
3698 tab_requisition.height) / 2);
3699 child_allocation.height = tab_requisition.height;
3701 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3702 if (tab_pos == GTK_POS_LEFT)
3703 child_allocation.x += xthickness;
3704 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3705 2 * (notebook->tab_hborder + focus_width)));
3709 if (page->tab_label)
3710 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3714 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3720 GtkNotebookPage *page = NULL;
3722 GList *last_list = NULL;
3724 gint tab_pos = get_effective_tab_pos (notebook);
3730 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3731 if (pack == GTK_PACK_END)
3732 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3739 case GTK_POS_BOTTOM:
3742 page = children->data;
3743 if (GTK_WIDGET_VISIBLE (page->child))
3745 if (page->pack == pack)
3747 *tab_space -= page->requisition.width;
3748 if (*tab_space < 0 || children == *end)
3752 *tab_space = - (*tab_space +
3753 page->requisition.width);
3759 last_list = children;
3761 if (direction == STEP_NEXT)
3762 children = children->next;
3764 children = children->prev;
3771 page = children->data;
3772 if (GTK_WIDGET_VISIBLE (page->child))
3774 if (page->pack == pack)
3776 *tab_space -= page->requisition.height;
3777 if (*tab_space < 0 || children == *end)
3781 *tab_space = - (*tab_space +
3782 page->requisition.height);
3788 last_list = children;
3790 if (direction == STEP_NEXT)
3791 children = children->next;
3793 children = children->prev;
3797 if (direction == STEP_PREV)
3799 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3800 direction = STEP_PREV;
3801 children = last_list;
3806 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3810 for (list = notebook->children; list != NULL; list = list->next)
3812 GtkNotebookPage *page = list->data;
3814 if (page->tab_label)
3816 if (page == notebook->cur_page)
3817 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3819 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3824 /* Private GtkNotebook Page Switch Methods:
3826 * gtk_notebook_real_switch_page
3829 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3830 GtkNotebookPage *page,
3833 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3834 g_return_if_fail (page != NULL);
3836 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3839 if (notebook->cur_page)
3840 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3842 notebook->cur_page = page;
3844 if (!notebook->focus_tab ||
3845 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3846 notebook->focus_tab =
3847 g_list_find (notebook->children, notebook->cur_page);
3849 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3851 /* If the focus was on the previous page, move it to the first
3852 * element on the new page, if possible, or if not, to the
3855 if (notebook->child_has_focus)
3857 if (notebook->cur_page->last_focus_child &&
3858 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3859 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3861 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3862 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3865 gtk_notebook_update_tab_states (notebook);
3866 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3867 g_object_notify (G_OBJECT (notebook), "page");
3870 /* Private GtkNotebook Page Switch Functions:
3872 * gtk_notebook_switch_page
3873 * gtk_notebook_page_select
3874 * gtk_notebook_switch_focus_tab
3875 * gtk_notebook_menu_switch_page
3878 gtk_notebook_switch_page (GtkNotebook *notebook,
3879 GtkNotebookPage *page,
3882 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3883 g_return_if_fail (page != NULL);
3885 if (notebook->cur_page == page)
3889 page_num = g_list_index (notebook->children, page);
3891 g_signal_emit (notebook,
3892 notebook_signals[SWITCH_PAGE],
3899 gtk_notebook_page_select (GtkNotebook *notebook,
3900 gboolean move_focus)
3902 GtkNotebookPage *page;
3903 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3904 gint tab_pos = get_effective_tab_pos (notebook);
3906 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3908 if (!notebook->focus_tab)
3911 page = notebook->focus_tab->data;
3912 gtk_notebook_switch_page (notebook, page, -1);
3921 case GTK_POS_BOTTOM:
3925 dir = GTK_DIR_RIGHT;
3932 if (gtk_widget_child_focus (page->child, dir))
3939 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3943 GtkNotebookPage *old_page = NULL;
3944 GtkNotebookPage *page;
3946 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3948 if (notebook->focus_tab == new_child)
3951 old_child = notebook->focus_tab;
3952 notebook->focus_tab = new_child;
3954 if (notebook->scrollable)
3955 gtk_notebook_redraw_arrows (notebook);
3957 if (!notebook->show_tabs || !notebook->focus_tab)
3961 old_page = old_child->data;
3963 page = notebook->focus_tab->data;
3964 if (GTK_WIDGET_MAPPED (page->tab_label))
3965 gtk_notebook_redraw_tabs (notebook);
3967 gtk_notebook_pages_allocate (notebook);
3969 gtk_notebook_switch_page (notebook, page,
3970 g_list_index (notebook->children, page));
3974 gtk_notebook_menu_switch_page (GtkWidget *widget,
3975 GtkNotebookPage *page)
3977 GtkNotebook *notebook;
3981 g_return_if_fail (widget != NULL);
3982 g_return_if_fail (page != NULL);
3984 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3985 (GTK_MENU (widget->parent)));
3987 if (notebook->cur_page == page)
3991 children = notebook->children;
3992 while (children && children->data != page)
3994 children = children->next;
3998 g_signal_emit (notebook,
3999 notebook_signals[SWITCH_PAGE],
4005 /* Private GtkNotebook Menu Functions:
4007 * gtk_notebook_menu_item_create
4008 * gtk_notebook_menu_label_unparent
4009 * gtk_notebook_menu_detacher
4012 gtk_notebook_menu_item_create (GtkNotebook *notebook,
4015 GtkNotebookPage *page;
4016 GtkWidget *menu_item;
4019 if (page->default_menu)
4021 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
4022 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
4024 page->menu_label = gtk_label_new ("");
4025 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
4028 gtk_widget_show (page->menu_label);
4029 menu_item = gtk_menu_item_new ();
4030 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
4031 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
4032 gtk_notebook_real_page_position (notebook, list));
4033 g_signal_connect (menu_item, "activate",
4034 G_CALLBACK (gtk_notebook_menu_switch_page), page);
4035 if (GTK_WIDGET_VISIBLE (page->child))
4036 gtk_widget_show (menu_item);
4040 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4043 gtk_widget_unparent (GTK_BIN(widget)->child);
4044 GTK_BIN(widget)->child = NULL;
4048 gtk_notebook_menu_detacher (GtkWidget *widget,
4051 GtkNotebook *notebook;
4053 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4055 notebook = GTK_NOTEBOOK (widget);
4056 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4058 notebook->menu = NULL;
4061 /* Private GtkNotebook Setter Functions:
4063 * gtk_notebook_set_homogeneous_tabs_internal
4064 * gtk_notebook_set_tab_border_internal
4065 * gtk_notebook_set_tab_hborder_internal
4066 * gtk_notebook_set_tab_vborder_internal
4069 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4070 gboolean homogeneous)
4072 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4074 if (homogeneous == notebook->homogeneous)
4077 notebook->homogeneous = homogeneous;
4078 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4080 g_object_notify (G_OBJECT (notebook), "homogeneous");
4084 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4087 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4089 notebook->tab_hborder = border_width;
4090 notebook->tab_vborder = border_width;
4092 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4093 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4095 g_object_freeze_notify (G_OBJECT (notebook));
4096 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4097 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4098 g_object_thaw_notify (G_OBJECT (notebook));
4102 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4105 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4107 if (notebook->tab_hborder == tab_hborder)
4110 notebook->tab_hborder = tab_hborder;
4112 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4113 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4115 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4119 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4122 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4124 if (notebook->tab_vborder == tab_vborder)
4127 notebook->tab_vborder = tab_vborder;
4129 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4130 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4132 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4135 /* Public GtkNotebook Page Insert/Remove Methods :
4137 * gtk_notebook_append_page
4138 * gtk_notebook_append_page_menu
4139 * gtk_notebook_prepend_page
4140 * gtk_notebook_prepend_page_menu
4141 * gtk_notebook_insert_page
4142 * gtk_notebook_insert_page_menu
4143 * gtk_notebook_remove_page
4146 * gtk_notebook_append_page:
4147 * @notebook: a #GtkNotebook
4148 * @child: the #GtkWidget to use as the contents of the page.
4149 * @tab_label: the #GtkWidget to be used as the label for the page,
4150 * or %NULL to use the default label, 'page N'.
4152 * Appends a page to @notebook.
4154 * Return value: the index (starting from 0) of the appended
4155 * page in the notebook, or -1 if function fails
4158 gtk_notebook_append_page (GtkNotebook *notebook,
4160 GtkWidget *tab_label)
4162 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4163 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4164 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4166 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4170 * gtk_notebook_append_page_menu:
4171 * @notebook: a #GtkNotebook
4172 * @child: the #GtkWidget to use as the contents of the page.
4173 * @tab_label: the #GtkWidget to be used as the label for the page,
4174 * or %NULL to use the default label, 'page N'.
4175 * @menu_label: the widget to use as a label for the page-switch
4176 * menu, if that is enabled. If %NULL, and @tab_label
4177 * is a #GtkLabel or %NULL, then the menu label will be
4178 * a newly created label with the same text as @tab_label;
4179 * If @tab_label is not a #GtkLabel, @menu_label must be
4180 * specified if the page-switch menu is to be used.
4182 * Appends a page to @notebook, specifying the widget to use as the
4183 * label in the popup menu.
4185 * Return value: the index (starting from 0) of the appended
4186 * page in the notebook, or -1 if function fails
4189 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4191 GtkWidget *tab_label,
4192 GtkWidget *menu_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);
4197 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4199 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4203 * gtk_notebook_prepend_page:
4204 * @notebook: a #GtkNotebook
4205 * @child: the #GtkWidget to use as the contents of the page.
4206 * @tab_label: the #GtkWidget to be used as the label for the page,
4207 * or %NULL to use the default label, 'page N'.
4209 * Prepends a page to @notebook.
4211 * Return value: the index (starting from 0) of the prepended
4212 * page in the notebook, or -1 if function fails
4215 gtk_notebook_prepend_page (GtkNotebook *notebook,
4217 GtkWidget *tab_label)
4219 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4220 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4221 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4223 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4227 * gtk_notebook_prepend_page_menu:
4228 * @notebook: a #GtkNotebook
4229 * @child: the #GtkWidget to use as the contents of the page.
4230 * @tab_label: the #GtkWidget to be used as the label for the page,
4231 * or %NULL to use the default label, 'page N'.
4232 * @menu_label: the widget to use as a label for the page-switch
4233 * menu, if that is enabled. If %NULL, and @tab_label
4234 * is a #GtkLabel or %NULL, then the menu label will be
4235 * a newly created label with the same text as @tab_label;
4236 * If @tab_label is not a #GtkLabel, @menu_label must be
4237 * specified if the page-switch menu is to be used.
4239 * Prepends a page to @notebook, specifying the widget to use as the
4240 * label in the popup menu.
4242 * Return value: the index (starting from 0) of the prepended
4243 * page in the notebook, or -1 if function fails
4246 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4248 GtkWidget *tab_label,
4249 GtkWidget *menu_label)
4251 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4252 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4253 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4254 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4256 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4260 * gtk_notebook_insert_page:
4261 * @notebook: a #GtkNotebook
4262 * @child: the #GtkWidget to use as the contents of the page.
4263 * @tab_label: the #GtkWidget to be used as the label for the page,
4264 * or %NULL to use the default label, 'page N'.
4265 * @position: the index (starting at 0) at which to insert the page,
4266 * or -1 to append the page after all other pages.
4268 * Insert a page into @notebook at the given position.
4270 * Return value: the index (starting from 0) of the inserted
4271 * page in the notebook, or -1 if function fails
4274 gtk_notebook_insert_page (GtkNotebook *notebook,
4276 GtkWidget *tab_label,
4279 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4280 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4281 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4283 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4288 gtk_notebook_page_compare_tab (gconstpointer a,
4291 return (((GtkNotebookPage *) a)->tab_label != b);
4295 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4299 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4302 list = g_list_find_custom (notebook->children, child,
4303 gtk_notebook_page_compare_tab);
4306 GtkNotebookPage *page = list->data;
4308 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4309 gtk_notebook_switch_page (notebook, page, -1);
4310 focus_tabs_in (notebook);
4317 * gtk_notebook_insert_page_menu:
4318 * @notebook: a #GtkNotebook
4319 * @child: the #GtkWidget to use as the contents of the page.
4320 * @tab_label: the #GtkWidget to be used as the label for the page,
4321 * or %NULL to use the default label, 'page N'.
4322 * @menu_label: the widget to use as a label for the page-switch
4323 * menu, if that is enabled. If %NULL, and @tab_label
4324 * is a #GtkLabel or %NULL, then the menu label will be
4325 * a newly created label with the same text as @tab_label;
4326 * If @tab_label is not a #GtkLabel, @menu_label must be
4327 * specified if the page-switch menu is to be used.
4328 * @position: the index (starting at 0) at which to insert the page,
4329 * or -1 to append the page after all other pages.
4331 * Insert a page into @notebook at the given position, specifying
4332 * the widget to use as the label in the popup menu.
4334 * Return value: the index (starting from 0) of the inserted
4335 * page in the notebook, or -1 if function fails
4338 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4340 GtkWidget *tab_label,
4341 GtkWidget *menu_label,
4344 GtkNotebookPage *page;
4347 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4348 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4349 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4350 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4352 gtk_widget_freeze_child_notify (child);
4354 page = g_new (GtkNotebookPage, 1);
4355 page->child = child;
4356 page->last_focus_child = NULL;
4357 page->requisition.width = 0;
4358 page->requisition.height = 0;
4359 page->allocation.x = 0;
4360 page->allocation.y = 0;
4361 page->allocation.width = 0;
4362 page->allocation.height = 0;
4363 page->default_menu = FALSE;
4364 page->default_tab = FALSE;
4365 page->mnemonic_activate_signal = 0;
4367 nchildren = g_list_length (notebook->children);
4368 if ((position < 0) || (position > nchildren))
4369 position = nchildren;
4371 notebook->children = g_list_insert (notebook->children, page, position);
4375 page->default_tab = TRUE;
4376 if (notebook->show_tabs)
4377 tab_label = gtk_label_new ("");
4379 page->tab_label = tab_label;
4380 page->menu_label = menu_label;
4381 page->expand = FALSE;
4383 page->pack = GTK_PACK_START;
4386 page->default_menu = TRUE;
4389 g_object_ref (page->menu_label);
4390 gtk_object_sink (GTK_OBJECT (page->menu_label));
4394 gtk_notebook_menu_item_create (notebook,
4395 g_list_find (notebook->children, page));
4397 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4399 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4401 gtk_notebook_update_labels (notebook);
4403 if (!notebook->first_tab)
4404 notebook->first_tab = notebook->children;
4406 if (!notebook->cur_page)
4407 gtk_widget_set_child_visible (child, TRUE);
4409 gtk_widget_set_child_visible (child, FALSE);
4413 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4414 gtk_widget_show (tab_label);
4416 gtk_widget_hide (tab_label);
4419 if (!notebook->cur_page)
4421 gtk_notebook_switch_page (notebook, page, 0);
4422 gtk_notebook_switch_focus_tab (notebook, NULL);
4425 gtk_notebook_update_tab_states (notebook);
4428 page->mnemonic_activate_signal =
4429 g_signal_connect (tab_label,
4430 "mnemonic_activate",
4431 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4434 gtk_widget_child_notify (child, "tab_expand");
4435 gtk_widget_child_notify (child, "tab_fill");
4436 gtk_widget_child_notify (child, "tab_pack");
4437 gtk_widget_child_notify (child, "tab_label");
4438 gtk_widget_child_notify (child, "menu_label");
4439 gtk_widget_child_notify (child, "position");
4440 gtk_widget_thaw_child_notify (child);
4446 * gtk_notebook_remove_page:
4447 * @notebook: a #GtkNotebook.
4448 * @page_num: the index of a notebook page, starting
4449 * from 0. If -1, the last page will
4452 * Removes a page from the notebook given its index
4456 gtk_notebook_remove_page (GtkNotebook *notebook,
4461 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4465 list = g_list_nth (notebook->children, page_num);
4467 gtk_notebook_real_remove (notebook, list, FALSE);
4471 list = g_list_last (notebook->children);
4473 gtk_notebook_real_remove (notebook, list, FALSE);
4477 /* Public GtkNotebook Page Switch Methods :
4478 * gtk_notebook_get_current_page
4479 * gtk_notebook_page_num
4480 * gtk_notebook_set_current_page
4481 * gtk_notebook_next_page
4482 * gtk_notebook_prev_page
4485 * gtk_notebook_get_current_page:
4486 * @notebook: a #GtkNotebook
4488 * Returns the page number of the current page.
4490 * Return value: the index (starting from 0) of the current
4491 * page in the notebook. If the notebook has no pages, then
4492 * -1 will be returned.
4495 gtk_notebook_get_current_page (GtkNotebook *notebook)
4497 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4499 if (!notebook->cur_page)
4502 return g_list_index (notebook->children, notebook->cur_page);
4506 * gtk_notebook_get_nth_page:
4507 * @notebook: a #GtkNotebook
4508 * @page_num: the index of a page in the noteobok, or -1
4509 * to get the last page.
4511 * Returns the child widget contained in page number @page_num.
4513 * Return value: the child widget, or %NULL if @page_num is
4517 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4520 GtkNotebookPage *page;
4523 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4526 list = g_list_nth (notebook->children, page_num);
4528 list = g_list_last (notebook->children);
4540 * gtk_notebook_get_n_pages:
4541 * @notebook: a #GtkNotebook
4543 * Gets the number of pages in a notebook.
4545 * Return value: the number of pages in the notebook.
4550 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4552 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4554 return g_list_length (notebook->children);
4558 * gtk_notebook_page_num:
4559 * @notebook: a #GtkNotebook
4560 * @child: a #GtkWidget
4562 * Finds the index of the page which contains the given child
4565 * Return value: the index of the page containing @child, or
4566 * -1 if @child is not in the notebook.
4569 gtk_notebook_page_num (GtkNotebook *notebook,
4575 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4578 children = notebook->children;
4581 GtkNotebookPage *page = children->data;
4583 if (page->child == child)
4586 children = children->next;
4594 * gtk_notebook_set_current_page:
4595 * @notebook: a #GtkNotebook
4596 * @page_num: index of the page to switch to, starting from 0.
4597 * If negative, the last page will be used. If greater
4598 * than the number of pages in the notebook, nothing
4601 * Switches to the page number @page_num.
4604 gtk_notebook_set_current_page (GtkNotebook *notebook,
4609 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4612 list = g_list_nth (notebook->children, page_num);
4614 list = g_list_last (notebook->children);
4616 page_num = g_list_index (notebook->children, list);
4619 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4623 * gtk_notebook_next_page:
4624 * @notebook: a #GtkNotebook
4626 * Switches to the next page. Nothing happens if the current page is
4630 gtk_notebook_next_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_NEXT, TRUE);
4644 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4648 * gtk_notebook_prev_page:
4649 * @notebook: a #GtkNotebook
4651 * Switches to the previous page. Nothing happens if the current page
4652 * is the first page.
4655 gtk_notebook_prev_page (GtkNotebook *notebook)
4659 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4661 list = g_list_find (notebook->children, notebook->cur_page);
4665 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4669 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4672 /* Public GtkNotebook/Tab Style Functions
4674 * gtk_notebook_set_show_border
4675 * gtk_notebook_set_show_tabs
4676 * gtk_notebook_set_tab_pos
4677 * gtk_notebook_set_homogeneous_tabs
4678 * gtk_notebook_set_tab_border
4679 * gtk_notebook_set_tab_hborder
4680 * gtk_notebook_set_tab_vborder
4681 * gtk_notebook_set_scrollable
4684 * gtk_notebook_set_show_border:
4685 * @notebook: a #GtkNotebook
4686 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4688 * Sets whether a bevel will be drawn around the notebook pages.
4689 * This only has a visual effect when the tabs are not shown.
4690 * See gtk_notebook_set_show_tabs().
4693 gtk_notebook_set_show_border (GtkNotebook *notebook,
4694 gboolean show_border)
4696 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4698 if (notebook->show_border != show_border)
4700 notebook->show_border = show_border;
4702 if (GTK_WIDGET_VISIBLE (notebook))
4703 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4705 g_object_notify (G_OBJECT (notebook), "show_border");
4710 * gtk_notebook_get_show_border:
4711 * @notebook: a #GtkNotebook
4713 * Returns whether a bevel will be drawn around the notebook pages. See
4714 * gtk_notebook_set_show_border().
4716 * Return value: %TRUE if the bevel is drawn
4719 gtk_notebook_get_show_border (GtkNotebook *notebook)
4721 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4723 return notebook->show_border;
4727 * gtk_notebook_set_show_tabs:
4728 * @notebook: a #GtkNotebook
4729 * @show_tabs: %TRUE if the tabs should be shown.
4731 * Sets whether to show the tabs for the notebook or not.
4734 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4737 GtkNotebookPage *page;
4740 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4742 show_tabs = show_tabs != FALSE;
4744 if (notebook->show_tabs == show_tabs)
4747 notebook->show_tabs = show_tabs;
4748 children = notebook->children;
4752 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4756 page = children->data;
4757 children = children->next;
4758 if (page->default_tab)
4760 gtk_widget_destroy (page->tab_label);
4761 page->tab_label = NULL;
4764 gtk_widget_hide (page->tab_label);
4769 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4770 gtk_notebook_update_labels (notebook);
4772 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4774 g_object_notify (G_OBJECT (notebook), "show_tabs");
4778 * gtk_notebook_get_show_tabs:
4779 * @notebook: a #GtkNotebook
4781 * Returns whether the tabs of the notebook are shown. See
4782 * gtk_notebook_set_show_tabs().
4784 * Return value: %TRUE if the tabs are shown
4787 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4789 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4791 return notebook->show_tabs;
4795 * gtk_notebook_set_tab_pos:
4796 * @notebook: a #GtkNotebook.
4797 * @pos: the edge to draw the tabs at.
4799 * Sets the edge at which the tabs for switching pages in the
4800 * notebook are drawn.
4803 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4804 GtkPositionType pos)
4806 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4808 if (notebook->tab_pos != pos)
4810 notebook->tab_pos = pos;
4811 if (GTK_WIDGET_VISIBLE (notebook))
4812 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4815 g_object_notify (G_OBJECT (notebook), "tab_pos");
4819 * gtk_notebook_get_tab_pos:
4820 * @notebook: a #GtkNotebook
4822 * Gets the edge at which the tabs for switching pages in the
4823 * notebook are drawn.
4825 * Return value: the edge at which the tabs are drawn
4828 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4830 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4832 return notebook->tab_pos;
4836 * gtk_notebook_set_homogeneous_tabs:
4837 * @notebook: a #GtkNotebook
4838 * @homogeneous: %TRUE if all tabs should be the same size.
4840 * Sets whether the tabs must have all the same size or not.
4843 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4844 gboolean homogeneous)
4846 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4848 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4852 * gtk_notebook_set_tab_border:
4853 * @notebook: a #GtkNotebook
4854 * @border_width: width of the border around the tab labels.
4856 * Sets the width the border around the tab labels
4857 * in a notebook. This is equivalent to calling
4858 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4859 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4862 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4865 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4867 gtk_notebook_set_tab_border_internal (notebook, border_width);
4871 * gtk_notebook_set_tab_hborder:
4872 * @notebook: a #GtkNotebook
4873 * @tab_hborder: width of the horizontal border of tab labels.
4875 * Sets the width of the horizontal border of tab labels.
4878 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4881 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4883 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4887 * gtk_notebook_set_tab_vborder:
4888 * @notebook: a #GtkNotebook
4889 * @tab_vborder: width of the vertical border of tab labels.
4891 * Sets the width of the vertical border of tab labels.
4894 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4897 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4899 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4903 * gtk_notebook_set_scrollable:
4904 * @notebook: a #GtkNotebook
4905 * @scrollable: %TRUE if scroll arrows should be added
4907 * Sets whether the tab label area will have arrows for scrolling if
4908 * there are too many tabs to fit in the area.
4911 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4912 gboolean scrollable)
4914 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4916 scrollable = (scrollable != FALSE);
4918 if (scrollable != notebook->scrollable)
4920 notebook->scrollable = scrollable;
4922 if (GTK_WIDGET_VISIBLE (notebook))
4923 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4925 g_object_notify (G_OBJECT (notebook), "scrollable");
4930 * gtk_notebook_get_scrollable:
4931 * @notebook: a #GtkNotebook
4933 * Returns whether the tab label area has arrows for scrolling. See
4934 * gtk_notebook_set_scrollable().
4936 * Return value: %TRUE if arrows for scrolling are present
4939 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4941 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4943 return notebook->scrollable;
4946 /* Public GtkNotebook Popup Menu Methods:
4948 * gtk_notebook_popup_enable
4949 * gtk_notebook_popup_disable
4954 * gtk_notebook_popup_enable:
4955 * @notebook: a #GtkNotebook
4957 * Enables the popup menu: if the user clicks with the right mouse button on
4958 * the bookmarks, a menu with all the pages will be popped up.
4961 gtk_notebook_popup_enable (GtkNotebook *notebook)
4965 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4970 notebook->menu = gtk_menu_new ();
4971 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4973 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4974 gtk_notebook_menu_item_create (notebook, list);
4976 gtk_notebook_update_labels (notebook);
4977 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4978 GTK_WIDGET (notebook),
4979 gtk_notebook_menu_detacher);
4981 g_object_notify (G_OBJECT (notebook), "enable_popup");
4985 * gtk_notebook_popup_disable:
4986 * @notebook: a #GtkNotebook
4988 * Disables the popup menu.
4991 gtk_notebook_popup_disable (GtkNotebook *notebook)
4993 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4995 if (!notebook->menu)
4998 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4999 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
5000 gtk_widget_destroy (notebook->menu);
5002 g_object_notify (G_OBJECT (notebook), "enable_popup");
5005 /* Public GtkNotebook Page Properties Functions:
5007 * gtk_notebook_get_tab_label
5008 * gtk_notebook_set_tab_label
5009 * gtk_notebook_set_tab_label_text
5010 * gtk_notebook_get_menu_label
5011 * gtk_notebook_set_menu_label
5012 * gtk_notebook_set_menu_label_text
5013 * gtk_notebook_set_tab_label_packing
5014 * gtk_notebook_query_tab_label_packing
5018 * gtk_notebook_get_tab_label:
5019 * @notebook: a #GtkNotebook
5022 * Returns the tab label widget for the page @child. %NULL is returned
5023 * if @child is not in @notebook or if no tab label has specifically
5024 * been set for @child.
5026 * Return value: the tab label
5029 gtk_notebook_get_tab_label (GtkNotebook *notebook,
5034 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5035 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5037 list = CHECK_FIND_CHILD (notebook, child);
5041 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5044 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5048 * gtk_notebook_set_tab_label:
5049 * @notebook: a #GtkNotebook
5051 * @tab_label: the tab label widget to use, or %NULL for default tab
5054 * Changes the tab label for @child. If %NULL is specified
5055 * for @tab_label, then the page will have the label 'page N'.
5058 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5060 GtkWidget *tab_label)
5062 GtkNotebookPage *page;
5065 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5066 g_return_if_fail (GTK_IS_WIDGET (child));
5068 list = CHECK_FIND_CHILD (notebook, child);
5072 /* a NULL pointer indicates a default_tab setting, otherwise
5073 * we need to set the associated label
5077 if (page->tab_label == tab_label)
5081 gtk_notebook_remove_tab_label (notebook, page);
5085 page->default_tab = FALSE;
5086 page->tab_label = tab_label;
5087 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5091 page->default_tab = TRUE;
5092 page->tab_label = NULL;
5094 if (notebook->show_tabs)
5098 g_snprintf (string, sizeof(string), _("Page %u"),
5099 gtk_notebook_real_page_position (notebook, list));
5100 page->tab_label = gtk_label_new (string);
5101 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5105 if (page->tab_label)
5106 page->mnemonic_activate_signal =
5107 g_signal_connect (page->tab_label,
5108 "mnemonic_activate",
5109 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5112 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5114 gtk_widget_show (page->tab_label);
5115 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5118 gtk_notebook_update_tab_states (notebook);
5119 gtk_widget_child_notify (child, "tab_label");
5123 * gtk_notebook_set_tab_label_text:
5124 * @notebook: a #GtkNotebook
5126 * @tab_text: the label text
5128 * Creates a new label and sets it as the tab label for the page
5129 * containing @child.
5132 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5134 const gchar *tab_text)
5136 GtkWidget *tab_label = NULL;
5138 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5141 tab_label = gtk_label_new (tab_text);
5142 gtk_notebook_set_tab_label (notebook, child, tab_label);
5143 gtk_widget_child_notify (child, "tab_label");
5147 * gtk_notebook_get_tab_label_text:
5148 * @notebook: a #GtkNotebook
5149 * @child: a widget contained in a page of @notebook
5151 * Retrieves the text of the tab label for the page containing
5154 * Returns value: the text of the tab label, or %NULL if the
5155 * tab label widget is not a #GtkLabel. The
5156 * string is owned by the widget and must not
5159 G_CONST_RETURN gchar *
5160 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5163 GtkWidget *tab_label;
5165 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5166 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5168 tab_label = gtk_notebook_get_tab_label (notebook, child);
5170 if (tab_label && GTK_IS_LABEL (tab_label))
5171 return gtk_label_get_text (GTK_LABEL (tab_label));
5177 * gtk_notebook_get_menu_label:
5178 * @notebook: a #GtkNotebook
5179 * @child: a widget contained in a page of @notebook
5181 * Retrieves the menu label widget of the page containing @child.
5183 * Return value: the menu label, or %NULL if the
5184 * notebook page does not have a menu label other
5185 * than the default (the tab label).
5188 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5193 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5194 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5196 list = CHECK_FIND_CHILD (notebook, child);
5200 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5203 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5207 * gtk_notebook_set_menu_label:
5208 * @notebook: a #GtkNotebook
5209 * @child: the child widget
5210 * @menu_label: the menu label, or NULL for default
5212 * Changes the menu label for the page containing @child.
5215 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5217 GtkWidget *menu_label)
5219 GtkNotebookPage *page;
5222 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5223 g_return_if_fail (GTK_IS_WIDGET (child));
5225 list = CHECK_FIND_CHILD (notebook, child);
5230 if (page->menu_label)
5233 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5234 page->menu_label->parent);
5236 if (!page->default_menu)
5237 g_object_unref (page->menu_label);
5242 page->menu_label = menu_label;
5243 g_object_ref (page->menu_label);
5244 gtk_object_sink (GTK_OBJECT(page->menu_label));
5245 page->default_menu = FALSE;
5248 page->default_menu = TRUE;
5251 gtk_notebook_menu_item_create (notebook, list);
5252 gtk_widget_child_notify (child, "menu_label");
5256 * gtk_notebook_set_menu_label_text:
5257 * @notebook: a #GtkNotebook
5258 * @child: the child widget
5259 * @menu_text: the label text
5261 * Creates a new label and sets it as the menu label of @child.
5264 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5266 const gchar *menu_text)
5268 GtkWidget *menu_label = NULL;
5270 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5273 menu_label = gtk_label_new (menu_text);
5274 gtk_notebook_set_menu_label (notebook, child, menu_label);
5275 gtk_widget_child_notify (child, "menu_label");
5279 * gtk_notebook_get_menu_label_text:
5280 * @notebook: a #GtkNotebook
5281 * @child: the child widget of a page of the notebook.
5283 * Retrieves the text of the menu label for the page containing
5286 * Returns value: the text of the tab label, or %NULL if the
5287 * widget does not have a menu label other than
5288 * the default menu label, or the menu label widget
5289 * is not a #GtkLabel. The string is owned by
5290 * the widget and must not be freed.
5292 G_CONST_RETURN gchar *
5293 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5296 GtkWidget *menu_label;
5298 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5299 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5301 menu_label = gtk_notebook_get_menu_label (notebook, child);
5303 if (menu_label && GTK_IS_LABEL (menu_label))
5304 return gtk_label_get_text (GTK_LABEL (menu_label));
5309 /* Helper function called when pages are reordered
5312 gtk_notebook_child_reordered (GtkNotebook *notebook,
5313 GtkNotebookPage *page)
5317 GtkWidget *menu_item;
5319 menu_item = page->menu_label->parent;
5320 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5321 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5322 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5325 gtk_notebook_update_tab_states (notebook);
5326 gtk_notebook_update_labels (notebook);
5330 * gtk_notebook_set_tab_label_packing:
5331 * @notebook: a #GtkNotebook
5332 * @child: the child widget
5333 * @expand: whether to expand the bookmark or not
5334 * @fill: whether the bookmark should fill the allocated area or not
5335 * @pack_type: the position of the bookmark
5337 * Sets the packing parameters for the tab label of the page
5338 * containing @child. See gtk_box_pack_start() for the exact meaning
5339 * of the parameters.
5342 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5346 GtkPackType pack_type)
5348 GtkNotebookPage *page;
5351 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5352 g_return_if_fail (GTK_IS_WIDGET (child));
5354 list = CHECK_FIND_CHILD (notebook, child);
5359 expand = expand != FALSE;
5360 fill = fill != FALSE;
5361 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5364 gtk_widget_freeze_child_notify (child);
5365 page->expand = expand;
5366 gtk_widget_child_notify (child, "tab_expand");
5368 gtk_widget_child_notify (child, "tab_fill");
5369 if (page->pack != pack_type)
5371 page->pack = pack_type;
5372 gtk_notebook_child_reordered (notebook, page);
5374 gtk_widget_child_notify (child, "tab_pack");
5375 gtk_widget_child_notify (child, "position");
5376 if (notebook->show_tabs)
5377 gtk_notebook_pages_allocate (notebook);
5378 gtk_widget_thaw_child_notify (child);
5382 * gtk_notebook_query_tab_label_packing:
5383 * @notebook: a #GtkNotebook
5385 * @expand: location to store the expand value (or NULL)
5386 * @fill: location to store the fill value (or NULL)
5387 * @pack_type: location to store the pack_type (or NULL)
5389 * Query the packing attributes for the tab label of the page
5390 * containing @child.
5393 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5397 GtkPackType *pack_type)
5401 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5402 g_return_if_fail (GTK_IS_WIDGET (child));
5404 list = CHECK_FIND_CHILD (notebook, child);
5409 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5411 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5413 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5417 * gtk_notebook_reorder_child:
5418 * @notebook: a #GtkNotebook
5419 * @child: the child to move
5420 * @position: the new position, or -1 to move to the end
5422 * Reorders the page containing @child, so that it appears in position
5423 * @position. If @position is greater than or equal to the number of
5424 * children in the list or negative, @child will be moved to the end
5428 gtk_notebook_reorder_child (GtkNotebook *notebook,
5432 GList *list, *new_list;
5433 GtkNotebookPage *page;
5437 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5438 g_return_if_fail (GTK_IS_WIDGET (child));
5440 list = CHECK_FIND_CHILD (notebook, child);
5444 max_pos = g_list_length (notebook->children) - 1;
5445 if (position < 0 || position > max_pos)
5448 old_pos = g_list_position (notebook->children, list);
5450 if (old_pos == position)
5454 notebook->children = g_list_delete_link (notebook->children, list);
5456 notebook->children = g_list_insert (notebook->children, page, position);
5457 new_list = g_list_nth (notebook->children, position);
5459 /* Fix up GList references in GtkNotebook structure */
5460 if (notebook->first_tab == list)
5461 notebook->first_tab = new_list;
5462 if (notebook->focus_tab == list)
5463 notebook->focus_tab = new_list;
5465 gtk_widget_freeze_child_notify (child);
5467 /* Move around the menu items if necessary */
5468 gtk_notebook_child_reordered (notebook, page);
5469 gtk_widget_child_notify (child, "tab_pack");
5470 gtk_widget_child_notify (child, "position");
5472 if (notebook->show_tabs)
5473 gtk_notebook_pages_allocate (notebook);
5475 gtk_widget_thaw_child_notify (child);