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"
38 #include "gtkprivate.h"
43 #define TAB_CURVATURE 1
45 #define ARROW_SPACING 0
46 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
47 #define NOTEBOOK_SCROLL_DELAY (100)
73 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
74 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
93 CHILD_PROP_MENU_LABEL,
95 CHILD_PROP_TAB_EXPAND,
100 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
102 struct _GtkNotebookPage
105 GtkWidget *tab_label;
106 GtkWidget *menu_label;
107 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
109 guint default_menu : 1; /* If true, we create the menu label ourself */
110 guint default_tab : 1; /* If true, we create the tab label ourself */
115 GtkRequisition requisition;
116 GtkAllocation allocation;
118 guint mnemonic_activate_signal;
121 #ifdef G_DISABLE_CHECKS
122 #define CHECK_FIND_CHILD(notebook, child) \
123 gtk_notebook_find_child (notebook, child, G_STRLOC)
125 #define CHECK_FIND_CHILD(notebook, child) \
126 gtk_notebook_find_child (notebook, child, NULL)
129 /*** GtkNotebook Methods ***/
130 static void gtk_notebook_class_init (GtkNotebookClass *klass);
131 static void gtk_notebook_init (GtkNotebook *notebook);
133 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
134 gboolean move_focus);
135 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
136 GtkNotebookTab type);
137 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
139 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
140 GtkDirectionType direction_type);
142 /*** GtkObject Methods ***/
143 static void gtk_notebook_destroy (GtkObject *object);
144 static void gtk_notebook_set_property (GObject *object,
148 static void gtk_notebook_get_property (GObject *object,
153 /*** GtkWidget Methods ***/
154 static void gtk_notebook_map (GtkWidget *widget);
155 static void gtk_notebook_unmap (GtkWidget *widget);
156 static void gtk_notebook_realize (GtkWidget *widget);
157 static void gtk_notebook_unrealize (GtkWidget *widget);
158 static void gtk_notebook_size_request (GtkWidget *widget,
159 GtkRequisition *requisition);
160 static void gtk_notebook_size_allocate (GtkWidget *widget,
161 GtkAllocation *allocation);
162 static gint gtk_notebook_expose (GtkWidget *widget,
163 GdkEventExpose *event);
164 static gboolean gtk_notebook_scroll (GtkWidget *widget,
165 GdkEventScroll *event);
166 static gint gtk_notebook_button_press (GtkWidget *widget,
167 GdkEventButton *event);
168 static gint gtk_notebook_button_release (GtkWidget *widget,
169 GdkEventButton *event);
170 static gint gtk_notebook_enter_notify (GtkWidget *widget,
171 GdkEventCrossing *event);
172 static gint gtk_notebook_leave_notify (GtkWidget *widget,
173 GdkEventCrossing *event);
174 static gint gtk_notebook_motion_notify (GtkWidget *widget,
175 GdkEventMotion *event);
176 static gint gtk_notebook_focus_in (GtkWidget *widget,
177 GdkEventFocus *event);
178 static gint gtk_notebook_focus_out (GtkWidget *widget,
179 GdkEventFocus *event);
180 static void gtk_notebook_grab_notify (GtkWidget *widget,
181 gboolean was_grabbed);
182 static void gtk_notebook_state_changed (GtkWidget *widget,
183 GtkStateType previous_state);
184 static void gtk_notebook_draw_focus (GtkWidget *widget);
185 static gint gtk_notebook_focus (GtkWidget *widget,
186 GtkDirectionType direction);
187 static void gtk_notebook_style_set (GtkWidget *widget,
190 /*** GtkContainer Methods ***/
191 static void gtk_notebook_set_child_property (GtkContainer *container,
196 static void gtk_notebook_get_child_property (GtkContainer *container,
201 static void gtk_notebook_add (GtkContainer *container,
203 static void gtk_notebook_remove (GtkContainer *container,
205 static void gtk_notebook_set_focus_child (GtkContainer *container,
207 static GType gtk_notebook_child_type (GtkContainer *container);
208 static void gtk_notebook_forall (GtkContainer *container,
209 gboolean include_internals,
210 GtkCallback callback,
211 gpointer callback_data);
213 /*** GtkNotebook Private Functions ***/
214 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
215 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
216 static void gtk_notebook_real_remove (GtkNotebook *notebook,
218 gboolean destroying);
219 static void gtk_notebook_update_labels (GtkNotebook *notebook);
220 static gint gtk_notebook_timer (GtkNotebook *notebook);
221 static gint gtk_notebook_page_compare (gconstpointer a,
223 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
225 const gchar *function);
226 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
228 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
231 gboolean find_visible);
233 /*** GtkNotebook Drawing Functions ***/
234 static void gtk_notebook_paint (GtkWidget *widget,
236 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
237 GtkNotebookPage *page,
239 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
240 GtkNotebookArrow arrow);
242 /*** GtkNotebook Size Allocate Functions ***/
243 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
244 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
245 GtkNotebookPage *page,
246 GtkAllocation *allocation);
247 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
253 /*** GtkNotebook Page Switch Methods ***/
254 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
255 GtkNotebookPage *page,
258 /*** GtkNotebook Page Switch Functions ***/
259 static void gtk_notebook_switch_page (GtkNotebook *notebook,
260 GtkNotebookPage *page,
262 static gint gtk_notebook_page_select (GtkNotebook *notebook,
263 gboolean move_focus);
264 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
266 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
267 GtkNotebookPage *page);
269 /*** GtkNotebook Menu Functions ***/
270 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
272 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
274 static void gtk_notebook_menu_detacher (GtkWidget *widget,
277 /*** GtkNotebook Private Setters ***/
278 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
279 gboolean homogeneous);
280 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
282 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
284 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
287 static gboolean focus_tabs_in (GtkNotebook *notebook);
288 static gboolean focus_child_in (GtkNotebook *notebook,
289 GtkDirectionType direction);
291 static GtkContainerClass *parent_class = NULL;
292 static guint notebook_signals[LAST_SIGNAL] = { 0 };
295 gtk_notebook_get_type (void)
297 static GType notebook_type = 0;
301 static const GTypeInfo notebook_info =
303 sizeof (GtkNotebookClass),
304 NULL, /* base_init */
305 NULL, /* base_finalize */
306 (GClassInitFunc) gtk_notebook_class_init,
307 NULL, /* class_finalize */
308 NULL, /* class_data */
309 sizeof (GtkNotebook),
311 (GInstanceInitFunc) gtk_notebook_init,
314 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
318 return notebook_type;
322 add_tab_bindings (GtkBindingSet *binding_set,
323 GdkModifierType modifiers,
324 GtkDirectionType direction)
326 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
328 GTK_TYPE_DIRECTION_TYPE, direction);
329 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
331 GTK_TYPE_DIRECTION_TYPE, direction);
335 add_arrow_bindings (GtkBindingSet *binding_set,
337 GtkDirectionType direction)
339 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
341 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
343 GTK_TYPE_DIRECTION_TYPE, direction);
344 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
346 GTK_TYPE_DIRECTION_TYPE, direction);
350 gtk_notebook_class_init (GtkNotebookClass *class)
352 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
353 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
354 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
355 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
356 GtkBindingSet *binding_set;
358 parent_class = g_type_class_peek_parent (class);
360 gobject_class->set_property = gtk_notebook_set_property;
361 gobject_class->get_property = gtk_notebook_get_property;
362 object_class->destroy = gtk_notebook_destroy;
364 widget_class->map = gtk_notebook_map;
365 widget_class->unmap = gtk_notebook_unmap;
366 widget_class->realize = gtk_notebook_realize;
367 widget_class->unrealize = gtk_notebook_unrealize;
368 widget_class->size_request = gtk_notebook_size_request;
369 widget_class->size_allocate = gtk_notebook_size_allocate;
370 widget_class->expose_event = gtk_notebook_expose;
371 widget_class->scroll_event = gtk_notebook_scroll;
372 widget_class->button_press_event = gtk_notebook_button_press;
373 widget_class->button_release_event = gtk_notebook_button_release;
374 widget_class->enter_notify_event = gtk_notebook_enter_notify;
375 widget_class->leave_notify_event = gtk_notebook_leave_notify;
376 widget_class->motion_notify_event = gtk_notebook_motion_notify;
377 widget_class->grab_notify = gtk_notebook_grab_notify;
378 widget_class->state_changed = gtk_notebook_state_changed;
379 widget_class->focus_in_event = gtk_notebook_focus_in;
380 widget_class->focus_out_event = gtk_notebook_focus_out;
381 widget_class->focus = gtk_notebook_focus;
382 widget_class->style_set = gtk_notebook_style_set;
384 container_class->add = gtk_notebook_add;
385 container_class->remove = gtk_notebook_remove;
386 container_class->forall = gtk_notebook_forall;
387 container_class->set_focus_child = gtk_notebook_set_focus_child;
388 container_class->get_child_property = gtk_notebook_get_child_property;
389 container_class->set_child_property = gtk_notebook_set_child_property;
390 container_class->child_type = gtk_notebook_child_type;
392 class->switch_page = gtk_notebook_real_switch_page;
394 class->focus_tab = gtk_notebook_focus_tab;
395 class->select_page = gtk_notebook_select_page;
396 class->change_current_page = gtk_notebook_change_current_page;
397 class->move_focus_out = gtk_notebook_move_focus_out;
399 g_object_class_install_property (gobject_class,
401 g_param_spec_int ("page",
403 P_("The index of the current page"),
407 GTK_PARAM_READWRITE));
408 g_object_class_install_property (gobject_class,
410 g_param_spec_enum ("tab-pos",
412 P_("Which side of the notebook holds the tabs"),
413 GTK_TYPE_POSITION_TYPE,
415 GTK_PARAM_READWRITE));
416 g_object_class_install_property (gobject_class,
418 g_param_spec_uint ("tab-border",
420 P_("Width of the border around the tab labels"),
424 GTK_PARAM_WRITABLE));
425 g_object_class_install_property (gobject_class,
427 g_param_spec_uint ("tab-hborder",
428 P_("Horizontal Tab Border"),
429 P_("Width of the horizontal border of tab labels"),
433 GTK_PARAM_READWRITE));
434 g_object_class_install_property (gobject_class,
436 g_param_spec_uint ("tab-vborder",
437 P_("Vertical Tab Border"),
438 P_("Width of the vertical border of tab labels"),
442 GTK_PARAM_READWRITE));
443 g_object_class_install_property (gobject_class,
445 g_param_spec_boolean ("show-tabs",
447 P_("Whether tabs should be shown or not"),
449 GTK_PARAM_READWRITE));
450 g_object_class_install_property (gobject_class,
452 g_param_spec_boolean ("show-border",
454 P_("Whether the border should be shown or not"),
456 GTK_PARAM_READWRITE));
457 g_object_class_install_property (gobject_class,
459 g_param_spec_boolean ("scrollable",
461 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
463 GTK_PARAM_READWRITE));
464 g_object_class_install_property (gobject_class,
466 g_param_spec_boolean ("enable-popup",
468 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
470 GTK_PARAM_READWRITE));
471 g_object_class_install_property (gobject_class,
473 g_param_spec_boolean ("homogeneous",
475 P_("Whether tabs should have homogeneous sizes"),
477 GTK_PARAM_READWRITE));
479 gtk_container_class_install_child_property (container_class,
480 CHILD_PROP_TAB_LABEL,
481 g_param_spec_string ("tab-label",
483 P_("The string displayed on the child's tab label"),
485 GTK_PARAM_READWRITE));
486 gtk_container_class_install_child_property (container_class,
487 CHILD_PROP_MENU_LABEL,
488 g_param_spec_string ("menu-label",
490 P_("The string displayed in the child's menu entry"),
492 GTK_PARAM_READWRITE));
493 gtk_container_class_install_child_property (container_class,
495 g_param_spec_int ("position",
497 P_("The index of the child in the parent"),
499 GTK_PARAM_READWRITE));
500 gtk_container_class_install_child_property (container_class,
501 CHILD_PROP_TAB_EXPAND,
502 g_param_spec_boolean ("tab-expand",
504 P_("Whether to expand the child's tab or not"),
506 GTK_PARAM_READWRITE));
507 gtk_container_class_install_child_property (container_class,
509 g_param_spec_boolean ("tab-fill",
511 P_("Whether the child's tab should fill the allocated area or not"),
513 GTK_PARAM_READWRITE));
514 gtk_container_class_install_child_property (container_class,
516 g_param_spec_enum ("tab-pack",
518 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
519 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
520 GTK_PARAM_READWRITE));
523 * GtkNotebook:has-secondary-backward-stepper:
525 * The "has-secondary-backward-stepper" property determines whether
526 * a second backward arrow button is displayed on the opposite end
531 gtk_widget_class_install_style_property (widget_class,
532 g_param_spec_boolean ("has-secondary-backward-stepper",
533 P_("Secondary backward stepper"),
534 P_("Display a second backward arrow button on the opposite end of the tab area"),
537 GTK_PARAM_READABLE));
540 * GtkNotebook:has-secondary-forward-stepper:
542 * The "has-secondary-forward-stepper" property determines whether
543 * a second forward arrow button is displayed on the opposite end
548 gtk_widget_class_install_style_property (widget_class,
549 g_param_spec_boolean ("has-secondary-forward-stepper",
550 P_("Secondary forward stepper"),
551 P_("Display a second forward arrow button on the opposite end of the tab area"),
554 GTK_PARAM_READABLE));
557 * GtkNotebook:has-backward-stepper:
559 * The "has-backward-stepper" property determines whether
560 * the standard backward arrow button is displayed.
564 gtk_widget_class_install_style_property (widget_class,
565 g_param_spec_boolean ("has-backward-stepper",
566 P_("Backward stepper"),
567 P_("Display the standard backward arrow button"),
570 GTK_PARAM_READABLE));
573 * GtkNotebook:has-forward-stepper:
575 * The "has-forward-stepper" property determines whether
576 * the standard forward arrow button is displayed.
580 gtk_widget_class_install_style_property (widget_class,
581 g_param_spec_boolean ("has-forward-stepper",
582 P_("Forward stepper"),
583 P_("Display the standard forward arrow button"),
586 GTK_PARAM_READABLE));
588 notebook_signals[SWITCH_PAGE] =
589 g_signal_new ("switch_page",
590 G_TYPE_FROM_CLASS (gobject_class),
592 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
594 _gtk_marshal_VOID__POINTER_UINT,
598 notebook_signals[FOCUS_TAB] =
599 g_signal_new ("focus_tab",
600 G_TYPE_FROM_CLASS (gobject_class),
601 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
602 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
604 _gtk_marshal_BOOLEAN__ENUM,
606 GTK_TYPE_NOTEBOOK_TAB);
607 notebook_signals[SELECT_PAGE] =
608 g_signal_new ("select_page",
609 G_TYPE_FROM_CLASS (gobject_class),
610 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
611 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
613 _gtk_marshal_BOOLEAN__BOOLEAN,
616 notebook_signals[CHANGE_CURRENT_PAGE] =
617 g_signal_new ("change_current_page",
618 G_TYPE_FROM_CLASS (gobject_class),
619 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
620 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
622 _gtk_marshal_VOID__INT,
625 notebook_signals[MOVE_FOCUS_OUT] =
626 g_signal_new ("move_focus_out",
627 G_TYPE_FROM_CLASS (gobject_class),
628 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
629 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
631 _gtk_marshal_VOID__ENUM,
633 GTK_TYPE_DIRECTION_TYPE);
636 binding_set = gtk_binding_set_by_class (class);
637 gtk_binding_entry_add_signal (binding_set,
640 G_TYPE_BOOLEAN, FALSE);
641 gtk_binding_entry_add_signal (binding_set,
644 G_TYPE_BOOLEAN, FALSE);
646 gtk_binding_entry_add_signal (binding_set,
649 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
650 gtk_binding_entry_add_signal (binding_set,
653 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
654 gtk_binding_entry_add_signal (binding_set,
657 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
658 gtk_binding_entry_add_signal (binding_set,
661 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
663 gtk_binding_entry_add_signal (binding_set,
664 GDK_Page_Up, GDK_CONTROL_MASK,
665 "change_current_page", 1,
667 gtk_binding_entry_add_signal (binding_set,
668 GDK_Page_Down, GDK_CONTROL_MASK,
669 "change_current_page", 1,
672 gtk_binding_entry_add_signal (binding_set,
673 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
674 "change_current_page", 1,
676 gtk_binding_entry_add_signal (binding_set,
677 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
678 "change_current_page", 1,
681 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
682 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
683 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
684 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
686 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
687 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
691 gtk_notebook_init (GtkNotebook *notebook)
693 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
694 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
696 notebook->cur_page = NULL;
697 notebook->children = NULL;
698 notebook->first_tab = NULL;
699 notebook->focus_tab = NULL;
700 notebook->event_window = NULL;
701 notebook->menu = NULL;
703 notebook->tab_hborder = 2;
704 notebook->tab_vborder = 2;
706 notebook->show_tabs = TRUE;
707 notebook->show_border = TRUE;
708 notebook->tab_pos = GTK_POS_TOP;
709 notebook->scrollable = FALSE;
710 notebook->in_child = 0;
711 notebook->click_child = 0;
712 notebook->button = 0;
713 notebook->need_timer = 0;
714 notebook->child_has_focus = FALSE;
715 notebook->have_visible_child = FALSE;
716 notebook->focus_out = FALSE;
718 notebook->has_before_previous = 1;
719 notebook->has_before_next = 0;
720 notebook->has_after_previous = 0;
721 notebook->has_after_next = 1;
725 gtk_notebook_select_page (GtkNotebook *notebook,
728 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
730 gtk_notebook_page_select (notebook, move_focus);
738 gtk_notebook_focus_tab (GtkNotebook *notebook,
743 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
747 case GTK_NOTEBOOK_TAB_FIRST:
748 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
750 gtk_notebook_switch_focus_tab (notebook, list);
752 case GTK_NOTEBOOK_TAB_LAST:
753 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
755 gtk_notebook_switch_focus_tab (notebook, list);
766 gtk_notebook_change_current_page (GtkNotebook *notebook,
769 GList *current = NULL;
771 if (notebook->cur_page)
772 current = g_list_find (notebook->children, notebook->cur_page);
776 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
777 offset += offset < 0 ? 1 : -1;
781 gtk_notebook_switch_page (notebook, current->data, -1);
783 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
786 static GtkDirectionType
787 get_effective_direction (GtkNotebook *notebook,
788 GtkDirectionType direction)
790 /* Remap the directions into the effective direction it would be for a
791 * GTK_POS_TOP notebook
794 #define D(rest) GTK_DIR_##rest
796 static const GtkDirectionType translate_direction[2][4][6] = {
797 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
798 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
799 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
800 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
801 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
802 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
803 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
804 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
809 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
811 return translate_direction[text_dir][notebook->tab_pos][direction];
815 get_effective_tab_pos (GtkNotebook *notebook)
817 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
819 switch (notebook->tab_pos)
822 return GTK_POS_RIGHT;
829 return notebook->tab_pos;
833 gtk_notebook_move_focus_out (GtkNotebook *notebook,
834 GtkDirectionType direction_type)
836 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
839 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
840 if (focus_tabs_in (notebook))
842 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
843 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
846 /* At this point, we know we should be focusing out of the notebook entirely. We
847 * do this by setting a flag, then propagating the focus motion to the notebook.
849 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
850 if (!GTK_WIDGET_TOPLEVEL (toplevel))
853 g_object_ref (notebook);
855 notebook->focus_out = TRUE;
856 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
857 notebook->focus_out = FALSE;
859 g_object_unref (notebook);
866 * Creates a new #GtkNotebook widget with no pages.
868 * Return value: the newly created #GtkNotebook
871 gtk_notebook_new (void)
873 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
876 /* Private GtkObject Methods :
878 * gtk_notebook_destroy
879 * gtk_notebook_set_arg
880 * gtk_notebook_get_arg
883 gtk_notebook_destroy (GtkObject *object)
886 GtkNotebook *notebook = GTK_NOTEBOOK (object);
889 gtk_notebook_popup_disable (notebook);
891 children = notebook->children;
894 GList *child = children;
895 children = child->next;
897 gtk_notebook_real_remove (notebook, child, TRUE);
900 GTK_OBJECT_CLASS (parent_class)->destroy (object);
904 gtk_notebook_set_property (GObject *object,
909 GtkNotebook *notebook;
911 notebook = GTK_NOTEBOOK (object);
916 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
918 case PROP_SHOW_BORDER:
919 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
921 case PROP_SCROLLABLE:
922 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
924 case PROP_ENABLE_POPUP:
925 if (g_value_get_boolean (value))
926 gtk_notebook_popup_enable (notebook);
928 gtk_notebook_popup_disable (notebook);
930 case PROP_HOMOGENEOUS:
931 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
934 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
937 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
939 case PROP_TAB_BORDER:
940 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
942 case PROP_TAB_HBORDER:
943 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
945 case PROP_TAB_VBORDER:
946 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
954 gtk_notebook_get_property (GObject *object,
959 GtkNotebook *notebook;
961 notebook = GTK_NOTEBOOK (object);
966 g_value_set_boolean (value, notebook->show_tabs);
968 case PROP_SHOW_BORDER:
969 g_value_set_boolean (value, notebook->show_border);
971 case PROP_SCROLLABLE:
972 g_value_set_boolean (value, notebook->scrollable);
974 case PROP_ENABLE_POPUP:
975 g_value_set_boolean (value, notebook->menu != NULL);
977 case PROP_HOMOGENEOUS:
978 g_value_set_boolean (value, notebook->homogeneous);
981 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
984 g_value_set_enum (value, notebook->tab_pos);
986 case PROP_TAB_HBORDER:
987 g_value_set_uint (value, notebook->tab_hborder);
989 case PROP_TAB_VBORDER:
990 g_value_set_uint (value, notebook->tab_vborder);
993 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
998 /* Private GtkWidget Methods :
1001 * gtk_notebook_unmap
1002 * gtk_notebook_realize
1003 * gtk_notebook_size_request
1004 * gtk_notebook_size_allocate
1005 * gtk_notebook_expose
1006 * gtk_notebook_scroll
1007 * gtk_notebook_button_press
1008 * gtk_notebook_button_release
1009 * gtk_notebook_enter_notify
1010 * gtk_notebook_leave_notify
1011 * gtk_notebook_motion_notify
1012 * gtk_notebook_focus_in
1013 * gtk_notebook_focus_out
1014 * gtk_notebook_draw_focus
1015 * gtk_notebook_style_set
1018 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1019 GdkRectangle *rectangle)
1021 GtkWidget *widget = GTK_WIDGET (notebook);
1022 gint border_width = GTK_CONTAINER (notebook)->border_width;
1023 GtkNotebookPage *visible_page = NULL;
1025 gint tab_pos = get_effective_tab_pos (notebook);
1027 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1029 GtkNotebookPage *page = tmp_list->data;
1030 if (GTK_WIDGET_VISIBLE (page->child))
1032 visible_page = page;
1037 if (notebook->show_tabs && visible_page)
1041 rectangle->x = widget->allocation.x + border_width;
1042 rectangle->y = widget->allocation.y + border_width;
1047 case GTK_POS_BOTTOM:
1048 rectangle->width = widget->allocation.width - 2 * border_width;
1049 rectangle->height = visible_page->requisition.height;
1050 if (tab_pos == GTK_POS_BOTTOM)
1051 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1055 rectangle->width = visible_page->requisition.width;
1056 rectangle->height = widget->allocation.height - 2 * border_width;
1057 if (tab_pos == GTK_POS_RIGHT)
1058 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1069 rectangle->x = rectangle->y = 0;
1070 rectangle->width = rectangle->height = 10;
1078 gtk_notebook_map (GtkWidget *widget)
1080 GtkNotebook *notebook;
1081 GtkNotebookPage *page;
1084 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1086 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1088 notebook = GTK_NOTEBOOK (widget);
1090 if (notebook->cur_page &&
1091 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1092 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1093 gtk_widget_map (notebook->cur_page->child);
1095 if (notebook->scrollable)
1096 gtk_notebook_pages_allocate (notebook);
1099 children = notebook->children;
1103 page = children->data;
1104 children = children->next;
1106 if (page->tab_label &&
1107 GTK_WIDGET_VISIBLE (page->tab_label) &&
1108 !GTK_WIDGET_MAPPED (page->tab_label))
1109 gtk_widget_map (page->tab_label);
1113 if (gtk_notebook_get_event_window_position (notebook, NULL))
1114 gdk_window_show_unraised (notebook->event_window);
1118 gtk_notebook_unmap (GtkWidget *widget)
1120 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1122 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1124 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1126 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1130 gtk_notebook_realize (GtkWidget *widget)
1132 GtkNotebook *notebook;
1133 GdkWindowAttr attributes;
1134 gint attributes_mask;
1135 GdkRectangle event_window_pos;
1137 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1139 notebook = GTK_NOTEBOOK (widget);
1140 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1142 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1144 widget->window = gtk_widget_get_parent_window (widget);
1145 g_object_ref (widget->window);
1147 attributes.window_type = GDK_WINDOW_CHILD;
1148 attributes.x = event_window_pos.x;
1149 attributes.y = event_window_pos.y;
1150 attributes.width = event_window_pos.width;
1151 attributes.height = event_window_pos.height;
1152 attributes.wclass = GDK_INPUT_ONLY;
1153 attributes.event_mask = gtk_widget_get_events (widget);
1154 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1155 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1157 attributes_mask = GDK_WA_X | GDK_WA_Y;
1159 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1160 &attributes, attributes_mask);
1161 gdk_window_set_user_data (notebook->event_window, notebook);
1163 widget->style = gtk_style_attach (widget->style, widget->window);
1167 gtk_notebook_unrealize (GtkWidget *widget)
1169 GtkNotebook *notebook;
1171 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1173 notebook = GTK_NOTEBOOK (widget);
1175 gdk_window_set_user_data (notebook->event_window, NULL);
1176 gdk_window_destroy (notebook->event_window);
1177 notebook->event_window = NULL;
1179 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1180 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1184 gtk_notebook_size_request (GtkWidget *widget,
1185 GtkRequisition *requisition)
1187 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1188 GtkNotebookPage *page;
1190 GtkRequisition child_requisition;
1191 gboolean switch_page = FALSE;
1195 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1197 widget->requisition.width = 0;
1198 widget->requisition.height = 0;
1200 for (children = notebook->children, vis_pages = 0; children;
1201 children = children->next)
1203 page = children->data;
1205 if (GTK_WIDGET_VISIBLE (page->child))
1208 gtk_widget_size_request (page->child, &child_requisition);
1210 widget->requisition.width = MAX (widget->requisition.width,
1211 child_requisition.width);
1212 widget->requisition.height = MAX (widget->requisition.height,
1213 child_requisition.height);
1215 if (notebook->menu && page->menu_label->parent &&
1216 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1217 gtk_widget_show (page->menu_label->parent);
1221 if (page == notebook->cur_page)
1223 if (notebook->menu && page->menu_label->parent &&
1224 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1225 gtk_widget_hide (page->menu_label->parent);
1229 if (notebook->show_border || notebook->show_tabs)
1231 widget->requisition.width += widget->style->xthickness * 2;
1232 widget->requisition.height += widget->style->ythickness * 2;
1234 if (notebook->show_tabs)
1237 gint tab_height = 0;
1241 for (children = notebook->children; children;
1242 children = children->next)
1244 page = children->data;
1246 if (GTK_WIDGET_VISIBLE (page->child))
1248 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1249 gtk_widget_show (page->tab_label);
1251 gtk_widget_size_request (page->tab_label,
1252 &child_requisition);
1254 page->requisition.width =
1255 child_requisition.width +
1256 2 * widget->style->xthickness;
1257 page->requisition.height =
1258 child_requisition.height +
1259 2 * widget->style->ythickness;
1261 switch (notebook->tab_pos)
1264 case GTK_POS_BOTTOM:
1265 page->requisition.height += 2 * (notebook->tab_vborder +
1267 tab_height = MAX (tab_height, page->requisition.height);
1268 tab_max = MAX (tab_max, page->requisition.width);
1272 page->requisition.width += 2 * (notebook->tab_hborder +
1274 tab_width = MAX (tab_width, page->requisition.width);
1275 tab_max = MAX (tab_max, page->requisition.height);
1279 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1280 gtk_widget_hide (page->tab_label);
1283 children = notebook->children;
1287 switch (notebook->tab_pos)
1290 case GTK_POS_BOTTOM:
1291 if (tab_height == 0)
1294 if (notebook->scrollable && vis_pages > 1 &&
1295 widget->requisition.width < tab_width)
1296 tab_height = MAX (tab_height, ARROW_SIZE);
1298 padding = 2 * (TAB_CURVATURE + focus_width +
1299 notebook->tab_hborder) - TAB_OVERLAP;
1303 page = children->data;
1304 children = children->next;
1306 if (!GTK_WIDGET_VISIBLE (page->child))
1309 if (notebook->homogeneous)
1310 page->requisition.width = tab_max;
1312 page->requisition.width += padding;
1314 tab_width += page->requisition.width;
1315 page->requisition.height = tab_height;
1318 if (notebook->scrollable && vis_pages > 1 &&
1319 widget->requisition.width < tab_width)
1320 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1322 if (notebook->homogeneous && !notebook->scrollable)
1323 widget->requisition.width = MAX (widget->requisition.width,
1324 vis_pages * tab_max +
1327 widget->requisition.width = MAX (widget->requisition.width,
1328 tab_width + TAB_OVERLAP);
1330 widget->requisition.height += tab_height;
1337 if (notebook->scrollable && vis_pages > 1 &&
1338 widget->requisition.height < tab_height)
1339 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1341 padding = 2 * (TAB_CURVATURE + focus_width +
1342 notebook->tab_vborder) - TAB_OVERLAP;
1347 page = children->data;
1348 children = children->next;
1350 if (!GTK_WIDGET_VISIBLE (page->child))
1353 page->requisition.width = tab_width;
1355 if (notebook->homogeneous)
1356 page->requisition.height = tab_max;
1358 page->requisition.height += padding;
1360 tab_height += page->requisition.height;
1363 if (notebook->scrollable && vis_pages > 1 &&
1364 widget->requisition.height < tab_height)
1365 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1367 widget->requisition.width += tab_width;
1369 if (notebook->homogeneous && !notebook->scrollable)
1370 widget->requisition.height =
1371 MAX (widget->requisition.height,
1372 vis_pages * tab_max + TAB_OVERLAP);
1374 widget->requisition.height =
1375 MAX (widget->requisition.height,
1376 tab_height + TAB_OVERLAP);
1378 if (!notebook->homogeneous || notebook->scrollable)
1380 widget->requisition.height = MAX (widget->requisition.height,
1381 vis_pages * tab_max +
1389 for (children = notebook->children; children;
1390 children = children->next)
1392 page = children->data;
1394 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1395 gtk_widget_hide (page->tab_label);
1400 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1401 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1407 for (children = notebook->children; children;
1408 children = children->next)
1410 page = children->data;
1411 if (GTK_WIDGET_VISIBLE (page->child))
1413 gtk_notebook_switch_page (notebook, page, -1);
1418 else if (GTK_WIDGET_VISIBLE (widget))
1420 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1421 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1424 if (vis_pages && !notebook->cur_page)
1426 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1429 notebook->first_tab = children;
1430 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1436 gtk_notebook_size_allocate (GtkWidget *widget,
1437 GtkAllocation *allocation)
1439 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1441 gint tab_pos = get_effective_tab_pos (notebook);
1443 widget->allocation = *allocation;
1444 if (GTK_WIDGET_REALIZED (widget))
1446 GdkRectangle position;
1448 if (gtk_notebook_get_event_window_position (notebook, &position))
1450 gdk_window_move_resize (notebook->event_window,
1451 position.x, position.y,
1452 position.width, position.height);
1453 if (GTK_WIDGET_MAPPED (notebook))
1454 gdk_window_show_unraised (notebook->event_window);
1457 gdk_window_hide (notebook->event_window);
1460 if (notebook->children)
1462 gint border_width = GTK_CONTAINER (widget)->border_width;
1463 GtkNotebookPage *page;
1464 GtkAllocation child_allocation;
1467 child_allocation.x = widget->allocation.x + border_width;
1468 child_allocation.y = widget->allocation.y + border_width;
1469 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1470 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1472 if (notebook->show_tabs || notebook->show_border)
1474 child_allocation.x += widget->style->xthickness;
1475 child_allocation.y += widget->style->ythickness;
1476 child_allocation.width = MAX (1, child_allocation.width -
1477 widget->style->xthickness * 2);
1478 child_allocation.height = MAX (1, child_allocation.height -
1479 widget->style->ythickness * 2);
1481 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1486 child_allocation.y += notebook->cur_page->requisition.height;
1487 case GTK_POS_BOTTOM:
1488 child_allocation.height =
1489 MAX (1, child_allocation.height -
1490 notebook->cur_page->requisition.height);
1493 child_allocation.x += notebook->cur_page->requisition.width;
1495 child_allocation.width =
1496 MAX (1, child_allocation.width -
1497 notebook->cur_page->requisition.width);
1503 children = notebook->children;
1506 page = children->data;
1507 children = children->next;
1509 if (GTK_WIDGET_VISIBLE (page->child))
1511 gtk_widget_size_allocate (page->child, &child_allocation);
1516 gtk_notebook_pages_allocate (notebook);
1521 gtk_notebook_expose (GtkWidget *widget,
1522 GdkEventExpose *event)
1524 GtkNotebook *notebook;
1525 GdkRectangle child_area;
1527 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1528 g_return_val_if_fail (event != NULL, FALSE);
1530 if (GTK_WIDGET_DRAWABLE (widget))
1532 notebook = GTK_NOTEBOOK (widget);
1534 gtk_notebook_paint (widget, &event->area);
1535 if (notebook->show_tabs)
1537 if (notebook->cur_page &&
1538 gtk_widget_intersect (notebook->cur_page->tab_label,
1539 &event->area, &child_area))
1540 gtk_notebook_draw_focus (widget);
1544 if (notebook->cur_page)
1545 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1546 notebook->cur_page->child,
1554 gtk_notebook_show_arrows (GtkNotebook *notebook)
1556 gboolean show_arrow = FALSE;
1559 if (!notebook->scrollable)
1562 children = notebook->children;
1565 GtkNotebookPage *page = children->data;
1567 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1570 children = children->next;
1577 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1578 GdkRectangle *rectangle,
1579 GtkNotebookArrow arrow)
1581 GdkRectangle event_window_pos;
1582 gboolean before = ARROW_IS_BEFORE (arrow);
1583 gboolean left = ARROW_IS_LEFT (arrow);
1585 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1587 rectangle->width = ARROW_SIZE;
1588 rectangle->height = ARROW_SIZE;
1590 switch (notebook->tab_pos)
1594 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1595 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1596 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1598 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1600 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1601 rectangle->y = event_window_pos.y;
1603 rectangle->y += event_window_pos.height - rectangle->height;
1606 case GTK_POS_BOTTOM:
1609 if (left || !notebook->has_before_previous)
1610 rectangle->x = event_window_pos.x;
1612 rectangle->x = event_window_pos.x + rectangle->width;
1616 if (!left || !notebook->has_after_next)
1617 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1619 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1621 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1627 static GtkNotebookArrow
1628 gtk_notebook_get_arrow (GtkNotebook *notebook,
1632 GdkRectangle arrow_rect;
1633 GdkRectangle event_window_pos;
1636 GtkNotebookArrow arrow[4];
1638 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1639 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1640 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1641 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1643 if (gtk_notebook_show_arrows (notebook))
1645 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1646 for (i = 0; i < 4; i++)
1648 if (arrow[i] == ARROW_NONE)
1651 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1653 x0 = x - arrow_rect.x;
1654 y0 = y - arrow_rect.y;
1656 if (y0 >= 0 && y0 < arrow_rect.height &&
1657 x0 >= 0 && x0 < arrow_rect.width)
1666 gtk_notebook_do_arrow (GtkNotebook *notebook,
1667 GtkNotebookArrow arrow)
1669 GtkWidget *widget = GTK_WIDGET (notebook);
1670 GtkDirectionType dir;
1671 gboolean is_rtl, left;
1673 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1674 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1675 (!ARROW_IS_LEFT (arrow) && is_rtl);
1677 if (!notebook->focus_tab ||
1678 gtk_notebook_search_page (notebook, notebook->focus_tab,
1679 left ? STEP_PREV : STEP_NEXT,
1682 if (notebook->tab_pos == GTK_POS_LEFT ||
1683 notebook->tab_pos == GTK_POS_RIGHT)
1684 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1686 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1687 gtk_widget_child_focus (widget, dir);
1692 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1693 GtkNotebookArrow arrow,
1694 GdkEventButton *event)
1696 GtkWidget *widget = GTK_WIDGET (notebook);
1697 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1698 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1699 (!ARROW_IS_LEFT (arrow) && is_rtl);
1701 if (!GTK_WIDGET_HAS_FOCUS (widget))
1702 gtk_widget_grab_focus (widget);
1704 notebook->button = event->button;
1705 notebook->click_child = arrow;
1707 if (event->button == 1)
1709 gtk_notebook_do_arrow (notebook, arrow);
1711 if (!notebook->timer)
1713 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1714 (GSourceFunc) gtk_notebook_timer,
1715 (gpointer) notebook);
1716 notebook->need_timer = TRUE;
1719 else if (event->button == 2)
1720 gtk_notebook_page_select (notebook, TRUE);
1721 else if (event->button == 3)
1722 gtk_notebook_switch_focus_tab (notebook,
1723 gtk_notebook_search_page (notebook,
1725 left ? STEP_NEXT : STEP_PREV,
1727 gtk_notebook_redraw_arrows (notebook);
1733 get_widget_coordinates (GtkWidget *widget,
1738 GdkWindow *window = ((GdkEventAny *)event)->window;
1741 if (!gdk_event_get_coords (event, &tx, &ty))
1744 while (window && window != widget->window)
1746 gint window_x, window_y;
1748 gdk_window_get_position (window, &window_x, &window_y);
1752 window = gdk_window_get_parent (window);
1767 gtk_notebook_scroll (GtkWidget *widget,
1768 GdkEventScroll *event)
1770 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1773 GtkWidget* originator;
1775 if (!notebook->cur_page)
1778 child = notebook->cur_page->child;
1779 originator = gtk_get_event_widget ((GdkEvent *)event);
1781 /* ignore scroll events from the content of the page */
1782 if (!originator || gtk_widget_is_ancestor (originator, child))
1785 switch (event->direction)
1787 case GDK_SCROLL_RIGHT:
1788 case GDK_SCROLL_DOWN:
1789 gtk_notebook_next_page (notebook);
1791 case GDK_SCROLL_LEFT:
1793 gtk_notebook_prev_page (notebook);
1801 gtk_notebook_button_press (GtkWidget *widget,
1802 GdkEventButton *event)
1804 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1805 GtkNotebookPage *page;
1807 GtkNotebookArrow arrow;
1811 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1815 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1818 arrow = gtk_notebook_get_arrow (notebook, x, y);
1820 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1822 if (event->button == 3 && notebook->menu)
1824 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1825 NULL, NULL, 3, event->time);
1829 if (event->button != 1)
1833 children = notebook->children;
1836 page = children->data;
1838 if (GTK_WIDGET_VISIBLE (page->child) &&
1839 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1840 (x >= page->allocation.x) &&
1841 (y >= page->allocation.y) &&
1842 (x <= (page->allocation.x + page->allocation.width)) &&
1843 (y <= (page->allocation.y + page->allocation.height)))
1845 gboolean page_changed = page != notebook->cur_page;
1846 gboolean was_focus = gtk_widget_is_focus (widget);
1848 gtk_notebook_switch_focus_tab (notebook, children);
1849 gtk_widget_grab_focus (widget);
1851 if (page_changed && !was_focus)
1852 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1856 children = children->next;
1864 stop_scrolling (GtkNotebook *notebook)
1866 if (notebook->timer)
1868 g_source_remove (notebook->timer);
1869 notebook->timer = 0;
1870 notebook->need_timer = FALSE;
1872 notebook->click_child = 0;
1873 notebook->button = 0;
1874 gtk_notebook_redraw_arrows (notebook);
1878 gtk_notebook_button_release (GtkWidget *widget,
1879 GdkEventButton *event)
1881 GtkNotebook *notebook;
1883 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1884 g_return_val_if_fail (event != NULL, FALSE);
1886 if (event->type != GDK_BUTTON_RELEASE)
1889 notebook = GTK_NOTEBOOK (widget);
1891 if (event->button == notebook->button)
1893 stop_scrolling (notebook);
1902 gtk_notebook_enter_notify (GtkWidget *widget,
1903 GdkEventCrossing *event)
1905 GtkNotebook *notebook;
1906 GtkNotebookArrow arrow;
1909 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1910 g_return_val_if_fail (event != NULL, FALSE);
1912 notebook = GTK_NOTEBOOK (widget);
1914 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1917 arrow = gtk_notebook_get_arrow (notebook, x, y);
1919 if (arrow != notebook->in_child)
1921 notebook->in_child = arrow;
1922 gtk_notebook_redraw_arrows (notebook);
1931 gtk_notebook_leave_notify (GtkWidget *widget,
1932 GdkEventCrossing *event)
1934 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1935 GtkNotebookArrow arrow;
1938 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1941 arrow = gtk_notebook_get_arrow (notebook, x, y);
1943 if (notebook->in_child)
1945 notebook->in_child = 0;
1946 gtk_notebook_redraw_arrows (notebook);
1953 gtk_notebook_motion_notify (GtkWidget *widget,
1954 GdkEventMotion *event)
1956 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1957 GtkNotebookArrow arrow;
1960 if (notebook->button)
1963 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1966 arrow = gtk_notebook_get_arrow (notebook, x, y);
1968 if (arrow != notebook->in_child)
1970 notebook->in_child = arrow;
1971 gtk_notebook_redraw_arrows (notebook);
1978 gtk_notebook_grab_notify (GtkWidget *widget,
1979 gboolean was_grabbed)
1982 stop_scrolling (GTK_NOTEBOOK (widget));
1986 gtk_notebook_state_changed (GtkWidget *widget,
1987 GtkStateType previous_state)
1989 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1990 stop_scrolling (GTK_NOTEBOOK (widget));
1994 gtk_notebook_focus_in (GtkWidget *widget,
1995 GdkEventFocus *event)
1997 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1999 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2005 gtk_notebook_focus_out (GtkWidget *widget,
2006 GdkEventFocus *event)
2008 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2014 gtk_notebook_draw_focus (GtkWidget *widget)
2016 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2018 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2019 notebook->focus_tab)
2021 GtkNotebookPage *page;
2025 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2027 page = notebook->focus_tab->data;
2029 area.x = page->tab_label->allocation.x - focus_width;
2030 area.y = page->tab_label->allocation.y - focus_width;
2031 area.width = page->tab_label->allocation.width + 2 * focus_width;
2032 area.height = page->tab_label->allocation.height + 2 * focus_width;
2034 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2039 gtk_notebook_style_set (GtkWidget *widget,
2042 GtkNotebook *notebook;
2044 gboolean has_before_previous;
2045 gboolean has_before_next;
2046 gboolean has_after_previous;
2047 gboolean has_after_next;
2049 notebook = GTK_NOTEBOOK (widget);
2051 gtk_widget_style_get (widget,
2052 "has_backward_stepper", &has_before_previous,
2053 "has_secondary_forward_stepper", &has_before_next,
2054 "has_secondary_backward_stepper", &has_after_previous,
2055 "has_forward_stepper", &has_after_next,
2058 notebook->has_before_previous = has_before_previous;
2059 notebook->has_before_next = has_before_next;
2060 notebook->has_after_previous = has_after_previous;
2061 notebook->has_after_next = has_after_next;
2063 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2066 /* Private GtkContainer Methods :
2068 * gtk_notebook_set_child_arg
2069 * gtk_notebook_get_child_arg
2071 * gtk_notebook_remove
2072 * gtk_notebook_focus
2073 * gtk_notebook_set_focus_child
2074 * gtk_notebook_child_type
2075 * gtk_notebook_forall
2078 gtk_notebook_set_child_property (GtkContainer *container,
2081 const GValue *value,
2086 GtkPackType pack_type;
2088 /* not finding child's page is valid for menus or labels */
2089 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2092 switch (property_id)
2094 case CHILD_PROP_TAB_LABEL:
2095 /* a NULL pointer indicates a default_tab setting, otherwise
2096 * we need to set the associated label
2098 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2099 g_value_get_string (value));
2101 case CHILD_PROP_MENU_LABEL:
2102 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2103 g_value_get_string (value));
2105 case CHILD_PROP_POSITION:
2106 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2107 g_value_get_int (value));
2109 case CHILD_PROP_TAB_EXPAND:
2110 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2111 &expand, &fill, &pack_type);
2112 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2113 g_value_get_boolean (value),
2116 case CHILD_PROP_TAB_FILL:
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_boolean (value),
2124 case CHILD_PROP_TAB_PACK:
2125 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2126 &expand, &fill, &pack_type);
2127 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2129 g_value_get_enum (value));
2132 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2138 gtk_notebook_get_child_property (GtkContainer *container,
2145 GtkNotebook *notebook;
2149 GtkPackType pack_type;
2151 notebook = GTK_NOTEBOOK (container);
2153 /* not finding child's page is valid for menus or labels */
2154 list = gtk_notebook_find_child (notebook, child, NULL);
2157 /* nothing to set on labels or menus */
2158 g_param_value_set_default (pspec, value);
2162 switch (property_id)
2164 case CHILD_PROP_TAB_LABEL:
2165 label = gtk_notebook_get_tab_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_MENU_LABEL:
2173 label = gtk_notebook_get_menu_label (notebook, child);
2175 if (label && GTK_IS_LABEL (label))
2176 g_value_set_string (value, GTK_LABEL (label)->label);
2178 g_value_set_string (value, NULL);
2180 case CHILD_PROP_POSITION:
2181 g_value_set_int (value, g_list_position (notebook->children, list));
2183 case CHILD_PROP_TAB_EXPAND:
2184 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2185 &expand, NULL, NULL);
2186 g_value_set_boolean (value, expand);
2188 case CHILD_PROP_TAB_FILL:
2189 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2191 g_value_set_boolean (value, fill);
2193 case CHILD_PROP_TAB_PACK:
2194 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2195 NULL, NULL, &pack_type);
2196 g_value_set_enum (value, pack_type);
2199 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2205 gtk_notebook_add (GtkContainer *container,
2208 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2210 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2215 gtk_notebook_remove (GtkContainer *container,
2218 GtkNotebook *notebook;
2219 GtkNotebookPage *page;
2222 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2223 g_return_if_fail (widget != NULL);
2225 notebook = GTK_NOTEBOOK (container);
2227 children = notebook->children;
2230 page = children->data;
2231 if (page->child == widget)
2233 gtk_notebook_real_remove (notebook, children, FALSE);
2236 children = children->next;
2241 focus_tabs_in (GtkNotebook *notebook)
2243 if (notebook->show_tabs && notebook->cur_page)
2245 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2247 gtk_notebook_switch_focus_tab (notebook,
2248 g_list_find (notebook->children,
2249 notebook->cur_page));
2258 focus_tabs_move (GtkNotebook *notebook,
2259 GtkDirectionType direction,
2260 gint search_direction)
2264 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2265 search_direction, TRUE);
2267 gtk_notebook_switch_focus_tab (notebook, new_page);
2269 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2275 focus_child_in (GtkNotebook *notebook,
2276 GtkDirectionType direction)
2278 if (notebook->cur_page)
2279 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2284 /* Focus in the notebook can either be on the pages, or on
2288 gtk_notebook_focus (GtkWidget *widget,
2289 GtkDirectionType direction)
2291 GtkWidget *old_focus_child;
2292 GtkNotebook *notebook;
2293 GtkDirectionType effective_direction;
2295 gboolean widget_is_focus;
2296 GtkContainer *container;
2298 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2300 container = GTK_CONTAINER (widget);
2301 notebook = GTK_NOTEBOOK (container);
2303 if (notebook->focus_out)
2305 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2309 widget_is_focus = gtk_widget_is_focus (widget);
2310 old_focus_child = container->focus_child;
2312 effective_direction = get_effective_direction (notebook, direction);
2314 if (old_focus_child) /* Focus on page child */
2316 if (gtk_widget_child_focus (old_focus_child, direction))
2319 switch (effective_direction)
2321 case GTK_DIR_TAB_BACKWARD:
2323 /* Focus onto the tabs */
2324 return focus_tabs_in (notebook);
2326 case GTK_DIR_TAB_FORWARD:
2332 else if (widget_is_focus) /* Focus was on tabs */
2334 switch (effective_direction)
2336 case GTK_DIR_TAB_BACKWARD:
2339 case GTK_DIR_TAB_FORWARD:
2341 /* We use TAB_FORWARD rather than direction so that we focus a more
2342 * predictable widget for the user; users may be using arrow focusing
2343 * in this situation even if they don't usually use arrow focusing.
2345 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2347 return focus_tabs_move (notebook, direction, STEP_PREV);
2349 return focus_tabs_move (notebook, direction, STEP_NEXT);
2352 else /* Focus was not on widget */
2354 switch (effective_direction)
2356 case GTK_DIR_TAB_FORWARD:
2358 if (focus_tabs_in (notebook))
2360 if (focus_child_in (notebook, direction))
2363 case GTK_DIR_TAB_BACKWARD:
2365 if (focus_child_in (notebook, direction))
2367 if (focus_tabs_in (notebook))
2372 return focus_child_in (notebook, direction);
2376 g_assert_not_reached ();
2381 gtk_notebook_set_focus_child (GtkContainer *container,
2384 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2385 GtkWidget *page_child;
2386 GtkWidget *toplevel;
2388 /* If the old focus widget was within a page of the notebook,
2389 * (child may either be NULL or not in this case), record it
2390 * for future use if we switch to the page with a mnemonic.
2393 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2394 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2396 page_child = GTK_WINDOW (toplevel)->focus_widget;
2399 if (page_child->parent == GTK_WIDGET (container))
2401 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2404 GtkNotebookPage *page = list->data;
2406 if (page->last_focus_child)
2407 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2409 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2410 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2416 page_child = page_child->parent;
2422 g_return_if_fail (GTK_IS_WIDGET (child));
2424 notebook->child_has_focus = TRUE;
2425 if (!notebook->focus_tab)
2428 GtkNotebookPage *page;
2430 children = notebook->children;
2433 page = children->data;
2434 if (page->child == child || page->tab_label == child)
2435 gtk_notebook_switch_focus_tab (notebook, children);
2436 children = children->next;
2441 parent_class->set_focus_child (container, child);
2445 gtk_notebook_forall (GtkContainer *container,
2446 gboolean include_internals,
2447 GtkCallback callback,
2448 gpointer callback_data)
2450 GtkNotebook *notebook;
2453 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2454 g_return_if_fail (callback != NULL);
2456 notebook = GTK_NOTEBOOK (container);
2458 children = notebook->children;
2461 GtkNotebookPage *page;
2463 page = children->data;
2464 children = children->next;
2465 (* callback) (page->child, callback_data);
2466 if (include_internals)
2468 if (page->tab_label)
2469 (* callback) (page->tab_label, callback_data);
2475 gtk_notebook_child_type (GtkContainer *container)
2477 return GTK_TYPE_WIDGET;
2480 /* Private GtkNotebook Functions:
2482 * gtk_notebook_redraw_tabs
2483 * gtk_notebook_real_remove
2484 * gtk_notebook_update_labels
2485 * gtk_notebook_timer
2486 * gtk_notebook_page_compare
2487 * gtk_notebook_real_page_position
2488 * gtk_notebook_search_page
2491 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2494 GtkNotebookPage *page;
2495 GdkRectangle redraw_rect;
2497 gint tab_pos = get_effective_tab_pos (notebook);
2499 widget = GTK_WIDGET (notebook);
2500 border = GTK_CONTAINER (notebook)->border_width;
2502 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2505 page = notebook->first_tab->data;
2507 redraw_rect.x = border;
2508 redraw_rect.y = border;
2512 case GTK_POS_BOTTOM:
2513 redraw_rect.y = (widget->allocation.height - border -
2514 page->allocation.height -
2515 widget->style->ythickness);
2516 if (page != notebook->cur_page)
2517 redraw_rect.y -= widget->style->ythickness;
2520 redraw_rect.width = widget->allocation.width - 2 * border;
2521 redraw_rect.height = (page->allocation.height +
2522 widget->style->ythickness);
2523 if (page != notebook->cur_page)
2524 redraw_rect.height += widget->style->ythickness;
2527 redraw_rect.x = (widget->allocation.width - border -
2528 page->allocation.width -
2529 widget->style->xthickness);
2530 if (page != notebook->cur_page)
2531 redraw_rect.x -= widget->style->xthickness;
2534 redraw_rect.width = (page->allocation.width +
2535 widget->style->xthickness);
2536 redraw_rect.height = widget->allocation.height - 2 * border;
2537 if (page != notebook->cur_page)
2538 redraw_rect.width += widget->style->xthickness;
2542 redraw_rect.x += widget->allocation.x;
2543 redraw_rect.y += widget->allocation.y;
2545 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2549 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2551 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2555 GtkNotebookArrow arrow[4];
2557 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2558 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2559 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2560 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2562 for (i = 0; i < 4; i++)
2564 if (arrow[i] == ARROW_NONE)
2567 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2568 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2575 gtk_notebook_timer (GtkNotebook *notebook)
2577 gboolean retval = FALSE;
2579 GDK_THREADS_ENTER ();
2581 if (notebook->timer)
2583 gtk_notebook_do_arrow (notebook, notebook->click_child);
2585 if (notebook->need_timer)
2587 notebook->need_timer = FALSE;
2588 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2589 (GSourceFunc) gtk_notebook_timer,
2590 (gpointer) notebook);
2596 GDK_THREADS_LEAVE ();
2602 gtk_notebook_page_compare (gconstpointer a,
2605 return (((GtkNotebookPage *) a)->child != b);
2609 gtk_notebook_find_child (GtkNotebook *notebook,
2611 const gchar *function)
2613 GList *list = g_list_find_custom (notebook->children, child,
2614 gtk_notebook_page_compare);
2616 #ifndef G_DISABLE_CHECKS
2617 if (!list && function)
2618 g_warning ("%s: unable to find child %p in notebook %p",
2619 function, child, notebook);
2626 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2627 GtkNotebookPage *page)
2629 if (page->tab_label)
2631 if (page->mnemonic_activate_signal)
2632 g_signal_handler_disconnect (page->tab_label,
2633 page->mnemonic_activate_signal);
2634 page->mnemonic_activate_signal = 0;
2636 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2637 gtk_widget_unparent (page->tab_label);
2642 gtk_notebook_real_remove (GtkNotebook *notebook,
2644 gboolean destroying)
2646 GtkNotebookPage *page;
2648 gint need_resize = FALSE;
2650 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2652 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2654 if (notebook->cur_page == list->data)
2656 notebook->cur_page = NULL;
2657 if (next_list && !destroying)
2658 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2661 if (list == notebook->first_tab)
2662 notebook->first_tab = next_list;
2663 if (list == notebook->focus_tab && !destroying)
2664 gtk_notebook_switch_focus_tab (notebook, next_list);
2668 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2671 gtk_widget_unparent (page->child);
2673 gtk_notebook_remove_tab_label (notebook, page);
2677 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2678 page->menu_label->parent);
2679 gtk_widget_queue_resize (notebook->menu);
2681 if (!page->default_menu)
2682 g_object_unref (page->menu_label);
2684 notebook->children = g_list_remove_link (notebook->children, list);
2687 if (page->last_focus_child)
2689 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2690 page->last_focus_child = NULL;
2695 gtk_notebook_update_labels (notebook);
2697 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2701 gtk_notebook_update_labels (GtkNotebook *notebook)
2703 GtkNotebookPage *page;
2708 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2710 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2713 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2714 if (notebook->show_tabs)
2716 if (page->default_tab)
2718 if (!page->tab_label)
2720 page->tab_label = gtk_label_new (string);
2721 gtk_widget_set_parent (page->tab_label,
2722 GTK_WIDGET (notebook));
2725 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2728 if (GTK_WIDGET_VISIBLE (page->child) &&
2729 !GTK_WIDGET_VISIBLE (page->tab_label))
2730 gtk_widget_show (page->tab_label);
2731 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2732 GTK_WIDGET_VISIBLE (page->tab_label))
2733 gtk_widget_hide (page->tab_label);
2735 if (notebook->menu && page->default_menu)
2737 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2738 gtk_label_set_text (GTK_LABEL (page->menu_label),
2739 GTK_LABEL (page->tab_label)->label);
2741 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2747 gtk_notebook_real_page_position (GtkNotebook *notebook,
2753 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2754 g_return_val_if_fail (list != NULL, -1);
2756 for (work = notebook->children, count_start = 0;
2757 work && work != list; work = work->next)
2758 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2764 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2767 return (count_start + g_list_length (list) - 1);
2771 gtk_notebook_search_page (GtkNotebook *notebook,
2774 gboolean find_visible)
2776 GtkNotebookPage *page = NULL;
2777 GList *old_list = NULL;
2780 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2785 flag = GTK_PACK_END;
2789 flag = GTK_PACK_START;
2796 if (!page || page->pack == flag)
2804 list = notebook->children;
2809 if (page->pack == flag &&
2810 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2825 if (page->pack != flag &&
2826 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2834 /* Private GtkNotebook Drawing Functions:
2836 * gtk_notebook_paint
2837 * gtk_notebook_draw_tab
2838 * gtk_notebook_draw_arrow
2841 gtk_notebook_paint (GtkWidget *widget,
2844 GtkNotebook *notebook;
2845 GtkNotebookPage *page;
2850 gint border_width = GTK_CONTAINER (widget)->border_width;
2851 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2855 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2856 g_return_if_fail (area != NULL);
2858 if (!GTK_WIDGET_DRAWABLE (widget))
2861 notebook = GTK_NOTEBOOK (widget);
2862 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2863 tab_pos = get_effective_tab_pos (notebook);
2865 if ((!notebook->show_tabs && !notebook->show_border) ||
2866 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2869 x = widget->allocation.x + border_width;
2870 y = widget->allocation.y + border_width;
2871 width = widget->allocation.width - border_width * 2;
2872 height = widget->allocation.height - border_width * 2;
2874 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2876 gtk_paint_box (widget->style, widget->window,
2877 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2878 area, widget, "notebook",
2879 x, y, width, height);
2884 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2886 page = notebook->first_tab->data;
2891 y += page->allocation.height + widget->style->ythickness;
2892 case GTK_POS_BOTTOM:
2893 height -= page->allocation.height + widget->style->ythickness;
2896 x += page->allocation.width + widget->style->xthickness;
2898 width -= page->allocation.width + widget->style->xthickness;
2901 gtk_paint_box (widget->style, widget->window,
2902 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2903 area, widget, "notebook",
2904 x, y, width, height);
2911 y += notebook->cur_page->allocation.height;
2912 case GTK_POS_BOTTOM:
2913 height -= notebook->cur_page->allocation.height;
2916 x += notebook->cur_page->allocation.width;
2918 width -= notebook->cur_page->allocation.width;
2925 case GTK_POS_BOTTOM:
2926 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2927 gap_width = notebook->cur_page->allocation.width;
2928 step = is_rtl ? STEP_NEXT : STEP_PREV;
2932 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2933 gap_width = notebook->cur_page->allocation.height;
2937 gtk_paint_box_gap (widget->style, widget->window,
2938 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2939 area, widget, "notebook",
2940 x, y, width, height,
2941 tab_pos, gap_x, gap_width);
2945 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2948 page = children->data;
2949 children = gtk_notebook_search_page (notebook, children,
2951 if (!GTK_WIDGET_VISIBLE (page->child))
2953 if (!GTK_WIDGET_MAPPED (page->tab_label))
2955 else if (page != notebook->cur_page)
2956 gtk_notebook_draw_tab (notebook, page, area);
2959 if (showarrow && notebook->scrollable)
2961 if (notebook->has_before_previous)
2962 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2963 if (notebook->has_before_next)
2964 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2965 if (notebook->has_after_previous)
2966 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2967 if (notebook->has_after_next)
2968 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2970 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2974 gtk_notebook_draw_tab (GtkNotebook *notebook,
2975 GtkNotebookPage *page,
2978 GdkRectangle child_area;
2979 GdkRectangle page_area;
2980 GtkStateType state_type;
2981 GtkPositionType gap_side;
2982 gint tab_pos = get_effective_tab_pos (notebook);
2984 g_return_if_fail (notebook != NULL);
2985 g_return_if_fail (page != NULL);
2986 g_return_if_fail (area != NULL);
2988 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2989 (page->allocation.width == 0) || (page->allocation.height == 0))
2992 page_area.x = page->allocation.x;
2993 page_area.y = page->allocation.y;
2994 page_area.width = page->allocation.width;
2995 page_area.height = page->allocation.height;
2997 if (gdk_rectangle_intersect (&page_area, area, &child_area))
3001 widget = GTK_WIDGET (notebook);
3006 gap_side = GTK_POS_BOTTOM;
3008 case GTK_POS_BOTTOM:
3009 gap_side = GTK_POS_TOP;
3012 gap_side = GTK_POS_RIGHT;
3015 gap_side = GTK_POS_LEFT;
3019 if (notebook->cur_page == page)
3020 state_type = GTK_STATE_NORMAL;
3022 state_type = GTK_STATE_ACTIVE;
3023 gtk_paint_extension(widget->style, widget->window,
3024 state_type, GTK_SHADOW_OUT,
3025 area, widget, "tab",
3026 page_area.x, page_area.y,
3027 page_area.width, page_area.height,
3029 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
3030 notebook->focus_tab && (notebook->focus_tab->data == page))
3034 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3036 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3037 area, widget, "tab",
3038 page->tab_label->allocation.x - focus_width,
3039 page->tab_label->allocation.y - focus_width,
3040 page->tab_label->allocation.width + 2 * focus_width,
3041 page->tab_label->allocation.height + 2 * focus_width);
3043 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3044 GTK_WIDGET_DRAWABLE (page->tab_label))
3046 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3048 /* This is a lame hack since all this code needs rewriting anyhow */
3050 expose_event->expose.window = g_object_ref (page->tab_label->window);
3051 expose_event->expose.area = child_area;
3052 expose_event->expose.region = gdk_region_rectangle (&child_area);
3053 expose_event->expose.send_event = TRUE;
3054 expose_event->expose.count = 0;
3056 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3058 gdk_event_free (expose_event);
3064 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3065 GtkNotebookArrow nbarrow)
3067 GtkStateType state_type;
3068 GtkShadowType shadow_type;
3070 GdkRectangle arrow_rect;
3072 gboolean is_rtl, left;
3074 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3076 widget = GTK_WIDGET (notebook);
3078 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3079 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3080 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3082 if (GTK_WIDGET_DRAWABLE (notebook))
3084 if (notebook->in_child == nbarrow)
3086 if (notebook->click_child == nbarrow)
3087 state_type = GTK_STATE_ACTIVE;
3089 state_type = GTK_STATE_PRELIGHT;
3092 state_type = GTK_WIDGET_STATE (widget);
3094 if (notebook->click_child == nbarrow)
3095 shadow_type = GTK_SHADOW_IN;
3097 shadow_type = GTK_SHADOW_OUT;
3099 if (notebook->focus_tab &&
3100 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3101 left? STEP_PREV : STEP_NEXT, TRUE))
3103 shadow_type = GTK_SHADOW_ETCHED_IN;
3104 state_type = GTK_STATE_INSENSITIVE;
3107 if (notebook->tab_pos == GTK_POS_LEFT ||
3108 notebook->tab_pos == GTK_POS_RIGHT)
3109 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3111 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3113 gtk_paint_arrow (widget->style, widget->window, state_type,
3114 shadow_type, NULL, widget, "notebook",
3115 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3116 ARROW_SIZE, ARROW_SIZE);
3120 /* Private GtkNotebook Size Allocate Functions:
3122 * gtk_notebook_pages_allocate
3123 * gtk_notebook_page_allocate
3124 * gtk_notebook_calc_tabs
3127 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3129 GtkWidget *widget = GTK_WIDGET (notebook);
3130 GtkContainer *container = GTK_CONTAINER (notebook);
3131 GtkNotebookPage *page = NULL;
3132 GtkAllocation *allocation = &widget->allocation;
3133 GtkAllocation child_allocation;
3134 GList *children = NULL;
3135 GList *last_child = NULL;
3136 gboolean showarrow = FALSE;
3143 gint tab_pos = get_effective_tab_pos (notebook);
3144 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3145 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3148 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3151 child_allocation.x = widget->allocation.x + container->border_width;
3152 child_allocation.y = widget->allocation.y + container->border_width;
3156 case GTK_POS_BOTTOM:
3157 child_allocation.y = (widget->allocation.y +
3158 allocation->height -
3159 notebook->cur_page->requisition.height -
3160 container->border_width);
3163 child_allocation.height = notebook->cur_page->requisition.height;
3167 child_allocation.x = (widget->allocation.x +
3169 notebook->cur_page->requisition.width -
3170 container->border_width);
3173 child_allocation.width = notebook->cur_page->requisition.width;
3177 if (notebook->scrollable)
3181 children = notebook->children;
3183 if (notebook->focus_tab)
3184 focus_tab = notebook->focus_tab;
3185 else if (notebook->first_tab)
3186 focus_tab = notebook->first_tab;
3188 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3193 case GTK_POS_BOTTOM:
3196 page = children->data;
3197 children = children->next;
3199 if (GTK_WIDGET_VISIBLE (page->child))
3200 tab_space += page->requisition.width;
3203 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3206 page = focus_tab->data;
3208 tab_space = allocation->width - TAB_OVERLAP -
3209 page->requisition.width - 2 * container->border_width;
3210 if (notebook->has_after_previous)
3211 tab_space -= ARROW_SPACING + ARROW_SIZE;
3212 if (notebook->has_after_next)
3213 tab_space -= ARROW_SPACING + ARROW_SIZE;
3214 if (notebook->has_before_previous)
3216 tab_space -= ARROW_SPACING + ARROW_SIZE;
3217 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3219 if (notebook->has_before_next)
3221 tab_space -= ARROW_SPACING + ARROW_SIZE;
3222 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3230 page = children->data;
3231 children = children->next;
3233 if (GTK_WIDGET_VISIBLE (page->child))
3234 tab_space += page->requisition.height;
3237 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3240 page = focus_tab->data;
3241 tab_space = allocation->height
3242 - TAB_OVERLAP - 2 * container->border_width
3243 - page->requisition.height;
3244 if (notebook->has_after_previous || notebook->has_after_next)
3245 tab_space -= ARROW_SPACING + ARROW_SIZE;
3246 if (notebook->has_before_previous || notebook->has_before_next)
3248 tab_space -= ARROW_SPACING + ARROW_SIZE;
3249 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3254 if (showarrow) /* first_tab <- focus_tab */
3258 notebook->first_tab = focus_tab;
3259 last_child = gtk_notebook_search_page (notebook, focus_tab,
3265 if (notebook->first_tab && notebook->first_tab != focus_tab)
3267 /* Is first_tab really predecessor of focus_tab ? */
3268 page = notebook->first_tab->data;
3269 if (GTK_WIDGET_VISIBLE (page->child))
3270 for (children = focus_tab;
3271 children && children != notebook->first_tab;
3272 children = gtk_notebook_search_page (notebook,
3278 notebook->first_tab = focus_tab;
3280 gtk_notebook_calc_tabs (notebook,
3281 gtk_notebook_search_page (notebook,
3285 &(notebook->first_tab), &tab_space,
3290 notebook->first_tab =
3291 gtk_notebook_search_page (notebook, notebook->first_tab,
3293 if (!notebook->first_tab)
3294 notebook->first_tab = focus_tab;
3295 last_child = gtk_notebook_search_page (notebook, focus_tab,
3298 else /* focus_tab -> end */
3300 if (!notebook->first_tab)
3301 notebook->first_tab = gtk_notebook_search_page (notebook,
3306 gtk_notebook_calc_tabs (notebook,
3307 gtk_notebook_search_page (notebook,
3311 &children, &tab_space, STEP_NEXT);
3314 last_child = children;
3315 else /* start <- first_tab */
3319 gtk_notebook_calc_tabs
3321 gtk_notebook_search_page (notebook,
3322 notebook->first_tab,
3325 &children, &tab_space, STEP_PREV);
3326 notebook->first_tab = gtk_notebook_search_page(notebook,
3336 tab_space = -tab_space;
3338 for (children = notebook->first_tab;
3339 children && children != last_child;
3340 children = gtk_notebook_search_page (notebook, children,
3347 /*unmap all non-visible tabs*/
3348 for (children = gtk_notebook_search_page (notebook, NULL,
3350 children && children != notebook->first_tab;
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);
3358 for (children = last_child; children;
3359 children = gtk_notebook_search_page (notebook, children,
3362 page = children->data;
3363 if (page->tab_label)
3364 gtk_widget_set_child_visible (page->tab_label, FALSE);
3367 else /* !showarrow */
3369 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3380 children = notebook->children;
3384 case GTK_POS_BOTTOM:
3387 page = children->data;
3388 children = children->next;
3390 if (GTK_WIDGET_VISIBLE (page->child))
3393 tab_space += page->requisition.width;
3398 tab_space -= allocation->width;
3404 page = children->data;
3405 children = children->next;
3407 if (GTK_WIDGET_VISIBLE (page->child))
3410 tab_space += page->requisition.height;
3415 tab_space -= allocation->height;
3417 tab_space += 2 * container->border_width + TAB_OVERLAP;
3419 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3421 if (notebook->homogeneous && n)
3425 children = notebook->first_tab;
3428 memo_x = child_allocation.x;
3429 if (notebook->children && is_rtl)
3431 child_allocation.x = (allocation->x + allocation->width -
3432 container->border_width);
3435 if (notebook->has_after_previous)
3436 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3437 if (notebook->has_after_next)
3438 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3444 if (children == last_child)
3446 /* FIXME double check */
3450 page = children->data;
3451 if (!showarrow && page->pack != GTK_PACK_START)
3453 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3456 if (n && (showarrow || page->expand || notebook->homogeneous))
3458 new_fill = (tab_space * i++) / n;
3459 delta = new_fill - old_fill;
3460 old_fill = new_fill;
3466 case GTK_POS_BOTTOM:
3467 child_allocation.width = (page->requisition.width +
3468 TAB_OVERLAP + delta);
3470 child_allocation.x -= child_allocation.width;
3474 child_allocation.height = (page->requisition.height +
3475 TAB_OVERLAP + delta);
3479 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3484 case GTK_POS_BOTTOM:
3486 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3488 child_allocation.x += TAB_OVERLAP;
3492 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3496 if (page->tab_label)
3497 gtk_widget_set_child_visible (page->tab_label, TRUE);
3502 children = notebook->children;
3507 case GTK_POS_BOTTOM:
3509 child_allocation.x = (allocation->x + allocation->width -
3510 container->border_width);
3512 child_allocation.x = memo_x;
3516 child_allocation.y = (allocation->y + allocation->height -
3517 container->border_width);
3521 while (children != last_child)
3523 page = children->data;
3524 children = children->next;
3526 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3530 if (n && (page->expand || notebook->homogeneous))
3532 new_fill = (tab_space * i++) / n;
3533 delta = new_fill - old_fill;
3534 old_fill = new_fill;
3540 case GTK_POS_BOTTOM:
3541 child_allocation.width = (page->requisition.width +
3542 TAB_OVERLAP + delta);
3544 child_allocation.x -= child_allocation.width;
3548 child_allocation.height = (page->requisition.height +
3549 TAB_OVERLAP + delta);
3550 child_allocation.y -= child_allocation.height;
3554 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3559 case GTK_POS_BOTTOM:
3561 child_allocation.x += TAB_OVERLAP;
3563 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3567 child_allocation.y += TAB_OVERLAP;
3571 if (page->tab_label)
3572 gtk_widget_set_child_visible (page->tab_label, TRUE);
3577 gtk_notebook_redraw_tabs (notebook);
3581 gtk_notebook_page_allocate (GtkNotebook *notebook,
3582 GtkNotebookPage *page,
3583 GtkAllocation *allocation)
3585 GtkWidget *widget = GTK_WIDGET (notebook);
3586 GtkAllocation child_allocation;
3587 GtkRequisition tab_requisition;
3592 gint tab_pos = get_effective_tab_pos (notebook);
3594 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3596 xthickness = widget->style->xthickness;
3597 ythickness = widget->style->ythickness;
3599 page->allocation = *allocation;
3600 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3602 if (notebook->cur_page != page)
3607 page->allocation.y += ythickness;
3608 case GTK_POS_BOTTOM:
3609 if (page->allocation.height > ythickness)
3610 page->allocation.height -= ythickness;
3613 page->allocation.x += xthickness;
3615 if (page->allocation.width > xthickness)
3616 page->allocation.width -= xthickness;
3624 case GTK_POS_BOTTOM:
3625 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3628 child_allocation.x = (xthickness + focus_width +
3629 notebook->tab_hborder);
3630 child_allocation.width = MAX (1, (page->allocation.width -
3631 2 * child_allocation.x));
3632 child_allocation.x += page->allocation.x;
3636 child_allocation.x = (page->allocation.x +
3637 (page->allocation.width -
3638 tab_requisition.width) / 2);
3639 child_allocation.width = tab_requisition.width;
3641 child_allocation.y = (notebook->tab_vborder + focus_width +
3642 page->allocation.y);
3643 if (tab_pos == GTK_POS_TOP)
3644 child_allocation.y += ythickness;
3645 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3646 2 * (notebook->tab_vborder + focus_width)));
3650 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3653 child_allocation.y = ythickness + padding;
3654 child_allocation.height = MAX (1, (page->allocation.height -
3655 2 * child_allocation.y));
3656 child_allocation.y += page->allocation.y;
3660 child_allocation.y = (page->allocation.y + (page->allocation.height -
3661 tab_requisition.height) / 2);
3662 child_allocation.height = tab_requisition.height;
3664 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3665 if (tab_pos == GTK_POS_LEFT)
3666 child_allocation.x += xthickness;
3667 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3668 2 * (notebook->tab_hborder + focus_width)));
3672 if (page->tab_label)
3673 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3677 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3683 GtkNotebookPage *page = NULL;
3685 GList *last_list = NULL;
3687 gint tab_pos = get_effective_tab_pos (notebook);
3693 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3694 if (pack == GTK_PACK_END)
3695 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3702 case GTK_POS_BOTTOM:
3705 page = children->data;
3706 if (GTK_WIDGET_VISIBLE (page->child))
3708 if (page->pack == pack)
3710 *tab_space -= page->requisition.width;
3711 if (*tab_space < 0 || children == *end)
3715 *tab_space = - (*tab_space +
3716 page->requisition.width);
3722 last_list = children;
3724 if (direction == STEP_NEXT)
3725 children = children->next;
3727 children = children->prev;
3734 page = children->data;
3735 if (GTK_WIDGET_VISIBLE (page->child))
3737 if (page->pack == pack)
3739 *tab_space -= page->requisition.height;
3740 if (*tab_space < 0 || children == *end)
3744 *tab_space = - (*tab_space +
3745 page->requisition.height);
3751 last_list = children;
3753 if (direction == STEP_NEXT)
3754 children = children->next;
3756 children = children->prev;
3760 if (direction == STEP_PREV)
3762 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3763 direction = STEP_PREV;
3764 children = last_list;
3769 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3773 for (list = notebook->children; list != NULL; list = list->next)
3775 GtkNotebookPage *page = list->data;
3777 if (page->tab_label)
3779 if (page == notebook->cur_page)
3780 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3782 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3787 /* Private GtkNotebook Page Switch Methods:
3789 * gtk_notebook_real_switch_page
3792 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3793 GtkNotebookPage *page,
3796 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3797 g_return_if_fail (page != NULL);
3799 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3802 if (notebook->cur_page)
3803 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3805 notebook->cur_page = page;
3807 if (!notebook->focus_tab ||
3808 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3809 notebook->focus_tab =
3810 g_list_find (notebook->children, notebook->cur_page);
3812 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3814 /* If the focus was on the previous page, move it to the first
3815 * element on the new page, if possible, or if not, to the
3818 if (notebook->child_has_focus)
3820 if (notebook->cur_page->last_focus_child &&
3821 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3822 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3824 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3825 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3828 gtk_notebook_update_tab_states (notebook);
3829 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3830 g_object_notify (G_OBJECT (notebook), "page");
3833 /* Private GtkNotebook Page Switch Functions:
3835 * gtk_notebook_switch_page
3836 * gtk_notebook_page_select
3837 * gtk_notebook_switch_focus_tab
3838 * gtk_notebook_menu_switch_page
3841 gtk_notebook_switch_page (GtkNotebook *notebook,
3842 GtkNotebookPage *page,
3845 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3846 g_return_if_fail (page != NULL);
3848 if (notebook->cur_page == page)
3852 page_num = g_list_index (notebook->children, page);
3854 g_signal_emit (notebook,
3855 notebook_signals[SWITCH_PAGE],
3862 gtk_notebook_page_select (GtkNotebook *notebook,
3863 gboolean move_focus)
3865 GtkNotebookPage *page;
3866 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3867 gint tab_pos = get_effective_tab_pos (notebook);
3869 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3871 if (!notebook->focus_tab)
3874 page = notebook->focus_tab->data;
3875 gtk_notebook_switch_page (notebook, page, -1);
3884 case GTK_POS_BOTTOM:
3888 dir = GTK_DIR_RIGHT;
3895 if (gtk_widget_child_focus (page->child, dir))
3902 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3906 GtkNotebookPage *old_page = NULL;
3907 GtkNotebookPage *page;
3909 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3911 if (notebook->focus_tab == new_child)
3914 old_child = notebook->focus_tab;
3915 notebook->focus_tab = new_child;
3917 if (notebook->scrollable)
3918 gtk_notebook_redraw_arrows (notebook);
3920 if (!notebook->show_tabs || !notebook->focus_tab)
3924 old_page = old_child->data;
3926 page = notebook->focus_tab->data;
3927 if (GTK_WIDGET_MAPPED (page->tab_label))
3928 gtk_notebook_redraw_tabs (notebook);
3930 gtk_notebook_pages_allocate (notebook);
3932 gtk_notebook_switch_page (notebook, page,
3933 g_list_index (notebook->children, page));
3937 gtk_notebook_menu_switch_page (GtkWidget *widget,
3938 GtkNotebookPage *page)
3940 GtkNotebook *notebook;
3944 g_return_if_fail (widget != NULL);
3945 g_return_if_fail (page != NULL);
3947 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3948 (GTK_MENU (widget->parent)));
3950 if (notebook->cur_page == page)
3954 children = notebook->children;
3955 while (children && children->data != page)
3957 children = children->next;
3961 g_signal_emit (notebook,
3962 notebook_signals[SWITCH_PAGE],
3968 /* Private GtkNotebook Menu Functions:
3970 * gtk_notebook_menu_item_create
3971 * gtk_notebook_menu_label_unparent
3972 * gtk_notebook_menu_detacher
3975 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3978 GtkNotebookPage *page;
3979 GtkWidget *menu_item;
3982 if (page->default_menu)
3984 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3985 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3987 page->menu_label = gtk_label_new ("");
3988 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3991 gtk_widget_show (page->menu_label);
3992 menu_item = gtk_menu_item_new ();
3993 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3994 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3995 gtk_notebook_real_page_position (notebook, list));
3996 g_signal_connect (menu_item, "activate",
3997 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3998 if (GTK_WIDGET_VISIBLE (page->child))
3999 gtk_widget_show (menu_item);
4003 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4006 gtk_widget_unparent (GTK_BIN(widget)->child);
4007 GTK_BIN(widget)->child = NULL;
4011 gtk_notebook_menu_detacher (GtkWidget *widget,
4014 GtkNotebook *notebook;
4016 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4018 notebook = GTK_NOTEBOOK (widget);
4019 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4021 notebook->menu = NULL;
4024 /* Private GtkNotebook Setter Functions:
4026 * gtk_notebook_set_homogeneous_tabs_internal
4027 * gtk_notebook_set_tab_border_internal
4028 * gtk_notebook_set_tab_hborder_internal
4029 * gtk_notebook_set_tab_vborder_internal
4032 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4033 gboolean homogeneous)
4035 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4037 if (homogeneous == notebook->homogeneous)
4040 notebook->homogeneous = homogeneous;
4041 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4043 g_object_notify (G_OBJECT (notebook), "homogeneous");
4047 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4050 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4052 notebook->tab_hborder = border_width;
4053 notebook->tab_vborder = border_width;
4055 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4056 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4058 g_object_freeze_notify (G_OBJECT (notebook));
4059 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4060 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4061 g_object_thaw_notify (G_OBJECT (notebook));
4065 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4068 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4070 if (notebook->tab_hborder == tab_hborder)
4073 notebook->tab_hborder = tab_hborder;
4075 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4076 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4078 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4082 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4085 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4087 if (notebook->tab_vborder == tab_vborder)
4090 notebook->tab_vborder = tab_vborder;
4092 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4093 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4095 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4098 /* Public GtkNotebook Page Insert/Remove Methods :
4100 * gtk_notebook_append_page
4101 * gtk_notebook_append_page_menu
4102 * gtk_notebook_prepend_page
4103 * gtk_notebook_prepend_page_menu
4104 * gtk_notebook_insert_page
4105 * gtk_notebook_insert_page_menu
4106 * gtk_notebook_remove_page
4109 * gtk_notebook_append_page:
4110 * @notebook: a #GtkNotebook
4111 * @child: the #GtkWidget to use as the contents of the page.
4112 * @tab_label: the #GtkWidget to be used as the label for the page,
4113 * or %NULL to use the default label, 'page N'.
4115 * Appends a page to @notebook.
4117 * Return value: the index (starting from 0) of the appended
4118 * page in the notebook, or -1 if function fails
4121 gtk_notebook_append_page (GtkNotebook *notebook,
4123 GtkWidget *tab_label)
4125 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4126 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4127 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4129 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4133 * gtk_notebook_append_page_menu:
4134 * @notebook: a #GtkNotebook
4135 * @child: the #GtkWidget to use as the contents of the page.
4136 * @tab_label: the #GtkWidget to be used as the label for the page,
4137 * or %NULL to use the default label, 'page N'.
4138 * @menu_label: the widget to use as a label for the page-switch
4139 * menu, if that is enabled. If %NULL, and @tab_label
4140 * is a #GtkLabel or %NULL, then the menu label will be
4141 * a newly created label with the same text as @tab_label;
4142 * If @tab_label is not a #GtkLabel, @menu_label must be
4143 * specified if the page-switch menu is to be used.
4145 * Appends a page to @notebook, specifying the widget to use as the
4146 * label in the popup menu.
4148 * Return value: the index (starting from 0) of the appended
4149 * page in the notebook, or -1 if function fails
4152 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4154 GtkWidget *tab_label,
4155 GtkWidget *menu_label)
4157 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4158 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4159 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4160 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4162 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4166 * gtk_notebook_prepend_page:
4167 * @notebook: a #GtkNotebook
4168 * @child: the #GtkWidget to use as the contents of the page.
4169 * @tab_label: the #GtkWidget to be used as the label for the page,
4170 * or %NULL to use the default label, 'page N'.
4172 * Prepends a page to @notebook.
4174 * Return value: the index (starting from 0) of the prepended
4175 * page in the notebook, or -1 if function fails
4178 gtk_notebook_prepend_page (GtkNotebook *notebook,
4180 GtkWidget *tab_label)
4182 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4183 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4184 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4186 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4190 * gtk_notebook_prepend_page_menu:
4191 * @notebook: a #GtkNotebook
4192 * @child: the #GtkWidget to use as the contents of the page.
4193 * @tab_label: the #GtkWidget to be used as the label for the page,
4194 * or %NULL to use the default label, 'page N'.
4195 * @menu_label: the widget to use as a label for the page-switch
4196 * menu, if that is enabled. If %NULL, and @tab_label
4197 * is a #GtkLabel or %NULL, then the menu label will be
4198 * a newly created label with the same text as @tab_label;
4199 * If @tab_label is not a #GtkLabel, @menu_label must be
4200 * specified if the page-switch menu is to be used.
4202 * Prepends a page to @notebook, specifying the widget to use as the
4203 * label in the popup menu.
4205 * Return value: the index (starting from 0) of the prepended
4206 * page in the notebook, or -1 if function fails
4209 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4211 GtkWidget *tab_label,
4212 GtkWidget *menu_label)
4214 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4215 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4216 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4217 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4219 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4223 * gtk_notebook_insert_page:
4224 * @notebook: a #GtkNotebook
4225 * @child: the #GtkWidget to use as the contents of the page.
4226 * @tab_label: the #GtkWidget to be used as the label for the page,
4227 * or %NULL to use the default label, 'page N'.
4228 * @position: the index (starting at 0) at which to insert the page,
4229 * or -1 to append the page after all other pages.
4231 * Insert a page into @notebook at the given position.
4233 * Return value: the index (starting from 0) of the inserted
4234 * page in the notebook, or -1 if function fails
4237 gtk_notebook_insert_page (GtkNotebook *notebook,
4239 GtkWidget *tab_label,
4242 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4243 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4244 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4246 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4251 gtk_notebook_page_compare_tab (gconstpointer a,
4254 return (((GtkNotebookPage *) a)->tab_label != b);
4258 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4262 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4265 list = g_list_find_custom (notebook->children, child,
4266 gtk_notebook_page_compare_tab);
4269 GtkNotebookPage *page = list->data;
4271 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4272 gtk_notebook_switch_page (notebook, page, -1);
4273 focus_tabs_in (notebook);
4280 * gtk_notebook_insert_page_menu:
4281 * @notebook: a #GtkNotebook
4282 * @child: the #GtkWidget to use as the contents of the page.
4283 * @tab_label: the #GtkWidget to be used as the label for the page,
4284 * or %NULL to use the default label, 'page N'.
4285 * @menu_label: the widget to use as a label for the page-switch
4286 * menu, if that is enabled. If %NULL, and @tab_label
4287 * is a #GtkLabel or %NULL, then the menu label will be
4288 * a newly created label with the same text as @tab_label;
4289 * If @tab_label is not a #GtkLabel, @menu_label must be
4290 * specified if the page-switch menu is to be used.
4291 * @position: the index (starting at 0) at which to insert the page,
4292 * or -1 to append the page after all other pages.
4294 * Insert a page into @notebook at the given position, specifying
4295 * the widget to use as the label in the popup menu.
4297 * Return value: the index (starting from 0) of the inserted
4298 * page in the notebook, or -1 if function fails
4301 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4303 GtkWidget *tab_label,
4304 GtkWidget *menu_label,
4307 GtkNotebookPage *page;
4310 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4311 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4312 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4313 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4315 gtk_widget_freeze_child_notify (child);
4317 page = g_new (GtkNotebookPage, 1);
4318 page->child = child;
4319 page->last_focus_child = NULL;
4320 page->requisition.width = 0;
4321 page->requisition.height = 0;
4322 page->allocation.x = 0;
4323 page->allocation.y = 0;
4324 page->allocation.width = 0;
4325 page->allocation.height = 0;
4326 page->default_menu = FALSE;
4327 page->default_tab = FALSE;
4328 page->mnemonic_activate_signal = 0;
4330 nchildren = g_list_length (notebook->children);
4331 if ((position < 0) || (position > nchildren))
4332 position = nchildren;
4334 notebook->children = g_list_insert (notebook->children, page, position);
4338 page->default_tab = TRUE;
4339 if (notebook->show_tabs)
4340 tab_label = gtk_label_new ("");
4342 page->tab_label = tab_label;
4343 page->menu_label = menu_label;
4344 page->expand = FALSE;
4346 page->pack = GTK_PACK_START;
4349 page->default_menu = TRUE;
4352 g_object_ref (page->menu_label);
4353 gtk_object_sink (GTK_OBJECT (page->menu_label));
4357 gtk_notebook_menu_item_create (notebook,
4358 g_list_find (notebook->children, page));
4360 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4362 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4364 gtk_notebook_update_labels (notebook);
4366 if (!notebook->first_tab)
4367 notebook->first_tab = notebook->children;
4369 if (!notebook->cur_page)
4370 gtk_widget_set_child_visible (child, TRUE);
4372 gtk_widget_set_child_visible (child, FALSE);
4376 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4377 gtk_widget_show (tab_label);
4379 gtk_widget_hide (tab_label);
4382 if (!notebook->cur_page)
4384 gtk_notebook_switch_page (notebook, page, 0);
4385 gtk_notebook_switch_focus_tab (notebook, NULL);
4388 gtk_notebook_update_tab_states (notebook);
4391 page->mnemonic_activate_signal =
4392 g_signal_connect (tab_label,
4393 "mnemonic_activate",
4394 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4397 gtk_widget_child_notify (child, "tab_expand");
4398 gtk_widget_child_notify (child, "tab_fill");
4399 gtk_widget_child_notify (child, "tab_pack");
4400 gtk_widget_child_notify (child, "tab_label");
4401 gtk_widget_child_notify (child, "menu_label");
4402 gtk_widget_child_notify (child, "position");
4403 gtk_widget_thaw_child_notify (child);
4409 * gtk_notebook_remove_page:
4410 * @notebook: a #GtkNotebook.
4411 * @page_num: the index of a notebook page, starting
4412 * from 0. If -1, the last page will
4415 * Removes a page from the notebook given its index
4419 gtk_notebook_remove_page (GtkNotebook *notebook,
4424 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4428 list = g_list_nth (notebook->children, page_num);
4430 gtk_notebook_real_remove (notebook, list, FALSE);
4434 list = g_list_last (notebook->children);
4436 gtk_notebook_real_remove (notebook, list, FALSE);
4440 /* Public GtkNotebook Page Switch Methods :
4441 * gtk_notebook_get_current_page
4442 * gtk_notebook_page_num
4443 * gtk_notebook_set_current_page
4444 * gtk_notebook_next_page
4445 * gtk_notebook_prev_page
4448 * gtk_notebook_get_current_page:
4449 * @notebook: a #GtkNotebook
4451 * Returns the page number of the current page.
4453 * Return value: the index (starting from 0) of the current
4454 * page in the notebook. If the notebook has no pages, then
4455 * -1 will be returned.
4458 gtk_notebook_get_current_page (GtkNotebook *notebook)
4460 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4462 if (!notebook->cur_page)
4465 return g_list_index (notebook->children, notebook->cur_page);
4469 * gtk_notebook_get_nth_page:
4470 * @notebook: a #GtkNotebook
4471 * @page_num: the index of a page in the noteobok, or -1
4472 * to get the last page.
4474 * Returns the child widget contained in page number @page_num.
4476 * Return value: the child widget, or %NULL if @page_num is
4480 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4483 GtkNotebookPage *page;
4486 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4489 list = g_list_nth (notebook->children, page_num);
4491 list = g_list_last (notebook->children);
4503 * gtk_notebook_get_n_pages:
4504 * @notebook: a #GtkNotebook
4506 * Gets the number of pages in a notebook.
4508 * Return value: the number of pages in the notebook.
4513 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4515 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4517 return g_list_length (notebook->children);
4521 * gtk_notebook_page_num:
4522 * @notebook: a #GtkNotebook
4523 * @child: a #GtkWidget
4525 * Finds the index of the page which contains the given child
4528 * Return value: the index of the page containing @child, or
4529 * -1 if @child is not in the notebook.
4532 gtk_notebook_page_num (GtkNotebook *notebook,
4538 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4541 children = notebook->children;
4544 GtkNotebookPage *page = children->data;
4546 if (page->child == child)
4549 children = children->next;
4557 * gtk_notebook_set_current_page:
4558 * @notebook: a #GtkNotebook
4559 * @page_num: index of the page to switch to, starting from 0.
4560 * If negative, the last page will be used. If greater
4561 * than the number of pages in the notebook, nothing
4564 * Switches to the page number @page_num.
4567 gtk_notebook_set_current_page (GtkNotebook *notebook,
4572 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4575 list = g_list_nth (notebook->children, page_num);
4577 list = g_list_last (notebook->children);
4579 page_num = g_list_index (notebook->children, list);
4582 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4586 * gtk_notebook_next_page:
4587 * @notebook: a #GtkNotebook
4589 * Switches to the next page. Nothing happens if the current page is
4593 gtk_notebook_next_page (GtkNotebook *notebook)
4597 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4599 list = g_list_find (notebook->children, notebook->cur_page);
4603 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4607 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4611 * gtk_notebook_prev_page:
4612 * @notebook: a #GtkNotebook
4614 * Switches to the previous page. Nothing happens if the current page
4615 * is the first page.
4618 gtk_notebook_prev_page (GtkNotebook *notebook)
4622 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4624 list = g_list_find (notebook->children, notebook->cur_page);
4628 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4632 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4635 /* Public GtkNotebook/Tab Style Functions
4637 * gtk_notebook_set_show_border
4638 * gtk_notebook_set_show_tabs
4639 * gtk_notebook_set_tab_pos
4640 * gtk_notebook_set_homogeneous_tabs
4641 * gtk_notebook_set_tab_border
4642 * gtk_notebook_set_tab_hborder
4643 * gtk_notebook_set_tab_vborder
4644 * gtk_notebook_set_scrollable
4647 * gtk_notebook_set_show_border:
4648 * @notebook: a #GtkNotebook
4649 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4651 * Sets whether a bevel will be drawn around the notebook pages.
4652 * This only has a visual effect when the tabs are not shown.
4653 * See gtk_notebook_set_show_tabs().
4656 gtk_notebook_set_show_border (GtkNotebook *notebook,
4657 gboolean show_border)
4659 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4661 if (notebook->show_border != show_border)
4663 notebook->show_border = show_border;
4665 if (GTK_WIDGET_VISIBLE (notebook))
4666 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4668 g_object_notify (G_OBJECT (notebook), "show_border");
4673 * gtk_notebook_get_show_border:
4674 * @notebook: a #GtkNotebook
4676 * Returns whether a bevel will be drawn around the notebook pages. See
4677 * gtk_notebook_set_show_border().
4679 * Return value: %TRUE if the bevel is drawn
4682 gtk_notebook_get_show_border (GtkNotebook *notebook)
4684 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4686 return notebook->show_border;
4690 * gtk_notebook_set_show_tabs:
4691 * @notebook: a #GtkNotebook
4692 * @show_tabs: %TRUE if the tabs should be shown.
4694 * Sets whether to show the tabs for the notebook or not.
4697 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4700 GtkNotebookPage *page;
4703 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4705 show_tabs = show_tabs != FALSE;
4707 if (notebook->show_tabs == show_tabs)
4710 notebook->show_tabs = show_tabs;
4711 children = notebook->children;
4715 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4719 page = children->data;
4720 children = children->next;
4721 if (page->default_tab)
4723 gtk_widget_destroy (page->tab_label);
4724 page->tab_label = NULL;
4727 gtk_widget_hide (page->tab_label);
4732 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4733 gtk_notebook_update_labels (notebook);
4735 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4737 g_object_notify (G_OBJECT (notebook), "show_tabs");
4741 * gtk_notebook_get_show_tabs:
4742 * @notebook: a #GtkNotebook
4744 * Returns whether the tabs of the notebook are shown. See
4745 * gtk_notebook_set_show_tabs().
4747 * Return value: %TRUE if the tabs are shown
4750 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4752 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4754 return notebook->show_tabs;
4758 * gtk_notebook_set_tab_pos:
4759 * @notebook: a #GtkNotebook.
4760 * @pos: the edge to draw the tabs at.
4762 * Sets the edge at which the tabs for switching pages in the
4763 * notebook are drawn.
4766 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4767 GtkPositionType pos)
4769 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4771 if (notebook->tab_pos != pos)
4773 notebook->tab_pos = pos;
4774 if (GTK_WIDGET_VISIBLE (notebook))
4775 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4778 g_object_notify (G_OBJECT (notebook), "tab_pos");
4782 * gtk_notebook_get_tab_pos:
4783 * @notebook: a #GtkNotebook
4785 * Gets the edge at which the tabs for switching pages in the
4786 * notebook are drawn.
4788 * Return value: the edge at which the tabs are drawn
4791 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4793 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4795 return notebook->tab_pos;
4799 * gtk_notebook_set_homogeneous_tabs:
4800 * @notebook: a #GtkNotebook
4801 * @homogeneous: %TRUE if all tabs should be the same size.
4803 * Sets whether the tabs must have all the same size or not.
4806 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4807 gboolean homogeneous)
4809 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4811 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4815 * gtk_notebook_set_tab_border:
4816 * @notebook: a #GtkNotebook
4817 * @border_width: width of the border around the tab labels.
4819 * Sets the width the border around the tab labels
4820 * in a notebook. This is equivalent to calling
4821 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4822 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4825 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4828 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4830 gtk_notebook_set_tab_border_internal (notebook, border_width);
4834 * gtk_notebook_set_tab_hborder:
4835 * @notebook: a #GtkNotebook
4836 * @tab_hborder: width of the horizontal border of tab labels.
4838 * Sets the width of the horizontal border of tab labels.
4841 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4844 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4846 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4850 * gtk_notebook_set_tab_vborder:
4851 * @notebook: a #GtkNotebook
4852 * @tab_vborder: width of the vertical border of tab labels.
4854 * Sets the width of the vertical border of tab labels.
4857 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4860 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4862 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4866 * gtk_notebook_set_scrollable:
4867 * @notebook: a #GtkNotebook
4868 * @scrollable: %TRUE if scroll arrows should be added
4870 * Sets whether the tab label area will have arrows for scrolling if
4871 * there are too many tabs to fit in the area.
4874 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4875 gboolean scrollable)
4877 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4879 scrollable = (scrollable != FALSE);
4881 if (scrollable != notebook->scrollable)
4883 notebook->scrollable = scrollable;
4885 if (GTK_WIDGET_VISIBLE (notebook))
4886 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4888 g_object_notify (G_OBJECT (notebook), "scrollable");
4893 * gtk_notebook_get_scrollable:
4894 * @notebook: a #GtkNotebook
4896 * Returns whether the tab label area has arrows for scrolling. See
4897 * gtk_notebook_set_scrollable().
4899 * Return value: %TRUE if arrows for scrolling are present
4902 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4904 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4906 return notebook->scrollable;
4909 /* Public GtkNotebook Popup Menu Methods:
4911 * gtk_notebook_popup_enable
4912 * gtk_notebook_popup_disable
4917 * gtk_notebook_popup_enable:
4918 * @notebook: a #GtkNotebook
4920 * Enables the popup menu: if the user clicks with the right mouse button on
4921 * the bookmarks, a menu with all the pages will be popped up.
4924 gtk_notebook_popup_enable (GtkNotebook *notebook)
4928 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4933 notebook->menu = gtk_menu_new ();
4934 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4936 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4937 gtk_notebook_menu_item_create (notebook, list);
4939 gtk_notebook_update_labels (notebook);
4940 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4941 GTK_WIDGET (notebook),
4942 gtk_notebook_menu_detacher);
4944 g_object_notify (G_OBJECT (notebook), "enable_popup");
4948 * gtk_notebook_popup_disable:
4949 * @notebook: a #GtkNotebook
4951 * Disables the popup menu.
4954 gtk_notebook_popup_disable (GtkNotebook *notebook)
4956 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4958 if (!notebook->menu)
4961 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4962 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4963 gtk_widget_destroy (notebook->menu);
4965 g_object_notify (G_OBJECT (notebook), "enable_popup");
4968 /* Public GtkNotebook Page Properties Functions:
4970 * gtk_notebook_get_tab_label
4971 * gtk_notebook_set_tab_label
4972 * gtk_notebook_set_tab_label_text
4973 * gtk_notebook_get_menu_label
4974 * gtk_notebook_set_menu_label
4975 * gtk_notebook_set_menu_label_text
4976 * gtk_notebook_set_tab_label_packing
4977 * gtk_notebook_query_tab_label_packing
4981 * gtk_notebook_get_tab_label:
4982 * @notebook: a #GtkNotebook
4985 * Returns the tab label widget for the page @child. %NULL is returned
4986 * if @child is not in @notebook or if no tab label has specifically
4987 * been set for @child.
4989 * Return value: the tab label
4992 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4997 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4998 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5000 list = CHECK_FIND_CHILD (notebook, child);
5004 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5007 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5011 * gtk_notebook_set_tab_label:
5012 * @notebook: a #GtkNotebook
5014 * @tab_label: the tab label widget to use, or %NULL for default tab
5017 * Changes the tab label for @child. If %NULL is specified
5018 * for @tab_label, then the page will have the label 'page N'.
5021 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5023 GtkWidget *tab_label)
5025 GtkNotebookPage *page;
5028 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5029 g_return_if_fail (GTK_IS_WIDGET (child));
5031 list = CHECK_FIND_CHILD (notebook, child);
5035 /* a NULL pointer indicates a default_tab setting, otherwise
5036 * we need to set the associated label
5040 if (page->tab_label == tab_label)
5044 gtk_notebook_remove_tab_label (notebook, page);
5048 page->default_tab = FALSE;
5049 page->tab_label = tab_label;
5050 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5054 page->default_tab = TRUE;
5055 page->tab_label = NULL;
5057 if (notebook->show_tabs)
5061 g_snprintf (string, sizeof(string), _("Page %u"),
5062 gtk_notebook_real_page_position (notebook, list));
5063 page->tab_label = gtk_label_new (string);
5064 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5068 if (page->tab_label)
5069 page->mnemonic_activate_signal =
5070 g_signal_connect (page->tab_label,
5071 "mnemonic_activate",
5072 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5075 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5077 gtk_widget_show (page->tab_label);
5078 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5081 gtk_notebook_update_tab_states (notebook);
5082 gtk_widget_child_notify (child, "tab_label");
5086 * gtk_notebook_set_tab_label_text:
5087 * @notebook: a #GtkNotebook
5089 * @tab_text: the label text
5091 * Creates a new label and sets it as the tab label for the page
5092 * containing @child.
5095 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5097 const gchar *tab_text)
5099 GtkWidget *tab_label = NULL;
5101 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5104 tab_label = gtk_label_new (tab_text);
5105 gtk_notebook_set_tab_label (notebook, child, tab_label);
5106 gtk_widget_child_notify (child, "tab_label");
5110 * gtk_notebook_get_tab_label_text:
5111 * @notebook: a #GtkNotebook
5112 * @child: a widget contained in a page of @notebook
5114 * Retrieves the text of the tab label for the page containing
5117 * Returns value: the text of the tab label, or %NULL if the
5118 * tab label widget is not a #GtkLabel. The
5119 * string is owned by the widget and must not
5122 G_CONST_RETURN gchar *
5123 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5126 GtkWidget *tab_label;
5128 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5129 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5131 tab_label = gtk_notebook_get_tab_label (notebook, child);
5133 if (tab_label && GTK_IS_LABEL (tab_label))
5134 return gtk_label_get_text (GTK_LABEL (tab_label));
5140 * gtk_notebook_get_menu_label:
5141 * @notebook: a #GtkNotebook
5142 * @child: a widget contained in a page of @notebook
5144 * Retrieves the menu label widget of the page containing @child.
5146 * Return value: the menu label, or %NULL if the
5147 * notebook page does not have a menu label other
5148 * than the default (the tab label).
5151 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5156 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5157 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5159 list = CHECK_FIND_CHILD (notebook, child);
5163 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5166 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5170 * gtk_notebook_set_menu_label:
5171 * @notebook: a #GtkNotebook
5172 * @child: the child widget
5173 * @menu_label: the menu label, or NULL for default
5175 * Changes the menu label for the page containing @child.
5178 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5180 GtkWidget *menu_label)
5182 GtkNotebookPage *page;
5185 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5186 g_return_if_fail (GTK_IS_WIDGET (child));
5188 list = CHECK_FIND_CHILD (notebook, child);
5193 if (page->menu_label)
5196 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5197 page->menu_label->parent);
5199 if (!page->default_menu)
5200 g_object_unref (page->menu_label);
5205 page->menu_label = menu_label;
5206 g_object_ref (page->menu_label);
5207 gtk_object_sink (GTK_OBJECT(page->menu_label));
5208 page->default_menu = FALSE;
5211 page->default_menu = TRUE;
5214 gtk_notebook_menu_item_create (notebook, list);
5215 gtk_widget_child_notify (child, "menu_label");
5219 * gtk_notebook_set_menu_label_text:
5220 * @notebook: a #GtkNotebook
5221 * @child: the child widget
5222 * @menu_text: the label text
5224 * Creates a new label and sets it as the menu label of @child.
5227 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5229 const gchar *menu_text)
5231 GtkWidget *menu_label = NULL;
5233 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5236 menu_label = gtk_label_new (menu_text);
5237 gtk_notebook_set_menu_label (notebook, child, menu_label);
5238 gtk_widget_child_notify (child, "menu_label");
5242 * gtk_notebook_get_menu_label_text:
5243 * @notebook: a #GtkNotebook
5244 * @child: the child widget of a page of the notebook.
5246 * Retrieves the text of the menu label for the page containing
5249 * Returns value: the text of the tab label, or %NULL if the
5250 * widget does not have a menu label other than
5251 * the default menu label, or the menu label widget
5252 * is not a #GtkLabel. The string is owned by
5253 * the widget and must not be freed.
5255 G_CONST_RETURN gchar *
5256 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5259 GtkWidget *menu_label;
5261 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5262 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5264 menu_label = gtk_notebook_get_menu_label (notebook, child);
5266 if (menu_label && GTK_IS_LABEL (menu_label))
5267 return gtk_label_get_text (GTK_LABEL (menu_label));
5272 /* Helper function called when pages are reordered
5275 gtk_notebook_child_reordered (GtkNotebook *notebook,
5276 GtkNotebookPage *page)
5280 GtkWidget *menu_item;
5282 menu_item = page->menu_label->parent;
5283 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5284 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5285 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5288 gtk_notebook_update_tab_states (notebook);
5289 gtk_notebook_update_labels (notebook);
5293 * gtk_notebook_set_tab_label_packing:
5294 * @notebook: a #GtkNotebook
5295 * @child: the child widget
5296 * @expand: whether to expand the bookmark or not
5297 * @fill: whether the bookmark should fill the allocated area or not
5298 * @pack_type: the position of the bookmark
5300 * Sets the packing parameters for the tab label of the page
5301 * containing @child. See gtk_box_pack_start() for the exact meaning
5302 * of the parameters.
5305 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5309 GtkPackType pack_type)
5311 GtkNotebookPage *page;
5314 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5315 g_return_if_fail (GTK_IS_WIDGET (child));
5317 list = CHECK_FIND_CHILD (notebook, child);
5322 expand = expand != FALSE;
5323 fill = fill != FALSE;
5324 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5327 gtk_widget_freeze_child_notify (child);
5328 page->expand = expand;
5329 gtk_widget_child_notify (child, "tab_expand");
5331 gtk_widget_child_notify (child, "tab_fill");
5332 if (page->pack != pack_type)
5334 page->pack = pack_type;
5335 gtk_notebook_child_reordered (notebook, page);
5337 gtk_widget_child_notify (child, "tab_pack");
5338 gtk_widget_child_notify (child, "position");
5339 if (notebook->show_tabs)
5340 gtk_notebook_pages_allocate (notebook);
5341 gtk_widget_thaw_child_notify (child);
5345 * gtk_notebook_query_tab_label_packing:
5346 * @notebook: a #GtkNotebook
5348 * @expand: location to store the expand value (or NULL)
5349 * @fill: location to store the fill value (or NULL)
5350 * @pack_type: location to store the pack_type (or NULL)
5352 * Query the packing attributes for the tab label of the page
5353 * containing @child.
5356 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5360 GtkPackType *pack_type)
5364 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5365 g_return_if_fail (GTK_IS_WIDGET (child));
5367 list = CHECK_FIND_CHILD (notebook, child);
5372 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5374 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5376 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5380 * gtk_notebook_reorder_child:
5381 * @notebook: a #GtkNotebook
5382 * @child: the child to move
5383 * @position: the new position, or -1 to move to the end
5385 * Reorders the page containing @child, so that it appears in position
5386 * @position. If @position is greater than or equal to the number of
5387 * children in the list or negative, @child will be moved to the end
5391 gtk_notebook_reorder_child (GtkNotebook *notebook,
5395 GList *list, *new_list;
5396 GtkNotebookPage *page;
5400 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5401 g_return_if_fail (GTK_IS_WIDGET (child));
5403 list = CHECK_FIND_CHILD (notebook, child);
5407 max_pos = g_list_length (notebook->children) - 1;
5408 if (position < 0 || position > max_pos)
5411 old_pos = g_list_position (notebook->children, list);
5413 if (old_pos == position)
5417 notebook->children = g_list_delete_link (notebook->children, list);
5419 notebook->children = g_list_insert (notebook->children, page, position);
5420 new_list = g_list_nth (notebook->children, position);
5422 /* Fix up GList references in GtkNotebook structure */
5423 if (notebook->first_tab == list)
5424 notebook->first_tab = new_list;
5425 if (notebook->focus_tab == list)
5426 notebook->focus_tab = new_list;
5428 gtk_widget_freeze_child_notify (child);
5430 /* Move around the menu items if necessary */
5431 gtk_notebook_child_reordered (notebook, page);
5432 gtk_widget_child_notify (child, "tab_pack");
5433 gtk_widget_child_notify (child, "position");
5435 if (notebook->show_tabs)
5436 gtk_notebook_pages_allocate (notebook);
5438 gtk_widget_thaw_child_notify (child);
5441 #define __GTK_NOTEBOOK_C__
5442 #include "gtkaliasdef.c"