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 SCROLL_DELAY_FACTOR 5
72 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
73 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
92 CHILD_PROP_MENU_LABEL,
94 CHILD_PROP_TAB_EXPAND,
99 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
101 struct _GtkNotebookPage
104 GtkWidget *tab_label;
105 GtkWidget *menu_label;
106 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
108 guint default_menu : 1; /* If true, we create the menu label ourself */
109 guint default_tab : 1; /* If true, we create the tab label ourself */
114 GtkRequisition requisition;
115 GtkAllocation allocation;
117 guint mnemonic_activate_signal;
120 #ifdef G_DISABLE_CHECKS
121 #define CHECK_FIND_CHILD(notebook, child) \
122 gtk_notebook_find_child (notebook, child, G_STRLOC)
124 #define CHECK_FIND_CHILD(notebook, child) \
125 gtk_notebook_find_child (notebook, child, NULL)
128 /*** GtkNotebook Methods ***/
129 static void gtk_notebook_class_init (GtkNotebookClass *klass);
130 static void gtk_notebook_init (GtkNotebook *notebook);
132 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
133 gboolean move_focus);
134 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
135 GtkNotebookTab type);
136 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
138 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
139 GtkDirectionType direction_type);
141 /*** GtkObject Methods ***/
142 static void gtk_notebook_destroy (GtkObject *object);
143 static void gtk_notebook_set_property (GObject *object,
147 static void gtk_notebook_get_property (GObject *object,
152 /*** GtkWidget Methods ***/
153 static void gtk_notebook_map (GtkWidget *widget);
154 static void gtk_notebook_unmap (GtkWidget *widget);
155 static void gtk_notebook_realize (GtkWidget *widget);
156 static void gtk_notebook_unrealize (GtkWidget *widget);
157 static void gtk_notebook_size_request (GtkWidget *widget,
158 GtkRequisition *requisition);
159 static void gtk_notebook_size_allocate (GtkWidget *widget,
160 GtkAllocation *allocation);
161 static gint gtk_notebook_expose (GtkWidget *widget,
162 GdkEventExpose *event);
163 static gboolean gtk_notebook_scroll (GtkWidget *widget,
164 GdkEventScroll *event);
165 static gint gtk_notebook_button_press (GtkWidget *widget,
166 GdkEventButton *event);
167 static gint gtk_notebook_button_release (GtkWidget *widget,
168 GdkEventButton *event);
169 static gint gtk_notebook_enter_notify (GtkWidget *widget,
170 GdkEventCrossing *event);
171 static gint gtk_notebook_leave_notify (GtkWidget *widget,
172 GdkEventCrossing *event);
173 static gint gtk_notebook_motion_notify (GtkWidget *widget,
174 GdkEventMotion *event);
175 static gint gtk_notebook_focus_in (GtkWidget *widget,
176 GdkEventFocus *event);
177 static gint gtk_notebook_focus_out (GtkWidget *widget,
178 GdkEventFocus *event);
179 static void gtk_notebook_grab_notify (GtkWidget *widget,
180 gboolean was_grabbed);
181 static void gtk_notebook_state_changed (GtkWidget *widget,
182 GtkStateType previous_state);
183 static void gtk_notebook_draw_focus (GtkWidget *widget);
184 static gint gtk_notebook_focus (GtkWidget *widget,
185 GtkDirectionType direction);
186 static void gtk_notebook_style_set (GtkWidget *widget,
189 /*** GtkContainer Methods ***/
190 static void gtk_notebook_set_child_property (GtkContainer *container,
195 static void gtk_notebook_get_child_property (GtkContainer *container,
200 static void gtk_notebook_add (GtkContainer *container,
202 static void gtk_notebook_remove (GtkContainer *container,
204 static void gtk_notebook_set_focus_child (GtkContainer *container,
206 static GType gtk_notebook_child_type (GtkContainer *container);
207 static void gtk_notebook_forall (GtkContainer *container,
208 gboolean include_internals,
209 GtkCallback callback,
210 gpointer callback_data);
212 /*** GtkNotebook Private Functions ***/
213 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
214 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
215 static void gtk_notebook_real_remove (GtkNotebook *notebook,
217 gboolean destroying);
218 static void gtk_notebook_update_labels (GtkNotebook *notebook);
219 static gint gtk_notebook_timer (GtkNotebook *notebook);
220 static gint gtk_notebook_page_compare (gconstpointer a,
222 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
224 const gchar *function);
225 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
227 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
230 gboolean find_visible);
232 /*** GtkNotebook Drawing Functions ***/
233 static void gtk_notebook_paint (GtkWidget *widget,
235 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
236 GtkNotebookPage *page,
238 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
239 GtkNotebookArrow arrow);
241 /*** GtkNotebook Size Allocate Functions ***/
242 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
243 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
244 GtkNotebookPage *page,
245 GtkAllocation *allocation);
246 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
252 /*** GtkNotebook Page Switch Methods ***/
253 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
254 GtkNotebookPage *page,
257 /*** GtkNotebook Page Switch Functions ***/
258 static void gtk_notebook_switch_page (GtkNotebook *notebook,
259 GtkNotebookPage *page,
261 static gint gtk_notebook_page_select (GtkNotebook *notebook,
262 gboolean move_focus);
263 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
265 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
266 GtkNotebookPage *page);
268 /*** GtkNotebook Menu Functions ***/
269 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
271 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
273 static void gtk_notebook_menu_detacher (GtkWidget *widget,
276 /*** GtkNotebook Private Setters ***/
277 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
278 gboolean homogeneous);
279 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
281 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
283 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
286 static gboolean focus_tabs_in (GtkNotebook *notebook);
287 static gboolean focus_child_in (GtkNotebook *notebook,
288 GtkDirectionType direction);
290 static void stop_scrolling (GtkNotebook *notebook);
293 static GtkContainerClass *parent_class = NULL;
294 static guint notebook_signals[LAST_SIGNAL] = { 0 };
297 gtk_notebook_get_type (void)
299 static GType notebook_type = 0;
303 static const GTypeInfo notebook_info =
305 sizeof (GtkNotebookClass),
306 NULL, /* base_init */
307 NULL, /* base_finalize */
308 (GClassInitFunc) gtk_notebook_class_init,
309 NULL, /* class_finalize */
310 NULL, /* class_data */
311 sizeof (GtkNotebook),
313 (GInstanceInitFunc) gtk_notebook_init,
316 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkNotebook"),
320 return notebook_type;
324 add_tab_bindings (GtkBindingSet *binding_set,
325 GdkModifierType modifiers,
326 GtkDirectionType direction)
328 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
330 GTK_TYPE_DIRECTION_TYPE, direction);
331 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
333 GTK_TYPE_DIRECTION_TYPE, direction);
337 add_arrow_bindings (GtkBindingSet *binding_set,
339 GtkDirectionType direction)
341 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
343 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
345 GTK_TYPE_DIRECTION_TYPE, direction);
346 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
348 GTK_TYPE_DIRECTION_TYPE, direction);
352 gtk_notebook_class_init (GtkNotebookClass *class)
354 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
355 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
356 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
357 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
358 GtkBindingSet *binding_set;
360 parent_class = g_type_class_peek_parent (class);
362 gobject_class->set_property = gtk_notebook_set_property;
363 gobject_class->get_property = gtk_notebook_get_property;
364 object_class->destroy = gtk_notebook_destroy;
366 widget_class->map = gtk_notebook_map;
367 widget_class->unmap = gtk_notebook_unmap;
368 widget_class->realize = gtk_notebook_realize;
369 widget_class->unrealize = gtk_notebook_unrealize;
370 widget_class->size_request = gtk_notebook_size_request;
371 widget_class->size_allocate = gtk_notebook_size_allocate;
372 widget_class->expose_event = gtk_notebook_expose;
373 widget_class->scroll_event = gtk_notebook_scroll;
374 widget_class->button_press_event = gtk_notebook_button_press;
375 widget_class->button_release_event = gtk_notebook_button_release;
376 widget_class->enter_notify_event = gtk_notebook_enter_notify;
377 widget_class->leave_notify_event = gtk_notebook_leave_notify;
378 widget_class->motion_notify_event = gtk_notebook_motion_notify;
379 widget_class->grab_notify = gtk_notebook_grab_notify;
380 widget_class->state_changed = gtk_notebook_state_changed;
381 widget_class->focus_in_event = gtk_notebook_focus_in;
382 widget_class->focus_out_event = gtk_notebook_focus_out;
383 widget_class->focus = gtk_notebook_focus;
384 widget_class->style_set = gtk_notebook_style_set;
386 container_class->add = gtk_notebook_add;
387 container_class->remove = gtk_notebook_remove;
388 container_class->forall = gtk_notebook_forall;
389 container_class->set_focus_child = gtk_notebook_set_focus_child;
390 container_class->get_child_property = gtk_notebook_get_child_property;
391 container_class->set_child_property = gtk_notebook_set_child_property;
392 container_class->child_type = gtk_notebook_child_type;
394 class->switch_page = gtk_notebook_real_switch_page;
396 class->focus_tab = gtk_notebook_focus_tab;
397 class->select_page = gtk_notebook_select_page;
398 class->change_current_page = gtk_notebook_change_current_page;
399 class->move_focus_out = gtk_notebook_move_focus_out;
401 g_object_class_install_property (gobject_class,
403 g_param_spec_int ("page",
405 P_("The index of the current page"),
409 GTK_PARAM_READWRITE));
410 g_object_class_install_property (gobject_class,
412 g_param_spec_enum ("tab-pos",
414 P_("Which side of the notebook holds the tabs"),
415 GTK_TYPE_POSITION_TYPE,
417 GTK_PARAM_READWRITE));
418 g_object_class_install_property (gobject_class,
420 g_param_spec_uint ("tab-border",
422 P_("Width of the border around the tab labels"),
426 GTK_PARAM_WRITABLE));
427 g_object_class_install_property (gobject_class,
429 g_param_spec_uint ("tab-hborder",
430 P_("Horizontal Tab Border"),
431 P_("Width of the horizontal border of tab labels"),
435 GTK_PARAM_READWRITE));
436 g_object_class_install_property (gobject_class,
438 g_param_spec_uint ("tab-vborder",
439 P_("Vertical Tab Border"),
440 P_("Width of the vertical border of tab labels"),
444 GTK_PARAM_READWRITE));
445 g_object_class_install_property (gobject_class,
447 g_param_spec_boolean ("show-tabs",
449 P_("Whether tabs should be shown or not"),
451 GTK_PARAM_READWRITE));
452 g_object_class_install_property (gobject_class,
454 g_param_spec_boolean ("show-border",
456 P_("Whether the border should be shown or not"),
458 GTK_PARAM_READWRITE));
459 g_object_class_install_property (gobject_class,
461 g_param_spec_boolean ("scrollable",
463 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
465 GTK_PARAM_READWRITE));
466 g_object_class_install_property (gobject_class,
468 g_param_spec_boolean ("enable-popup",
470 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
472 GTK_PARAM_READWRITE));
473 g_object_class_install_property (gobject_class,
475 g_param_spec_boolean ("homogeneous",
477 P_("Whether tabs should have homogeneous sizes"),
479 GTK_PARAM_READWRITE));
481 gtk_container_class_install_child_property (container_class,
482 CHILD_PROP_TAB_LABEL,
483 g_param_spec_string ("tab-label",
485 P_("The string displayed on the child's tab label"),
487 GTK_PARAM_READWRITE));
488 gtk_container_class_install_child_property (container_class,
489 CHILD_PROP_MENU_LABEL,
490 g_param_spec_string ("menu-label",
492 P_("The string displayed in the child's menu entry"),
494 GTK_PARAM_READWRITE));
495 gtk_container_class_install_child_property (container_class,
497 g_param_spec_int ("position",
499 P_("The index of the child in the parent"),
501 GTK_PARAM_READWRITE));
502 gtk_container_class_install_child_property (container_class,
503 CHILD_PROP_TAB_EXPAND,
504 g_param_spec_boolean ("tab-expand",
506 P_("Whether to expand the child's tab or not"),
508 GTK_PARAM_READWRITE));
509 gtk_container_class_install_child_property (container_class,
511 g_param_spec_boolean ("tab-fill",
513 P_("Whether the child's tab should fill the allocated area or not"),
515 GTK_PARAM_READWRITE));
516 gtk_container_class_install_child_property (container_class,
518 g_param_spec_enum ("tab-pack",
520 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
521 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
522 GTK_PARAM_READWRITE));
525 * GtkNotebook:has-secondary-backward-stepper:
527 * The "has-secondary-backward-stepper" property determines whether
528 * a second backward arrow button is displayed on the opposite end
533 gtk_widget_class_install_style_property (widget_class,
534 g_param_spec_boolean ("has-secondary-backward-stepper",
535 P_("Secondary backward stepper"),
536 P_("Display a second backward arrow button on the opposite end of the tab area"),
539 GTK_PARAM_READABLE));
542 * GtkNotebook:has-secondary-forward-stepper:
544 * The "has-secondary-forward-stepper" property determines whether
545 * a second forward arrow button is displayed on the opposite end
550 gtk_widget_class_install_style_property (widget_class,
551 g_param_spec_boolean ("has-secondary-forward-stepper",
552 P_("Secondary forward stepper"),
553 P_("Display a second forward arrow button on the opposite end of the tab area"),
556 GTK_PARAM_READABLE));
559 * GtkNotebook:has-backward-stepper:
561 * The "has-backward-stepper" property determines whether
562 * the standard backward arrow button is displayed.
566 gtk_widget_class_install_style_property (widget_class,
567 g_param_spec_boolean ("has-backward-stepper",
568 P_("Backward stepper"),
569 P_("Display the standard backward arrow button"),
572 GTK_PARAM_READABLE));
575 * GtkNotebook:has-forward-stepper:
577 * The "has-forward-stepper" property determines whether
578 * the standard forward arrow button is displayed.
582 gtk_widget_class_install_style_property (widget_class,
583 g_param_spec_boolean ("has-forward-stepper",
584 P_("Forward stepper"),
585 P_("Display the standard forward arrow button"),
588 GTK_PARAM_READABLE));
590 notebook_signals[SWITCH_PAGE] =
591 g_signal_new (I_("switch_page"),
592 G_TYPE_FROM_CLASS (gobject_class),
594 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
596 _gtk_marshal_VOID__POINTER_UINT,
600 notebook_signals[FOCUS_TAB] =
601 g_signal_new (I_("focus_tab"),
602 G_TYPE_FROM_CLASS (gobject_class),
603 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
604 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
606 _gtk_marshal_BOOLEAN__ENUM,
608 GTK_TYPE_NOTEBOOK_TAB);
609 notebook_signals[SELECT_PAGE] =
610 g_signal_new (I_("select_page"),
611 G_TYPE_FROM_CLASS (gobject_class),
612 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
613 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
615 _gtk_marshal_BOOLEAN__BOOLEAN,
618 notebook_signals[CHANGE_CURRENT_PAGE] =
619 g_signal_new (I_("change_current_page"),
620 G_TYPE_FROM_CLASS (gobject_class),
621 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
622 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
624 _gtk_marshal_VOID__INT,
627 notebook_signals[MOVE_FOCUS_OUT] =
628 g_signal_new (I_("move_focus_out"),
629 G_TYPE_FROM_CLASS (gobject_class),
630 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
631 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
633 _gtk_marshal_VOID__ENUM,
635 GTK_TYPE_DIRECTION_TYPE);
638 binding_set = gtk_binding_set_by_class (class);
639 gtk_binding_entry_add_signal (binding_set,
642 G_TYPE_BOOLEAN, FALSE);
643 gtk_binding_entry_add_signal (binding_set,
646 G_TYPE_BOOLEAN, FALSE);
648 gtk_binding_entry_add_signal (binding_set,
651 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
652 gtk_binding_entry_add_signal (binding_set,
655 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
656 gtk_binding_entry_add_signal (binding_set,
659 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
660 gtk_binding_entry_add_signal (binding_set,
663 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
665 gtk_binding_entry_add_signal (binding_set,
666 GDK_Page_Up, GDK_CONTROL_MASK,
667 "change_current_page", 1,
669 gtk_binding_entry_add_signal (binding_set,
670 GDK_Page_Down, GDK_CONTROL_MASK,
671 "change_current_page", 1,
674 gtk_binding_entry_add_signal (binding_set,
675 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
676 "change_current_page", 1,
678 gtk_binding_entry_add_signal (binding_set,
679 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
680 "change_current_page", 1,
683 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
684 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
685 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
686 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
688 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
689 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
693 gtk_notebook_init (GtkNotebook *notebook)
695 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
696 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
698 notebook->cur_page = NULL;
699 notebook->children = NULL;
700 notebook->first_tab = NULL;
701 notebook->focus_tab = NULL;
702 notebook->event_window = NULL;
703 notebook->menu = NULL;
705 notebook->tab_hborder = 2;
706 notebook->tab_vborder = 2;
708 notebook->show_tabs = TRUE;
709 notebook->show_border = TRUE;
710 notebook->tab_pos = GTK_POS_TOP;
711 notebook->scrollable = FALSE;
712 notebook->in_child = 0;
713 notebook->click_child = 0;
714 notebook->button = 0;
715 notebook->need_timer = 0;
716 notebook->child_has_focus = FALSE;
717 notebook->have_visible_child = FALSE;
718 notebook->focus_out = FALSE;
720 notebook->has_before_previous = 1;
721 notebook->has_before_next = 0;
722 notebook->has_after_previous = 0;
723 notebook->has_after_next = 1;
727 gtk_notebook_select_page (GtkNotebook *notebook,
730 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
732 gtk_notebook_page_select (notebook, move_focus);
740 gtk_notebook_focus_tab (GtkNotebook *notebook,
745 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
749 case GTK_NOTEBOOK_TAB_FIRST:
750 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
752 gtk_notebook_switch_focus_tab (notebook, list);
754 case GTK_NOTEBOOK_TAB_LAST:
755 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
757 gtk_notebook_switch_focus_tab (notebook, list);
768 gtk_notebook_change_current_page (GtkNotebook *notebook,
771 GList *current = NULL;
773 if (notebook->cur_page)
774 current = g_list_find (notebook->children, notebook->cur_page);
778 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
779 offset += offset < 0 ? 1 : -1;
783 gtk_notebook_switch_page (notebook, current->data, -1);
785 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
788 static GtkDirectionType
789 get_effective_direction (GtkNotebook *notebook,
790 GtkDirectionType direction)
792 /* Remap the directions into the effective direction it would be for a
793 * GTK_POS_TOP notebook
796 #define D(rest) GTK_DIR_##rest
798 static const GtkDirectionType translate_direction[2][4][6] = {
799 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
800 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
801 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
802 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
803 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
804 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
805 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
806 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
811 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
813 return translate_direction[text_dir][notebook->tab_pos][direction];
817 get_effective_tab_pos (GtkNotebook *notebook)
819 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
821 switch (notebook->tab_pos)
824 return GTK_POS_RIGHT;
831 return notebook->tab_pos;
835 gtk_notebook_move_focus_out (GtkNotebook *notebook,
836 GtkDirectionType direction_type)
838 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
841 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
842 if (focus_tabs_in (notebook))
844 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
845 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
848 /* At this point, we know we should be focusing out of the notebook entirely. We
849 * do this by setting a flag, then propagating the focus motion to the notebook.
851 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
852 if (!GTK_WIDGET_TOPLEVEL (toplevel))
855 g_object_ref (notebook);
857 notebook->focus_out = TRUE;
858 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
859 notebook->focus_out = FALSE;
861 g_object_unref (notebook);
868 * Creates a new #GtkNotebook widget with no pages.
870 * Return value: the newly created #GtkNotebook
873 gtk_notebook_new (void)
875 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
878 /* Private GtkObject Methods :
880 * gtk_notebook_destroy
881 * gtk_notebook_set_arg
882 * gtk_notebook_get_arg
885 gtk_notebook_destroy (GtkObject *object)
888 GtkNotebook *notebook = GTK_NOTEBOOK (object);
891 gtk_notebook_popup_disable (notebook);
893 children = notebook->children;
896 GList *child = children;
897 children = child->next;
899 gtk_notebook_real_remove (notebook, child, TRUE);
902 GTK_OBJECT_CLASS (parent_class)->destroy (object);
906 gtk_notebook_set_property (GObject *object,
911 GtkNotebook *notebook;
913 notebook = GTK_NOTEBOOK (object);
918 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
920 case PROP_SHOW_BORDER:
921 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
923 case PROP_SCROLLABLE:
924 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
926 case PROP_ENABLE_POPUP:
927 if (g_value_get_boolean (value))
928 gtk_notebook_popup_enable (notebook);
930 gtk_notebook_popup_disable (notebook);
932 case PROP_HOMOGENEOUS:
933 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
936 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
939 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
941 case PROP_TAB_BORDER:
942 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
944 case PROP_TAB_HBORDER:
945 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
947 case PROP_TAB_VBORDER:
948 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
956 gtk_notebook_get_property (GObject *object,
961 GtkNotebook *notebook;
963 notebook = GTK_NOTEBOOK (object);
968 g_value_set_boolean (value, notebook->show_tabs);
970 case PROP_SHOW_BORDER:
971 g_value_set_boolean (value, notebook->show_border);
973 case PROP_SCROLLABLE:
974 g_value_set_boolean (value, notebook->scrollable);
976 case PROP_ENABLE_POPUP:
977 g_value_set_boolean (value, notebook->menu != NULL);
979 case PROP_HOMOGENEOUS:
980 g_value_set_boolean (value, notebook->homogeneous);
983 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
986 g_value_set_enum (value, notebook->tab_pos);
988 case PROP_TAB_HBORDER:
989 g_value_set_uint (value, notebook->tab_hborder);
991 case PROP_TAB_VBORDER:
992 g_value_set_uint (value, notebook->tab_vborder);
995 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1000 /* Private GtkWidget Methods :
1003 * gtk_notebook_unmap
1004 * gtk_notebook_realize
1005 * gtk_notebook_size_request
1006 * gtk_notebook_size_allocate
1007 * gtk_notebook_expose
1008 * gtk_notebook_scroll
1009 * gtk_notebook_button_press
1010 * gtk_notebook_button_release
1011 * gtk_notebook_enter_notify
1012 * gtk_notebook_leave_notify
1013 * gtk_notebook_motion_notify
1014 * gtk_notebook_focus_in
1015 * gtk_notebook_focus_out
1016 * gtk_notebook_draw_focus
1017 * gtk_notebook_style_set
1020 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1021 GdkRectangle *rectangle)
1023 GtkWidget *widget = GTK_WIDGET (notebook);
1024 gint border_width = GTK_CONTAINER (notebook)->border_width;
1025 GtkNotebookPage *visible_page = NULL;
1027 gint tab_pos = get_effective_tab_pos (notebook);
1029 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1031 GtkNotebookPage *page = tmp_list->data;
1032 if (GTK_WIDGET_VISIBLE (page->child))
1034 visible_page = page;
1039 if (notebook->show_tabs && visible_page)
1043 rectangle->x = widget->allocation.x + border_width;
1044 rectangle->y = widget->allocation.y + border_width;
1049 case GTK_POS_BOTTOM:
1050 rectangle->width = widget->allocation.width - 2 * border_width;
1051 rectangle->height = visible_page->requisition.height;
1052 if (tab_pos == GTK_POS_BOTTOM)
1053 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1057 rectangle->width = visible_page->requisition.width;
1058 rectangle->height = widget->allocation.height - 2 * border_width;
1059 if (tab_pos == GTK_POS_RIGHT)
1060 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1071 rectangle->x = rectangle->y = 0;
1072 rectangle->width = rectangle->height = 10;
1080 gtk_notebook_map (GtkWidget *widget)
1082 GtkNotebook *notebook;
1083 GtkNotebookPage *page;
1086 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1088 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1090 notebook = GTK_NOTEBOOK (widget);
1092 if (notebook->cur_page &&
1093 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1094 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1095 gtk_widget_map (notebook->cur_page->child);
1097 if (notebook->scrollable)
1098 gtk_notebook_pages_allocate (notebook);
1101 children = notebook->children;
1105 page = children->data;
1106 children = children->next;
1108 if (page->tab_label &&
1109 GTK_WIDGET_VISIBLE (page->tab_label) &&
1110 !GTK_WIDGET_MAPPED (page->tab_label))
1111 gtk_widget_map (page->tab_label);
1115 if (gtk_notebook_get_event_window_position (notebook, NULL))
1116 gdk_window_show_unraised (notebook->event_window);
1120 gtk_notebook_unmap (GtkWidget *widget)
1122 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1124 stop_scrolling (GTK_NOTEBOOK (widget));
1126 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1128 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1130 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1134 gtk_notebook_realize (GtkWidget *widget)
1136 GtkNotebook *notebook;
1137 GdkWindowAttr attributes;
1138 gint attributes_mask;
1139 GdkRectangle event_window_pos;
1141 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1143 notebook = GTK_NOTEBOOK (widget);
1144 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1146 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1148 widget->window = gtk_widget_get_parent_window (widget);
1149 g_object_ref (widget->window);
1151 attributes.window_type = GDK_WINDOW_CHILD;
1152 attributes.x = event_window_pos.x;
1153 attributes.y = event_window_pos.y;
1154 attributes.width = event_window_pos.width;
1155 attributes.height = event_window_pos.height;
1156 attributes.wclass = GDK_INPUT_ONLY;
1157 attributes.event_mask = gtk_widget_get_events (widget);
1158 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1159 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1161 attributes_mask = GDK_WA_X | GDK_WA_Y;
1163 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1164 &attributes, attributes_mask);
1165 gdk_window_set_user_data (notebook->event_window, notebook);
1167 widget->style = gtk_style_attach (widget->style, widget->window);
1171 gtk_notebook_unrealize (GtkWidget *widget)
1173 GtkNotebook *notebook;
1175 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1177 notebook = GTK_NOTEBOOK (widget);
1179 gdk_window_set_user_data (notebook->event_window, NULL);
1180 gdk_window_destroy (notebook->event_window);
1181 notebook->event_window = NULL;
1183 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1184 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1188 gtk_notebook_size_request (GtkWidget *widget,
1189 GtkRequisition *requisition)
1191 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1192 GtkNotebookPage *page;
1194 GtkRequisition child_requisition;
1195 gboolean switch_page = FALSE;
1199 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1201 widget->requisition.width = 0;
1202 widget->requisition.height = 0;
1204 for (children = notebook->children, vis_pages = 0; children;
1205 children = children->next)
1207 page = children->data;
1209 if (GTK_WIDGET_VISIBLE (page->child))
1212 gtk_widget_size_request (page->child, &child_requisition);
1214 widget->requisition.width = MAX (widget->requisition.width,
1215 child_requisition.width);
1216 widget->requisition.height = MAX (widget->requisition.height,
1217 child_requisition.height);
1219 if (notebook->menu && page->menu_label->parent &&
1220 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1221 gtk_widget_show (page->menu_label->parent);
1225 if (page == notebook->cur_page)
1227 if (notebook->menu && page->menu_label->parent &&
1228 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1229 gtk_widget_hide (page->menu_label->parent);
1233 if (notebook->show_border || notebook->show_tabs)
1235 widget->requisition.width += widget->style->xthickness * 2;
1236 widget->requisition.height += widget->style->ythickness * 2;
1238 if (notebook->show_tabs)
1241 gint tab_height = 0;
1245 for (children = notebook->children; children;
1246 children = children->next)
1248 page = children->data;
1250 if (GTK_WIDGET_VISIBLE (page->child))
1252 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1253 gtk_widget_show (page->tab_label);
1255 gtk_widget_size_request (page->tab_label,
1256 &child_requisition);
1258 page->requisition.width =
1259 child_requisition.width +
1260 2 * widget->style->xthickness;
1261 page->requisition.height =
1262 child_requisition.height +
1263 2 * widget->style->ythickness;
1265 switch (notebook->tab_pos)
1268 case GTK_POS_BOTTOM:
1269 page->requisition.height += 2 * (notebook->tab_vborder +
1271 tab_height = MAX (tab_height, page->requisition.height);
1272 tab_max = MAX (tab_max, page->requisition.width);
1276 page->requisition.width += 2 * (notebook->tab_hborder +
1278 tab_width = MAX (tab_width, page->requisition.width);
1279 tab_max = MAX (tab_max, page->requisition.height);
1283 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1284 gtk_widget_hide (page->tab_label);
1287 children = notebook->children;
1291 switch (notebook->tab_pos)
1294 case GTK_POS_BOTTOM:
1295 if (tab_height == 0)
1298 if (notebook->scrollable && vis_pages > 1 &&
1299 widget->requisition.width < tab_width)
1300 tab_height = MAX (tab_height, ARROW_SIZE);
1302 padding = 2 * (TAB_CURVATURE + focus_width +
1303 notebook->tab_hborder) - TAB_OVERLAP;
1307 page = children->data;
1308 children = children->next;
1310 if (!GTK_WIDGET_VISIBLE (page->child))
1313 if (notebook->homogeneous)
1314 page->requisition.width = tab_max;
1316 page->requisition.width += padding;
1318 tab_width += page->requisition.width;
1319 page->requisition.height = tab_height;
1322 if (notebook->scrollable && vis_pages > 1 &&
1323 widget->requisition.width < tab_width)
1324 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1326 if (notebook->homogeneous && !notebook->scrollable)
1327 widget->requisition.width = MAX (widget->requisition.width,
1328 vis_pages * tab_max +
1331 widget->requisition.width = MAX (widget->requisition.width,
1332 tab_width + TAB_OVERLAP);
1334 widget->requisition.height += tab_height;
1341 if (notebook->scrollable && vis_pages > 1 &&
1342 widget->requisition.height < tab_height)
1343 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1345 padding = 2 * (TAB_CURVATURE + focus_width +
1346 notebook->tab_vborder) - TAB_OVERLAP;
1351 page = children->data;
1352 children = children->next;
1354 if (!GTK_WIDGET_VISIBLE (page->child))
1357 page->requisition.width = tab_width;
1359 if (notebook->homogeneous)
1360 page->requisition.height = tab_max;
1362 page->requisition.height += padding;
1364 tab_height += page->requisition.height;
1367 if (notebook->scrollable && vis_pages > 1 &&
1368 widget->requisition.height < tab_height)
1369 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1371 widget->requisition.width += tab_width;
1373 if (notebook->homogeneous && !notebook->scrollable)
1374 widget->requisition.height =
1375 MAX (widget->requisition.height,
1376 vis_pages * tab_max + TAB_OVERLAP);
1378 widget->requisition.height =
1379 MAX (widget->requisition.height,
1380 tab_height + TAB_OVERLAP);
1382 if (!notebook->homogeneous || notebook->scrollable)
1384 widget->requisition.height = MAX (widget->requisition.height,
1385 vis_pages * tab_max +
1393 for (children = notebook->children; children;
1394 children = children->next)
1396 page = children->data;
1398 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1399 gtk_widget_hide (page->tab_label);
1404 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1405 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1411 for (children = notebook->children; children;
1412 children = children->next)
1414 page = children->data;
1415 if (GTK_WIDGET_VISIBLE (page->child))
1417 gtk_notebook_switch_page (notebook, page, -1);
1422 else if (GTK_WIDGET_VISIBLE (widget))
1424 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1425 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1428 if (vis_pages && !notebook->cur_page)
1430 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1433 notebook->first_tab = children;
1434 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1440 gtk_notebook_size_allocate (GtkWidget *widget,
1441 GtkAllocation *allocation)
1443 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1445 gint tab_pos = get_effective_tab_pos (notebook);
1447 widget->allocation = *allocation;
1448 if (GTK_WIDGET_REALIZED (widget))
1450 GdkRectangle position;
1452 if (gtk_notebook_get_event_window_position (notebook, &position))
1454 gdk_window_move_resize (notebook->event_window,
1455 position.x, position.y,
1456 position.width, position.height);
1457 if (GTK_WIDGET_MAPPED (notebook))
1458 gdk_window_show_unraised (notebook->event_window);
1461 gdk_window_hide (notebook->event_window);
1464 if (notebook->children)
1466 gint border_width = GTK_CONTAINER (widget)->border_width;
1467 GtkNotebookPage *page;
1468 GtkAllocation child_allocation;
1471 child_allocation.x = widget->allocation.x + border_width;
1472 child_allocation.y = widget->allocation.y + border_width;
1473 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1474 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1476 if (notebook->show_tabs || notebook->show_border)
1478 child_allocation.x += widget->style->xthickness;
1479 child_allocation.y += widget->style->ythickness;
1480 child_allocation.width = MAX (1, child_allocation.width -
1481 widget->style->xthickness * 2);
1482 child_allocation.height = MAX (1, child_allocation.height -
1483 widget->style->ythickness * 2);
1485 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1490 child_allocation.y += notebook->cur_page->requisition.height;
1491 case GTK_POS_BOTTOM:
1492 child_allocation.height =
1493 MAX (1, child_allocation.height -
1494 notebook->cur_page->requisition.height);
1497 child_allocation.x += notebook->cur_page->requisition.width;
1499 child_allocation.width =
1500 MAX (1, child_allocation.width -
1501 notebook->cur_page->requisition.width);
1507 children = notebook->children;
1510 page = children->data;
1511 children = children->next;
1513 if (GTK_WIDGET_VISIBLE (page->child))
1515 gtk_widget_size_allocate (page->child, &child_allocation);
1520 gtk_notebook_pages_allocate (notebook);
1525 gtk_notebook_expose (GtkWidget *widget,
1526 GdkEventExpose *event)
1528 GtkNotebook *notebook;
1529 GdkRectangle child_area;
1531 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1532 g_return_val_if_fail (event != NULL, FALSE);
1534 if (GTK_WIDGET_DRAWABLE (widget))
1536 notebook = GTK_NOTEBOOK (widget);
1538 gtk_notebook_paint (widget, &event->area);
1539 if (notebook->show_tabs)
1541 if (notebook->cur_page &&
1542 gtk_widget_intersect (notebook->cur_page->tab_label,
1543 &event->area, &child_area))
1544 gtk_notebook_draw_focus (widget);
1548 if (notebook->cur_page)
1549 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1550 notebook->cur_page->child,
1558 gtk_notebook_show_arrows (GtkNotebook *notebook)
1560 gboolean show_arrow = FALSE;
1563 if (!notebook->scrollable)
1566 children = notebook->children;
1569 GtkNotebookPage *page = children->data;
1571 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1574 children = children->next;
1581 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1582 GdkRectangle *rectangle,
1583 GtkNotebookArrow arrow)
1585 GdkRectangle event_window_pos;
1586 gboolean before = ARROW_IS_BEFORE (arrow);
1587 gboolean left = ARROW_IS_LEFT (arrow);
1589 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1591 rectangle->width = ARROW_SIZE;
1592 rectangle->height = ARROW_SIZE;
1594 switch (notebook->tab_pos)
1598 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1599 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1600 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1602 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1604 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1605 rectangle->y = event_window_pos.y;
1607 rectangle->y += event_window_pos.height - rectangle->height;
1610 case GTK_POS_BOTTOM:
1613 if (left || !notebook->has_before_previous)
1614 rectangle->x = event_window_pos.x;
1616 rectangle->x = event_window_pos.x + rectangle->width;
1620 if (!left || !notebook->has_after_next)
1621 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1623 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1625 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1631 static GtkNotebookArrow
1632 gtk_notebook_get_arrow (GtkNotebook *notebook,
1636 GdkRectangle arrow_rect;
1637 GdkRectangle event_window_pos;
1640 GtkNotebookArrow arrow[4];
1642 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1643 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1644 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1645 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1647 if (gtk_notebook_show_arrows (notebook))
1649 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1650 for (i = 0; i < 4; i++)
1652 if (arrow[i] == ARROW_NONE)
1655 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1657 x0 = x - arrow_rect.x;
1658 y0 = y - arrow_rect.y;
1660 if (y0 >= 0 && y0 < arrow_rect.height &&
1661 x0 >= 0 && x0 < arrow_rect.width)
1670 gtk_notebook_do_arrow (GtkNotebook *notebook,
1671 GtkNotebookArrow arrow)
1673 GtkWidget *widget = GTK_WIDGET (notebook);
1674 GtkDirectionType dir;
1675 gboolean is_rtl, left;
1677 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1678 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1679 (!ARROW_IS_LEFT (arrow) && is_rtl);
1681 if (!notebook->focus_tab ||
1682 gtk_notebook_search_page (notebook, notebook->focus_tab,
1683 left ? STEP_PREV : STEP_NEXT,
1686 if (notebook->tab_pos == GTK_POS_LEFT ||
1687 notebook->tab_pos == GTK_POS_RIGHT)
1688 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
1690 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1691 gtk_widget_child_focus (widget, dir);
1696 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1697 GtkNotebookArrow arrow,
1698 GdkEventButton *event)
1700 GtkWidget *widget = GTK_WIDGET (notebook);
1701 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
1702 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
1703 (!ARROW_IS_LEFT (arrow) && is_rtl);
1705 if (!GTK_WIDGET_HAS_FOCUS (widget))
1706 gtk_widget_grab_focus (widget);
1708 notebook->button = event->button;
1709 notebook->click_child = arrow;
1711 if (event->button == 1)
1713 gtk_notebook_do_arrow (notebook, arrow);
1715 if (!notebook->timer)
1717 GtkSettings *settings = gtk_widget_get_settings (widget);
1720 g_object_get (settings, "gtk-timeout-initial", &timeout, NULL);
1722 notebook->timer = g_timeout_add (timeout,
1723 (GSourceFunc) gtk_notebook_timer,
1724 (gpointer) notebook);
1725 notebook->need_timer = TRUE;
1728 else if (event->button == 2)
1729 gtk_notebook_page_select (notebook, TRUE);
1730 else if (event->button == 3)
1731 gtk_notebook_switch_focus_tab (notebook,
1732 gtk_notebook_search_page (notebook,
1734 left ? STEP_NEXT : STEP_PREV,
1736 gtk_notebook_redraw_arrows (notebook);
1742 get_widget_coordinates (GtkWidget *widget,
1747 GdkWindow *window = ((GdkEventAny *)event)->window;
1750 if (!gdk_event_get_coords (event, &tx, &ty))
1753 while (window && window != widget->window)
1755 gint window_x, window_y;
1757 gdk_window_get_position (window, &window_x, &window_y);
1761 window = gdk_window_get_parent (window);
1776 gtk_notebook_scroll (GtkWidget *widget,
1777 GdkEventScroll *event)
1779 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1782 GtkWidget* originator;
1784 if (!notebook->cur_page)
1787 child = notebook->cur_page->child;
1788 originator = gtk_get_event_widget ((GdkEvent *)event);
1790 /* ignore scroll events from the content of the page */
1791 if (!originator || gtk_widget_is_ancestor (originator, child))
1794 switch (event->direction)
1796 case GDK_SCROLL_RIGHT:
1797 case GDK_SCROLL_DOWN:
1798 gtk_notebook_next_page (notebook);
1800 case GDK_SCROLL_LEFT:
1802 gtk_notebook_prev_page (notebook);
1810 gtk_notebook_button_press (GtkWidget *widget,
1811 GdkEventButton *event)
1813 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1814 GtkNotebookPage *page;
1816 GtkNotebookArrow arrow;
1820 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1824 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1827 arrow = gtk_notebook_get_arrow (notebook, x, y);
1829 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1831 if (event->button == 3 && notebook->menu)
1833 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1834 NULL, NULL, 3, event->time);
1838 if (event->button != 1)
1842 children = notebook->children;
1845 page = children->data;
1847 if (GTK_WIDGET_VISIBLE (page->child) &&
1848 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1849 (x >= page->allocation.x) &&
1850 (y >= page->allocation.y) &&
1851 (x <= (page->allocation.x + page->allocation.width)) &&
1852 (y <= (page->allocation.y + page->allocation.height)))
1854 gboolean page_changed = page != notebook->cur_page;
1855 gboolean was_focus = gtk_widget_is_focus (widget);
1857 gtk_notebook_switch_focus_tab (notebook, children);
1858 gtk_widget_grab_focus (widget);
1860 if (page_changed && !was_focus)
1861 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1865 children = children->next;
1873 stop_scrolling (GtkNotebook *notebook)
1875 if (notebook->timer)
1877 g_source_remove (notebook->timer);
1878 notebook->timer = 0;
1879 notebook->need_timer = FALSE;
1881 notebook->click_child = 0;
1882 notebook->button = 0;
1883 gtk_notebook_redraw_arrows (notebook);
1887 gtk_notebook_button_release (GtkWidget *widget,
1888 GdkEventButton *event)
1890 GtkNotebook *notebook;
1892 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1893 g_return_val_if_fail (event != NULL, FALSE);
1895 if (event->type != GDK_BUTTON_RELEASE)
1898 notebook = GTK_NOTEBOOK (widget);
1900 if (event->button == notebook->button)
1902 stop_scrolling (notebook);
1911 gtk_notebook_enter_notify (GtkWidget *widget,
1912 GdkEventCrossing *event)
1914 GtkNotebook *notebook;
1915 GtkNotebookArrow arrow;
1918 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1919 g_return_val_if_fail (event != NULL, FALSE);
1921 notebook = GTK_NOTEBOOK (widget);
1923 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1926 arrow = gtk_notebook_get_arrow (notebook, x, y);
1928 if (arrow != notebook->in_child)
1930 notebook->in_child = arrow;
1931 gtk_notebook_redraw_arrows (notebook);
1940 gtk_notebook_leave_notify (GtkWidget *widget,
1941 GdkEventCrossing *event)
1943 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1946 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1949 if (notebook->in_child)
1951 notebook->in_child = 0;
1952 gtk_notebook_redraw_arrows (notebook);
1959 gtk_notebook_motion_notify (GtkWidget *widget,
1960 GdkEventMotion *event)
1962 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1963 GtkNotebookArrow arrow;
1966 if (notebook->button)
1969 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1972 arrow = gtk_notebook_get_arrow (notebook, x, y);
1974 if (arrow != notebook->in_child)
1976 notebook->in_child = arrow;
1977 gtk_notebook_redraw_arrows (notebook);
1984 gtk_notebook_grab_notify (GtkWidget *widget,
1985 gboolean was_grabbed)
1988 stop_scrolling (GTK_NOTEBOOK (widget));
1992 gtk_notebook_state_changed (GtkWidget *widget,
1993 GtkStateType previous_state)
1995 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1996 stop_scrolling (GTK_NOTEBOOK (widget));
2000 gtk_notebook_focus_in (GtkWidget *widget,
2001 GdkEventFocus *event)
2003 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2005 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2011 gtk_notebook_focus_out (GtkWidget *widget,
2012 GdkEventFocus *event)
2014 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2020 gtk_notebook_draw_focus (GtkWidget *widget)
2022 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2024 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2025 notebook->focus_tab)
2027 GtkNotebookPage *page;
2031 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2033 page = notebook->focus_tab->data;
2035 area.x = page->tab_label->allocation.x - focus_width;
2036 area.y = page->tab_label->allocation.y - focus_width;
2037 area.width = page->tab_label->allocation.width + 2 * focus_width;
2038 area.height = page->tab_label->allocation.height + 2 * focus_width;
2040 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2045 gtk_notebook_style_set (GtkWidget *widget,
2048 GtkNotebook *notebook;
2050 gboolean has_before_previous;
2051 gboolean has_before_next;
2052 gboolean has_after_previous;
2053 gboolean has_after_next;
2055 notebook = GTK_NOTEBOOK (widget);
2057 gtk_widget_style_get (widget,
2058 "has-backward-stepper", &has_before_previous,
2059 "has-secondary-forward-stepper", &has_before_next,
2060 "has-secondary-backward-stepper", &has_after_previous,
2061 "has-forward-stepper", &has_after_next,
2064 notebook->has_before_previous = has_before_previous;
2065 notebook->has_before_next = has_before_next;
2066 notebook->has_after_previous = has_after_previous;
2067 notebook->has_after_next = has_after_next;
2069 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2072 /* Private GtkContainer Methods :
2074 * gtk_notebook_set_child_arg
2075 * gtk_notebook_get_child_arg
2077 * gtk_notebook_remove
2078 * gtk_notebook_focus
2079 * gtk_notebook_set_focus_child
2080 * gtk_notebook_child_type
2081 * gtk_notebook_forall
2084 gtk_notebook_set_child_property (GtkContainer *container,
2087 const GValue *value,
2092 GtkPackType pack_type;
2094 /* not finding child's page is valid for menus or labels */
2095 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
2098 switch (property_id)
2100 case CHILD_PROP_TAB_LABEL:
2101 /* a NULL pointer indicates a default_tab setting, otherwise
2102 * we need to set the associated label
2104 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
2105 g_value_get_string (value));
2107 case CHILD_PROP_MENU_LABEL:
2108 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
2109 g_value_get_string (value));
2111 case CHILD_PROP_POSITION:
2112 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
2113 g_value_get_int (value));
2115 case CHILD_PROP_TAB_EXPAND:
2116 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2117 &expand, &fill, &pack_type);
2118 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2119 g_value_get_boolean (value),
2122 case CHILD_PROP_TAB_FILL:
2123 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2124 &expand, &fill, &pack_type);
2125 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2127 g_value_get_boolean (value),
2130 case CHILD_PROP_TAB_PACK:
2131 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2132 &expand, &fill, &pack_type);
2133 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2135 g_value_get_enum (value));
2138 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2144 gtk_notebook_get_child_property (GtkContainer *container,
2151 GtkNotebook *notebook;
2155 GtkPackType pack_type;
2157 notebook = GTK_NOTEBOOK (container);
2159 /* not finding child's page is valid for menus or labels */
2160 list = gtk_notebook_find_child (notebook, child, NULL);
2163 /* nothing to set on labels or menus */
2164 g_param_value_set_default (pspec, value);
2168 switch (property_id)
2170 case CHILD_PROP_TAB_LABEL:
2171 label = gtk_notebook_get_tab_label (notebook, child);
2173 if (label && GTK_IS_LABEL (label))
2174 g_value_set_string (value, GTK_LABEL (label)->label);
2176 g_value_set_string (value, NULL);
2178 case CHILD_PROP_MENU_LABEL:
2179 label = gtk_notebook_get_menu_label (notebook, child);
2181 if (label && GTK_IS_LABEL (label))
2182 g_value_set_string (value, GTK_LABEL (label)->label);
2184 g_value_set_string (value, NULL);
2186 case CHILD_PROP_POSITION:
2187 g_value_set_int (value, g_list_position (notebook->children, list));
2189 case CHILD_PROP_TAB_EXPAND:
2190 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2191 &expand, NULL, NULL);
2192 g_value_set_boolean (value, expand);
2194 case CHILD_PROP_TAB_FILL:
2195 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2197 g_value_set_boolean (value, fill);
2199 case CHILD_PROP_TAB_PACK:
2200 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2201 NULL, NULL, &pack_type);
2202 g_value_set_enum (value, pack_type);
2205 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2211 gtk_notebook_add (GtkContainer *container,
2214 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2216 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2221 gtk_notebook_remove (GtkContainer *container,
2224 GtkNotebook *notebook;
2225 GtkNotebookPage *page;
2228 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2229 g_return_if_fail (widget != NULL);
2231 notebook = GTK_NOTEBOOK (container);
2233 children = notebook->children;
2236 page = children->data;
2237 if (page->child == widget)
2239 gtk_notebook_real_remove (notebook, children, FALSE);
2242 children = children->next;
2247 focus_tabs_in (GtkNotebook *notebook)
2249 if (notebook->show_tabs && notebook->cur_page)
2251 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2253 gtk_notebook_switch_focus_tab (notebook,
2254 g_list_find (notebook->children,
2255 notebook->cur_page));
2264 focus_tabs_move (GtkNotebook *notebook,
2265 GtkDirectionType direction,
2266 gint search_direction)
2270 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2271 search_direction, TRUE);
2273 gtk_notebook_switch_focus_tab (notebook, new_page);
2275 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2281 focus_child_in (GtkNotebook *notebook,
2282 GtkDirectionType direction)
2284 if (notebook->cur_page)
2285 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2290 /* Focus in the notebook can either be on the pages, or on
2294 gtk_notebook_focus (GtkWidget *widget,
2295 GtkDirectionType direction)
2297 GtkWidget *old_focus_child;
2298 GtkNotebook *notebook;
2299 GtkDirectionType effective_direction;
2301 gboolean widget_is_focus;
2302 GtkContainer *container;
2304 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2306 container = GTK_CONTAINER (widget);
2307 notebook = GTK_NOTEBOOK (container);
2309 if (notebook->focus_out)
2311 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2315 widget_is_focus = gtk_widget_is_focus (widget);
2316 old_focus_child = container->focus_child;
2318 effective_direction = get_effective_direction (notebook, direction);
2320 if (old_focus_child) /* Focus on page child */
2322 if (gtk_widget_child_focus (old_focus_child, direction))
2325 switch (effective_direction)
2327 case GTK_DIR_TAB_BACKWARD:
2329 /* Focus onto the tabs */
2330 return focus_tabs_in (notebook);
2332 case GTK_DIR_TAB_FORWARD:
2338 else if (widget_is_focus) /* Focus was on tabs */
2340 switch (effective_direction)
2342 case GTK_DIR_TAB_BACKWARD:
2345 case GTK_DIR_TAB_FORWARD:
2347 /* We use TAB_FORWARD rather than direction so that we focus a more
2348 * predictable widget for the user; users may be using arrow focusing
2349 * in this situation even if they don't usually use arrow focusing.
2351 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2353 return focus_tabs_move (notebook, direction, STEP_PREV);
2355 return focus_tabs_move (notebook, direction, STEP_NEXT);
2358 else /* Focus was not on widget */
2360 switch (effective_direction)
2362 case GTK_DIR_TAB_FORWARD:
2364 if (focus_tabs_in (notebook))
2366 if (focus_child_in (notebook, direction))
2369 case GTK_DIR_TAB_BACKWARD:
2371 if (focus_child_in (notebook, direction))
2373 if (focus_tabs_in (notebook))
2378 return focus_child_in (notebook, direction);
2382 g_assert_not_reached ();
2387 gtk_notebook_set_focus_child (GtkContainer *container,
2390 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2391 GtkWidget *page_child;
2392 GtkWidget *toplevel;
2394 /* If the old focus widget was within a page of the notebook,
2395 * (child may either be NULL or not in this case), record it
2396 * for future use if we switch to the page with a mnemonic.
2399 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2400 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2402 page_child = GTK_WINDOW (toplevel)->focus_widget;
2405 if (page_child->parent == GTK_WIDGET (container))
2407 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2410 GtkNotebookPage *page = list->data;
2412 if (page->last_focus_child)
2413 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2415 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2416 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2422 page_child = page_child->parent;
2428 g_return_if_fail (GTK_IS_WIDGET (child));
2430 notebook->child_has_focus = TRUE;
2431 if (!notebook->focus_tab)
2434 GtkNotebookPage *page;
2436 children = notebook->children;
2439 page = children->data;
2440 if (page->child == child || page->tab_label == child)
2441 gtk_notebook_switch_focus_tab (notebook, children);
2442 children = children->next;
2447 parent_class->set_focus_child (container, child);
2451 gtk_notebook_forall (GtkContainer *container,
2452 gboolean include_internals,
2453 GtkCallback callback,
2454 gpointer callback_data)
2456 GtkNotebook *notebook;
2459 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2460 g_return_if_fail (callback != NULL);
2462 notebook = GTK_NOTEBOOK (container);
2464 children = notebook->children;
2467 GtkNotebookPage *page;
2469 page = children->data;
2470 children = children->next;
2471 (* callback) (page->child, callback_data);
2472 if (include_internals)
2474 if (page->tab_label)
2475 (* callback) (page->tab_label, callback_data);
2481 gtk_notebook_child_type (GtkContainer *container)
2483 return GTK_TYPE_WIDGET;
2486 /* Private GtkNotebook Functions:
2488 * gtk_notebook_redraw_tabs
2489 * gtk_notebook_real_remove
2490 * gtk_notebook_update_labels
2491 * gtk_notebook_timer
2492 * gtk_notebook_page_compare
2493 * gtk_notebook_real_page_position
2494 * gtk_notebook_search_page
2497 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2500 GtkNotebookPage *page;
2501 GdkRectangle redraw_rect;
2503 gint tab_pos = get_effective_tab_pos (notebook);
2505 widget = GTK_WIDGET (notebook);
2506 border = GTK_CONTAINER (notebook)->border_width;
2508 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2511 page = notebook->first_tab->data;
2513 redraw_rect.x = border;
2514 redraw_rect.y = border;
2518 case GTK_POS_BOTTOM:
2519 redraw_rect.y = (widget->allocation.height - border -
2520 page->allocation.height -
2521 widget->style->ythickness);
2522 if (page != notebook->cur_page)
2523 redraw_rect.y -= widget->style->ythickness;
2526 redraw_rect.width = widget->allocation.width - 2 * border;
2527 redraw_rect.height = (page->allocation.height +
2528 widget->style->ythickness);
2529 if (page != notebook->cur_page)
2530 redraw_rect.height += widget->style->ythickness;
2533 redraw_rect.x = (widget->allocation.width - border -
2534 page->allocation.width -
2535 widget->style->xthickness);
2536 if (page != notebook->cur_page)
2537 redraw_rect.x -= widget->style->xthickness;
2540 redraw_rect.width = (page->allocation.width +
2541 widget->style->xthickness);
2542 redraw_rect.height = widget->allocation.height - 2 * border;
2543 if (page != notebook->cur_page)
2544 redraw_rect.width += widget->style->xthickness;
2548 redraw_rect.x += widget->allocation.x;
2549 redraw_rect.y += widget->allocation.y;
2551 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2555 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2557 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2561 GtkNotebookArrow arrow[4];
2563 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2564 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2565 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2566 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2568 for (i = 0; i < 4; i++)
2570 if (arrow[i] == ARROW_NONE)
2573 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2574 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2581 gtk_notebook_timer (GtkNotebook *notebook)
2583 gboolean retval = FALSE;
2585 GDK_THREADS_ENTER ();
2587 if (notebook->timer)
2589 gtk_notebook_do_arrow (notebook, notebook->click_child);
2591 if (notebook->need_timer)
2593 GtkSettings *settings;
2596 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2597 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
2599 notebook->need_timer = FALSE;
2600 notebook->timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
2601 (GSourceFunc) gtk_notebook_timer,
2602 (gpointer) notebook);
2608 GDK_THREADS_LEAVE ();
2614 gtk_notebook_page_compare (gconstpointer a,
2617 return (((GtkNotebookPage *) a)->child != b);
2621 gtk_notebook_find_child (GtkNotebook *notebook,
2623 const gchar *function)
2625 GList *list = g_list_find_custom (notebook->children, child,
2626 gtk_notebook_page_compare);
2628 #ifndef G_DISABLE_CHECKS
2629 if (!list && function)
2630 g_warning ("%s: unable to find child %p in notebook %p",
2631 function, child, notebook);
2638 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2639 GtkNotebookPage *page)
2641 if (page->tab_label)
2643 if (page->mnemonic_activate_signal)
2644 g_signal_handler_disconnect (page->tab_label,
2645 page->mnemonic_activate_signal);
2646 page->mnemonic_activate_signal = 0;
2648 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2649 gtk_widget_unparent (page->tab_label);
2654 gtk_notebook_real_remove (GtkNotebook *notebook,
2656 gboolean destroying)
2658 GtkNotebookPage *page;
2660 gint need_resize = FALSE;
2662 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2664 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2666 if (notebook->cur_page == list->data)
2668 notebook->cur_page = NULL;
2669 if (next_list && !destroying)
2670 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2673 if (list == notebook->first_tab)
2674 notebook->first_tab = next_list;
2675 if (list == notebook->focus_tab && !destroying)
2676 gtk_notebook_switch_focus_tab (notebook, next_list);
2680 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2683 gtk_widget_unparent (page->child);
2685 gtk_notebook_remove_tab_label (notebook, page);
2689 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2690 page->menu_label->parent);
2691 gtk_widget_queue_resize (notebook->menu);
2693 if (!page->default_menu)
2694 g_object_unref (page->menu_label);
2696 notebook->children = g_list_remove_link (notebook->children, list);
2699 if (page->last_focus_child)
2701 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2702 page->last_focus_child = NULL;
2707 gtk_notebook_update_labels (notebook);
2709 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2713 gtk_notebook_update_labels (GtkNotebook *notebook)
2715 GtkNotebookPage *page;
2720 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2722 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2725 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2726 if (notebook->show_tabs)
2728 if (page->default_tab)
2730 if (!page->tab_label)
2732 page->tab_label = gtk_label_new (string);
2733 gtk_widget_set_parent (page->tab_label,
2734 GTK_WIDGET (notebook));
2737 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2740 if (GTK_WIDGET_VISIBLE (page->child) &&
2741 !GTK_WIDGET_VISIBLE (page->tab_label))
2742 gtk_widget_show (page->tab_label);
2743 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2744 GTK_WIDGET_VISIBLE (page->tab_label))
2745 gtk_widget_hide (page->tab_label);
2747 if (notebook->menu && page->default_menu)
2749 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2750 gtk_label_set_text (GTK_LABEL (page->menu_label),
2751 GTK_LABEL (page->tab_label)->label);
2753 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2759 gtk_notebook_real_page_position (GtkNotebook *notebook,
2765 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2766 g_return_val_if_fail (list != NULL, -1);
2768 for (work = notebook->children, count_start = 0;
2769 work && work != list; work = work->next)
2770 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2776 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2779 return (count_start + g_list_length (list) - 1);
2783 gtk_notebook_search_page (GtkNotebook *notebook,
2786 gboolean find_visible)
2788 GtkNotebookPage *page = NULL;
2789 GList *old_list = NULL;
2792 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2797 flag = GTK_PACK_END;
2801 flag = GTK_PACK_START;
2808 if (!page || page->pack == flag)
2816 list = notebook->children;
2821 if (page->pack == flag &&
2822 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2837 if (page->pack != flag &&
2838 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2846 /* Private GtkNotebook Drawing Functions:
2848 * gtk_notebook_paint
2849 * gtk_notebook_draw_tab
2850 * gtk_notebook_draw_arrow
2853 gtk_notebook_paint (GtkWidget *widget,
2856 GtkNotebook *notebook;
2857 GtkNotebookPage *page;
2862 gint border_width = GTK_CONTAINER (widget)->border_width;
2863 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
2867 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2868 g_return_if_fail (area != NULL);
2870 if (!GTK_WIDGET_DRAWABLE (widget))
2873 notebook = GTK_NOTEBOOK (widget);
2874 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2875 tab_pos = get_effective_tab_pos (notebook);
2877 if ((!notebook->show_tabs && !notebook->show_border) ||
2878 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2881 x = widget->allocation.x + border_width;
2882 y = widget->allocation.y + border_width;
2883 width = widget->allocation.width - border_width * 2;
2884 height = widget->allocation.height - border_width * 2;
2886 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2888 gtk_paint_box (widget->style, widget->window,
2889 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2890 area, widget, "notebook",
2891 x, y, width, height);
2896 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2898 page = notebook->first_tab->data;
2903 y += page->allocation.height + widget->style->ythickness;
2904 case GTK_POS_BOTTOM:
2905 height -= page->allocation.height + widget->style->ythickness;
2908 x += page->allocation.width + widget->style->xthickness;
2910 width -= page->allocation.width + widget->style->xthickness;
2913 gtk_paint_box (widget->style, widget->window,
2914 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2915 area, widget, "notebook",
2916 x, y, width, height);
2923 y += notebook->cur_page->allocation.height;
2924 case GTK_POS_BOTTOM:
2925 height -= notebook->cur_page->allocation.height;
2928 x += notebook->cur_page->allocation.width;
2930 width -= notebook->cur_page->allocation.width;
2937 case GTK_POS_BOTTOM:
2938 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2939 gap_width = notebook->cur_page->allocation.width;
2940 step = is_rtl ? STEP_NEXT : STEP_PREV;
2944 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2945 gap_width = notebook->cur_page->allocation.height;
2949 gtk_paint_box_gap (widget->style, widget->window,
2950 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2951 area, widget, "notebook",
2952 x, y, width, height,
2953 tab_pos, gap_x, gap_width);
2957 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
2960 page = children->data;
2961 children = gtk_notebook_search_page (notebook, children,
2963 if (!GTK_WIDGET_VISIBLE (page->child))
2965 if (!GTK_WIDGET_MAPPED (page->tab_label))
2967 else if (page != notebook->cur_page)
2968 gtk_notebook_draw_tab (notebook, page, area);
2971 if (showarrow && notebook->scrollable)
2973 if (notebook->has_before_previous)
2974 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2975 if (notebook->has_before_next)
2976 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2977 if (notebook->has_after_previous)
2978 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2979 if (notebook->has_after_next)
2980 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2982 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2986 gtk_notebook_draw_tab (GtkNotebook *notebook,
2987 GtkNotebookPage *page,
2990 GdkRectangle child_area;
2991 GdkRectangle page_area;
2992 GtkStateType state_type;
2993 GtkPositionType gap_side;
2994 gint tab_pos = get_effective_tab_pos (notebook);
2996 g_return_if_fail (notebook != NULL);
2997 g_return_if_fail (page != NULL);
2998 g_return_if_fail (area != NULL);
3000 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
3001 (page->allocation.width == 0) || (page->allocation.height == 0))
3004 page_area.x = page->allocation.x;
3005 page_area.y = page->allocation.y;
3006 page_area.width = page->allocation.width;
3007 page_area.height = page->allocation.height;
3009 if (gdk_rectangle_intersect (&page_area, area, &child_area))
3013 widget = GTK_WIDGET (notebook);
3018 gap_side = GTK_POS_BOTTOM;
3020 case GTK_POS_BOTTOM:
3021 gap_side = GTK_POS_TOP;
3024 gap_side = GTK_POS_RIGHT;
3027 gap_side = GTK_POS_LEFT;
3031 if (notebook->cur_page == page)
3032 state_type = GTK_STATE_NORMAL;
3034 state_type = GTK_STATE_ACTIVE;
3035 gtk_paint_extension(widget->style, widget->window,
3036 state_type, GTK_SHADOW_OUT,
3037 area, widget, "tab",
3038 page_area.x, page_area.y,
3039 page_area.width, page_area.height,
3041 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
3042 notebook->focus_tab && (notebook->focus_tab->data == page))
3046 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3048 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
3049 area, widget, "tab",
3050 page->tab_label->allocation.x - focus_width,
3051 page->tab_label->allocation.y - focus_width,
3052 page->tab_label->allocation.width + 2 * focus_width,
3053 page->tab_label->allocation.height + 2 * focus_width);
3055 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
3056 GTK_WIDGET_DRAWABLE (page->tab_label))
3058 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
3060 /* This is a lame hack since all this code needs rewriting anyhow */
3062 expose_event->expose.window = g_object_ref (page->tab_label->window);
3063 expose_event->expose.area = child_area;
3064 expose_event->expose.region = gdk_region_rectangle (&child_area);
3065 expose_event->expose.send_event = TRUE;
3066 expose_event->expose.count = 0;
3068 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
3070 gdk_event_free (expose_event);
3076 gtk_notebook_draw_arrow (GtkNotebook *notebook,
3077 GtkNotebookArrow nbarrow)
3079 GtkStateType state_type;
3080 GtkShadowType shadow_type;
3082 GdkRectangle arrow_rect;
3084 gboolean is_rtl, left;
3086 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
3088 widget = GTK_WIDGET (notebook);
3090 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3091 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
3092 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
3094 if (GTK_WIDGET_DRAWABLE (notebook))
3096 if (notebook->in_child == nbarrow)
3098 if (notebook->click_child == nbarrow)
3099 state_type = GTK_STATE_ACTIVE;
3101 state_type = GTK_STATE_PRELIGHT;
3104 state_type = GTK_WIDGET_STATE (widget);
3106 if (notebook->click_child == nbarrow)
3107 shadow_type = GTK_SHADOW_IN;
3109 shadow_type = GTK_SHADOW_OUT;
3111 if (notebook->focus_tab &&
3112 !gtk_notebook_search_page (notebook, notebook->focus_tab,
3113 left? STEP_PREV : STEP_NEXT, TRUE))
3115 shadow_type = GTK_SHADOW_ETCHED_IN;
3116 state_type = GTK_STATE_INSENSITIVE;
3119 if (notebook->tab_pos == GTK_POS_LEFT ||
3120 notebook->tab_pos == GTK_POS_RIGHT)
3121 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
3123 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
3125 gtk_paint_arrow (widget->style, widget->window, state_type,
3126 shadow_type, NULL, widget, "notebook",
3127 arrow, TRUE, arrow_rect.x, arrow_rect.y,
3128 ARROW_SIZE, ARROW_SIZE);
3132 /* Private GtkNotebook Size Allocate Functions:
3134 * gtk_notebook_pages_allocate
3135 * gtk_notebook_page_allocate
3136 * gtk_notebook_calc_tabs
3139 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3141 GtkWidget *widget = GTK_WIDGET (notebook);
3142 GtkContainer *container = GTK_CONTAINER (notebook);
3143 GtkNotebookPage *page = NULL;
3144 GtkAllocation *allocation = &widget->allocation;
3145 GtkAllocation child_allocation;
3146 GList *children = NULL;
3147 GList *last_child = NULL;
3148 gboolean showarrow = FALSE;
3155 gint tab_pos = get_effective_tab_pos (notebook);
3156 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
3157 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
3160 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3163 child_allocation.x = widget->allocation.x + container->border_width;
3164 child_allocation.y = widget->allocation.y + container->border_width;
3168 case GTK_POS_BOTTOM:
3169 child_allocation.y = (widget->allocation.y +
3170 allocation->height -
3171 notebook->cur_page->requisition.height -
3172 container->border_width);
3175 child_allocation.height = notebook->cur_page->requisition.height;
3179 child_allocation.x = (widget->allocation.x +
3181 notebook->cur_page->requisition.width -
3182 container->border_width);
3185 child_allocation.width = notebook->cur_page->requisition.width;
3189 if (notebook->scrollable)
3193 children = notebook->children;
3195 if (notebook->focus_tab)
3196 focus_tab = notebook->focus_tab;
3197 else if (notebook->first_tab)
3198 focus_tab = notebook->first_tab;
3200 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3205 case GTK_POS_BOTTOM:
3208 page = children->data;
3209 children = children->next;
3211 if (GTK_WIDGET_VISIBLE (page->child))
3212 tab_space += page->requisition.width;
3215 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3218 page = focus_tab->data;
3220 tab_space = allocation->width - TAB_OVERLAP -
3221 page->requisition.width - 2 * container->border_width;
3222 if (notebook->has_after_previous)
3223 tab_space -= ARROW_SPACING + ARROW_SIZE;
3224 if (notebook->has_after_next)
3225 tab_space -= ARROW_SPACING + ARROW_SIZE;
3226 if (notebook->has_before_previous)
3228 tab_space -= ARROW_SPACING + ARROW_SIZE;
3229 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3231 if (notebook->has_before_next)
3233 tab_space -= ARROW_SPACING + ARROW_SIZE;
3234 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3242 page = children->data;
3243 children = children->next;
3245 if (GTK_WIDGET_VISIBLE (page->child))
3246 tab_space += page->requisition.height;
3249 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3252 page = focus_tab->data;
3253 tab_space = allocation->height
3254 - TAB_OVERLAP - 2 * container->border_width
3255 - page->requisition.height;
3256 if (notebook->has_after_previous || notebook->has_after_next)
3257 tab_space -= ARROW_SPACING + ARROW_SIZE;
3258 if (notebook->has_before_previous || notebook->has_before_next)
3260 tab_space -= ARROW_SPACING + ARROW_SIZE;
3261 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3266 if (showarrow) /* first_tab <- focus_tab */
3270 notebook->first_tab = focus_tab;
3271 last_child = gtk_notebook_search_page (notebook, focus_tab,
3277 if (notebook->first_tab && notebook->first_tab != focus_tab)
3279 /* Is first_tab really predecessor of focus_tab ? */
3280 page = notebook->first_tab->data;
3281 if (GTK_WIDGET_VISIBLE (page->child))
3282 for (children = focus_tab;
3283 children && children != notebook->first_tab;
3284 children = gtk_notebook_search_page (notebook,
3290 notebook->first_tab = focus_tab;
3292 gtk_notebook_calc_tabs (notebook,
3293 gtk_notebook_search_page (notebook,
3297 &(notebook->first_tab), &tab_space,
3302 notebook->first_tab =
3303 gtk_notebook_search_page (notebook, notebook->first_tab,
3305 if (!notebook->first_tab)
3306 notebook->first_tab = focus_tab;
3307 last_child = gtk_notebook_search_page (notebook, focus_tab,
3310 else /* focus_tab -> end */
3312 if (!notebook->first_tab)
3313 notebook->first_tab = gtk_notebook_search_page (notebook,
3318 gtk_notebook_calc_tabs (notebook,
3319 gtk_notebook_search_page (notebook,
3323 &children, &tab_space, STEP_NEXT);
3326 last_child = children;
3327 else /* start <- first_tab */
3331 gtk_notebook_calc_tabs
3333 gtk_notebook_search_page (notebook,
3334 notebook->first_tab,
3337 &children, &tab_space, STEP_PREV);
3338 notebook->first_tab = gtk_notebook_search_page(notebook,
3348 tab_space = -tab_space;
3350 for (children = notebook->first_tab;
3351 children && children != last_child;
3352 children = gtk_notebook_search_page (notebook, children,
3359 /*unmap all non-visible tabs*/
3360 for (children = gtk_notebook_search_page (notebook, NULL,
3362 children && children != notebook->first_tab;
3363 children = gtk_notebook_search_page (notebook, children,
3366 page = children->data;
3367 if (page->tab_label)
3368 gtk_widget_set_child_visible (page->tab_label, FALSE);
3370 for (children = last_child; children;
3371 children = gtk_notebook_search_page (notebook, children,
3374 page = children->data;
3375 if (page->tab_label)
3376 gtk_widget_set_child_visible (page->tab_label, FALSE);
3379 else /* !showarrow */
3381 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3392 children = notebook->children;
3396 case GTK_POS_BOTTOM:
3399 page = children->data;
3400 children = children->next;
3402 if (GTK_WIDGET_VISIBLE (page->child))
3405 tab_space += page->requisition.width;
3410 tab_space -= allocation->width;
3416 page = children->data;
3417 children = children->next;
3419 if (GTK_WIDGET_VISIBLE (page->child))
3422 tab_space += page->requisition.height;
3427 tab_space -= allocation->height;
3429 tab_space += 2 * container->border_width + TAB_OVERLAP;
3431 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3433 if (notebook->homogeneous && n)
3437 children = notebook->first_tab;
3440 memo_x = child_allocation.x;
3441 if (notebook->children && is_rtl)
3443 child_allocation.x = (allocation->x + allocation->width -
3444 container->border_width);
3447 if (notebook->has_after_previous)
3448 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3449 if (notebook->has_after_next)
3450 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
3456 if (children == last_child)
3458 /* FIXME double check */
3462 page = children->data;
3463 if (!showarrow && page->pack != GTK_PACK_START)
3465 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3468 if (n && (showarrow || page->expand || notebook->homogeneous))
3470 new_fill = (tab_space * i++) / n;
3471 delta = new_fill - old_fill;
3472 old_fill = new_fill;
3478 case GTK_POS_BOTTOM:
3479 child_allocation.width = (page->requisition.width +
3480 TAB_OVERLAP + delta);
3482 child_allocation.x -= child_allocation.width;
3486 child_allocation.height = (page->requisition.height +
3487 TAB_OVERLAP + delta);
3491 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3496 case GTK_POS_BOTTOM:
3498 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3500 child_allocation.x += TAB_OVERLAP;
3504 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3508 if (page->tab_label)
3509 gtk_widget_set_child_visible (page->tab_label, TRUE);
3514 children = notebook->children;
3519 case GTK_POS_BOTTOM:
3521 child_allocation.x = (allocation->x + allocation->width -
3522 container->border_width);
3524 child_allocation.x = memo_x;
3528 child_allocation.y = (allocation->y + allocation->height -
3529 container->border_width);
3533 while (children != last_child)
3535 page = children->data;
3536 children = children->next;
3538 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3542 if (n && (page->expand || notebook->homogeneous))
3544 new_fill = (tab_space * i++) / n;
3545 delta = new_fill - old_fill;
3546 old_fill = new_fill;
3552 case GTK_POS_BOTTOM:
3553 child_allocation.width = (page->requisition.width +
3554 TAB_OVERLAP + delta);
3556 child_allocation.x -= child_allocation.width;
3560 child_allocation.height = (page->requisition.height +
3561 TAB_OVERLAP + delta);
3562 child_allocation.y -= child_allocation.height;
3566 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3571 case GTK_POS_BOTTOM:
3573 child_allocation.x += TAB_OVERLAP;
3575 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3579 child_allocation.y += TAB_OVERLAP;
3583 if (page->tab_label)
3584 gtk_widget_set_child_visible (page->tab_label, TRUE);
3589 gtk_notebook_redraw_tabs (notebook);
3593 gtk_notebook_page_allocate (GtkNotebook *notebook,
3594 GtkNotebookPage *page,
3595 GtkAllocation *allocation)
3597 GtkWidget *widget = GTK_WIDGET (notebook);
3598 GtkAllocation child_allocation;
3599 GtkRequisition tab_requisition;
3604 gint tab_pos = get_effective_tab_pos (notebook);
3606 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3608 xthickness = widget->style->xthickness;
3609 ythickness = widget->style->ythickness;
3611 page->allocation = *allocation;
3612 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3614 if (notebook->cur_page != page)
3619 page->allocation.y += ythickness;
3620 case GTK_POS_BOTTOM:
3621 page->allocation.height = MAX (1, page->allocation.height - ythickness);
3624 page->allocation.x += xthickness;
3626 page->allocation.width = MAX (1, page->allocation.width - xthickness);
3634 case GTK_POS_BOTTOM:
3635 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3638 child_allocation.x = (xthickness + focus_width +
3639 notebook->tab_hborder);
3640 child_allocation.width = MAX (1, (page->allocation.width -
3641 2 * child_allocation.x));
3642 child_allocation.x += page->allocation.x;
3646 child_allocation.x = (page->allocation.x +
3647 (page->allocation.width -
3648 tab_requisition.width) / 2);
3649 child_allocation.width = tab_requisition.width;
3651 child_allocation.y = (notebook->tab_vborder + focus_width +
3652 page->allocation.y);
3653 if (tab_pos == GTK_POS_TOP)
3654 child_allocation.y += ythickness;
3655 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3656 2 * (notebook->tab_vborder + focus_width)));
3660 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3663 child_allocation.y = ythickness + padding;
3664 child_allocation.height = MAX (1, (page->allocation.height -
3665 2 * child_allocation.y));
3666 child_allocation.y += page->allocation.y;
3670 child_allocation.y = (page->allocation.y + (page->allocation.height -
3671 tab_requisition.height) / 2);
3672 child_allocation.height = tab_requisition.height;
3674 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3675 if (tab_pos == GTK_POS_LEFT)
3676 child_allocation.x += xthickness;
3677 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3678 2 * (notebook->tab_hborder + focus_width)));
3682 if (page->tab_label)
3683 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3687 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3693 GtkNotebookPage *page = NULL;
3695 GList *last_list = NULL;
3697 gint tab_pos = get_effective_tab_pos (notebook);
3703 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3704 if (pack == GTK_PACK_END)
3705 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3712 case GTK_POS_BOTTOM:
3715 page = children->data;
3716 if (GTK_WIDGET_VISIBLE (page->child))
3718 if (page->pack == pack)
3720 *tab_space -= page->requisition.width;
3721 if (*tab_space < 0 || children == *end)
3725 *tab_space = - (*tab_space +
3726 page->requisition.width);
3732 last_list = children;
3734 if (direction == STEP_NEXT)
3735 children = children->next;
3737 children = children->prev;
3744 page = children->data;
3745 if (GTK_WIDGET_VISIBLE (page->child))
3747 if (page->pack == pack)
3749 *tab_space -= page->requisition.height;
3750 if (*tab_space < 0 || children == *end)
3754 *tab_space = - (*tab_space +
3755 page->requisition.height);
3761 last_list = children;
3763 if (direction == STEP_NEXT)
3764 children = children->next;
3766 children = children->prev;
3770 if (direction == STEP_PREV)
3772 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3773 direction = STEP_PREV;
3774 children = last_list;
3779 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3783 for (list = notebook->children; list != NULL; list = list->next)
3785 GtkNotebookPage *page = list->data;
3787 if (page->tab_label)
3789 if (page == notebook->cur_page)
3790 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3792 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3797 /* Private GtkNotebook Page Switch Methods:
3799 * gtk_notebook_real_switch_page
3802 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3803 GtkNotebookPage *page,
3806 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3807 g_return_if_fail (page != NULL);
3809 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3812 if (notebook->cur_page)
3813 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3815 notebook->cur_page = page;
3817 if (!notebook->focus_tab ||
3818 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3819 notebook->focus_tab =
3820 g_list_find (notebook->children, notebook->cur_page);
3822 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3824 /* If the focus was on the previous page, move it to the first
3825 * element on the new page, if possible, or if not, to the
3828 if (notebook->child_has_focus)
3830 if (notebook->cur_page->last_focus_child &&
3831 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3832 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3834 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3835 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3838 gtk_notebook_update_tab_states (notebook);
3839 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3840 g_object_notify (G_OBJECT (notebook), "page");
3843 /* Private GtkNotebook Page Switch Functions:
3845 * gtk_notebook_switch_page
3846 * gtk_notebook_page_select
3847 * gtk_notebook_switch_focus_tab
3848 * gtk_notebook_menu_switch_page
3851 gtk_notebook_switch_page (GtkNotebook *notebook,
3852 GtkNotebookPage *page,
3855 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3856 g_return_if_fail (page != NULL);
3858 if (notebook->cur_page == page)
3862 page_num = g_list_index (notebook->children, page);
3864 g_signal_emit (notebook,
3865 notebook_signals[SWITCH_PAGE],
3872 gtk_notebook_page_select (GtkNotebook *notebook,
3873 gboolean move_focus)
3875 GtkNotebookPage *page;
3876 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3877 gint tab_pos = get_effective_tab_pos (notebook);
3879 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3881 if (!notebook->focus_tab)
3884 page = notebook->focus_tab->data;
3885 gtk_notebook_switch_page (notebook, page, -1);
3894 case GTK_POS_BOTTOM:
3898 dir = GTK_DIR_RIGHT;
3905 if (gtk_widget_child_focus (page->child, dir))
3912 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3916 GtkNotebookPage *page;
3918 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3920 if (notebook->focus_tab == new_child)
3923 old_child = notebook->focus_tab;
3924 notebook->focus_tab = new_child;
3926 if (notebook->scrollable)
3927 gtk_notebook_redraw_arrows (notebook);
3929 if (!notebook->show_tabs || !notebook->focus_tab)
3932 page = notebook->focus_tab->data;
3933 if (GTK_WIDGET_MAPPED (page->tab_label))
3934 gtk_notebook_redraw_tabs (notebook);
3936 gtk_notebook_pages_allocate (notebook);
3938 gtk_notebook_switch_page (notebook, page,
3939 g_list_index (notebook->children, page));
3943 gtk_notebook_menu_switch_page (GtkWidget *widget,
3944 GtkNotebookPage *page)
3946 GtkNotebook *notebook;
3950 g_return_if_fail (widget != NULL);
3951 g_return_if_fail (page != NULL);
3953 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3954 (GTK_MENU (widget->parent)));
3956 if (notebook->cur_page == page)
3960 children = notebook->children;
3961 while (children && children->data != page)
3963 children = children->next;
3967 g_signal_emit (notebook,
3968 notebook_signals[SWITCH_PAGE],
3974 /* Private GtkNotebook Menu Functions:
3976 * gtk_notebook_menu_item_create
3977 * gtk_notebook_menu_label_unparent
3978 * gtk_notebook_menu_detacher
3981 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3984 GtkNotebookPage *page;
3985 GtkWidget *menu_item;
3988 if (page->default_menu)
3990 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3991 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3993 page->menu_label = gtk_label_new ("");
3994 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3997 gtk_widget_show (page->menu_label);
3998 menu_item = gtk_menu_item_new ();
3999 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
4000 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
4001 gtk_notebook_real_page_position (notebook, list));
4002 g_signal_connect (menu_item, "activate",
4003 G_CALLBACK (gtk_notebook_menu_switch_page), page);
4004 if (GTK_WIDGET_VISIBLE (page->child))
4005 gtk_widget_show (menu_item);
4009 gtk_notebook_menu_label_unparent (GtkWidget *widget,
4012 gtk_widget_unparent (GTK_BIN(widget)->child);
4013 GTK_BIN(widget)->child = NULL;
4017 gtk_notebook_menu_detacher (GtkWidget *widget,
4020 GtkNotebook *notebook;
4022 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4024 notebook = GTK_NOTEBOOK (widget);
4025 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
4027 notebook->menu = NULL;
4030 /* Private GtkNotebook Setter Functions:
4032 * gtk_notebook_set_homogeneous_tabs_internal
4033 * gtk_notebook_set_tab_border_internal
4034 * gtk_notebook_set_tab_hborder_internal
4035 * gtk_notebook_set_tab_vborder_internal
4038 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
4039 gboolean homogeneous)
4041 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4043 if (homogeneous == notebook->homogeneous)
4046 notebook->homogeneous = homogeneous;
4047 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4049 g_object_notify (G_OBJECT (notebook), "homogeneous");
4053 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
4056 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4058 notebook->tab_hborder = border_width;
4059 notebook->tab_vborder = border_width;
4061 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4062 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4064 g_object_freeze_notify (G_OBJECT (notebook));
4065 g_object_notify (G_OBJECT (notebook), "tab-hborder");
4066 g_object_notify (G_OBJECT (notebook), "tab-vborder");
4067 g_object_thaw_notify (G_OBJECT (notebook));
4071 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
4074 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4076 if (notebook->tab_hborder == tab_hborder)
4079 notebook->tab_hborder = tab_hborder;
4081 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4082 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4084 g_object_notify (G_OBJECT (notebook), "tab-hborder");
4088 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
4091 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4093 if (notebook->tab_vborder == tab_vborder)
4096 notebook->tab_vborder = tab_vborder;
4098 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4099 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4101 g_object_notify (G_OBJECT (notebook), "tab-vborder");
4104 /* Public GtkNotebook Page Insert/Remove Methods :
4106 * gtk_notebook_append_page
4107 * gtk_notebook_append_page_menu
4108 * gtk_notebook_prepend_page
4109 * gtk_notebook_prepend_page_menu
4110 * gtk_notebook_insert_page
4111 * gtk_notebook_insert_page_menu
4112 * gtk_notebook_remove_page
4115 * gtk_notebook_append_page:
4116 * @notebook: a #GtkNotebook
4117 * @child: the #GtkWidget to use as the contents of the page.
4118 * @tab_label: the #GtkWidget to be used as the label for the page,
4119 * or %NULL to use the default label, 'page N'.
4121 * Appends a page to @notebook.
4123 * Return value: the index (starting from 0) of the appended
4124 * page in the notebook, or -1 if function fails
4127 gtk_notebook_append_page (GtkNotebook *notebook,
4129 GtkWidget *tab_label)
4131 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4132 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4133 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4135 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4139 * gtk_notebook_append_page_menu:
4140 * @notebook: a #GtkNotebook
4141 * @child: the #GtkWidget to use as the contents of the page.
4142 * @tab_label: the #GtkWidget to be used as the label for the page,
4143 * or %NULL to use the default label, 'page N'.
4144 * @menu_label: the widget to use as a label for the page-switch
4145 * menu, if that is enabled. If %NULL, and @tab_label
4146 * is a #GtkLabel or %NULL, then the menu label will be
4147 * a newly created label with the same text as @tab_label;
4148 * If @tab_label is not a #GtkLabel, @menu_label must be
4149 * specified if the page-switch menu is to be used.
4151 * Appends a page to @notebook, specifying the widget to use as the
4152 * label in the popup menu.
4154 * Return value: the index (starting from 0) of the appended
4155 * page in the notebook, or -1 if function fails
4158 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4160 GtkWidget *tab_label,
4161 GtkWidget *menu_label)
4163 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4164 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4165 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4166 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4168 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4172 * gtk_notebook_prepend_page:
4173 * @notebook: a #GtkNotebook
4174 * @child: the #GtkWidget to use as the contents of the page.
4175 * @tab_label: the #GtkWidget to be used as the label for the page,
4176 * or %NULL to use the default label, 'page N'.
4178 * Prepends a page to @notebook.
4180 * Return value: the index (starting from 0) of the prepended
4181 * page in the notebook, or -1 if function fails
4184 gtk_notebook_prepend_page (GtkNotebook *notebook,
4186 GtkWidget *tab_label)
4188 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4189 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4190 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4192 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4196 * gtk_notebook_prepend_page_menu:
4197 * @notebook: a #GtkNotebook
4198 * @child: the #GtkWidget to use as the contents of the page.
4199 * @tab_label: the #GtkWidget to be used as the label for the page,
4200 * or %NULL to use the default label, 'page N'.
4201 * @menu_label: the widget to use as a label for the page-switch
4202 * menu, if that is enabled. If %NULL, and @tab_label
4203 * is a #GtkLabel or %NULL, then the menu label will be
4204 * a newly created label with the same text as @tab_label;
4205 * If @tab_label is not a #GtkLabel, @menu_label must be
4206 * specified if the page-switch menu is to be used.
4208 * Prepends a page to @notebook, specifying the widget to use as the
4209 * label in the popup menu.
4211 * Return value: the index (starting from 0) of the prepended
4212 * page in the notebook, or -1 if function fails
4215 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4217 GtkWidget *tab_label,
4218 GtkWidget *menu_label)
4220 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4221 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4222 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4223 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4225 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4229 * gtk_notebook_insert_page:
4230 * @notebook: a #GtkNotebook
4231 * @child: the #GtkWidget to use as the contents of the page.
4232 * @tab_label: the #GtkWidget to be used as the label for the page,
4233 * or %NULL to use the default label, 'page N'.
4234 * @position: the index (starting at 0) at which to insert the page,
4235 * or -1 to append the page after all other pages.
4237 * Insert a page into @notebook at the given position.
4239 * Return value: the index (starting from 0) of the inserted
4240 * page in the notebook, or -1 if function fails
4243 gtk_notebook_insert_page (GtkNotebook *notebook,
4245 GtkWidget *tab_label,
4248 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4249 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4250 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4252 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4257 gtk_notebook_page_compare_tab (gconstpointer a,
4260 return (((GtkNotebookPage *) a)->tab_label != b);
4264 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4268 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4271 list = g_list_find_custom (notebook->children, child,
4272 gtk_notebook_page_compare_tab);
4275 GtkNotebookPage *page = list->data;
4277 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4278 gtk_notebook_switch_page (notebook, page, -1);
4279 focus_tabs_in (notebook);
4286 * gtk_notebook_insert_page_menu:
4287 * @notebook: a #GtkNotebook
4288 * @child: the #GtkWidget to use as the contents of the page.
4289 * @tab_label: the #GtkWidget to be used as the label for the page,
4290 * or %NULL to use the default label, 'page N'.
4291 * @menu_label: the widget to use as a label for the page-switch
4292 * menu, if that is enabled. If %NULL, and @tab_label
4293 * is a #GtkLabel or %NULL, then the menu label will be
4294 * a newly created label with the same text as @tab_label;
4295 * If @tab_label is not a #GtkLabel, @menu_label must be
4296 * specified if the page-switch menu is to be used.
4297 * @position: the index (starting at 0) at which to insert the page,
4298 * or -1 to append the page after all other pages.
4300 * Insert a page into @notebook at the given position, specifying
4301 * the widget to use as the label in the popup menu.
4303 * Return value: the index (starting from 0) of the inserted
4304 * page in the notebook, or -1 if function fails
4307 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4309 GtkWidget *tab_label,
4310 GtkWidget *menu_label,
4313 GtkNotebookPage *page;
4316 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4317 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
4318 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
4319 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
4321 gtk_widget_freeze_child_notify (child);
4323 page = g_new (GtkNotebookPage, 1);
4324 page->child = child;
4325 page->last_focus_child = NULL;
4326 page->requisition.width = 0;
4327 page->requisition.height = 0;
4328 page->allocation.x = 0;
4329 page->allocation.y = 0;
4330 page->allocation.width = 0;
4331 page->allocation.height = 0;
4332 page->default_menu = FALSE;
4333 page->default_tab = FALSE;
4334 page->mnemonic_activate_signal = 0;
4336 nchildren = g_list_length (notebook->children);
4337 if ((position < 0) || (position > nchildren))
4338 position = nchildren;
4340 notebook->children = g_list_insert (notebook->children, page, position);
4344 page->default_tab = TRUE;
4345 if (notebook->show_tabs)
4346 tab_label = gtk_label_new ("");
4348 page->tab_label = tab_label;
4349 page->menu_label = menu_label;
4350 page->expand = FALSE;
4352 page->pack = GTK_PACK_START;
4355 page->default_menu = TRUE;
4358 g_object_ref (page->menu_label);
4359 gtk_object_sink (GTK_OBJECT (page->menu_label));
4363 gtk_notebook_menu_item_create (notebook,
4364 g_list_find (notebook->children, page));
4366 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4368 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4370 gtk_notebook_update_labels (notebook);
4372 if (!notebook->first_tab)
4373 notebook->first_tab = notebook->children;
4375 /* child visible will be turned on by switch_page below */
4376 gtk_widget_set_child_visible (child, FALSE);
4380 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4381 gtk_widget_show (tab_label);
4383 gtk_widget_hide (tab_label);
4386 if (!notebook->cur_page)
4388 gtk_notebook_switch_page (notebook, page, 0);
4389 gtk_notebook_switch_focus_tab (notebook, NULL);
4392 gtk_notebook_update_tab_states (notebook);
4395 page->mnemonic_activate_signal =
4396 g_signal_connect (tab_label,
4397 "mnemonic_activate",
4398 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4401 gtk_widget_child_notify (child, "tab-expand");
4402 gtk_widget_child_notify (child, "tab-fill");
4403 gtk_widget_child_notify (child, "tab-pack");
4404 gtk_widget_child_notify (child, "tab-label");
4405 gtk_widget_child_notify (child, "menu-label");
4406 gtk_widget_child_notify (child, "position");
4407 gtk_widget_thaw_child_notify (child);
4413 * gtk_notebook_remove_page:
4414 * @notebook: a #GtkNotebook.
4415 * @page_num: the index of a notebook page, starting
4416 * from 0. If -1, the last page will
4419 * Removes a page from the notebook given its index
4423 gtk_notebook_remove_page (GtkNotebook *notebook,
4428 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4432 list = g_list_nth (notebook->children, page_num);
4434 gtk_notebook_real_remove (notebook, list, FALSE);
4438 list = g_list_last (notebook->children);
4440 gtk_notebook_real_remove (notebook, list, FALSE);
4444 /* Public GtkNotebook Page Switch Methods :
4445 * gtk_notebook_get_current_page
4446 * gtk_notebook_page_num
4447 * gtk_notebook_set_current_page
4448 * gtk_notebook_next_page
4449 * gtk_notebook_prev_page
4452 * gtk_notebook_get_current_page:
4453 * @notebook: a #GtkNotebook
4455 * Returns the page number of the current page.
4457 * Return value: the index (starting from 0) of the current
4458 * page in the notebook. If the notebook has no pages, then
4459 * -1 will be returned.
4462 gtk_notebook_get_current_page (GtkNotebook *notebook)
4464 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4466 if (!notebook->cur_page)
4469 return g_list_index (notebook->children, notebook->cur_page);
4473 * gtk_notebook_get_nth_page:
4474 * @notebook: a #GtkNotebook
4475 * @page_num: the index of a page in the noteobok, or -1
4476 * to get the last page.
4478 * Returns the child widget contained in page number @page_num.
4480 * Return value: the child widget, or %NULL if @page_num is
4484 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4487 GtkNotebookPage *page;
4490 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4493 list = g_list_nth (notebook->children, page_num);
4495 list = g_list_last (notebook->children);
4507 * gtk_notebook_get_n_pages:
4508 * @notebook: a #GtkNotebook
4510 * Gets the number of pages in a notebook.
4512 * Return value: the number of pages in the notebook.
4517 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4519 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4521 return g_list_length (notebook->children);
4525 * gtk_notebook_page_num:
4526 * @notebook: a #GtkNotebook
4527 * @child: a #GtkWidget
4529 * Finds the index of the page which contains the given child
4532 * Return value: the index of the page containing @child, or
4533 * -1 if @child is not in the notebook.
4536 gtk_notebook_page_num (GtkNotebook *notebook,
4542 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4545 children = notebook->children;
4548 GtkNotebookPage *page = children->data;
4550 if (page->child == child)
4553 children = children->next;
4561 * gtk_notebook_set_current_page:
4562 * @notebook: a #GtkNotebook
4563 * @page_num: index of the page to switch to, starting from 0.
4564 * If negative, the last page will be used. If greater
4565 * than the number of pages in the notebook, nothing
4568 * Switches to the page number @page_num.
4571 gtk_notebook_set_current_page (GtkNotebook *notebook,
4576 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4579 list = g_list_nth (notebook->children, page_num);
4581 list = g_list_last (notebook->children);
4583 page_num = g_list_index (notebook->children, list);
4586 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4590 * gtk_notebook_next_page:
4591 * @notebook: a #GtkNotebook
4593 * Switches to the next page. Nothing happens if the current page is
4597 gtk_notebook_next_page (GtkNotebook *notebook)
4601 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4603 list = g_list_find (notebook->children, notebook->cur_page);
4607 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4611 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4615 * gtk_notebook_prev_page:
4616 * @notebook: a #GtkNotebook
4618 * Switches to the previous page. Nothing happens if the current page
4619 * is the first page.
4622 gtk_notebook_prev_page (GtkNotebook *notebook)
4626 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4628 list = g_list_find (notebook->children, notebook->cur_page);
4632 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4636 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4639 /* Public GtkNotebook/Tab Style Functions
4641 * gtk_notebook_set_show_border
4642 * gtk_notebook_set_show_tabs
4643 * gtk_notebook_set_tab_pos
4644 * gtk_notebook_set_homogeneous_tabs
4645 * gtk_notebook_set_tab_border
4646 * gtk_notebook_set_tab_hborder
4647 * gtk_notebook_set_tab_vborder
4648 * gtk_notebook_set_scrollable
4651 * gtk_notebook_set_show_border:
4652 * @notebook: a #GtkNotebook
4653 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4655 * Sets whether a bevel will be drawn around the notebook pages.
4656 * This only has a visual effect when the tabs are not shown.
4657 * See gtk_notebook_set_show_tabs().
4660 gtk_notebook_set_show_border (GtkNotebook *notebook,
4661 gboolean show_border)
4663 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4665 if (notebook->show_border != show_border)
4667 notebook->show_border = show_border;
4669 if (GTK_WIDGET_VISIBLE (notebook))
4670 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4672 g_object_notify (G_OBJECT (notebook), "show-border");
4677 * gtk_notebook_get_show_border:
4678 * @notebook: a #GtkNotebook
4680 * Returns whether a bevel will be drawn around the notebook pages. See
4681 * gtk_notebook_set_show_border().
4683 * Return value: %TRUE if the bevel is drawn
4686 gtk_notebook_get_show_border (GtkNotebook *notebook)
4688 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4690 return notebook->show_border;
4694 * gtk_notebook_set_show_tabs:
4695 * @notebook: a #GtkNotebook
4696 * @show_tabs: %TRUE if the tabs should be shown.
4698 * Sets whether to show the tabs for the notebook or not.
4701 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4704 GtkNotebookPage *page;
4707 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4709 show_tabs = show_tabs != FALSE;
4711 if (notebook->show_tabs == show_tabs)
4714 notebook->show_tabs = show_tabs;
4715 children = notebook->children;
4719 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4723 page = children->data;
4724 children = children->next;
4725 if (page->default_tab)
4727 gtk_widget_destroy (page->tab_label);
4728 page->tab_label = NULL;
4731 gtk_widget_hide (page->tab_label);
4736 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4737 gtk_notebook_update_labels (notebook);
4739 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4741 g_object_notify (G_OBJECT (notebook), "show-tabs");
4745 * gtk_notebook_get_show_tabs:
4746 * @notebook: a #GtkNotebook
4748 * Returns whether the tabs of the notebook are shown. See
4749 * gtk_notebook_set_show_tabs().
4751 * Return value: %TRUE if the tabs are shown
4754 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4756 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4758 return notebook->show_tabs;
4762 * gtk_notebook_set_tab_pos:
4763 * @notebook: a #GtkNotebook.
4764 * @pos: the edge to draw the tabs at.
4766 * Sets the edge at which the tabs for switching pages in the
4767 * notebook are drawn.
4770 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4771 GtkPositionType pos)
4773 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4775 if (notebook->tab_pos != pos)
4777 notebook->tab_pos = pos;
4778 if (GTK_WIDGET_VISIBLE (notebook))
4779 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4782 g_object_notify (G_OBJECT (notebook), "tab-pos");
4786 * gtk_notebook_get_tab_pos:
4787 * @notebook: a #GtkNotebook
4789 * Gets the edge at which the tabs for switching pages in the
4790 * notebook are drawn.
4792 * Return value: the edge at which the tabs are drawn
4795 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4797 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4799 return notebook->tab_pos;
4803 * gtk_notebook_set_homogeneous_tabs:
4804 * @notebook: a #GtkNotebook
4805 * @homogeneous: %TRUE if all tabs should be the same size.
4807 * Sets whether the tabs must have all the same size or not.
4810 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4811 gboolean homogeneous)
4813 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4815 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4819 * gtk_notebook_set_tab_border:
4820 * @notebook: a #GtkNotebook
4821 * @border_width: width of the border around the tab labels.
4823 * Sets the width the border around the tab labels
4824 * in a notebook. This is equivalent to calling
4825 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4826 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4829 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4832 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4834 gtk_notebook_set_tab_border_internal (notebook, border_width);
4838 * gtk_notebook_set_tab_hborder:
4839 * @notebook: a #GtkNotebook
4840 * @tab_hborder: width of the horizontal border of tab labels.
4842 * Sets the width of the horizontal border of tab labels.
4845 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4848 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4850 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4854 * gtk_notebook_set_tab_vborder:
4855 * @notebook: a #GtkNotebook
4856 * @tab_vborder: width of the vertical border of tab labels.
4858 * Sets the width of the vertical border of tab labels.
4861 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4864 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4866 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4870 * gtk_notebook_set_scrollable:
4871 * @notebook: a #GtkNotebook
4872 * @scrollable: %TRUE if scroll arrows should be added
4874 * Sets whether the tab label area will have arrows for scrolling if
4875 * there are too many tabs to fit in the area.
4878 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4879 gboolean scrollable)
4881 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4883 scrollable = (scrollable != FALSE);
4885 if (scrollable != notebook->scrollable)
4887 notebook->scrollable = scrollable;
4889 if (GTK_WIDGET_VISIBLE (notebook))
4890 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4892 g_object_notify (G_OBJECT (notebook), "scrollable");
4897 * gtk_notebook_get_scrollable:
4898 * @notebook: a #GtkNotebook
4900 * Returns whether the tab label area has arrows for scrolling. See
4901 * gtk_notebook_set_scrollable().
4903 * Return value: %TRUE if arrows for scrolling are present
4906 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4908 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4910 return notebook->scrollable;
4913 /* Public GtkNotebook Popup Menu Methods:
4915 * gtk_notebook_popup_enable
4916 * gtk_notebook_popup_disable
4921 * gtk_notebook_popup_enable:
4922 * @notebook: a #GtkNotebook
4924 * Enables the popup menu: if the user clicks with the right mouse button on
4925 * the bookmarks, a menu with all the pages will be popped up.
4928 gtk_notebook_popup_enable (GtkNotebook *notebook)
4932 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4937 notebook->menu = gtk_menu_new ();
4938 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4940 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4941 gtk_notebook_menu_item_create (notebook, list);
4943 gtk_notebook_update_labels (notebook);
4944 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4945 GTK_WIDGET (notebook),
4946 gtk_notebook_menu_detacher);
4948 g_object_notify (G_OBJECT (notebook), "enable-popup");
4952 * gtk_notebook_popup_disable:
4953 * @notebook: a #GtkNotebook
4955 * Disables the popup menu.
4958 gtk_notebook_popup_disable (GtkNotebook *notebook)
4960 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4962 if (!notebook->menu)
4965 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4966 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4967 gtk_widget_destroy (notebook->menu);
4969 g_object_notify (G_OBJECT (notebook), "enable-popup");
4972 /* Public GtkNotebook Page Properties Functions:
4974 * gtk_notebook_get_tab_label
4975 * gtk_notebook_set_tab_label
4976 * gtk_notebook_set_tab_label_text
4977 * gtk_notebook_get_menu_label
4978 * gtk_notebook_set_menu_label
4979 * gtk_notebook_set_menu_label_text
4980 * gtk_notebook_set_tab_label_packing
4981 * gtk_notebook_query_tab_label_packing
4985 * gtk_notebook_get_tab_label:
4986 * @notebook: a #GtkNotebook
4989 * Returns the tab label widget for the page @child. %NULL is returned
4990 * if @child is not in @notebook or if no tab label has specifically
4991 * been set for @child.
4993 * Return value: the tab label
4996 gtk_notebook_get_tab_label (GtkNotebook *notebook,
5001 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5002 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5004 list = CHECK_FIND_CHILD (notebook, child);
5008 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
5011 return GTK_NOTEBOOK_PAGE (list)->tab_label;
5015 * gtk_notebook_set_tab_label:
5016 * @notebook: a #GtkNotebook
5018 * @tab_label: the tab label widget to use, or %NULL for default tab
5021 * Changes the tab label for @child. If %NULL is specified
5022 * for @tab_label, then the page will have the label 'page N'.
5025 gtk_notebook_set_tab_label (GtkNotebook *notebook,
5027 GtkWidget *tab_label)
5029 GtkNotebookPage *page;
5032 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5033 g_return_if_fail (GTK_IS_WIDGET (child));
5035 list = CHECK_FIND_CHILD (notebook, child);
5039 /* a NULL pointer indicates a default_tab setting, otherwise
5040 * we need to set the associated label
5044 if (page->tab_label == tab_label)
5048 gtk_notebook_remove_tab_label (notebook, page);
5052 page->default_tab = FALSE;
5053 page->tab_label = tab_label;
5054 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5058 page->default_tab = TRUE;
5059 page->tab_label = NULL;
5061 if (notebook->show_tabs)
5065 g_snprintf (string, sizeof(string), _("Page %u"),
5066 gtk_notebook_real_page_position (notebook, list));
5067 page->tab_label = gtk_label_new (string);
5068 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
5072 if (page->tab_label)
5073 page->mnemonic_activate_signal =
5074 g_signal_connect (page->tab_label,
5075 "mnemonic_activate",
5076 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
5079 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
5081 gtk_widget_show (page->tab_label);
5082 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5085 gtk_notebook_update_tab_states (notebook);
5086 gtk_widget_child_notify (child, "tab-label");
5090 * gtk_notebook_set_tab_label_text:
5091 * @notebook: a #GtkNotebook
5093 * @tab_text: the label text
5095 * Creates a new label and sets it as the tab label for the page
5096 * containing @child.
5099 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
5101 const gchar *tab_text)
5103 GtkWidget *tab_label = NULL;
5105 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5108 tab_label = gtk_label_new (tab_text);
5109 gtk_notebook_set_tab_label (notebook, child, tab_label);
5110 gtk_widget_child_notify (child, "tab-label");
5114 * gtk_notebook_get_tab_label_text:
5115 * @notebook: a #GtkNotebook
5116 * @child: a widget contained in a page of @notebook
5118 * Retrieves the text of the tab label for the page containing
5121 * Returns value: the text of the tab label, or %NULL if the
5122 * tab label widget is not a #GtkLabel. The
5123 * string is owned by the widget and must not
5126 G_CONST_RETURN gchar *
5127 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
5130 GtkWidget *tab_label;
5132 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5133 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5135 tab_label = gtk_notebook_get_tab_label (notebook, child);
5137 if (tab_label && GTK_IS_LABEL (tab_label))
5138 return gtk_label_get_text (GTK_LABEL (tab_label));
5144 * gtk_notebook_get_menu_label:
5145 * @notebook: a #GtkNotebook
5146 * @child: a widget contained in a page of @notebook
5148 * Retrieves the menu label widget of the page containing @child.
5150 * Return value: the menu label, or %NULL if the
5151 * notebook page does not have a menu label other
5152 * than the default (the tab label).
5155 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5160 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5161 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5163 list = CHECK_FIND_CHILD (notebook, child);
5167 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5170 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5174 * gtk_notebook_set_menu_label:
5175 * @notebook: a #GtkNotebook
5176 * @child: the child widget
5177 * @menu_label: the menu label, or NULL for default
5179 * Changes the menu label for the page containing @child.
5182 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5184 GtkWidget *menu_label)
5186 GtkNotebookPage *page;
5189 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5190 g_return_if_fail (GTK_IS_WIDGET (child));
5192 list = CHECK_FIND_CHILD (notebook, child);
5197 if (page->menu_label)
5200 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5201 page->menu_label->parent);
5203 if (!page->default_menu)
5204 g_object_unref (page->menu_label);
5209 page->menu_label = menu_label;
5210 g_object_ref (page->menu_label);
5211 gtk_object_sink (GTK_OBJECT(page->menu_label));
5212 page->default_menu = FALSE;
5215 page->default_menu = TRUE;
5218 gtk_notebook_menu_item_create (notebook, list);
5219 gtk_widget_child_notify (child, "menu-label");
5223 * gtk_notebook_set_menu_label_text:
5224 * @notebook: a #GtkNotebook
5225 * @child: the child widget
5226 * @menu_text: the label text
5228 * Creates a new label and sets it as the menu label of @child.
5231 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5233 const gchar *menu_text)
5235 GtkWidget *menu_label = NULL;
5237 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5240 menu_label = gtk_label_new (menu_text);
5241 gtk_notebook_set_menu_label (notebook, child, menu_label);
5242 gtk_widget_child_notify (child, "menu-label");
5246 * gtk_notebook_get_menu_label_text:
5247 * @notebook: a #GtkNotebook
5248 * @child: the child widget of a page of the notebook.
5250 * Retrieves the text of the menu label for the page containing
5253 * Returns value: the text of the tab label, or %NULL if the
5254 * widget does not have a menu label other than
5255 * the default menu label, or the menu label widget
5256 * is not a #GtkLabel. The string is owned by
5257 * the widget and must not be freed.
5259 G_CONST_RETURN gchar *
5260 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5263 GtkWidget *menu_label;
5265 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5266 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5268 menu_label = gtk_notebook_get_menu_label (notebook, child);
5270 if (menu_label && GTK_IS_LABEL (menu_label))
5271 return gtk_label_get_text (GTK_LABEL (menu_label));
5276 /* Helper function called when pages are reordered
5279 gtk_notebook_child_reordered (GtkNotebook *notebook,
5280 GtkNotebookPage *page)
5284 GtkWidget *menu_item;
5286 menu_item = page->menu_label->parent;
5287 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5288 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5289 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5292 gtk_notebook_update_tab_states (notebook);
5293 gtk_notebook_update_labels (notebook);
5297 * gtk_notebook_set_tab_label_packing:
5298 * @notebook: a #GtkNotebook
5299 * @child: the child widget
5300 * @expand: whether to expand the bookmark or not
5301 * @fill: whether the bookmark should fill the allocated area or not
5302 * @pack_type: the position of the bookmark
5304 * Sets the packing parameters for the tab label of the page
5305 * containing @child. See gtk_box_pack_start() for the exact meaning
5306 * of the parameters.
5309 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5313 GtkPackType pack_type)
5315 GtkNotebookPage *page;
5318 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5319 g_return_if_fail (GTK_IS_WIDGET (child));
5321 list = CHECK_FIND_CHILD (notebook, child);
5326 expand = expand != FALSE;
5327 fill = fill != FALSE;
5328 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5331 gtk_widget_freeze_child_notify (child);
5332 page->expand = expand;
5333 gtk_widget_child_notify (child, "tab-expand");
5335 gtk_widget_child_notify (child, "tab-fill");
5336 if (page->pack != pack_type)
5338 page->pack = pack_type;
5339 gtk_notebook_child_reordered (notebook, page);
5341 gtk_widget_child_notify (child, "tab-pack");
5342 gtk_widget_child_notify (child, "position");
5343 if (notebook->show_tabs)
5344 gtk_notebook_pages_allocate (notebook);
5345 gtk_widget_thaw_child_notify (child);
5349 * gtk_notebook_query_tab_label_packing:
5350 * @notebook: a #GtkNotebook
5352 * @expand: location to store the expand value (or NULL)
5353 * @fill: location to store the fill value (or NULL)
5354 * @pack_type: location to store the pack_type (or NULL)
5356 * Query the packing attributes for the tab label of the page
5357 * containing @child.
5360 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5364 GtkPackType *pack_type)
5368 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5369 g_return_if_fail (GTK_IS_WIDGET (child));
5371 list = CHECK_FIND_CHILD (notebook, child);
5376 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5378 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5380 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5384 * gtk_notebook_reorder_child:
5385 * @notebook: a #GtkNotebook
5386 * @child: the child to move
5387 * @position: the new position, or -1 to move to the end
5389 * Reorders the page containing @child, so that it appears in position
5390 * @position. If @position is greater than or equal to the number of
5391 * children in the list or negative, @child will be moved to the end
5395 gtk_notebook_reorder_child (GtkNotebook *notebook,
5399 GList *list, *new_list;
5400 GtkNotebookPage *page;
5404 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5405 g_return_if_fail (GTK_IS_WIDGET (child));
5407 list = CHECK_FIND_CHILD (notebook, child);
5411 max_pos = g_list_length (notebook->children) - 1;
5412 if (position < 0 || position > max_pos)
5415 old_pos = g_list_position (notebook->children, list);
5417 if (old_pos == position)
5421 notebook->children = g_list_delete_link (notebook->children, list);
5423 notebook->children = g_list_insert (notebook->children, page, position);
5424 new_list = g_list_nth (notebook->children, position);
5426 /* Fix up GList references in GtkNotebook structure */
5427 if (notebook->first_tab == list)
5428 notebook->first_tab = new_list;
5429 if (notebook->focus_tab == list)
5430 notebook->focus_tab = new_list;
5432 gtk_widget_freeze_child_notify (child);
5434 /* Move around the menu items if necessary */
5435 gtk_notebook_child_reordered (notebook, page);
5436 gtk_widget_child_notify (child, "tab-pack");
5437 gtk_widget_child_notify (child, "position");
5439 if (notebook->show_tabs)
5440 gtk_notebook_pages_allocate (notebook);
5442 gtk_widget_thaw_child_notify (child);
5445 #define __GTK_NOTEBOOK_C__
5446 #include "gtkaliasdef.c"