1 /* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
2 /* GTK - The GIMP Toolkit
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gtknotebook.h"
32 #include "gtkmenuitem.h"
34 #include <gdk/gdkkeysyms.h>
37 #include "gtkmarshalers.h"
38 #include "gtkbindings.h"
39 #include "gtkprivate.h"
45 #define ARROW_SPACING 0
46 #define SCROLL_DELAY_FACTOR 5
47 #define SCROLL_THRESHOLD 12
48 #define DND_THRESHOLD_MULTIPLIER 4
82 } GtkNotebookPointerPosition;
87 DRAG_OPERATION_REORDER,
89 } GtkNotebookDragOperation;
91 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
92 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
111 CHILD_PROP_TAB_LABEL,
112 CHILD_PROP_MENU_LABEL,
114 CHILD_PROP_TAB_EXPAND,
117 CHILD_PROP_REORDERABLE,
118 CHILD_PROP_DETACHABLE
121 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
123 /* some useful defines for calculating coords */
124 #define PAGE_LEFT_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x)
125 #define PAGE_RIGHT_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width)
126 #define PAGE_MIDDLE_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width / 2)
127 #define PAGE_TOP_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y)
128 #define PAGE_BOTTOM_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height)
129 #define PAGE_MIDDLE_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height / 2)
131 struct _GtkNotebookPage
134 GtkWidget *tab_label;
135 GtkWidget *menu_label;
136 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
138 guint default_menu : 1; /* If true, we create the menu label ourself */
139 guint default_tab : 1; /* If true, we create the tab label ourself */
143 guint reorderable : 1;
144 guint detachable : 1;
146 GtkRequisition requisition;
147 GtkAllocation allocation;
149 gulong mnemonic_activate_signal;
150 gulong notify_visible_handler;
153 #define GTK_NOTEBOOK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_NOTEBOOK, GtkNotebookPrivate))
155 typedef struct _GtkNotebookPrivate GtkNotebookPrivate;
157 struct _GtkNotebookPrivate
164 GtkTargetList *source_targets;
165 gboolean during_detach;
166 gboolean has_scrolled;
169 static const GtkTargetEntry notebook_targets[] = {
170 { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
171 { "application/x-rootwindow-drop", 0, 1 }
174 #ifdef G_DISABLE_CHECKS
175 #define CHECK_FIND_CHILD(notebook, child) \
176 gtk_notebook_find_child (notebook, child, G_STRLOC)
178 #define CHECK_FIND_CHILD(notebook, child) \
179 gtk_notebook_find_child (notebook, child, NULL)
182 /*** GtkNotebook Methods ***/
183 static void gtk_notebook_class_init (GtkNotebookClass *klass);
184 static void gtk_notebook_init (GtkNotebook *notebook);
186 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
187 gboolean move_focus);
188 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
189 GtkNotebookTab type);
190 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
192 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
193 GtkDirectionType direction_type);
194 static void gtk_notebook_reorder_tab (GtkNotebook *notebook,
195 GtkDirectionType direction_type,
196 gboolean move_to_last);
198 /*** GtkObject Methods ***/
199 static void gtk_notebook_destroy (GtkObject *object);
200 static void gtk_notebook_set_property (GObject *object,
204 static void gtk_notebook_get_property (GObject *object,
209 /*** GtkWidget Methods ***/
210 static void gtk_notebook_map (GtkWidget *widget);
211 static void gtk_notebook_unmap (GtkWidget *widget);
212 static void gtk_notebook_realize (GtkWidget *widget);
213 static void gtk_notebook_unrealize (GtkWidget *widget);
214 static void gtk_notebook_size_request (GtkWidget *widget,
215 GtkRequisition *requisition);
216 static void gtk_notebook_size_allocate (GtkWidget *widget,
217 GtkAllocation *allocation);
218 static gint gtk_notebook_expose (GtkWidget *widget,
219 GdkEventExpose *event);
220 static gboolean gtk_notebook_scroll (GtkWidget *widget,
221 GdkEventScroll *event);
222 static gint gtk_notebook_button_press (GtkWidget *widget,
223 GdkEventButton *event);
224 static gint gtk_notebook_button_release (GtkWidget *widget,
225 GdkEventButton *event);
226 static gboolean gtk_notebook_popup_menu (GtkWidget *widget);
227 static gint gtk_notebook_enter_notify (GtkWidget *widget,
228 GdkEventCrossing *event);
229 static gint gtk_notebook_leave_notify (GtkWidget *widget,
230 GdkEventCrossing *event);
231 static gint gtk_notebook_motion_notify (GtkWidget *widget,
232 GdkEventMotion *event);
233 static gint gtk_notebook_focus_in (GtkWidget *widget,
234 GdkEventFocus *event);
235 static gint gtk_notebook_focus_out (GtkWidget *widget,
236 GdkEventFocus *event);
237 static void gtk_notebook_grab_notify (GtkWidget *widget,
238 gboolean was_grabbed);
239 static void gtk_notebook_state_changed (GtkWidget *widget,
240 GtkStateType previous_state);
241 static void gtk_notebook_draw_focus (GtkWidget *widget);
242 static gint gtk_notebook_focus (GtkWidget *widget,
243 GtkDirectionType direction);
244 static void gtk_notebook_style_set (GtkWidget *widget,
247 /*** Drag and drop Methods ***/
248 static void gtk_notebook_drag_begin (GtkWidget *widget,
249 GdkDragContext *context);
250 static gboolean gtk_notebook_drag_motion (GtkWidget *widget,
251 GdkDragContext *context,
255 static gboolean gtk_notebook_drag_drop (GtkWidget *widget,
256 GdkDragContext *context,
260 static void gtk_notebook_drag_data_get (GtkWidget *widget,
261 GdkDragContext *context,
262 GtkSelectionData *data,
265 static void gtk_notebook_drag_data_received (GtkWidget *widget,
266 GdkDragContext *context,
269 GtkSelectionData *data,
273 /*** GtkContainer Methods ***/
274 static void gtk_notebook_set_child_property (GtkContainer *container,
279 static void gtk_notebook_get_child_property (GtkContainer *container,
284 static void gtk_notebook_add (GtkContainer *container,
286 static void gtk_notebook_remove (GtkContainer *container,
288 static void gtk_notebook_set_focus_child (GtkContainer *container,
290 static GType gtk_notebook_child_type (GtkContainer *container);
291 static void gtk_notebook_forall (GtkContainer *container,
292 gboolean include_internals,
293 GtkCallback callback,
294 gpointer callback_data);
296 /*** GtkNotebook Methods ***/
297 static gint gtk_notebook_real_insert_page (GtkNotebook *notebook,
299 GtkWidget *tab_label,
300 GtkWidget *menu_label,
303 /*** GtkNotebook Private Functions ***/
304 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
305 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
306 static void gtk_notebook_real_remove (GtkNotebook *notebook,
308 static void gtk_notebook_update_labels (GtkNotebook *notebook);
309 static gint gtk_notebook_timer (GtkNotebook *notebook);
310 static gint gtk_notebook_page_compare (gconstpointer a,
312 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
314 const gchar *function);
315 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
317 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
320 gboolean find_visible);
322 /*** GtkNotebook Drawing Functions ***/
323 static void gtk_notebook_paint (GtkWidget *widget,
325 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
326 GtkNotebookPage *page,
328 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
329 GtkNotebookArrow arrow);
331 /*** GtkNotebook Size Allocate Functions ***/
332 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
333 GtkNotebookDragOperation operation);
334 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
335 GtkNotebookPage *page,
336 GtkAllocation *allocation);
337 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
343 /*** GtkNotebook Page Switch Methods ***/
344 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
345 GtkNotebookPage *page,
348 /*** GtkNotebook Page Switch Functions ***/
349 static void gtk_notebook_switch_page (GtkNotebook *notebook,
350 GtkNotebookPage *page,
352 static gint gtk_notebook_page_select (GtkNotebook *notebook,
353 gboolean move_focus);
354 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
356 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
357 GtkNotebookPage *page);
359 /*** GtkNotebook Menu Functions ***/
360 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
362 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
364 static void gtk_notebook_menu_detacher (GtkWidget *widget,
367 /*** GtkNotebook Private Setters ***/
368 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
369 gboolean homogeneous);
370 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
372 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
374 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
377 static void gtk_notebook_update_tab_states (GtkNotebook *notebook);
378 static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
382 static gboolean focus_tabs_in (GtkNotebook *notebook);
383 static gboolean focus_child_in (GtkNotebook *notebook,
384 GtkDirectionType direction);
386 static void stop_scrolling (GtkNotebook *notebook);
389 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
390 static gpointer window_creation_hook_data;
392 static GtkContainerClass *parent_class = NULL;
393 static guint notebook_signals[LAST_SIGNAL] = { 0 };
396 gtk_notebook_get_type (void)
398 static GType notebook_type = 0;
402 static const GTypeInfo notebook_info =
404 sizeof (GtkNotebookClass),
405 NULL, /* base_init */
406 NULL, /* base_finalize */
407 (GClassInitFunc) gtk_notebook_class_init,
408 NULL, /* class_finalize */
409 NULL, /* class_data */
410 sizeof (GtkNotebook),
412 (GInstanceInitFunc) gtk_notebook_init,
415 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkNotebook"),
419 return notebook_type;
423 add_tab_bindings (GtkBindingSet *binding_set,
424 GdkModifierType modifiers,
425 GtkDirectionType direction)
427 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
429 GTK_TYPE_DIRECTION_TYPE, direction);
430 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
432 GTK_TYPE_DIRECTION_TYPE, direction);
436 add_arrow_bindings (GtkBindingSet *binding_set,
438 GtkDirectionType direction)
440 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
442 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
444 GTK_TYPE_DIRECTION_TYPE, direction);
445 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
447 GTK_TYPE_DIRECTION_TYPE, direction);
451 add_reorder_bindings (GtkBindingSet *binding_set,
453 GtkDirectionType direction,
454 gboolean move_to_last)
456 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
458 gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
460 GTK_TYPE_DIRECTION_TYPE, direction,
461 G_TYPE_BOOLEAN, move_to_last);
462 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
464 GTK_TYPE_DIRECTION_TYPE, direction,
465 G_TYPE_BOOLEAN, move_to_last);
469 gtk_notebook_class_init (GtkNotebookClass *class)
471 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
472 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
473 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
474 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
475 GtkBindingSet *binding_set;
477 parent_class = g_type_class_peek_parent (class);
479 gobject_class->set_property = gtk_notebook_set_property;
480 gobject_class->get_property = gtk_notebook_get_property;
481 object_class->destroy = gtk_notebook_destroy;
483 widget_class->map = gtk_notebook_map;
484 widget_class->unmap = gtk_notebook_unmap;
485 widget_class->realize = gtk_notebook_realize;
486 widget_class->unrealize = gtk_notebook_unrealize;
487 widget_class->size_request = gtk_notebook_size_request;
488 widget_class->size_allocate = gtk_notebook_size_allocate;
489 widget_class->expose_event = gtk_notebook_expose;
490 widget_class->scroll_event = gtk_notebook_scroll;
491 widget_class->button_press_event = gtk_notebook_button_press;
492 widget_class->button_release_event = gtk_notebook_button_release;
493 widget_class->popup_menu = gtk_notebook_popup_menu;
494 widget_class->enter_notify_event = gtk_notebook_enter_notify;
495 widget_class->leave_notify_event = gtk_notebook_leave_notify;
496 widget_class->motion_notify_event = gtk_notebook_motion_notify;
497 widget_class->grab_notify = gtk_notebook_grab_notify;
498 widget_class->state_changed = gtk_notebook_state_changed;
499 widget_class->focus_in_event = gtk_notebook_focus_in;
500 widget_class->focus_out_event = gtk_notebook_focus_out;
501 widget_class->focus = gtk_notebook_focus;
502 widget_class->style_set = gtk_notebook_style_set;
503 widget_class->drag_begin = gtk_notebook_drag_begin;
504 widget_class->drag_motion = gtk_notebook_drag_motion;
505 widget_class->drag_drop = gtk_notebook_drag_drop;
506 widget_class->drag_data_get = gtk_notebook_drag_data_get;
507 widget_class->drag_data_received = gtk_notebook_drag_data_received;
509 container_class->add = gtk_notebook_add;
510 container_class->remove = gtk_notebook_remove;
511 container_class->forall = gtk_notebook_forall;
512 container_class->set_focus_child = gtk_notebook_set_focus_child;
513 container_class->get_child_property = gtk_notebook_get_child_property;
514 container_class->set_child_property = gtk_notebook_set_child_property;
515 container_class->child_type = gtk_notebook_child_type;
517 class->switch_page = gtk_notebook_real_switch_page;
518 class->insert_page = gtk_notebook_real_insert_page;
520 class->focus_tab = gtk_notebook_focus_tab;
521 class->select_page = gtk_notebook_select_page;
522 class->change_current_page = gtk_notebook_change_current_page;
523 class->move_focus_out = gtk_notebook_move_focus_out;
524 class->reorder_tab = gtk_notebook_reorder_tab;
526 g_object_class_install_property (gobject_class,
528 g_param_spec_int ("page",
530 P_("The index of the current page"),
534 GTK_PARAM_READWRITE));
535 g_object_class_install_property (gobject_class,
537 g_param_spec_enum ("tab-pos",
539 P_("Which side of the notebook holds the tabs"),
540 GTK_TYPE_POSITION_TYPE,
542 GTK_PARAM_READWRITE));
543 g_object_class_install_property (gobject_class,
545 g_param_spec_uint ("tab-border",
547 P_("Width of the border around the tab labels"),
551 GTK_PARAM_WRITABLE));
552 g_object_class_install_property (gobject_class,
554 g_param_spec_uint ("tab-hborder",
555 P_("Horizontal Tab Border"),
556 P_("Width of the horizontal border of tab labels"),
560 GTK_PARAM_READWRITE));
561 g_object_class_install_property (gobject_class,
563 g_param_spec_uint ("tab-vborder",
564 P_("Vertical Tab Border"),
565 P_("Width of the vertical border of tab labels"),
569 GTK_PARAM_READWRITE));
570 g_object_class_install_property (gobject_class,
572 g_param_spec_boolean ("show-tabs",
574 P_("Whether tabs should be shown or not"),
576 GTK_PARAM_READWRITE));
577 g_object_class_install_property (gobject_class,
579 g_param_spec_boolean ("show-border",
581 P_("Whether the border should be shown or not"),
583 GTK_PARAM_READWRITE));
584 g_object_class_install_property (gobject_class,
586 g_param_spec_boolean ("scrollable",
588 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
590 GTK_PARAM_READWRITE));
591 g_object_class_install_property (gobject_class,
593 g_param_spec_boolean ("enable-popup",
595 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
597 GTK_PARAM_READWRITE));
598 g_object_class_install_property (gobject_class,
600 g_param_spec_boolean ("homogeneous",
602 P_("Whether tabs should have homogeneous sizes"),
604 GTK_PARAM_READWRITE));
605 g_object_class_install_property (gobject_class,
607 g_param_spec_int ("group-id",
609 P_("Group ID for tabs drag and drop"),
613 GTK_PARAM_READWRITE));
615 gtk_container_class_install_child_property (container_class,
616 CHILD_PROP_TAB_LABEL,
617 g_param_spec_string ("tab-label",
619 P_("The string displayed on the child's tab label"),
621 GTK_PARAM_READWRITE));
622 gtk_container_class_install_child_property (container_class,
623 CHILD_PROP_MENU_LABEL,
624 g_param_spec_string ("menu-label",
626 P_("The string displayed in the child's menu entry"),
628 GTK_PARAM_READWRITE));
629 gtk_container_class_install_child_property (container_class,
631 g_param_spec_int ("position",
633 P_("The index of the child in the parent"),
635 GTK_PARAM_READWRITE));
636 gtk_container_class_install_child_property (container_class,
637 CHILD_PROP_TAB_EXPAND,
638 g_param_spec_boolean ("tab-expand",
640 P_("Whether to expand the child's tab or not"),
642 GTK_PARAM_READWRITE));
643 gtk_container_class_install_child_property (container_class,
645 g_param_spec_boolean ("tab-fill",
647 P_("Whether the child's tab should fill the allocated area or not"),
649 GTK_PARAM_READWRITE));
650 gtk_container_class_install_child_property (container_class,
652 g_param_spec_enum ("tab-pack",
654 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
655 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
656 GTK_PARAM_READWRITE));
657 gtk_container_class_install_child_property (container_class,
658 CHILD_PROP_REORDERABLE,
659 g_param_spec_boolean ("reorderable",
660 P_("Tab reorderable"),
661 P_("Whether the tab is reorderable by user action or not"),
663 GTK_PARAM_READWRITE));
664 gtk_container_class_install_child_property (container_class,
665 CHILD_PROP_DETACHABLE,
666 g_param_spec_boolean ("detachable",
667 P_("Tab detachable"),
668 P_("Whether the tab is detachable"),
670 GTK_PARAM_READWRITE));
673 * GtkNotebook:has-secondary-backward-stepper:
675 * The "has-secondary-backward-stepper" property determines whether
676 * a second backward arrow button is displayed on the opposite end
681 gtk_widget_class_install_style_property (widget_class,
682 g_param_spec_boolean ("has-secondary-backward-stepper",
683 P_("Secondary backward stepper"),
684 P_("Display a second backward arrow button on the opposite end of the tab area"),
686 GTK_PARAM_READABLE));
689 * GtkNotebook:has-secondary-forward-stepper:
691 * The "has-secondary-forward-stepper" property determines whether
692 * a second forward arrow button is displayed on the opposite end
697 gtk_widget_class_install_style_property (widget_class,
698 g_param_spec_boolean ("has-secondary-forward-stepper",
699 P_("Secondary forward stepper"),
700 P_("Display a second forward arrow button on the opposite end of the tab area"),
702 GTK_PARAM_READABLE));
705 * GtkNotebook:has-backward-stepper:
707 * The "has-backward-stepper" property determines whether
708 * the standard backward arrow button is displayed.
712 gtk_widget_class_install_style_property (widget_class,
713 g_param_spec_boolean ("has-backward-stepper",
714 P_("Backward stepper"),
715 P_("Display the standard backward arrow button"),
717 GTK_PARAM_READABLE));
720 * GtkNotebook:has-forward-stepper:
722 * The "has-forward-stepper" property determines whether
723 * the standard forward arrow button is displayed.
727 gtk_widget_class_install_style_property (widget_class,
728 g_param_spec_boolean ("has-forward-stepper",
729 P_("Forward stepper"),
730 P_("Display the standard forward arrow button"),
732 GTK_PARAM_READABLE));
735 * GtkNotebook:tab-overlap:
737 * The "tab-overlap" property defines size of tab overlap
742 gtk_widget_class_install_style_property (widget_class,
743 g_param_spec_int ("tab-overlap",
745 P_("Size of tab overlap area"),
749 GTK_PARAM_READABLE));
752 * GtkNotebook:tab-curvature:
754 * The "tab-curvature" property defines size of tab curvature.
758 gtk_widget_class_install_style_property (widget_class,
759 g_param_spec_int ("tab-curvature",
761 P_("Size of tab curvature"),
765 GTK_PARAM_READABLE));
767 notebook_signals[SWITCH_PAGE] =
768 g_signal_new (I_("switch_page"),
769 G_TYPE_FROM_CLASS (gobject_class),
771 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
773 _gtk_marshal_VOID__POINTER_UINT,
777 notebook_signals[FOCUS_TAB] =
778 g_signal_new (I_("focus_tab"),
779 G_TYPE_FROM_CLASS (gobject_class),
780 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
781 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
783 _gtk_marshal_BOOLEAN__ENUM,
785 GTK_TYPE_NOTEBOOK_TAB);
786 notebook_signals[SELECT_PAGE] =
787 g_signal_new (I_("select_page"),
788 G_TYPE_FROM_CLASS (gobject_class),
789 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
790 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
792 _gtk_marshal_BOOLEAN__BOOLEAN,
795 notebook_signals[CHANGE_CURRENT_PAGE] =
796 g_signal_new (I_("change_current_page"),
797 G_TYPE_FROM_CLASS (gobject_class),
798 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
799 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
801 _gtk_marshal_VOID__INT,
804 notebook_signals[MOVE_FOCUS_OUT] =
805 g_signal_new (I_("move_focus_out"),
806 G_TYPE_FROM_CLASS (gobject_class),
807 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
808 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
810 _gtk_marshal_VOID__ENUM,
812 GTK_TYPE_DIRECTION_TYPE);
813 notebook_signals[REORDER_TAB] =
814 g_signal_new (I_("reorder_tab"),
815 G_TYPE_FROM_CLASS (gobject_class),
816 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
817 G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
819 _gtk_marshal_VOID__ENUM_BOOLEAN,
821 GTK_TYPE_DIRECTION_TYPE,
824 * GtkNotebook::page-reordered:
825 * @notebook: the #GtkNotebook
826 * @child: the child #GtkWidget affected
827 * @page_num: the new page number for @child
829 * the ::page-reordered signal is emitted in the notebook
830 * right after a page has been reordered.
834 notebook_signals[PAGE_REORDERED] =
835 g_signal_new (I_("page_reordered"),
836 G_TYPE_FROM_CLASS (gobject_class),
839 _gtk_marshal_VOID__OBJECT_UINT,
844 * GtkNotebook::page-removed:
845 * @notebook: the #GtkNotebook
846 * @child: the child #GtkWidget affected
847 * @page_num: the @child page number
849 * the ::page-removed signal is emitted in the notebook
850 * right before a page is removed from the notebook.
854 notebook_signals[PAGE_REMOVED] =
855 g_signal_new (I_("page_removed"),
856 G_TYPE_FROM_CLASS (gobject_class),
859 _gtk_marshal_VOID__OBJECT_UINT,
864 * GtkNotebook::page-attached:
865 * @notebook: the #GtkNotebook
866 * @child: the child #GtkWidget affected
867 * @page_num: the new page number for @child
869 * the ::page-added signal is emitted in the notebook
870 * right after a page is added to the notebook.
874 notebook_signals[PAGE_ADDED] =
875 g_signal_new (I_("page_added"),
876 G_TYPE_FROM_CLASS (gobject_class),
879 _gtk_marshal_VOID__OBJECT_UINT,
884 binding_set = gtk_binding_set_by_class (class);
885 gtk_binding_entry_add_signal (binding_set,
888 G_TYPE_BOOLEAN, FALSE);
889 gtk_binding_entry_add_signal (binding_set,
892 G_TYPE_BOOLEAN, FALSE);
894 gtk_binding_entry_add_signal (binding_set,
897 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
898 gtk_binding_entry_add_signal (binding_set,
901 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
902 gtk_binding_entry_add_signal (binding_set,
905 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
906 gtk_binding_entry_add_signal (binding_set,
909 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
911 gtk_binding_entry_add_signal (binding_set,
912 GDK_Page_Up, GDK_CONTROL_MASK,
913 "change_current_page", 1,
915 gtk_binding_entry_add_signal (binding_set,
916 GDK_Page_Down, GDK_CONTROL_MASK,
917 "change_current_page", 1,
920 gtk_binding_entry_add_signal (binding_set,
921 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
922 "change_current_page", 1,
924 gtk_binding_entry_add_signal (binding_set,
925 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
926 "change_current_page", 1,
929 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
930 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
931 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
932 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
934 add_reorder_bindings (binding_set, GDK_Up, GTK_DIR_UP, FALSE);
935 add_reorder_bindings (binding_set, GDK_Down, GTK_DIR_DOWN, FALSE);
936 add_reorder_bindings (binding_set, GDK_Left, GTK_DIR_LEFT, FALSE);
937 add_reorder_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT, FALSE);
938 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_LEFT, TRUE);
939 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_UP, TRUE);
940 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_RIGHT, TRUE);
941 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_DOWN, TRUE);
943 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
944 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
946 g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
950 gtk_notebook_init (GtkNotebook *notebook)
952 GtkNotebookPrivate *priv;
954 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
955 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
957 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
959 notebook->cur_page = NULL;
960 notebook->children = NULL;
961 notebook->first_tab = NULL;
962 notebook->focus_tab = NULL;
963 notebook->event_window = NULL;
964 notebook->menu = NULL;
966 notebook->tab_hborder = 2;
967 notebook->tab_vborder = 2;
969 notebook->show_tabs = TRUE;
970 notebook->show_border = TRUE;
971 notebook->tab_pos = GTK_POS_TOP;
972 notebook->scrollable = FALSE;
973 notebook->in_child = 0;
974 notebook->click_child = 0;
975 notebook->button = 0;
976 notebook->need_timer = 0;
977 notebook->child_has_focus = FALSE;
978 notebook->have_visible_child = FALSE;
979 notebook->focus_out = FALSE;
981 notebook->has_before_previous = 1;
982 notebook->has_before_next = 0;
983 notebook->has_after_previous = 0;
984 notebook->has_after_next = 1;
987 priv->pressed_button = -1;
989 priv->source_targets = gtk_target_list_new (notebook_targets,
990 G_N_ELEMENTS (notebook_targets));
992 gtk_drag_dest_set (GTK_WIDGET (notebook),
993 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
994 notebook_targets, G_N_ELEMENTS (notebook_targets),
999 gtk_notebook_select_page (GtkNotebook *notebook,
1000 gboolean move_focus)
1002 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1004 gtk_notebook_page_select (notebook, move_focus);
1012 gtk_notebook_focus_tab (GtkNotebook *notebook,
1013 GtkNotebookTab type)
1017 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1021 case GTK_NOTEBOOK_TAB_FIRST:
1022 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1024 gtk_notebook_switch_focus_tab (notebook, list);
1026 case GTK_NOTEBOOK_TAB_LAST:
1027 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
1029 gtk_notebook_switch_focus_tab (notebook, list);
1040 gtk_notebook_change_current_page (GtkNotebook *notebook,
1043 GList *current = NULL;
1045 if (notebook->cur_page)
1046 current = g_list_find (notebook->children, notebook->cur_page);
1050 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
1051 offset += offset < 0 ? 1 : -1;
1055 gtk_notebook_switch_page (notebook, current->data, -1);
1057 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1060 static GtkDirectionType
1061 get_effective_direction (GtkNotebook *notebook,
1062 GtkDirectionType direction)
1064 /* Remap the directions into the effective direction it would be for a
1065 * GTK_POS_TOP notebook
1068 #define D(rest) GTK_DIR_##rest
1070 static const GtkDirectionType translate_direction[2][4][6] = {
1071 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1072 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1073 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1074 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
1075 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1076 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1077 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
1078 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
1083 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
1085 return translate_direction[text_dir][notebook->tab_pos][direction];
1089 get_effective_tab_pos (GtkNotebook *notebook)
1091 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
1093 switch (notebook->tab_pos)
1096 return GTK_POS_RIGHT;
1098 return GTK_POS_LEFT;
1103 return notebook->tab_pos;
1107 gtk_notebook_move_focus_out (GtkNotebook *notebook,
1108 GtkDirectionType direction_type)
1110 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1111 GtkWidget *toplevel;
1113 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
1114 if (focus_tabs_in (notebook))
1116 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
1117 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
1120 /* At this point, we know we should be focusing out of the notebook entirely. We
1121 * do this by setting a flag, then propagating the focus motion to the notebook.
1123 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
1124 if (!GTK_WIDGET_TOPLEVEL (toplevel))
1127 g_object_ref (notebook);
1129 notebook->focus_out = TRUE;
1130 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
1131 notebook->focus_out = FALSE;
1133 g_object_unref (notebook);
1137 reorder_tab (GtkNotebook *notebook, GList *position, GList *tab)
1141 /* check that we aren't inserting the tab in the
1142 * same relative position, taking packing into account */
1143 elem = (position) ? position->prev : g_list_last (notebook->children);
1145 while (elem && GTK_NOTEBOOK_PAGE (elem)->pack != GTK_NOTEBOOK_PAGE (tab)->pack)
1149 return g_list_position (notebook->children, tab);
1151 /* now actually reorder the tab */
1152 if (notebook->first_tab == tab)
1153 notebook->first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
1156 notebook->children = g_list_remove_link (notebook->children, tab);
1159 elem = g_list_last (notebook->children);
1162 elem = position->prev;
1163 position->prev = tab;
1169 notebook->children = tab;
1172 tab->next = position;
1174 return g_list_position (notebook->children, tab);
1178 gtk_notebook_reorder_tab (GtkNotebook *notebook,
1179 GtkDirectionType direction_type,
1180 gboolean move_to_last)
1182 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1183 GtkNotebookPage *page;
1184 GList *last, *child;
1187 if (!notebook->cur_page ||
1188 !notebook->cur_page->reorderable)
1191 if (effective_direction != GTK_DIR_LEFT &&
1192 effective_direction != GTK_DIR_RIGHT)
1197 child = notebook->focus_tab;
1202 child = gtk_notebook_search_page (notebook, last,
1203 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1206 while (child && GTK_NOTEBOOK_PAGE (last)->pack == GTK_NOTEBOOK_PAGE (child)->pack);
1211 child = gtk_notebook_search_page (notebook, notebook->focus_tab,
1212 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1215 if (!child || child->data == notebook->cur_page)
1220 if (page->pack == notebook->cur_page->pack)
1222 if (effective_direction == GTK_DIR_RIGHT)
1223 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child->next : child, notebook->focus_tab);
1225 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child : child->next, notebook->focus_tab);
1227 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1229 g_signal_emit (notebook,
1230 notebook_signals[PAGE_REORDERED],
1232 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
1240 * Creates a new #GtkNotebook widget with no pages.
1242 * Return value: the newly created #GtkNotebook
1245 gtk_notebook_new (void)
1247 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
1250 /* Private GtkObject Methods :
1252 * gtk_notebook_destroy
1253 * gtk_notebook_set_arg
1254 * gtk_notebook_get_arg
1257 gtk_notebook_destroy (GtkObject *object)
1259 GtkNotebook *notebook = GTK_NOTEBOOK (object);
1260 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1263 gtk_notebook_popup_disable (notebook);
1265 if (priv->source_targets)
1267 gtk_target_list_unref (priv->source_targets);
1268 priv->source_targets = NULL;
1271 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1275 gtk_notebook_set_property (GObject *object,
1277 const GValue *value,
1280 GtkNotebook *notebook;
1282 notebook = GTK_NOTEBOOK (object);
1286 case PROP_SHOW_TABS:
1287 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
1289 case PROP_SHOW_BORDER:
1290 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
1292 case PROP_SCROLLABLE:
1293 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
1295 case PROP_ENABLE_POPUP:
1296 if (g_value_get_boolean (value))
1297 gtk_notebook_popup_enable (notebook);
1299 gtk_notebook_popup_disable (notebook);
1301 case PROP_HOMOGENEOUS:
1302 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
1305 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
1308 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
1310 case PROP_TAB_BORDER:
1311 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
1313 case PROP_TAB_HBORDER:
1314 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
1316 case PROP_TAB_VBORDER:
1317 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
1320 gtk_notebook_set_group_id (notebook, g_value_get_int (value));
1328 gtk_notebook_get_property (GObject *object,
1333 GtkNotebook *notebook;
1334 GtkNotebookPrivate *priv;
1336 notebook = GTK_NOTEBOOK (object);
1337 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1341 case PROP_SHOW_TABS:
1342 g_value_set_boolean (value, notebook->show_tabs);
1344 case PROP_SHOW_BORDER:
1345 g_value_set_boolean (value, notebook->show_border);
1347 case PROP_SCROLLABLE:
1348 g_value_set_boolean (value, notebook->scrollable);
1350 case PROP_ENABLE_POPUP:
1351 g_value_set_boolean (value, notebook->menu != NULL);
1353 case PROP_HOMOGENEOUS:
1354 g_value_set_boolean (value, notebook->homogeneous);
1357 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
1360 g_value_set_enum (value, notebook->tab_pos);
1362 case PROP_TAB_HBORDER:
1363 g_value_set_uint (value, notebook->tab_hborder);
1365 case PROP_TAB_VBORDER:
1366 g_value_set_uint (value, notebook->tab_vborder);
1369 g_value_set_int (value, priv->group_id);
1372 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1377 /* Private GtkWidget Methods :
1380 * gtk_notebook_unmap
1381 * gtk_notebook_realize
1382 * gtk_notebook_size_request
1383 * gtk_notebook_size_allocate
1384 * gtk_notebook_expose
1385 * gtk_notebook_scroll
1386 * gtk_notebook_button_press
1387 * gtk_notebook_button_release
1388 * gtk_notebook_popup_menu
1389 * gtk_notebook_enter_notify
1390 * gtk_notebook_leave_notify
1391 * gtk_notebook_motion_notify
1392 * gtk_notebook_focus_in
1393 * gtk_notebook_focus_out
1394 * gtk_notebook_draw_focus
1395 * gtk_notebook_style_set
1396 * gtk_notebook_drag_begin
1397 * gtk_notebook_drag_motion
1398 * gtk_notebook_drag_drop
1399 * gtk_notebook_drag_data_get
1400 * gtk_notebook_drag_data_received
1403 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1404 GdkRectangle *rectangle)
1406 GtkWidget *widget = GTK_WIDGET (notebook);
1407 gint border_width = GTK_CONTAINER (notebook)->border_width;
1408 GtkNotebookPage *visible_page = NULL;
1410 gint tab_pos = get_effective_tab_pos (notebook);
1412 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1414 GtkNotebookPage *page = tmp_list->data;
1415 if (GTK_WIDGET_VISIBLE (page->child))
1417 visible_page = page;
1422 if (notebook->show_tabs && visible_page)
1426 rectangle->x = widget->allocation.x + border_width;
1427 rectangle->y = widget->allocation.y + border_width;
1432 case GTK_POS_BOTTOM:
1433 rectangle->width = widget->allocation.width - 2 * border_width;
1434 rectangle->height = visible_page->requisition.height;
1435 if (tab_pos == GTK_POS_BOTTOM)
1436 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1440 rectangle->width = visible_page->requisition.width;
1441 rectangle->height = widget->allocation.height - 2 * border_width;
1442 if (tab_pos == GTK_POS_RIGHT)
1443 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1454 rectangle->x = rectangle->y = 0;
1455 rectangle->width = rectangle->height = 10;
1463 gtk_notebook_map (GtkWidget *widget)
1465 GtkNotebook *notebook;
1466 GtkNotebookPage *page;
1469 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1471 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1473 notebook = GTK_NOTEBOOK (widget);
1475 if (notebook->cur_page &&
1476 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1477 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1478 gtk_widget_map (notebook->cur_page->child);
1480 if (notebook->scrollable)
1481 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1484 children = notebook->children;
1488 page = children->data;
1489 children = children->next;
1491 if (page->tab_label &&
1492 GTK_WIDGET_VISIBLE (page->tab_label) &&
1493 !GTK_WIDGET_MAPPED (page->tab_label))
1494 gtk_widget_map (page->tab_label);
1498 if (gtk_notebook_get_event_window_position (notebook, NULL))
1499 gdk_window_show_unraised (notebook->event_window);
1503 gtk_notebook_unmap (GtkWidget *widget)
1505 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1507 stop_scrolling (GTK_NOTEBOOK (widget));
1509 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1511 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1513 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1517 gtk_notebook_realize (GtkWidget *widget)
1519 GtkNotebook *notebook;
1520 GdkWindowAttr attributes;
1521 gint attributes_mask;
1522 GdkRectangle event_window_pos;
1524 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1526 notebook = GTK_NOTEBOOK (widget);
1527 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1529 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1531 widget->window = gtk_widget_get_parent_window (widget);
1532 g_object_ref (widget->window);
1534 attributes.window_type = GDK_WINDOW_CHILD;
1535 attributes.x = event_window_pos.x;
1536 attributes.y = event_window_pos.y;
1537 attributes.width = event_window_pos.width;
1538 attributes.height = event_window_pos.height;
1539 attributes.wclass = GDK_INPUT_ONLY;
1540 attributes.event_mask = gtk_widget_get_events (widget);
1541 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1542 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1543 GDK_BUTTON1_MOTION_MASK |
1545 attributes_mask = GDK_WA_X | GDK_WA_Y;
1547 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1548 &attributes, attributes_mask);
1549 gdk_window_set_user_data (notebook->event_window, notebook);
1551 widget->style = gtk_style_attach (widget->style, widget->window);
1555 gtk_notebook_unrealize (GtkWidget *widget)
1557 GtkNotebook *notebook;
1559 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1561 notebook = GTK_NOTEBOOK (widget);
1563 gdk_window_set_user_data (notebook->event_window, NULL);
1564 gdk_window_destroy (notebook->event_window);
1565 notebook->event_window = NULL;
1567 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1568 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1572 gtk_notebook_size_request (GtkWidget *widget,
1573 GtkRequisition *requisition)
1575 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1576 GtkNotebookPage *page;
1578 GtkRequisition child_requisition;
1579 gboolean switch_page = FALSE;
1585 gtk_widget_style_get (widget,
1586 "focus-line-width", &focus_width,
1587 "tab-overlap", &tab_overlap,
1588 "tab-curvature", &tab_curvature,
1591 widget->requisition.width = 0;
1592 widget->requisition.height = 0;
1594 for (children = notebook->children, vis_pages = 0; children;
1595 children = children->next)
1597 page = children->data;
1599 if (GTK_WIDGET_VISIBLE (page->child))
1602 gtk_widget_size_request (page->child, &child_requisition);
1604 widget->requisition.width = MAX (widget->requisition.width,
1605 child_requisition.width);
1606 widget->requisition.height = MAX (widget->requisition.height,
1607 child_requisition.height);
1609 if (notebook->menu && page->menu_label->parent &&
1610 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1611 gtk_widget_show (page->menu_label->parent);
1615 if (page == notebook->cur_page)
1617 if (notebook->menu && page->menu_label->parent &&
1618 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1619 gtk_widget_hide (page->menu_label->parent);
1623 if (notebook->show_border || notebook->show_tabs)
1625 widget->requisition.width += widget->style->xthickness * 2;
1626 widget->requisition.height += widget->style->ythickness * 2;
1628 if (notebook->show_tabs)
1631 gint tab_height = 0;
1635 for (children = notebook->children; children;
1636 children = children->next)
1638 page = children->data;
1640 if (GTK_WIDGET_VISIBLE (page->child))
1642 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1643 gtk_widget_show (page->tab_label);
1645 gtk_widget_size_request (page->tab_label,
1646 &child_requisition);
1648 page->requisition.width =
1649 child_requisition.width +
1650 2 * widget->style->xthickness;
1651 page->requisition.height =
1652 child_requisition.height +
1653 2 * widget->style->ythickness;
1655 switch (notebook->tab_pos)
1658 case GTK_POS_BOTTOM:
1659 page->requisition.height += 2 * (notebook->tab_vborder +
1661 tab_height = MAX (tab_height, page->requisition.height);
1662 tab_max = MAX (tab_max, page->requisition.width);
1666 page->requisition.width += 2 * (notebook->tab_hborder +
1668 tab_width = MAX (tab_width, page->requisition.width);
1669 tab_max = MAX (tab_max, page->requisition.height);
1673 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1674 gtk_widget_hide (page->tab_label);
1677 children = notebook->children;
1681 switch (notebook->tab_pos)
1684 case GTK_POS_BOTTOM:
1685 if (tab_height == 0)
1688 if (notebook->scrollable && vis_pages > 1 &&
1689 widget->requisition.width < tab_width)
1690 tab_height = MAX (tab_height, ARROW_SIZE);
1692 padding = 2 * (tab_curvature + focus_width +
1693 notebook->tab_hborder) - tab_overlap;
1697 page = children->data;
1698 children = children->next;
1700 if (!GTK_WIDGET_VISIBLE (page->child))
1703 if (notebook->homogeneous)
1704 page->requisition.width = tab_max;
1706 page->requisition.width += padding;
1708 tab_width += page->requisition.width;
1709 page->requisition.height = tab_height;
1712 if (notebook->scrollable && vis_pages > 1 &&
1713 widget->requisition.width < tab_width)
1714 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1716 if (notebook->homogeneous && !notebook->scrollable)
1717 widget->requisition.width = MAX (widget->requisition.width,
1718 vis_pages * tab_max +
1721 widget->requisition.width = MAX (widget->requisition.width,
1722 tab_width + tab_overlap);
1724 widget->requisition.height += tab_height;
1731 if (notebook->scrollable && vis_pages > 1 &&
1732 widget->requisition.height < tab_height)
1733 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1735 padding = 2 * (tab_curvature + focus_width +
1736 notebook->tab_vborder) - tab_overlap;
1741 page = children->data;
1742 children = children->next;
1744 if (!GTK_WIDGET_VISIBLE (page->child))
1747 page->requisition.width = tab_width;
1749 if (notebook->homogeneous)
1750 page->requisition.height = tab_max;
1752 page->requisition.height += padding;
1754 tab_height += page->requisition.height;
1757 if (notebook->scrollable && vis_pages > 1 &&
1758 widget->requisition.height < tab_height)
1759 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1761 widget->requisition.width += tab_width;
1763 if (notebook->homogeneous && !notebook->scrollable)
1764 widget->requisition.height =
1765 MAX (widget->requisition.height,
1766 vis_pages * tab_max + tab_overlap);
1768 widget->requisition.height =
1769 MAX (widget->requisition.height,
1770 tab_height + tab_overlap);
1772 if (!notebook->homogeneous || notebook->scrollable)
1774 widget->requisition.height = MAX (widget->requisition.height,
1775 vis_pages * tab_max +
1783 for (children = notebook->children; children;
1784 children = children->next)
1786 page = children->data;
1788 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1789 gtk_widget_hide (page->tab_label);
1794 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1795 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1801 for (children = notebook->children; children;
1802 children = children->next)
1804 page = children->data;
1805 if (GTK_WIDGET_VISIBLE (page->child))
1807 gtk_notebook_switch_page (notebook, page, -1);
1812 else if (GTK_WIDGET_VISIBLE (widget))
1814 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1815 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1818 if (vis_pages && !notebook->cur_page)
1820 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1823 notebook->first_tab = children;
1824 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1830 gtk_notebook_size_allocate (GtkWidget *widget,
1831 GtkAllocation *allocation)
1833 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1835 gint tab_pos = get_effective_tab_pos (notebook);
1837 widget->allocation = *allocation;
1838 if (GTK_WIDGET_REALIZED (widget))
1840 GdkRectangle position;
1842 if (gtk_notebook_get_event_window_position (notebook, &position))
1844 gdk_window_move_resize (notebook->event_window,
1845 position.x, position.y,
1846 position.width, position.height);
1847 if (GTK_WIDGET_MAPPED (notebook))
1848 gdk_window_show_unraised (notebook->event_window);
1851 gdk_window_hide (notebook->event_window);
1854 if (notebook->children)
1856 gint border_width = GTK_CONTAINER (widget)->border_width;
1857 GtkNotebookPage *page;
1858 GtkAllocation child_allocation;
1861 child_allocation.x = widget->allocation.x + border_width;
1862 child_allocation.y = widget->allocation.y + border_width;
1863 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1864 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1866 if (notebook->show_tabs || notebook->show_border)
1868 child_allocation.x += widget->style->xthickness;
1869 child_allocation.y += widget->style->ythickness;
1870 child_allocation.width = MAX (1, child_allocation.width -
1871 widget->style->xthickness * 2);
1872 child_allocation.height = MAX (1, child_allocation.height -
1873 widget->style->ythickness * 2);
1875 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1880 child_allocation.y += notebook->cur_page->requisition.height;
1881 case GTK_POS_BOTTOM:
1882 child_allocation.height =
1883 MAX (1, child_allocation.height -
1884 notebook->cur_page->requisition.height);
1887 child_allocation.x += notebook->cur_page->requisition.width;
1889 child_allocation.width =
1890 MAX (1, child_allocation.width -
1891 notebook->cur_page->requisition.width);
1897 children = notebook->children;
1900 page = children->data;
1901 children = children->next;
1903 if (GTK_WIDGET_VISIBLE (page->child))
1905 gtk_widget_size_allocate (page->child, &child_allocation);
1910 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1915 gtk_notebook_expose (GtkWidget *widget,
1916 GdkEventExpose *event)
1918 GtkNotebook *notebook;
1919 GdkRectangle child_area;
1921 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1922 g_return_val_if_fail (event != NULL, FALSE);
1924 if (GTK_WIDGET_DRAWABLE (widget))
1926 notebook = GTK_NOTEBOOK (widget);
1928 gtk_notebook_paint (widget, &event->area);
1929 if (notebook->show_tabs)
1931 if (notebook->cur_page &&
1932 gtk_widget_intersect (notebook->cur_page->tab_label,
1933 &event->area, &child_area))
1934 gtk_notebook_draw_focus (widget);
1938 if (notebook->cur_page)
1939 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1940 notebook->cur_page->child,
1948 gtk_notebook_show_arrows (GtkNotebook *notebook)
1950 gboolean show_arrow = FALSE;
1953 if (!notebook->scrollable)
1956 children = notebook->children;
1959 GtkNotebookPage *page = children->data;
1961 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1964 children = children->next;
1971 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1972 GdkRectangle *rectangle,
1973 GtkNotebookArrow arrow)
1975 GdkRectangle event_window_pos;
1976 gboolean before = ARROW_IS_BEFORE (arrow);
1977 gboolean left = ARROW_IS_LEFT (arrow);
1979 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1981 rectangle->width = ARROW_SIZE;
1982 rectangle->height = ARROW_SIZE;
1984 switch (notebook->tab_pos)
1988 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1989 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1990 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1992 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1994 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1995 rectangle->y = event_window_pos.y;
1997 rectangle->y += event_window_pos.height - rectangle->height;
2000 case GTK_POS_BOTTOM:
2003 if (left || !notebook->has_before_previous)
2004 rectangle->x = event_window_pos.x;
2006 rectangle->x = event_window_pos.x + rectangle->width;
2010 if (!left || !notebook->has_after_next)
2011 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
2013 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
2015 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
2021 static GtkNotebookArrow
2022 gtk_notebook_get_arrow (GtkNotebook *notebook,
2026 GdkRectangle arrow_rect;
2027 GdkRectangle event_window_pos;
2030 GtkNotebookArrow arrow[4];
2032 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2033 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2034 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2035 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2037 if (gtk_notebook_show_arrows (notebook))
2039 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
2040 for (i = 0; i < 4; i++)
2042 if (arrow[i] == ARROW_NONE)
2045 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
2047 x0 = x - arrow_rect.x;
2048 y0 = y - arrow_rect.y;
2050 if (y0 >= 0 && y0 < arrow_rect.height &&
2051 x0 >= 0 && x0 < arrow_rect.width)
2060 gtk_notebook_do_arrow (GtkNotebook *notebook,
2061 GtkNotebookArrow arrow)
2063 GtkWidget *widget = GTK_WIDGET (notebook);
2064 GtkDirectionType dir;
2065 gboolean is_rtl, left;
2067 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2068 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2069 (!ARROW_IS_LEFT (arrow) && is_rtl);
2071 if (!notebook->focus_tab ||
2072 gtk_notebook_search_page (notebook, notebook->focus_tab,
2073 left ? STEP_PREV : STEP_NEXT,
2076 if (notebook->tab_pos == GTK_POS_LEFT ||
2077 notebook->tab_pos == GTK_POS_RIGHT)
2078 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
2080 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
2081 gtk_widget_child_focus (widget, dir);
2086 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
2087 GtkNotebookArrow arrow,
2088 GdkEventButton *event)
2090 GtkWidget *widget = GTK_WIDGET (notebook);
2091 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2092 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2093 (!ARROW_IS_LEFT (arrow) && is_rtl);
2095 if (!GTK_WIDGET_HAS_FOCUS (widget))
2096 gtk_widget_grab_focus (widget);
2098 notebook->button = event->button;
2099 notebook->click_child = arrow;
2101 if (event->button == 1)
2103 gtk_notebook_do_arrow (notebook, arrow);
2105 if (!notebook->timer)
2107 GtkSettings *settings = gtk_widget_get_settings (widget);
2110 g_object_get (settings, "gtk-timeout-initial", &timeout, NULL);
2112 notebook->timer = g_timeout_add (timeout,
2113 (GSourceFunc) gtk_notebook_timer,
2114 (gpointer) notebook);
2115 notebook->need_timer = TRUE;
2118 else if (event->button == 2)
2119 gtk_notebook_page_select (notebook, TRUE);
2120 else if (event->button == 3)
2121 gtk_notebook_switch_focus_tab (notebook,
2122 gtk_notebook_search_page (notebook,
2124 left ? STEP_NEXT : STEP_PREV,
2126 gtk_notebook_redraw_arrows (notebook);
2132 get_widget_coordinates (GtkWidget *widget,
2137 GdkWindow *window = ((GdkEventAny *)event)->window;
2140 if (!gdk_event_get_coords (event, &tx, &ty))
2143 while (window && window != widget->window)
2145 gint window_x, window_y;
2147 gdk_window_get_position (window, &window_x, &window_y);
2151 window = gdk_window_get_parent (window);
2166 gtk_notebook_scroll (GtkWidget *widget,
2167 GdkEventScroll *event)
2169 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2172 GtkWidget* originator;
2174 if (!notebook->cur_page)
2177 child = notebook->cur_page->child;
2178 originator = gtk_get_event_widget ((GdkEvent *)event);
2180 /* ignore scroll events from the content of the page */
2181 if (!originator || gtk_widget_is_ancestor (originator, child))
2184 switch (event->direction)
2186 case GDK_SCROLL_RIGHT:
2187 case GDK_SCROLL_DOWN:
2188 gtk_notebook_next_page (notebook);
2190 case GDK_SCROLL_LEFT:
2192 gtk_notebook_prev_page (notebook);
2200 gtk_notebook_button_press (GtkWidget *widget,
2201 GdkEventButton *event)
2203 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2204 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2205 GtkNotebookPage *page;
2207 GtkNotebookArrow arrow;
2211 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
2215 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2218 arrow = gtk_notebook_get_arrow (notebook, x, y);
2220 return gtk_notebook_arrow_button_press (notebook, arrow, event);
2222 if (event->button == 3 && notebook->menu)
2224 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2225 NULL, NULL, 3, event->time);
2229 if (event->button != 1)
2232 notebook->button = event->button;
2234 children = notebook->children;
2238 page = children->data;
2240 if (GTK_WIDGET_VISIBLE (page->child) &&
2241 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
2242 (x >= page->allocation.x) &&
2243 (y >= page->allocation.y) &&
2244 (x <= (page->allocation.x + page->allocation.width)) &&
2245 (y <= (page->allocation.y + page->allocation.height)))
2247 gboolean page_changed = page != notebook->cur_page;
2248 gboolean was_focus = gtk_widget_is_focus (widget);
2250 gtk_notebook_switch_focus_tab (notebook, children);
2251 gtk_widget_grab_focus (widget);
2253 if (page_changed && !was_focus)
2254 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
2256 /* save press to possibly begin a drag */
2257 if (page->reorderable || page->detachable)
2259 priv->during_detach = FALSE;
2260 priv->pressed_button = event->button;
2261 gtk_grab_add (widget);
2266 children = children->next;
2274 popup_position_func (GtkMenu *menu,
2280 GtkNotebook *notebook = data;
2282 GtkRequisition requisition;
2284 if (notebook->focus_tab)
2286 GtkNotebookPage *page;
2288 page = notebook->focus_tab->data;
2289 w = page->tab_label;
2293 w = GTK_WIDGET (notebook);
2296 gdk_window_get_origin (w->window, x, y);
2297 gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
2299 if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
2300 *x += w->allocation.x + w->allocation.width - requisition.width;
2302 *x += w->allocation.x;
2304 *y += w->allocation.y + w->allocation.height;
2310 gtk_notebook_popup_menu (GtkWidget *widget)
2312 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2316 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2317 popup_position_func, notebook,
2318 0, gtk_get_current_event_time ());
2319 gtk_menu_shell_select_first (GTK_MENU_SHELL (notebook->menu), FALSE);
2327 stop_scrolling (GtkNotebook *notebook)
2329 if (notebook->timer)
2331 g_source_remove (notebook->timer);
2332 notebook->timer = 0;
2333 notebook->need_timer = FALSE;
2335 notebook->click_child = 0;
2336 notebook->button = 0;
2337 gtk_notebook_redraw_arrows (notebook);
2341 get_drop_position (GtkNotebook *notebook,
2347 GtkNotebookPage *page;
2350 is_rtl = gtk_widget_get_direction ((GtkWidget *) notebook) == GTK_TEXT_DIR_RTL;
2351 children = notebook->children;
2355 page = children->data;
2357 if (GTK_WIDGET_VISIBLE (page->child) &&
2359 GTK_WIDGET_MAPPED (page->tab_label) &&
2362 switch (notebook->tab_pos)
2365 case GTK_POS_BOTTOM:
2368 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) > x) ||
2369 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) < x))
2374 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) < x) ||
2375 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) > x))
2382 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_Y (page) > y) ||
2383 (page->pack == GTK_PACK_END && PAGE_MIDDLE_Y (page) < y))
2390 children = children->next;
2397 gtk_notebook_button_release (GtkWidget *widget,
2398 GdkEventButton *event)
2400 GtkNotebook *notebook;
2401 GtkNotebookPrivate *priv;
2403 gint old_page_num, page_num;
2405 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2406 g_return_val_if_fail (event != NULL, FALSE);
2408 if (event->type != GDK_BUTTON_RELEASE)
2411 notebook = GTK_NOTEBOOK (widget);
2412 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2414 if (notebook->cur_page->reorderable &&
2415 event->button == priv->pressed_button)
2417 gtk_grab_remove (widget);
2418 priv->pressed_button = -1;
2420 if (!priv->during_detach)
2422 element = get_drop_position (notebook,
2423 notebook->cur_page->pack,
2424 PAGE_MIDDLE_X (notebook->cur_page),
2425 PAGE_MIDDLE_Y (notebook->cur_page));
2426 old_page_num = g_list_position (notebook->children, notebook->focus_tab);
2427 page_num = reorder_tab (notebook, element, notebook->focus_tab);
2429 if (priv->has_scrolled ||
2430 old_page_num != page_num)
2431 g_signal_emit (notebook,
2432 notebook_signals[PAGE_REORDERED], 0,
2433 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
2436 priv->has_scrolled = FALSE;
2439 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
2441 if (priv->dnd_timer)
2443 g_source_remove (priv->dnd_timer);
2444 priv->dnd_timer = 0;
2448 if (event->button == notebook->button)
2450 stop_scrolling (notebook);
2459 gtk_notebook_enter_notify (GtkWidget *widget,
2460 GdkEventCrossing *event)
2462 GtkNotebook *notebook;
2463 GtkNotebookArrow arrow;
2466 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2467 g_return_val_if_fail (event != NULL, FALSE);
2469 notebook = GTK_NOTEBOOK (widget);
2471 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2474 arrow = gtk_notebook_get_arrow (notebook, x, y);
2476 if (arrow != notebook->in_child)
2478 notebook->in_child = arrow;
2479 gtk_notebook_redraw_arrows (notebook);
2488 gtk_notebook_leave_notify (GtkWidget *widget,
2489 GdkEventCrossing *event)
2491 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2494 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2497 if (notebook->in_child)
2499 notebook->in_child = 0;
2500 gtk_notebook_redraw_arrows (notebook);
2506 static GtkNotebookPointerPosition
2507 get_pointer_position (GtkNotebook *notebook)
2509 GtkWidget *widget = (GtkWidget *) notebook;
2510 GtkContainer *container = (GtkContainer *) notebook;
2511 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2514 if (!notebook->scrollable)
2515 return POINTER_BETWEEN;
2517 if (notebook->tab_pos == GTK_POS_TOP ||
2518 notebook->tab_pos == GTK_POS_BOTTOM)
2520 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2522 if (priv->mouse_x > widget->allocation.width - 2 * container->border_width - SCROLL_THRESHOLD)
2523 return (is_rtl) ? POINTER_BEFORE : POINTER_AFTER;
2524 else if (priv->mouse_x < SCROLL_THRESHOLD + container->border_width)
2525 return (is_rtl) ? POINTER_AFTER : POINTER_BEFORE;
2527 return POINTER_BETWEEN;
2531 if (priv->mouse_y > widget->allocation.height - 2 * container->border_width - SCROLL_THRESHOLD)
2532 return POINTER_AFTER;
2533 else if (priv->mouse_y < SCROLL_THRESHOLD + container->border_width)
2534 return POINTER_BEFORE;
2536 return POINTER_BETWEEN;
2541 scroll_notebook_timer (gpointer data)
2543 GtkNotebook *notebook = (GtkNotebook *) data;
2544 GtkNotebookPrivate *priv;
2545 GtkNotebookPointerPosition pointer_position;
2546 GList *element, *first_tab;
2548 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2549 pointer_position = get_pointer_position (notebook);
2551 element = get_drop_position (notebook,
2552 notebook->cur_page->pack,
2553 PAGE_MIDDLE_X (notebook->cur_page),
2554 PAGE_MIDDLE_Y (notebook->cur_page));
2556 reorder_tab (notebook, element, notebook->focus_tab);
2558 first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
2559 (pointer_position == POINTER_BEFORE) ? STEP_PREV : STEP_NEXT,
2563 notebook->first_tab = first_tab;
2564 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2571 check_threshold (GtkNotebook *notebook,
2576 gint dnd_threshold, width, height;
2577 GdkRectangle rectangle = { 0, }; /* shut up gcc */
2578 GtkSettings *settings;
2580 widget = GTK_WIDGET (notebook);
2581 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2582 g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &dnd_threshold, NULL);
2584 gdk_drawable_get_size (GDK_DRAWABLE (notebook->event_window), &width, &height);
2586 /* we want a large threshold */
2587 dnd_threshold *= DND_THRESHOLD_MULTIPLIER;
2589 rectangle.x = - dnd_threshold;
2590 rectangle.width = width + 2 * dnd_threshold;
2591 rectangle.y = - dnd_threshold;
2592 rectangle.height = height + 2 * dnd_threshold;
2594 return (current_x < rectangle.x ||
2595 current_x > rectangle.x + rectangle.width ||
2596 current_y < rectangle.y ||
2597 current_y > rectangle.y + rectangle.height);
2601 gtk_notebook_motion_notify (GtkWidget *widget,
2602 GdkEventMotion *event)
2604 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2605 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2606 GtkNotebookPointerPosition pointer_position;
2607 GtkSettings *settings;
2611 if (priv->pressed_button == -1)
2614 if (!notebook->cur_page)
2617 priv->mouse_x = (gint) event->x;
2618 priv->mouse_y = (gint) event->y;
2620 if (notebook->cur_page->detachable &&
2621 check_threshold (notebook, priv->mouse_x, priv->mouse_y))
2623 /* move the page to the current position */
2624 element = get_drop_position (notebook,
2625 notebook->cur_page->pack,
2626 PAGE_MIDDLE_X (notebook->cur_page),
2627 PAGE_MIDDLE_Y (notebook->cur_page));
2628 reorder_tab (notebook, element, notebook->focus_tab);
2629 priv->during_detach = TRUE;
2631 gtk_drag_begin (widget, priv->source_targets, GDK_ACTION_MOVE,
2632 priv->pressed_button, (GdkEvent*) event);
2636 if (notebook->cur_page->reorderable)
2638 pointer_position = get_pointer_position (notebook);
2640 if (pointer_position != POINTER_BETWEEN &&
2641 gtk_notebook_show_arrows (notebook))
2643 if (!priv->dnd_timer)
2645 priv->has_scrolled = TRUE;
2646 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2647 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
2649 priv->dnd_timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
2650 (GSourceFunc) scroll_notebook_timer,
2651 (gpointer) notebook);
2656 if (priv->dnd_timer)
2658 g_source_remove (priv->dnd_timer);
2659 priv->dnd_timer = 0;
2663 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2670 gtk_notebook_grab_notify (GtkWidget *widget,
2671 gboolean was_grabbed)
2674 stop_scrolling (GTK_NOTEBOOK (widget));
2678 gtk_notebook_state_changed (GtkWidget *widget,
2679 GtkStateType previous_state)
2681 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2682 stop_scrolling (GTK_NOTEBOOK (widget));
2686 gtk_notebook_focus_in (GtkWidget *widget,
2687 GdkEventFocus *event)
2689 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2691 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2697 gtk_notebook_focus_out (GtkWidget *widget,
2698 GdkEventFocus *event)
2700 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2706 gtk_notebook_draw_focus (GtkWidget *widget)
2708 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2710 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2711 notebook->focus_tab)
2713 GtkNotebookPage *page;
2717 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2719 page = notebook->focus_tab->data;
2721 area.x = page->tab_label->allocation.x - focus_width;
2722 area.y = page->tab_label->allocation.y - focus_width;
2723 area.width = page->tab_label->allocation.width + 2 * focus_width;
2724 area.height = page->tab_label->allocation.height + 2 * focus_width;
2726 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2731 gtk_notebook_style_set (GtkWidget *widget,
2734 GtkNotebook *notebook;
2736 gboolean has_before_previous;
2737 gboolean has_before_next;
2738 gboolean has_after_previous;
2739 gboolean has_after_next;
2741 notebook = GTK_NOTEBOOK (widget);
2743 gtk_widget_style_get (widget,
2744 "has-backward-stepper", &has_before_previous,
2745 "has-secondary-forward-stepper", &has_before_next,
2746 "has-secondary-backward-stepper", &has_after_previous,
2747 "has-forward-stepper", &has_after_next,
2750 notebook->has_before_previous = has_before_previous;
2751 notebook->has_before_next = has_before_next;
2752 notebook->has_after_previous = has_after_previous;
2753 notebook->has_after_next = has_after_next;
2755 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2759 gtk_notebook_drag_begin (GtkWidget *widget,
2760 GdkDragContext *context)
2762 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
2763 GtkNotebook *notebook = (GtkNotebook*) widget;
2764 GtkWidget *tab_label;
2767 if (priv->dnd_timer)
2769 g_source_remove (priv->dnd_timer);
2770 priv->dnd_timer = 0;
2773 tab_label = notebook->cur_page->tab_label;
2775 pixmap = gdk_pixmap_new (tab_label->window,
2776 tab_label->allocation.width + 2,
2777 tab_label->allocation.height + 2,
2780 gdk_draw_drawable (pixmap,
2781 tab_label->style->base_gc [GTK_WIDGET_STATE (widget)],
2783 tab_label->allocation.x,
2784 tab_label->allocation.y,
2787 gdk_draw_rectangle (pixmap,
2788 widget->style->black_gc,
2791 tab_label->allocation.width + 1,
2792 tab_label->allocation.height + 1);
2794 gtk_drag_set_icon_pixmap (context,
2795 gdk_drawable_get_colormap (pixmap),
2800 gtk_notebook_pages_allocate (GTK_NOTEBOOK (widget), DRAG_OPERATION_DETACH);
2804 gtk_notebook_drag_motion (GtkWidget *widget,
2805 GdkDragContext *context,
2810 GtkWidget *source_widget;
2811 gint widget_group, source_widget_group;
2813 source_widget = gtk_drag_get_source_widget (context);
2815 g_assert (source_widget);
2817 widget_group = gtk_notebook_get_group_id (GTK_NOTEBOOK (widget));
2818 source_widget_group = gtk_notebook_get_group_id (GTK_NOTEBOOK (source_widget));
2820 if (widget_group != -1 &&
2821 source_widget_group != -1 &&
2822 widget_group == source_widget_group)
2825 gdk_drag_status (context, 0, time);
2831 gtk_notebook_drag_drop (GtkWidget *widget,
2832 GdkDragContext *context,
2839 target = gtk_drag_dest_find_target (widget, context, NULL);
2841 if (target == GDK_NONE)
2842 gtk_drag_finish (context, FALSE, FALSE, time);
2848 do_detach_tab (GtkNotebook *from,
2850 GtkNotebookPage *page_info,
2854 GtkWidget *child, *tab_label, *menu_label;
2855 gboolean tab_expand, tab_fill, reorderable, detachable;
2860 menu_label = tab_label = child = NULL;
2862 if (page_info->menu_label)
2863 menu_label = g_object_ref (page_info->menu_label);
2865 if (page_info->tab_label)
2866 tab_label = g_object_ref (page_info->tab_label);
2868 if (page_info->child)
2869 child = g_object_ref (page_info->child);
2871 /* preserve properties */
2872 tab_expand = page_info->expand;
2873 tab_fill = page_info->fill;
2874 tab_pack = page_info->pack;
2875 reorderable = page_info->reorderable;
2876 detachable = page_info->detachable;
2878 gtk_container_remove (GTK_CONTAINER (from), child);
2880 element = get_drop_position (to,
2882 GTK_WIDGET (to)->allocation.x + x,
2883 GTK_WIDGET (to)->allocation.y + y);
2885 page_num = g_list_position (to->children, element);
2886 gtk_notebook_insert_page_menu (to, child, tab_label, menu_label, page_num);
2888 gtk_container_child_set (GTK_CONTAINER (to), child,
2889 "tab-pack", tab_pack,
2890 "tab-expand", tab_expand,
2891 "tab-fill", tab_fill,
2892 "reorderable", reorderable,
2893 "detachable", detachable,
2896 g_object_unref (child);
2899 g_object_unref (tab_label);
2902 g_object_unref (menu_label);
2904 gtk_notebook_set_current_page (to, page_num);
2908 gtk_notebook_drag_data_get (GtkWidget *widget,
2909 GdkDragContext *context,
2910 GtkSelectionData *data,
2914 GtkNotebook *dest_notebook, *notebook;
2917 if (data->target != gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB") &&
2918 (data->target != gdk_atom_intern_static_string ("application/x-rootwindow-drop") ||
2919 !window_creation_hook))
2922 notebook = GTK_NOTEBOOK (widget);
2923 page_num = g_list_index (notebook->children, notebook->cur_page);
2925 if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
2927 gtk_selection_data_set (data,
2930 (void*) notebook->cur_page,
2931 sizeof (GtkNotebookPage));
2935 GdkDisplay *display;
2938 display = gtk_widget_get_display (widget);
2939 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
2941 dest_notebook = (* window_creation_hook) (notebook,
2942 notebook->cur_page->child,
2944 window_creation_hook_data);
2947 do_detach_tab (notebook, dest_notebook, notebook->cur_page, 0, 0);
2952 gtk_notebook_drag_data_received (GtkWidget *widget,
2953 GdkDragContext *context,
2956 GtkSelectionData *data,
2960 GtkNotebook *notebook;
2961 GtkWidget *source_widget;
2962 GtkNotebookPage *page_info;
2964 notebook = GTK_NOTEBOOK (widget);
2965 source_widget = gtk_drag_get_source_widget (context);
2967 if (source_widget &&
2968 data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
2970 page_info = (void*) data->data;
2972 do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, page_info, x, y);
2973 gtk_drag_finish (context, TRUE, FALSE, time);
2976 gtk_drag_finish (context, FALSE, FALSE, time);
2979 /* Private GtkContainer Methods :
2981 * gtk_notebook_set_child_arg
2982 * gtk_notebook_get_child_arg
2984 * gtk_notebook_remove
2985 * gtk_notebook_focus
2986 * gtk_notebook_set_focus_child
2987 * gtk_notebook_child_type
2988 * gtk_notebook_forall
2991 gtk_notebook_set_child_property (GtkContainer *container,
2994 const GValue *value,
2999 GtkPackType pack_type;
3001 /* not finding child's page is valid for menus or labels */
3002 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
3005 switch (property_id)
3007 case CHILD_PROP_TAB_LABEL:
3008 /* a NULL pointer indicates a default_tab setting, otherwise
3009 * we need to set the associated label
3011 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
3012 g_value_get_string (value));
3014 case CHILD_PROP_MENU_LABEL:
3015 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
3016 g_value_get_string (value));
3018 case CHILD_PROP_POSITION:
3019 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
3020 g_value_get_int (value));
3022 case CHILD_PROP_TAB_EXPAND:
3023 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3024 &expand, &fill, &pack_type);
3025 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3026 g_value_get_boolean (value),
3029 case CHILD_PROP_TAB_FILL:
3030 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3031 &expand, &fill, &pack_type);
3032 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3034 g_value_get_boolean (value),
3037 case CHILD_PROP_TAB_PACK:
3038 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3039 &expand, &fill, &pack_type);
3040 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3042 g_value_get_enum (value));
3044 case CHILD_PROP_REORDERABLE:
3045 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (container), child,
3046 g_value_get_boolean (value));
3048 case CHILD_PROP_DETACHABLE:
3049 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (container), child,
3050 g_value_get_boolean (value));
3053 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3059 gtk_notebook_get_child_property (GtkContainer *container,
3066 GtkNotebook *notebook;
3070 GtkPackType pack_type;
3072 notebook = GTK_NOTEBOOK (container);
3074 /* not finding child's page is valid for menus or labels */
3075 list = gtk_notebook_find_child (notebook, child, NULL);
3078 /* nothing to set on labels or menus */
3079 g_param_value_set_default (pspec, value);
3083 switch (property_id)
3085 case CHILD_PROP_TAB_LABEL:
3086 label = gtk_notebook_get_tab_label (notebook, child);
3088 if (label && GTK_IS_LABEL (label))
3089 g_value_set_string (value, GTK_LABEL (label)->label);
3091 g_value_set_string (value, NULL);
3093 case CHILD_PROP_MENU_LABEL:
3094 label = gtk_notebook_get_menu_label (notebook, child);
3096 if (label && GTK_IS_LABEL (label))
3097 g_value_set_string (value, GTK_LABEL (label)->label);
3099 g_value_set_string (value, NULL);
3101 case CHILD_PROP_POSITION:
3102 g_value_set_int (value, g_list_position (notebook->children, list));
3104 case CHILD_PROP_TAB_EXPAND:
3105 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3106 &expand, NULL, NULL);
3107 g_value_set_boolean (value, expand);
3109 case CHILD_PROP_TAB_FILL:
3110 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3112 g_value_set_boolean (value, fill);
3114 case CHILD_PROP_TAB_PACK:
3115 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3116 NULL, NULL, &pack_type);
3117 g_value_set_enum (value, pack_type);
3119 case CHILD_PROP_REORDERABLE:
3120 g_value_set_boolean (value,
3121 gtk_notebook_get_tab_reorderable (GTK_NOTEBOOK (container), child));
3123 case CHILD_PROP_DETACHABLE:
3124 g_value_set_boolean (value,
3125 gtk_notebook_get_tab_detachable (GTK_NOTEBOOK (container), child));
3128 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3134 gtk_notebook_add (GtkContainer *container,
3137 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3139 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
3144 gtk_notebook_remove (GtkContainer *container,
3147 GtkNotebook *notebook;
3148 GtkNotebookPage *page;
3152 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3153 g_return_if_fail (widget != NULL);
3155 notebook = GTK_NOTEBOOK (container);
3157 children = notebook->children;
3160 page = children->data;
3162 if (page->child == widget)
3166 children = children->next;
3169 g_signal_emit (notebook,
3170 notebook_signals[PAGE_REMOVED],
3175 gtk_notebook_real_remove (notebook, children);
3179 focus_tabs_in (GtkNotebook *notebook)
3181 if (notebook->show_tabs && notebook->cur_page)
3183 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3185 gtk_notebook_switch_focus_tab (notebook,
3186 g_list_find (notebook->children,
3187 notebook->cur_page));
3196 focus_tabs_move (GtkNotebook *notebook,
3197 GtkDirectionType direction,
3198 gint search_direction)
3202 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
3203 search_direction, TRUE);
3205 gtk_notebook_switch_focus_tab (notebook, new_page);
3207 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
3213 focus_child_in (GtkNotebook *notebook,
3214 GtkDirectionType direction)
3216 if (notebook->cur_page)
3217 return gtk_widget_child_focus (notebook->cur_page->child, direction);
3222 /* Focus in the notebook can either be on the pages, or on
3226 gtk_notebook_focus (GtkWidget *widget,
3227 GtkDirectionType direction)
3229 GtkWidget *old_focus_child;
3230 GtkNotebook *notebook;
3231 GtkDirectionType effective_direction;
3233 gboolean widget_is_focus;
3234 GtkContainer *container;
3236 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3238 container = GTK_CONTAINER (widget);
3239 notebook = GTK_NOTEBOOK (container);
3241 if (notebook->focus_out)
3243 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
3247 widget_is_focus = gtk_widget_is_focus (widget);
3248 old_focus_child = container->focus_child;
3250 effective_direction = get_effective_direction (notebook, direction);
3252 if (old_focus_child) /* Focus on page child */
3254 if (gtk_widget_child_focus (old_focus_child, direction))
3257 switch (effective_direction)
3259 case GTK_DIR_TAB_BACKWARD:
3261 /* Focus onto the tabs */
3262 return focus_tabs_in (notebook);
3264 case GTK_DIR_TAB_FORWARD:
3270 else if (widget_is_focus) /* Focus was on tabs */
3272 switch (effective_direction)
3274 case GTK_DIR_TAB_BACKWARD:
3277 case GTK_DIR_TAB_FORWARD:
3279 /* We use TAB_FORWARD rather than direction so that we focus a more
3280 * predictable widget for the user; users may be using arrow focusing
3281 * in this situation even if they don't usually use arrow focusing.
3283 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
3285 return focus_tabs_move (notebook, direction, STEP_PREV);
3287 return focus_tabs_move (notebook, direction, STEP_NEXT);
3290 else /* Focus was not on widget */
3292 switch (effective_direction)
3294 case GTK_DIR_TAB_FORWARD:
3296 if (focus_tabs_in (notebook))
3298 if (focus_child_in (notebook, direction))
3301 case GTK_DIR_TAB_BACKWARD:
3303 if (focus_child_in (notebook, direction))
3305 if (focus_tabs_in (notebook))
3310 return focus_child_in (notebook, direction);
3314 g_assert_not_reached ();
3319 gtk_notebook_set_focus_child (GtkContainer *container,
3322 GtkNotebook *notebook = GTK_NOTEBOOK (container);
3323 GtkWidget *page_child;
3324 GtkWidget *toplevel;
3326 /* If the old focus widget was within a page of the notebook,
3327 * (child may either be NULL or not in this case), record it
3328 * for future use if we switch to the page with a mnemonic.
3331 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
3332 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
3334 page_child = GTK_WINDOW (toplevel)->focus_widget;
3337 if (page_child->parent == GTK_WIDGET (container))
3339 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
3342 GtkNotebookPage *page = list->data;
3344 if (page->last_focus_child)
3345 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3347 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
3348 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3354 page_child = page_child->parent;
3360 g_return_if_fail (GTK_IS_WIDGET (child));
3362 notebook->child_has_focus = TRUE;
3363 if (!notebook->focus_tab)
3366 GtkNotebookPage *page;
3368 children = notebook->children;
3371 page = children->data;
3372 if (page->child == child || page->tab_label == child)
3373 gtk_notebook_switch_focus_tab (notebook, children);
3374 children = children->next;
3379 parent_class->set_focus_child (container, child);
3383 gtk_notebook_forall (GtkContainer *container,
3384 gboolean include_internals,
3385 GtkCallback callback,
3386 gpointer callback_data)
3388 GtkNotebook *notebook;
3391 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3392 g_return_if_fail (callback != NULL);
3394 notebook = GTK_NOTEBOOK (container);
3396 children = notebook->children;
3399 GtkNotebookPage *page;
3401 page = children->data;
3402 children = children->next;
3403 (* callback) (page->child, callback_data);
3404 if (include_internals)
3406 if (page->tab_label)
3407 (* callback) (page->tab_label, callback_data);
3413 gtk_notebook_child_type (GtkContainer *container)
3415 return GTK_TYPE_WIDGET;
3418 /* Private GtkNotebook Methods:
3420 * gtk_notebook_real_insert_page
3423 page_visible_cb (GtkWidget *page,
3427 GtkNotebook *notebook = (GtkNotebook *)data;
3431 if (notebook->cur_page &&
3432 notebook->cur_page->child == page &&
3433 !GTK_WIDGET_VISIBLE (page))
3435 list = g_list_find (notebook->children, notebook->cur_page);
3438 next = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3440 next = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3444 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next), -1);
3449 gtk_notebook_real_insert_page (GtkNotebook *notebook,
3451 GtkWidget *tab_label,
3452 GtkWidget *menu_label,
3455 GtkNotebookPage *page;
3458 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3459 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
3460 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
3461 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
3463 gtk_widget_freeze_child_notify (child);
3465 page = g_new (GtkNotebookPage, 1);
3466 page->child = child;
3467 page->last_focus_child = NULL;
3468 page->requisition.width = 0;
3469 page->requisition.height = 0;
3470 page->allocation.x = 0;
3471 page->allocation.y = 0;
3472 page->allocation.width = 0;
3473 page->allocation.height = 0;
3474 page->default_menu = FALSE;
3475 page->default_tab = FALSE;
3476 page->mnemonic_activate_signal = 0;
3477 page->reorderable = FALSE;
3478 page->detachable = FALSE;
3480 nchildren = g_list_length (notebook->children);
3481 if ((position < 0) || (position > nchildren))
3482 position = nchildren;
3484 notebook->children = g_list_insert (notebook->children, page, position);
3488 page->default_tab = TRUE;
3489 if (notebook->show_tabs)
3490 tab_label = gtk_label_new ("");
3492 page->tab_label = tab_label;
3493 page->menu_label = menu_label;
3494 page->expand = FALSE;
3496 page->pack = GTK_PACK_START;
3499 page->default_menu = TRUE;
3502 g_object_ref_sink (page->menu_label);
3506 gtk_notebook_menu_item_create (notebook,
3507 g_list_find (notebook->children, page));
3509 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3511 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3513 gtk_notebook_update_labels (notebook);
3515 if (!notebook->first_tab)
3516 notebook->first_tab = notebook->children;
3518 /* child visible will be turned on by switch_page below */
3519 gtk_widget_set_child_visible (child, FALSE);
3523 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3524 gtk_widget_show (tab_label);
3526 gtk_widget_hide (tab_label);
3529 if (!notebook->cur_page)
3531 gtk_notebook_switch_page (notebook, page, 0);
3532 gtk_notebook_switch_focus_tab (notebook, NULL);
3535 page->notify_visible_handler = g_signal_connect (G_OBJECT (child), "notify::visible",
3536 G_CALLBACK (page_visible_cb), notebook);
3537 gtk_notebook_update_tab_states (notebook);
3540 page->mnemonic_activate_signal =
3541 g_signal_connect (tab_label,
3542 "mnemonic_activate",
3543 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
3546 gtk_widget_child_notify (child, "tab-expand");
3547 gtk_widget_child_notify (child, "tab-fill");
3548 gtk_widget_child_notify (child, "tab-pack");
3549 gtk_widget_child_notify (child, "tab-label");
3550 gtk_widget_child_notify (child, "menu-label");
3551 gtk_widget_child_notify (child, "position");
3552 gtk_widget_thaw_child_notify (child);
3554 g_signal_emit (notebook,
3555 notebook_signals[PAGE_ADDED],
3563 /* Private GtkNotebook Functions:
3565 * gtk_notebook_redraw_tabs
3566 * gtk_notebook_real_remove
3567 * gtk_notebook_update_labels
3568 * gtk_notebook_timer
3569 * gtk_notebook_page_compare
3570 * gtk_notebook_real_page_position
3571 * gtk_notebook_search_page
3574 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
3577 GtkNotebookPage *page;
3578 GdkRectangle redraw_rect;
3580 gint tab_pos = get_effective_tab_pos (notebook);
3582 widget = GTK_WIDGET (notebook);
3583 border = GTK_CONTAINER (notebook)->border_width;
3585 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
3588 page = notebook->first_tab->data;
3590 redraw_rect.x = border;
3591 redraw_rect.y = border;
3595 case GTK_POS_BOTTOM:
3596 redraw_rect.y = (widget->allocation.height - border -
3597 page->allocation.height -
3598 widget->style->ythickness);
3599 if (page != notebook->cur_page)
3600 redraw_rect.y -= widget->style->ythickness;
3603 redraw_rect.width = widget->allocation.width - 2 * border;
3604 redraw_rect.height = (page->allocation.height +
3605 widget->style->ythickness);
3606 if (page != notebook->cur_page)
3607 redraw_rect.height += widget->style->ythickness;
3610 redraw_rect.x = (widget->allocation.width - border -
3611 page->allocation.width -
3612 widget->style->xthickness);
3613 if (page != notebook->cur_page)
3614 redraw_rect.x -= widget->style->xthickness;
3617 redraw_rect.width = (page->allocation.width +
3618 widget->style->xthickness);
3619 redraw_rect.height = widget->allocation.height - 2 * border;
3620 if (page != notebook->cur_page)
3621 redraw_rect.width += widget->style->xthickness;
3625 redraw_rect.x += widget->allocation.x;
3626 redraw_rect.y += widget->allocation.y;
3628 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
3632 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
3634 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
3638 GtkNotebookArrow arrow[4];
3640 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
3641 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
3642 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
3643 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
3645 for (i = 0; i < 4; i++)
3647 if (arrow[i] == ARROW_NONE)
3650 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
3651 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
3658 gtk_notebook_timer (GtkNotebook *notebook)
3660 gboolean retval = FALSE;
3662 GDK_THREADS_ENTER ();
3664 if (notebook->timer)
3666 gtk_notebook_do_arrow (notebook, notebook->click_child);
3668 if (notebook->need_timer)
3670 GtkSettings *settings;
3673 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
3674 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
3676 notebook->need_timer = FALSE;
3677 notebook->timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
3678 (GSourceFunc) gtk_notebook_timer,
3679 (gpointer) notebook);
3685 GDK_THREADS_LEAVE ();
3691 gtk_notebook_page_compare (gconstpointer a,
3694 return (((GtkNotebookPage *) a)->child != b);
3698 gtk_notebook_find_child (GtkNotebook *notebook,
3700 const gchar *function)
3702 GList *list = g_list_find_custom (notebook->children, child,
3703 gtk_notebook_page_compare);
3705 #ifndef G_DISABLE_CHECKS
3706 if (!list && function)
3707 g_warning ("%s: unable to find child %p in notebook %p",
3708 function, child, notebook);
3715 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
3716 GtkNotebookPage *page)
3718 if (page->tab_label)
3720 if (page->mnemonic_activate_signal)
3721 g_signal_handler_disconnect (page->tab_label,
3722 page->mnemonic_activate_signal);
3723 page->mnemonic_activate_signal = 0;
3725 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3726 gtk_widget_unparent (page->tab_label);
3727 page->tab_label = NULL;
3732 gtk_notebook_real_remove (GtkNotebook *notebook,
3735 GtkNotebookPage *page;
3737 gint need_resize = FALSE;
3739 gboolean destroying;
3741 destroying = GTK_OBJECT_FLAGS (notebook) & GTK_IN_DESTRUCTION;
3743 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3745 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3747 if (notebook->cur_page == list->data)
3749 notebook->cur_page = NULL;
3750 if (next_list && !destroying)
3751 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
3754 if (list == notebook->first_tab)
3755 notebook->first_tab = next_list;
3756 if (list == notebook->focus_tab && !destroying)
3757 gtk_notebook_switch_focus_tab (notebook, next_list);
3761 g_signal_handler_disconnect (page->child, page->notify_visible_handler);
3763 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
3766 gtk_widget_unparent (page->child);
3768 gtk_notebook_remove_tab_label (notebook, page);
3772 gtk_container_remove (GTK_CONTAINER (notebook->menu),
3773 page->menu_label->parent);
3774 gtk_widget_queue_resize (notebook->menu);
3776 if (!page->default_menu)
3777 g_object_unref (page->menu_label);
3779 notebook->children = g_list_remove_link (notebook->children, list);
3782 if (page->last_focus_child)
3784 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3785 page->last_focus_child = NULL;
3790 gtk_notebook_update_labels (notebook);
3792 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3796 gtk_notebook_update_labels (GtkNotebook *notebook)
3798 GtkNotebookPage *page;
3803 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
3805 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
3808 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
3809 if (notebook->show_tabs)
3811 if (page->default_tab)
3813 if (!page->tab_label)
3815 page->tab_label = gtk_label_new (string);
3816 gtk_widget_set_parent (page->tab_label,
3817 GTK_WIDGET (notebook));
3820 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
3823 if (GTK_WIDGET_VISIBLE (page->child) &&
3824 !GTK_WIDGET_VISIBLE (page->tab_label))
3825 gtk_widget_show (page->tab_label);
3826 else if (!GTK_WIDGET_VISIBLE (page->child) &&
3827 GTK_WIDGET_VISIBLE (page->tab_label))
3828 gtk_widget_hide (page->tab_label);
3830 if (notebook->menu && page->default_menu)
3832 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3833 gtk_label_set_text (GTK_LABEL (page->menu_label),
3834 GTK_LABEL (page->tab_label)->label);
3836 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
3842 gtk_notebook_real_page_position (GtkNotebook *notebook,
3848 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3849 g_return_val_if_fail (list != NULL, -1);
3851 for (work = notebook->children, count_start = 0;
3852 work && work != list; work = work->next)
3853 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
3859 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
3862 return (count_start + g_list_length (list) - 1);
3866 gtk_notebook_search_page (GtkNotebook *notebook,
3869 gboolean find_visible)
3871 GtkNotebookPage *page = NULL;
3872 GList *old_list = NULL;
3875 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3880 flag = GTK_PACK_END;
3884 flag = GTK_PACK_START;
3891 if (!page || page->pack == flag)
3899 list = notebook->children;
3904 if (page->pack == flag &&
3905 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
3920 if (page->pack != flag &&
3921 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
3929 /* Private GtkNotebook Drawing Functions:
3931 * gtk_notebook_paint
3932 * gtk_notebook_draw_tab
3933 * gtk_notebook_draw_arrow
3936 gtk_notebook_paint (GtkWidget *widget,
3939 GtkNotebook *notebook;
3940 GtkNotebookPage *page;
3945 gint border_width = GTK_CONTAINER (widget)->border_width;
3946 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
3950 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3951 g_return_if_fail (area != NULL);
3953 if (!GTK_WIDGET_DRAWABLE (widget))
3956 notebook = GTK_NOTEBOOK (widget);
3957 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3958 tab_pos = get_effective_tab_pos (notebook);
3960 if ((!notebook->show_tabs && !notebook->show_border) ||
3961 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
3964 x = widget->allocation.x + border_width;
3965 y = widget->allocation.y + border_width;
3966 width = widget->allocation.width - border_width * 2;
3967 height = widget->allocation.height - border_width * 2;
3969 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
3971 gtk_paint_box (widget->style, widget->window,
3972 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
3973 area, widget, "notebook",
3974 x, y, width, height);
3979 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
3981 page = notebook->first_tab->data;
3986 y += page->allocation.height + widget->style->ythickness;
3987 case GTK_POS_BOTTOM:
3988 height -= page->allocation.height + widget->style->ythickness;
3991 x += page->allocation.width + widget->style->xthickness;
3993 width -= page->allocation.width + widget->style->xthickness;
3996 gtk_paint_box (widget->style, widget->window,
3997 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
3998 area, widget, "notebook",
3999 x, y, width, height);
4006 y += notebook->cur_page->allocation.height;
4007 case GTK_POS_BOTTOM:
4008 height -= notebook->cur_page->allocation.height;
4011 x += notebook->cur_page->allocation.width;
4013 width -= notebook->cur_page->allocation.width;
4020 case GTK_POS_BOTTOM:
4021 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
4022 gap_width = notebook->cur_page->allocation.width;
4023 step = is_rtl ? STEP_NEXT : STEP_PREV;
4027 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
4028 gap_width = notebook->cur_page->allocation.height;
4032 gtk_paint_box_gap (widget->style, widget->window,
4033 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4034 area, widget, "notebook",
4035 x, y, width, height,
4036 tab_pos, gap_x, gap_width);
4040 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
4043 page = children->data;
4044 children = gtk_notebook_search_page (notebook, children,
4046 if (!GTK_WIDGET_VISIBLE (page->child))
4048 if (!GTK_WIDGET_MAPPED (page->tab_label))
4050 else if (page != notebook->cur_page)
4051 gtk_notebook_draw_tab (notebook, page, area);
4054 if (showarrow && notebook->scrollable)
4056 if (notebook->has_before_previous)
4057 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
4058 if (notebook->has_before_next)
4059 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
4060 if (notebook->has_after_previous)
4061 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
4062 if (notebook->has_after_next)
4063 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
4065 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
4069 gtk_notebook_draw_tab (GtkNotebook *notebook,
4070 GtkNotebookPage *page,
4073 GdkRectangle child_area;
4074 GdkRectangle page_area;
4075 GtkStateType state_type;
4076 GtkPositionType gap_side;
4077 gint tab_pos = get_effective_tab_pos (notebook);
4079 g_return_if_fail (notebook != NULL);
4080 g_return_if_fail (page != NULL);
4081 g_return_if_fail (area != NULL);
4083 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
4084 (page->allocation.width == 0) || (page->allocation.height == 0))
4087 page_area.x = page->allocation.x;
4088 page_area.y = page->allocation.y;
4089 page_area.width = page->allocation.width;
4090 page_area.height = page->allocation.height;
4092 if (gdk_rectangle_intersect (&page_area, area, &child_area))
4096 widget = GTK_WIDGET (notebook);
4101 gap_side = GTK_POS_BOTTOM;
4103 case GTK_POS_BOTTOM:
4104 gap_side = GTK_POS_TOP;
4107 gap_side = GTK_POS_RIGHT;
4110 gap_side = GTK_POS_LEFT;
4114 if (notebook->cur_page == page)
4115 state_type = GTK_STATE_NORMAL;
4117 state_type = GTK_STATE_ACTIVE;
4118 gtk_paint_extension(widget->style, widget->window,
4119 state_type, GTK_SHADOW_OUT,
4120 area, widget, "tab",
4121 page_area.x, page_area.y,
4122 page_area.width, page_area.height,
4124 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
4125 notebook->focus_tab && (notebook->focus_tab->data == page))
4129 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
4131 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
4132 area, widget, "tab",
4133 page->tab_label->allocation.x - focus_width,
4134 page->tab_label->allocation.y - focus_width,
4135 page->tab_label->allocation.width + 2 * focus_width,
4136 page->tab_label->allocation.height + 2 * focus_width);
4138 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
4139 GTK_WIDGET_DRAWABLE (page->tab_label))
4141 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
4143 /* This is a lame hack since all this code needs rewriting anyhow */
4145 expose_event->expose.window = g_object_ref (page->tab_label->window);
4146 expose_event->expose.area = child_area;
4147 expose_event->expose.region = gdk_region_rectangle (&child_area);
4148 expose_event->expose.send_event = TRUE;
4149 expose_event->expose.count = 0;
4151 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
4153 gdk_event_free (expose_event);
4159 gtk_notebook_draw_arrow (GtkNotebook *notebook,
4160 GtkNotebookArrow nbarrow)
4162 GtkStateType state_type;
4163 GtkShadowType shadow_type;
4165 GdkRectangle arrow_rect;
4167 gboolean is_rtl, left;
4169 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
4171 widget = GTK_WIDGET (notebook);
4173 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
4174 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
4175 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
4177 if (GTK_WIDGET_DRAWABLE (notebook))
4179 if (notebook->in_child == nbarrow)
4181 if (notebook->click_child == nbarrow)
4182 state_type = GTK_STATE_ACTIVE;
4184 state_type = GTK_STATE_PRELIGHT;
4187 state_type = GTK_WIDGET_STATE (widget);
4189 if (notebook->click_child == nbarrow)
4190 shadow_type = GTK_SHADOW_IN;
4192 shadow_type = GTK_SHADOW_OUT;
4194 if (notebook->focus_tab &&
4195 !gtk_notebook_search_page (notebook, notebook->focus_tab,
4196 left? STEP_PREV : STEP_NEXT, TRUE))
4198 shadow_type = GTK_SHADOW_ETCHED_IN;
4199 state_type = GTK_STATE_INSENSITIVE;
4202 if (notebook->tab_pos == GTK_POS_LEFT ||
4203 notebook->tab_pos == GTK_POS_RIGHT)
4204 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
4206 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
4208 gtk_paint_arrow (widget->style, widget->window, state_type,
4209 shadow_type, NULL, widget, "notebook",
4210 arrow, TRUE, arrow_rect.x, arrow_rect.y,
4211 ARROW_SIZE, ARROW_SIZE);
4216 get_notebook_tabs_space (GtkNotebook *notebook, gint *min, gint *max)
4218 GtkWidget *widget = (GtkWidget *) notebook;
4219 GtkContainer *container = (GtkContainer *) notebook;
4221 if (notebook->tab_pos == GTK_POS_TOP ||
4222 notebook->tab_pos == GTK_POS_BOTTOM)
4224 *min = widget->allocation.x + container->border_width;
4225 *max = widget->allocation.x + widget->allocation.width - container->border_width;
4227 if (gtk_notebook_show_arrows (notebook))
4229 if (notebook->has_after_previous)
4230 *max -= ARROW_SPACING + ARROW_SIZE;
4231 if (notebook->has_after_next)
4232 *max -= ARROW_SPACING + ARROW_SIZE;
4233 if (notebook->has_before_previous)
4234 *min += ARROW_SPACING + ARROW_SIZE;
4235 if (notebook->has_before_next)
4236 *min += ARROW_SPACING + ARROW_SIZE;
4241 *min = widget->allocation.y + container->border_width;
4242 *max = widget->allocation.y + widget->allocation.height - container->border_width;
4244 if (gtk_notebook_show_arrows (notebook))
4246 if (notebook->has_after_previous || notebook->has_after_next)
4247 *max -= ARROW_SPACING + ARROW_SIZE;
4248 if (notebook->has_before_previous || notebook->has_before_next)
4249 *min += ARROW_SPACING + ARROW_SIZE;
4254 /* Private GtkNotebook Size Allocate Functions:
4256 * gtk_notebook_pages_allocate
4257 * gtk_notebook_page_allocate
4258 * gtk_notebook_calc_tabs
4261 gtk_notebook_pages_allocate (GtkNotebook *notebook,
4262 GtkNotebookDragOperation operation)
4264 GtkWidget *widget = GTK_WIDGET (notebook);
4265 GtkContainer *container = GTK_CONTAINER (notebook);
4266 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
4267 GtkNotebookPage *page = NULL;
4268 GtkAllocation *allocation = &widget->allocation;
4269 GtkAllocation child_allocation;
4270 GList *children = NULL;
4271 GList *last_child = NULL;
4272 gboolean showarrow = FALSE;
4279 gint tab_pos = get_effective_tab_pos (notebook);
4280 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
4281 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
4283 gint memo_x, anchor_x, anchor_y;
4284 gint min, max, top_y, bottom_y, left_x, right_x;
4285 gboolean packing_changed = FALSE;
4286 gboolean gap_left = FALSE;
4288 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
4291 gtk_widget_style_get (widget, "tab-overlap", &tab_overlap, NULL);
4293 child_allocation.x = widget->allocation.x + container->border_width;
4294 child_allocation.y = widget->allocation.y + container->border_width;
4298 case GTK_POS_BOTTOM:
4299 child_allocation.y = (widget->allocation.y +
4300 allocation->height -
4301 notebook->cur_page->requisition.height -
4302 container->border_width);
4305 child_allocation.height = notebook->cur_page->requisition.height;
4309 child_allocation.x = (widget->allocation.x +
4311 notebook->cur_page->requisition.width -
4312 container->border_width);
4315 child_allocation.width = notebook->cur_page->requisition.width;
4319 if (notebook->scrollable)
4323 children = notebook->children;
4325 if (notebook->focus_tab)
4326 focus_tab = notebook->focus_tab;
4327 else if (notebook->first_tab)
4328 focus_tab = notebook->first_tab;
4330 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
4335 case GTK_POS_BOTTOM:
4338 page = children->data;
4339 children = children->next;
4341 if (GTK_WIDGET_VISIBLE (page->child))
4342 tab_space += page->requisition.width;
4346 allocation->width - 2 * container->border_width - tab_overlap)
4349 page = focus_tab->data;
4351 tab_space = allocation->width - tab_overlap -
4352 page->requisition.width - 2 * container->border_width;
4353 if (notebook->has_after_previous)
4354 tab_space -= ARROW_SPACING + ARROW_SIZE;
4355 if (notebook->has_after_next)
4356 tab_space -= ARROW_SPACING + ARROW_SIZE;
4357 if (notebook->has_before_previous)
4359 tab_space -= ARROW_SPACING + ARROW_SIZE;
4360 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4362 if (notebook->has_before_next)
4364 tab_space -= ARROW_SPACING + ARROW_SIZE;
4365 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4373 page = children->data;
4374 children = children->next;
4376 if (GTK_WIDGET_VISIBLE (page->child))
4377 tab_space += page->requisition.height;
4380 (allocation->height - 2 * container->border_width - tab_overlap))
4383 page = focus_tab->data;
4384 tab_space = allocation->height
4385 - tab_overlap - 2 * container->border_width
4386 - page->requisition.height;
4387 if (notebook->has_after_previous || notebook->has_after_next)
4388 tab_space -= ARROW_SPACING + ARROW_SIZE;
4389 if (notebook->has_before_previous || notebook->has_before_next)
4391 tab_space -= ARROW_SPACING + ARROW_SIZE;
4392 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
4397 if (showarrow) /* first_tab <- focus_tab */
4401 notebook->first_tab = focus_tab;
4402 last_child = gtk_notebook_search_page (notebook, focus_tab,
4408 if (notebook->first_tab && notebook->first_tab != focus_tab)
4410 /* Is first_tab really predecessor of focus_tab ? */
4411 page = notebook->first_tab->data;
4412 if (GTK_WIDGET_VISIBLE (page->child))
4413 for (children = focus_tab;
4414 children && children != notebook->first_tab;
4415 children = gtk_notebook_search_page (notebook,
4421 notebook->first_tab = focus_tab;
4423 gtk_notebook_calc_tabs (notebook,
4424 gtk_notebook_search_page (notebook,
4428 &(notebook->first_tab), &tab_space,
4433 notebook->first_tab =
4434 gtk_notebook_search_page (notebook, notebook->first_tab,
4436 if (!notebook->first_tab)
4437 notebook->first_tab = focus_tab;
4438 last_child = gtk_notebook_search_page (notebook, focus_tab,
4441 else /* focus_tab -> end */
4443 if (!notebook->first_tab)
4444 notebook->first_tab = gtk_notebook_search_page (notebook,
4449 gtk_notebook_calc_tabs (notebook,
4450 gtk_notebook_search_page (notebook,
4454 &children, &tab_space, STEP_NEXT);
4457 last_child = children;
4458 else /* start <- first_tab */
4462 gtk_notebook_calc_tabs
4464 gtk_notebook_search_page (notebook,
4465 notebook->first_tab,
4468 &children, &tab_space, STEP_PREV);
4469 notebook->first_tab = gtk_notebook_search_page(notebook,
4479 tab_space = -tab_space;
4481 for (children = notebook->first_tab;
4482 children && children != last_child;
4483 children = gtk_notebook_search_page (notebook, children,
4490 /*unmap all non-visible tabs*/
4491 for (children = gtk_notebook_search_page (notebook, NULL,
4493 children && children != notebook->first_tab;
4494 children = gtk_notebook_search_page (notebook, children,
4497 page = children->data;
4498 if (page->tab_label)
4499 gtk_widget_set_child_visible (page->tab_label, FALSE);
4501 for (children = last_child; children;
4502 children = gtk_notebook_search_page (notebook, children,
4505 page = children->data;
4506 if (page->tab_label)
4507 gtk_widget_set_child_visible (page->tab_label, FALSE);
4510 else /* !showarrow */
4512 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4523 children = notebook->children;
4527 case GTK_POS_BOTTOM:
4530 page = children->data;
4531 children = children->next;
4533 if (GTK_WIDGET_VISIBLE (page->child))
4536 tab_space += page->requisition.width;
4541 tab_space -= allocation->width;
4547 page = children->data;
4548 children = children->next;
4550 if (GTK_WIDGET_VISIBLE (page->child))
4553 tab_space += page->requisition.height;
4558 tab_space -= allocation->height;
4560 tab_space += 2 * container->border_width + tab_overlap;
4562 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4564 if (notebook->homogeneous && n)
4568 children = notebook->first_tab;
4571 memo_x = child_allocation.x;
4572 if (notebook->children && is_rtl)
4574 child_allocation.x = (allocation->x + allocation->width -
4575 container->border_width);
4578 if (notebook->has_after_previous)
4579 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4580 if (notebook->has_after_next)
4581 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4585 get_notebook_tabs_space (notebook, &min, &max);
4586 anchor_x = child_allocation.x;
4587 anchor_y = child_allocation.y;
4589 left_x = CLAMP (widget->allocation.x + priv->mouse_x - notebook->cur_page->allocation.width / 2,
4590 min, max - notebook->cur_page->allocation.width);
4591 top_y = CLAMP (widget->allocation.y + priv->mouse_y - notebook->cur_page->allocation.height / 2,
4592 min, max - notebook->cur_page->allocation.height);
4593 right_x = left_x + notebook->cur_page->allocation.width;
4594 bottom_y = top_y + notebook->cur_page->allocation.height;
4598 if (children == last_child)
4600 /* FIXME double check */
4604 page = children->data;
4606 if (page->pack != GTK_PACK_START)
4610 else if (operation == DRAG_OPERATION_REORDER)
4611 packing_changed = TRUE;
4614 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
4617 if (n && (showarrow || page->expand || notebook->homogeneous))
4619 new_fill = (tab_space * i++) / n;
4620 delta = new_fill - old_fill;
4621 old_fill = new_fill;
4627 case GTK_POS_BOTTOM:
4628 child_allocation.width = (page->requisition.width +
4629 tab_overlap + delta);
4631 /* make sure that the reordered tab doesn't go past the last position */
4632 if (operation == DRAG_OPERATION_REORDER &&
4633 !gap_left && packing_changed)
4637 if ((notebook->cur_page->pack == GTK_PACK_START && left_x >= anchor_x) ||
4638 (notebook->cur_page->pack == GTK_PACK_END && left_x < anchor_x))
4640 left_x = notebook->cur_page->allocation.x = anchor_x;
4641 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4642 ¬ebook->cur_page->allocation);
4644 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4649 if ((notebook->cur_page->pack == GTK_PACK_START && right_x <= anchor_x) ||
4650 (notebook->cur_page->pack == GTK_PACK_END && right_x > anchor_x))
4652 anchor_x -= notebook->cur_page->allocation.width;
4654 left_x = notebook->cur_page->allocation.x = anchor_x;
4655 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4656 ¬ebook->cur_page->allocation);
4658 anchor_x += tab_overlap;
4665 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4666 child_allocation.x = left_x;
4670 anchor_x -= child_allocation.width;
4672 if (operation == DRAG_OPERATION_REORDER && page->pack == notebook->cur_page->pack)
4675 left_x >= anchor_x &&
4676 left_x <= anchor_x + child_allocation.width / 2)
4677 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4679 right_x > anchor_x + child_allocation.width / 2 &&
4680 right_x <= anchor_x + child_allocation.width)
4681 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4684 child_allocation.x = anchor_x;
4690 child_allocation.height = (page->requisition.height +
4691 tab_overlap + delta);
4693 /* make sure that the reordered tab doesn't go past the last position */
4694 if (operation == DRAG_OPERATION_REORDER &&
4695 !gap_left && packing_changed)
4697 if ((notebook->cur_page->pack == GTK_PACK_START && top_y >= anchor_y) ||
4698 (notebook->cur_page->pack == GTK_PACK_END && top_y < anchor_y))
4700 top_y = notebook->cur_page->allocation.y = anchor_y;
4701 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4702 ¬ebook->cur_page->allocation);
4704 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4710 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4711 child_allocation.y = top_y;
4714 if (operation == DRAG_OPERATION_REORDER &&
4715 page->pack == notebook->cur_page->pack &&
4716 top_y >= anchor_y &&
4717 top_y <= anchor_y + child_allocation.height / 2)
4718 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4720 child_allocation.y = anchor_y;
4726 gtk_notebook_page_allocate (notebook, page, &child_allocation);
4731 case GTK_POS_BOTTOM:
4732 if (operation != DRAG_OPERATION_REORDER ||
4733 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4735 if (operation == DRAG_OPERATION_REORDER)
4737 if (page->pack == notebook->cur_page->pack &&
4739 left_x > anchor_x + child_allocation.width / 2 &&
4740 left_x <= anchor_x + child_allocation.width)
4741 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4742 else if (page->pack == notebook->cur_page->pack &&
4744 right_x >= anchor_x &&
4745 right_x <= anchor_x + child_allocation.width / 2)
4746 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4750 anchor_x += child_allocation.width - tab_overlap;
4752 anchor_x += tab_overlap;
4758 if (operation != DRAG_OPERATION_REORDER ||
4759 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4761 if (operation == DRAG_OPERATION_REORDER &&
4762 page->pack == notebook->cur_page->pack &&
4763 page != notebook->cur_page &&
4764 top_y > anchor_y + child_allocation.height / 2 &&
4765 top_y <= anchor_y + child_allocation.height)
4766 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4768 anchor_y += child_allocation.height - tab_overlap;
4774 if (page->tab_label)
4775 gtk_widget_set_child_visible (page->tab_label, TRUE);
4778 /* don't move the tab past the last position */
4779 if (operation == DRAG_OPERATION_REORDER &&
4780 notebook->cur_page->pack == GTK_PACK_START)
4785 case GTK_POS_BOTTOM:
4786 if ((!is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x) ||
4787 (is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x))
4790 anchor_x -= notebook->cur_page->allocation.width;
4792 notebook->cur_page->allocation.x = anchor_x;
4793 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4794 ¬ebook->cur_page->allocation);
4799 if (PAGE_TOP_Y (notebook->cur_page) > anchor_y)
4801 notebook->cur_page->allocation.y = anchor_y;
4802 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4803 ¬ebook->cur_page->allocation);
4811 children = notebook->children;
4816 case GTK_POS_BOTTOM:
4818 anchor_x = (allocation->x + allocation->width -
4819 container->border_width);
4825 anchor_y = (allocation->y + allocation->height -
4826 container->border_width);
4830 while (children != last_child)
4832 page = children->data;
4833 children = children->next;
4835 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
4839 if (n && (page->expand || notebook->homogeneous))
4841 new_fill = (tab_space * i++) / n;
4842 delta = new_fill - old_fill;
4843 old_fill = new_fill;
4849 case GTK_POS_BOTTOM:
4850 child_allocation.width = (page->requisition.width +
4851 tab_overlap + delta);
4853 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4854 child_allocation.x = left_x;
4858 anchor_x -= child_allocation.width;
4860 if (operation == DRAG_OPERATION_REORDER)
4862 if (page->pack == notebook->cur_page->pack &&
4864 left_x >= anchor_x &&
4865 left_x <= anchor_x + child_allocation.width / 2)
4866 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4867 else if (page->pack == notebook->cur_page->pack &&
4869 right_x > anchor_x + child_allocation.width / 2 &&
4870 right_x <= anchor_x + child_allocation.width)
4871 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4874 child_allocation.x = anchor_x;
4880 child_allocation.height = (page->requisition.height +
4881 tab_overlap + delta);
4883 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4884 child_allocation.y = top_y;
4887 anchor_y -= child_allocation.height;
4889 if (operation == DRAG_OPERATION_REORDER &&
4890 page->pack == notebook->cur_page->pack &&
4891 bottom_y > anchor_y + child_allocation.height / 2 &&
4892 bottom_y <= anchor_y + child_allocation.height)
4893 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
4895 child_allocation.y = anchor_y;
4901 gtk_notebook_page_allocate (notebook, page, &child_allocation);
4906 case GTK_POS_BOTTOM:
4907 if (operation != DRAG_OPERATION_REORDER ||
4908 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4910 if (operation == DRAG_OPERATION_REORDER)
4912 if (page->pack == notebook->cur_page->pack &&
4914 left_x > anchor_x + child_allocation.width / 2 &&
4915 left_x <= anchor_x + child_allocation.width)
4916 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4917 else if (page->pack == notebook->cur_page->pack &&
4919 right_x >= anchor_x &&
4920 right_x <= anchor_x + child_allocation.width / 2)
4921 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4925 anchor_x += tab_overlap;
4927 anchor_x += child_allocation.width - tab_overlap;
4933 if (operation != DRAG_OPERATION_REORDER ||
4934 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4936 if (operation == DRAG_OPERATION_REORDER &&
4937 page->pack == notebook->cur_page->pack &&
4938 page != notebook->cur_page &&
4939 bottom_y >= anchor_y &&
4940 bottom_y <= anchor_y + child_allocation.height / 2)
4941 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
4943 anchor_y += tab_overlap;
4949 if (page->tab_label)
4950 gtk_widget_set_child_visible (page->tab_label, TRUE);
4953 /* don't move the tab past the last position */
4954 if (operation == DRAG_OPERATION_REORDER &&
4955 notebook->cur_page->pack == GTK_PACK_END)
4960 case GTK_POS_BOTTOM:
4961 if ((!is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x) ||
4962 (is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x))
4965 anchor_x -= notebook->cur_page->allocation.width;
4967 notebook->cur_page->allocation.x = anchor_x;
4968 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4969 ¬ebook->cur_page->allocation);
4974 if (PAGE_BOTTOM_Y (notebook->cur_page) < anchor_y)
4976 anchor_y -= notebook->cur_page->allocation.height;
4977 notebook->cur_page->allocation.y = anchor_y;
4978 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4979 ¬ebook->cur_page->allocation);
4987 gtk_notebook_redraw_tabs (notebook);
4991 gtk_notebook_page_allocate (GtkNotebook *notebook,
4992 GtkNotebookPage *page,
4993 GtkAllocation *allocation)
4995 GtkWidget *widget = GTK_WIDGET (notebook);
4996 GtkAllocation child_allocation;
4997 GtkRequisition tab_requisition;
5003 gint tab_pos = get_effective_tab_pos (notebook);
5005 gtk_widget_style_get (widget,
5006 "focus-line-width", &focus_width,
5007 "tab-curvature", &tab_curvature,
5010 xthickness = widget->style->xthickness;
5011 ythickness = widget->style->ythickness;
5013 page->allocation = *allocation;
5014 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
5016 if (notebook->cur_page != page)
5021 page->allocation.y += ythickness;
5022 case GTK_POS_BOTTOM:
5023 page->allocation.height = MAX (1, page->allocation.height - ythickness);
5026 page->allocation.x += xthickness;
5028 page->allocation.width = MAX (1, page->allocation.width - xthickness);
5036 case GTK_POS_BOTTOM:
5037 padding = tab_curvature + focus_width + notebook->tab_hborder;
5040 child_allocation.x = (xthickness + focus_width +
5041 notebook->tab_hborder);
5042 child_allocation.width = MAX (1, (page->allocation.width -
5043 2 * child_allocation.x));
5044 child_allocation.x += page->allocation.x;
5048 child_allocation.x = (page->allocation.x +
5049 (page->allocation.width -
5050 tab_requisition.width) / 2);
5051 child_allocation.width = tab_requisition.width;
5053 child_allocation.y = (notebook->tab_vborder + focus_width +
5054 page->allocation.y);
5055 if (tab_pos == GTK_POS_TOP)
5056 child_allocation.y += ythickness;
5057 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
5058 2 * (notebook->tab_vborder + focus_width)));
5062 padding = tab_curvature + focus_width + notebook->tab_vborder;
5065 child_allocation.y = ythickness + padding;
5066 child_allocation.height = MAX (1, (page->allocation.height -
5067 2 * child_allocation.y));
5068 child_allocation.y += page->allocation.y;
5072 child_allocation.y = (page->allocation.y + (page->allocation.height -
5073 tab_requisition.height) / 2);
5074 child_allocation.height = tab_requisition.height;
5076 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
5077 if (tab_pos == GTK_POS_LEFT)
5078 child_allocation.x += xthickness;
5079 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
5080 2 * (notebook->tab_hborder + focus_width)));
5084 if (page->tab_label)
5085 gtk_widget_size_allocate (page->tab_label, &child_allocation);
5089 gtk_notebook_calc_tabs (GtkNotebook *notebook,
5095 GtkNotebookPage *page = NULL;
5097 GList *last_list = NULL;
5099 gint tab_pos = get_effective_tab_pos (notebook);
5105 pack = GTK_NOTEBOOK_PAGE (start)->pack;
5106 if (pack == GTK_PACK_END)
5107 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
5114 case GTK_POS_BOTTOM:
5117 page = children->data;
5118 if (GTK_WIDGET_VISIBLE (page->child))
5120 if (page->pack == pack)
5122 *tab_space -= page->requisition.width;
5123 if (*tab_space < 0 || children == *end)
5127 *tab_space = - (*tab_space +
5128 page->requisition.width);
5134 last_list = children;
5136 if (direction == STEP_NEXT)
5137 children = children->next;
5139 children = children->prev;
5146 page = children->data;
5147 if (GTK_WIDGET_VISIBLE (page->child))
5149 if (page->pack == pack)
5151 *tab_space -= page->requisition.height;
5152 if (*tab_space < 0 || children == *end)
5156 *tab_space = - (*tab_space +
5157 page->requisition.height);
5163 last_list = children;
5165 if (direction == STEP_NEXT)
5166 children = children->next;
5168 children = children->prev;
5172 if (direction == STEP_PREV)
5174 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
5175 direction = STEP_PREV;
5176 children = last_list;
5181 gtk_notebook_update_tab_states (GtkNotebook *notebook)
5185 for (list = notebook->children; list != NULL; list = list->next)
5187 GtkNotebookPage *page = list->data;
5189 if (page->tab_label)
5191 if (page == notebook->cur_page)
5192 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
5194 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
5199 /* Private GtkNotebook Page Switch Methods:
5201 * gtk_notebook_real_switch_page
5204 gtk_notebook_real_switch_page (GtkNotebook *notebook,
5205 GtkNotebookPage *page,
5208 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5209 g_return_if_fail (page != NULL);
5211 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
5214 if (notebook->cur_page)
5215 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
5217 notebook->cur_page = page;
5219 if (!notebook->focus_tab ||
5220 notebook->focus_tab->data != (gpointer) notebook->cur_page)
5221 notebook->focus_tab =
5222 g_list_find (notebook->children, notebook->cur_page);
5224 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
5226 /* If the focus was on the previous page, move it to the first
5227 * element on the new page, if possible, or if not, to the
5230 if (notebook->child_has_focus)
5232 if (notebook->cur_page->last_focus_child &&
5233 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
5234 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
5236 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
5237 gtk_widget_grab_focus (GTK_WIDGET (notebook));
5240 gtk_notebook_update_tab_states (notebook);
5241 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5242 g_object_notify (G_OBJECT (notebook), "page");
5245 /* Private GtkNotebook Page Switch Functions:
5247 * gtk_notebook_switch_page
5248 * gtk_notebook_page_select
5249 * gtk_notebook_switch_focus_tab
5250 * gtk_notebook_menu_switch_page
5253 gtk_notebook_switch_page (GtkNotebook *notebook,
5254 GtkNotebookPage *page,
5257 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5258 g_return_if_fail (page != NULL);
5260 if (notebook->cur_page == page)
5264 page_num = g_list_index (notebook->children, page);
5266 g_signal_emit (notebook,
5267 notebook_signals[SWITCH_PAGE],
5274 gtk_notebook_page_select (GtkNotebook *notebook,
5275 gboolean move_focus)
5277 GtkNotebookPage *page;
5278 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
5279 gint tab_pos = get_effective_tab_pos (notebook);
5281 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
5283 if (!notebook->focus_tab)
5286 page = notebook->focus_tab->data;
5287 gtk_notebook_switch_page (notebook, page, -1);
5296 case GTK_POS_BOTTOM:
5300 dir = GTK_DIR_RIGHT;
5307 if (gtk_widget_child_focus (page->child, dir))
5314 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
5318 GtkNotebookPage *page;
5320 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5322 if (notebook->focus_tab == new_child)
5325 old_child = notebook->focus_tab;
5326 notebook->focus_tab = new_child;
5328 if (notebook->scrollable)
5329 gtk_notebook_redraw_arrows (notebook);
5331 if (!notebook->show_tabs || !notebook->focus_tab)
5334 page = notebook->focus_tab->data;
5335 if (GTK_WIDGET_MAPPED (page->tab_label))
5336 gtk_notebook_redraw_tabs (notebook);
5338 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
5340 gtk_notebook_switch_page (notebook, page,
5341 g_list_index (notebook->children, page));
5345 gtk_notebook_menu_switch_page (GtkWidget *widget,
5346 GtkNotebookPage *page)
5348 GtkNotebook *notebook;
5352 g_return_if_fail (widget != NULL);
5353 g_return_if_fail (page != NULL);
5355 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
5356 (GTK_MENU (widget->parent)));
5358 if (notebook->cur_page == page)
5362 children = notebook->children;
5363 while (children && children->data != page)
5365 children = children->next;
5369 g_signal_emit (notebook,
5370 notebook_signals[SWITCH_PAGE],
5376 /* Private GtkNotebook Menu Functions:
5378 * gtk_notebook_menu_item_create
5379 * gtk_notebook_menu_label_unparent
5380 * gtk_notebook_menu_detacher
5383 gtk_notebook_menu_item_create (GtkNotebook *notebook,
5386 GtkNotebookPage *page;
5387 GtkWidget *menu_item;
5390 if (page->default_menu)
5392 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
5393 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
5395 page->menu_label = gtk_label_new ("");
5396 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
5399 gtk_widget_show (page->menu_label);
5400 menu_item = gtk_menu_item_new ();
5401 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
5402 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
5403 gtk_notebook_real_page_position (notebook, list));
5404 g_signal_connect (menu_item, "activate",
5405 G_CALLBACK (gtk_notebook_menu_switch_page), page);
5406 if (GTK_WIDGET_VISIBLE (page->child))
5407 gtk_widget_show (menu_item);
5411 gtk_notebook_menu_label_unparent (GtkWidget *widget,
5414 gtk_widget_unparent (GTK_BIN(widget)->child);
5415 GTK_BIN(widget)->child = NULL;
5419 gtk_notebook_menu_detacher (GtkWidget *widget,
5422 GtkNotebook *notebook;
5424 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
5426 notebook = GTK_NOTEBOOK (widget);
5427 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
5429 notebook->menu = NULL;
5432 /* Private GtkNotebook Setter Functions:
5434 * gtk_notebook_set_homogeneous_tabs_internal
5435 * gtk_notebook_set_tab_border_internal
5436 * gtk_notebook_set_tab_hborder_internal
5437 * gtk_notebook_set_tab_vborder_internal
5440 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
5441 gboolean homogeneous)
5443 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5445 if (homogeneous == notebook->homogeneous)
5448 notebook->homogeneous = homogeneous;
5449 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5451 g_object_notify (G_OBJECT (notebook), "homogeneous");
5455 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
5458 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5460 notebook->tab_hborder = border_width;
5461 notebook->tab_vborder = border_width;
5463 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5464 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5466 g_object_freeze_notify (G_OBJECT (notebook));
5467 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5468 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5469 g_object_thaw_notify (G_OBJECT (notebook));
5473 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
5476 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5478 if (notebook->tab_hborder == tab_hborder)
5481 notebook->tab_hborder = tab_hborder;
5483 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5484 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5486 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5490 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
5493 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5495 if (notebook->tab_vborder == tab_vborder)
5498 notebook->tab_vborder = tab_vborder;
5500 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5501 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5503 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5506 /* Public GtkNotebook Page Insert/Remove Methods :
5508 * gtk_notebook_append_page
5509 * gtk_notebook_append_page_menu
5510 * gtk_notebook_prepend_page
5511 * gtk_notebook_prepend_page_menu
5512 * gtk_notebook_insert_page
5513 * gtk_notebook_insert_page_menu
5514 * gtk_notebook_remove_page
5517 * gtk_notebook_append_page:
5518 * @notebook: a #GtkNotebook
5519 * @child: the #GtkWidget to use as the contents of the page.
5520 * @tab_label: the #GtkWidget to be used as the label for the page,
5521 * or %NULL to use the default label, 'page N'.
5523 * Appends a page to @notebook.
5525 * Return value: the index (starting from 0) of the appended
5526 * page in the notebook, or -1 if function fails
5529 gtk_notebook_append_page (GtkNotebook *notebook,
5531 GtkWidget *tab_label)
5533 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5534 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5535 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5537 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
5541 * gtk_notebook_append_page_menu:
5542 * @notebook: a #GtkNotebook
5543 * @child: the #GtkWidget to use as the contents of the page.
5544 * @tab_label: the #GtkWidget to be used as the label for the page,
5545 * or %NULL to use the default label, 'page N'.
5546 * @menu_label: the widget to use as a label for the page-switch
5547 * menu, if that is enabled. If %NULL, and @tab_label
5548 * is a #GtkLabel or %NULL, then the menu label will be
5549 * a newly created label with the same text as @tab_label;
5550 * If @tab_label is not a #GtkLabel, @menu_label must be
5551 * specified if the page-switch menu is to be used.
5553 * Appends a page to @notebook, specifying the widget to use as the
5554 * label in the popup menu.
5556 * Return value: the index (starting from 0) of the appended
5557 * page in the notebook, or -1 if function fails
5560 gtk_notebook_append_page_menu (GtkNotebook *notebook,
5562 GtkWidget *tab_label,
5563 GtkWidget *menu_label)
5565 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5566 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5567 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5568 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5570 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
5574 * gtk_notebook_prepend_page:
5575 * @notebook: a #GtkNotebook
5576 * @child: the #GtkWidget to use as the contents of the page.
5577 * @tab_label: the #GtkWidget to be used as the label for the page,
5578 * or %NULL to use the default label, 'page N'.
5580 * Prepends a page to @notebook.
5582 * Return value: the index (starting from 0) of the prepended
5583 * page in the notebook, or -1 if function fails
5586 gtk_notebook_prepend_page (GtkNotebook *notebook,
5588 GtkWidget *tab_label)
5590 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5591 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5592 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5594 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
5598 * gtk_notebook_prepend_page_menu:
5599 * @notebook: a #GtkNotebook
5600 * @child: the #GtkWidget to use as the contents of the page.
5601 * @tab_label: the #GtkWidget to be used as the label for the page,
5602 * or %NULL to use the default label, 'page N'.
5603 * @menu_label: the widget to use as a label for the page-switch
5604 * menu, if that is enabled. If %NULL, and @tab_label
5605 * is a #GtkLabel or %NULL, then the menu label will be
5606 * a newly created label with the same text as @tab_label;
5607 * If @tab_label is not a #GtkLabel, @menu_label must be
5608 * specified if the page-switch menu is to be used.
5610 * Prepends a page to @notebook, specifying the widget to use as the
5611 * label in the popup menu.
5613 * Return value: the index (starting from 0) of the prepended
5614 * page in the notebook, or -1 if function fails
5617 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
5619 GtkWidget *tab_label,
5620 GtkWidget *menu_label)
5622 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5623 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5624 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5625 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5627 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
5631 * gtk_notebook_insert_page:
5632 * @notebook: a #GtkNotebook
5633 * @child: the #GtkWidget to use as the contents of the page.
5634 * @tab_label: the #GtkWidget to be used as the label for the page,
5635 * or %NULL to use the default label, 'page N'.
5636 * @position: the index (starting at 0) at which to insert the page,
5637 * or -1 to append the page after all other pages.
5639 * Insert a page into @notebook at the given position.
5641 * Return value: the index (starting from 0) of the inserted
5642 * page in the notebook, or -1 if function fails
5645 gtk_notebook_insert_page (GtkNotebook *notebook,
5647 GtkWidget *tab_label,
5650 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5651 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5652 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5654 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
5659 gtk_notebook_page_compare_tab (gconstpointer a,
5662 return (((GtkNotebookPage *) a)->tab_label != b);
5666 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
5670 GtkNotebook *notebook = GTK_NOTEBOOK (data);
5673 list = g_list_find_custom (notebook->children, child,
5674 gtk_notebook_page_compare_tab);
5677 GtkNotebookPage *page = list->data;
5679 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
5680 gtk_notebook_switch_page (notebook, page, -1);
5681 focus_tabs_in (notebook);
5688 * gtk_notebook_insert_page_menu:
5689 * @notebook: a #GtkNotebook
5690 * @child: the #GtkWidget to use as the contents of the page.
5691 * @tab_label: the #GtkWidget to be used as the label for the page,
5692 * or %NULL to use the default label, 'page N'.
5693 * @menu_label: the widget to use as a label for the page-switch
5694 * menu, if that is enabled. If %NULL, and @tab_label
5695 * is a #GtkLabel or %NULL, then the menu label will be
5696 * a newly created label with the same text as @tab_label;
5697 * If @tab_label is not a #GtkLabel, @menu_label must be
5698 * specified if the page-switch menu is to be used.
5699 * @position: the index (starting at 0) at which to insert the page,
5700 * or -1 to append the page after all other pages.
5702 * Insert a page into @notebook at the given position, specifying
5703 * the widget to use as the label in the popup menu.
5705 * Return value: the index (starting from 0) of the inserted
5706 * page in the notebook
5709 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
5711 GtkWidget *tab_label,
5712 GtkWidget *menu_label,
5715 GtkNotebookClass *class;
5717 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5718 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5719 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5720 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5722 class = GTK_NOTEBOOK_GET_CLASS (notebook);
5724 return (class->insert_page) (notebook, child, tab_label, menu_label, position);
5728 * gtk_notebook_remove_page:
5729 * @notebook: a #GtkNotebook.
5730 * @page_num: the index of a notebook page, starting
5731 * from 0. If -1, the last page will
5734 * Removes a page from the notebook given its index
5738 gtk_notebook_remove_page (GtkNotebook *notebook,
5743 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5746 list = g_list_nth (notebook->children, page_num);
5748 list = g_list_last (notebook->children);
5751 gtk_container_remove (GTK_CONTAINER (notebook),
5752 ((GtkNotebookPage *) list->data)->child);
5755 /* Public GtkNotebook Page Switch Methods :
5756 * gtk_notebook_get_current_page
5757 * gtk_notebook_page_num
5758 * gtk_notebook_set_current_page
5759 * gtk_notebook_next_page
5760 * gtk_notebook_prev_page
5763 * gtk_notebook_get_current_page:
5764 * @notebook: a #GtkNotebook
5766 * Returns the page number of the current page.
5768 * Return value: the index (starting from 0) of the current
5769 * page in the notebook. If the notebook has no pages, then
5770 * -1 will be returned.
5773 gtk_notebook_get_current_page (GtkNotebook *notebook)
5775 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5777 if (!notebook->cur_page)
5780 return g_list_index (notebook->children, notebook->cur_page);
5784 * gtk_notebook_get_nth_page:
5785 * @notebook: a #GtkNotebook
5786 * @page_num: the index of a page in the noteobok, or -1
5787 * to get the last page.
5789 * Returns the child widget contained in page number @page_num.
5791 * Return value: the child widget, or %NULL if @page_num is
5795 gtk_notebook_get_nth_page (GtkNotebook *notebook,
5798 GtkNotebookPage *page;
5801 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5804 list = g_list_nth (notebook->children, page_num);
5806 list = g_list_last (notebook->children);
5818 * gtk_notebook_get_n_pages:
5819 * @notebook: a #GtkNotebook
5821 * Gets the number of pages in a notebook.
5823 * Return value: the number of pages in the notebook.
5828 gtk_notebook_get_n_pages (GtkNotebook *notebook)
5830 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
5832 return g_list_length (notebook->children);
5836 * gtk_notebook_page_num:
5837 * @notebook: a #GtkNotebook
5838 * @child: a #GtkWidget
5840 * Finds the index of the page which contains the given child
5843 * Return value: the index of the page containing @child, or
5844 * -1 if @child is not in the notebook.
5847 gtk_notebook_page_num (GtkNotebook *notebook,
5853 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5856 children = notebook->children;
5859 GtkNotebookPage *page = children->data;
5861 if (page->child == child)
5864 children = children->next;
5872 * gtk_notebook_set_current_page:
5873 * @notebook: a #GtkNotebook
5874 * @page_num: index of the page to switch to, starting from 0.
5875 * If negative, the last page will be used. If greater
5876 * than the number of pages in the notebook, nothing
5879 * Switches to the page number @page_num.
5882 gtk_notebook_set_current_page (GtkNotebook *notebook,
5887 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5890 list = g_list_nth (notebook->children, page_num);
5892 list = g_list_last (notebook->children);
5894 page_num = g_list_index (notebook->children, list);
5897 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
5901 * gtk_notebook_next_page:
5902 * @notebook: a #GtkNotebook
5904 * Switches to the next page. Nothing happens if the current page is
5908 gtk_notebook_next_page (GtkNotebook *notebook)
5912 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5914 list = g_list_find (notebook->children, notebook->cur_page);
5918 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
5922 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
5926 * gtk_notebook_prev_page:
5927 * @notebook: a #GtkNotebook
5929 * Switches to the previous page. Nothing happens if the current page
5930 * is the first page.
5933 gtk_notebook_prev_page (GtkNotebook *notebook)
5937 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5939 list = g_list_find (notebook->children, notebook->cur_page);
5943 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
5947 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
5950 /* Public GtkNotebook/Tab Style Functions
5952 * gtk_notebook_set_show_border
5953 * gtk_notebook_set_show_tabs
5954 * gtk_notebook_set_tab_pos
5955 * gtk_notebook_set_homogeneous_tabs
5956 * gtk_notebook_set_tab_border
5957 * gtk_notebook_set_tab_hborder
5958 * gtk_notebook_set_tab_vborder
5959 * gtk_notebook_set_scrollable
5962 * gtk_notebook_set_show_border:
5963 * @notebook: a #GtkNotebook
5964 * @show_border: %TRUE if a bevel should be drawn around the notebook.
5966 * Sets whether a bevel will be drawn around the notebook pages.
5967 * This only has a visual effect when the tabs are not shown.
5968 * See gtk_notebook_set_show_tabs().
5971 gtk_notebook_set_show_border (GtkNotebook *notebook,
5972 gboolean show_border)
5974 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5976 if (notebook->show_border != show_border)
5978 notebook->show_border = show_border;
5980 if (GTK_WIDGET_VISIBLE (notebook))
5981 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5983 g_object_notify (G_OBJECT (notebook), "show-border");
5988 * gtk_notebook_get_show_border:
5989 * @notebook: a #GtkNotebook
5991 * Returns whether a bevel will be drawn around the notebook pages. See
5992 * gtk_notebook_set_show_border().
5994 * Return value: %TRUE if the bevel is drawn
5997 gtk_notebook_get_show_border (GtkNotebook *notebook)
5999 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6001 return notebook->show_border;
6005 * gtk_notebook_set_show_tabs:
6006 * @notebook: a #GtkNotebook
6007 * @show_tabs: %TRUE if the tabs should be shown.
6009 * Sets whether to show the tabs for the notebook or not.
6012 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
6015 GtkNotebookPage *page;
6018 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6020 show_tabs = show_tabs != FALSE;
6022 if (notebook->show_tabs == show_tabs)
6025 notebook->show_tabs = show_tabs;
6026 children = notebook->children;
6030 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
6034 page = children->data;
6035 children = children->next;
6036 if (page->default_tab)
6038 gtk_widget_destroy (page->tab_label);
6039 page->tab_label = NULL;
6042 gtk_widget_hide (page->tab_label);
6047 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
6048 gtk_notebook_update_labels (notebook);
6050 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6052 g_object_notify (G_OBJECT (notebook), "show-tabs");
6056 * gtk_notebook_get_show_tabs:
6057 * @notebook: a #GtkNotebook
6059 * Returns whether the tabs of the notebook are shown. See
6060 * gtk_notebook_set_show_tabs().
6062 * Return value: %TRUE if the tabs are shown
6065 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
6067 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6069 return notebook->show_tabs;
6073 * gtk_notebook_set_tab_pos:
6074 * @notebook: a #GtkNotebook.
6075 * @pos: the edge to draw the tabs at.
6077 * Sets the edge at which the tabs for switching pages in the
6078 * notebook are drawn.
6081 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
6082 GtkPositionType pos)
6084 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6086 if (notebook->tab_pos != pos)
6088 notebook->tab_pos = pos;
6089 if (GTK_WIDGET_VISIBLE (notebook))
6090 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6093 g_object_notify (G_OBJECT (notebook), "tab-pos");
6097 * gtk_notebook_get_tab_pos:
6098 * @notebook: a #GtkNotebook
6100 * Gets the edge at which the tabs for switching pages in the
6101 * notebook are drawn.
6103 * Return value: the edge at which the tabs are drawn
6106 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
6108 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
6110 return notebook->tab_pos;
6114 * gtk_notebook_set_homogeneous_tabs:
6115 * @notebook: a #GtkNotebook
6116 * @homogeneous: %TRUE if all tabs should be the same size.
6118 * Sets whether the tabs must have all the same size or not.
6121 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
6122 gboolean homogeneous)
6124 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6126 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
6130 * gtk_notebook_set_tab_border:
6131 * @notebook: a #GtkNotebook
6132 * @border_width: width of the border around the tab labels.
6134 * Sets the width the border around the tab labels
6135 * in a notebook. This is equivalent to calling
6136 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
6137 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
6140 gtk_notebook_set_tab_border (GtkNotebook *notebook,
6143 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6145 gtk_notebook_set_tab_border_internal (notebook, border_width);
6149 * gtk_notebook_set_tab_hborder:
6150 * @notebook: a #GtkNotebook
6151 * @tab_hborder: width of the horizontal border of tab labels.
6153 * Sets the width of the horizontal border of tab labels.
6156 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
6159 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6161 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
6165 * gtk_notebook_set_tab_vborder:
6166 * @notebook: a #GtkNotebook
6167 * @tab_vborder: width of the vertical border of tab labels.
6169 * Sets the width of the vertical border of tab labels.
6172 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
6175 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6177 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
6181 * gtk_notebook_set_scrollable:
6182 * @notebook: a #GtkNotebook
6183 * @scrollable: %TRUE if scroll arrows should be added
6185 * Sets whether the tab label area will have arrows for scrolling if
6186 * there are too many tabs to fit in the area.
6189 gtk_notebook_set_scrollable (GtkNotebook *notebook,
6190 gboolean scrollable)
6192 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6194 scrollable = (scrollable != FALSE);
6196 if (scrollable != notebook->scrollable)
6198 notebook->scrollable = scrollable;
6200 if (GTK_WIDGET_VISIBLE (notebook))
6201 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6203 g_object_notify (G_OBJECT (notebook), "scrollable");
6208 * gtk_notebook_get_scrollable:
6209 * @notebook: a #GtkNotebook
6211 * Returns whether the tab label area has arrows for scrolling. See
6212 * gtk_notebook_set_scrollable().
6214 * Return value: %TRUE if arrows for scrolling are present
6217 gtk_notebook_get_scrollable (GtkNotebook *notebook)
6219 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6221 return notebook->scrollable;
6224 /* Public GtkNotebook Popup Menu Methods:
6226 * gtk_notebook_popup_enable
6227 * gtk_notebook_popup_disable
6232 * gtk_notebook_popup_enable:
6233 * @notebook: a #GtkNotebook
6235 * Enables the popup menu: if the user clicks with the right mouse button on
6236 * the bookmarks, a menu with all the pages will be popped up.
6239 gtk_notebook_popup_enable (GtkNotebook *notebook)
6243 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6248 notebook->menu = gtk_menu_new ();
6249 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
6251 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
6252 gtk_notebook_menu_item_create (notebook, list);
6254 gtk_notebook_update_labels (notebook);
6255 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
6256 GTK_WIDGET (notebook),
6257 gtk_notebook_menu_detacher);
6259 g_object_notify (G_OBJECT (notebook), "enable-popup");
6263 * gtk_notebook_popup_disable:
6264 * @notebook: a #GtkNotebook
6266 * Disables the popup menu.
6269 gtk_notebook_popup_disable (GtkNotebook *notebook)
6271 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6273 if (!notebook->menu)
6276 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
6277 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
6278 gtk_widget_destroy (notebook->menu);
6280 g_object_notify (G_OBJECT (notebook), "enable-popup");
6283 /* Public GtkNotebook Page Properties Functions:
6285 * gtk_notebook_get_tab_label
6286 * gtk_notebook_set_tab_label
6287 * gtk_notebook_set_tab_label_text
6288 * gtk_notebook_get_menu_label
6289 * gtk_notebook_set_menu_label
6290 * gtk_notebook_set_menu_label_text
6291 * gtk_notebook_set_tab_label_packing
6292 * gtk_notebook_query_tab_label_packing
6293 * gtk_notebook_get_tab_reorderable
6294 * gtk_notebook_set_tab_reorderable
6295 * gtk_notebook_get_tab_detachable
6296 * gtk_notebook_set_tab_detachable
6300 * gtk_notebook_get_tab_label:
6301 * @notebook: a #GtkNotebook
6304 * Returns the tab label widget for the page @child. %NULL is returned
6305 * if @child is not in @notebook or if no tab label has specifically
6306 * been set for @child.
6308 * Return value: the tab label
6311 gtk_notebook_get_tab_label (GtkNotebook *notebook,
6316 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6317 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6319 list = CHECK_FIND_CHILD (notebook, child);
6323 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
6326 return GTK_NOTEBOOK_PAGE (list)->tab_label;
6330 * gtk_notebook_set_tab_label:
6331 * @notebook: a #GtkNotebook
6333 * @tab_label: the tab label widget to use, or %NULL for default tab
6336 * Changes the tab label for @child. If %NULL is specified
6337 * for @tab_label, then the page will have the label 'page N'.
6340 gtk_notebook_set_tab_label (GtkNotebook *notebook,
6342 GtkWidget *tab_label)
6344 GtkNotebookPage *page;
6347 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6348 g_return_if_fail (GTK_IS_WIDGET (child));
6350 list = CHECK_FIND_CHILD (notebook, child);
6354 /* a NULL pointer indicates a default_tab setting, otherwise
6355 * we need to set the associated label
6359 if (page->tab_label == tab_label)
6363 gtk_notebook_remove_tab_label (notebook, page);
6367 page->default_tab = FALSE;
6368 page->tab_label = tab_label;
6369 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6373 page->default_tab = TRUE;
6374 page->tab_label = NULL;
6376 if (notebook->show_tabs)
6380 g_snprintf (string, sizeof(string), _("Page %u"),
6381 gtk_notebook_real_page_position (notebook, list));
6382 page->tab_label = gtk_label_new (string);
6383 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6387 if (page->tab_label)
6388 page->mnemonic_activate_signal =
6389 g_signal_connect (page->tab_label,
6390 "mnemonic_activate",
6391 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
6394 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
6396 gtk_widget_show (page->tab_label);
6397 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6400 gtk_notebook_update_tab_states (notebook);
6401 gtk_widget_child_notify (child, "tab-label");
6405 * gtk_notebook_set_tab_label_text:
6406 * @notebook: a #GtkNotebook
6408 * @tab_text: the label text
6410 * Creates a new label and sets it as the tab label for the page
6411 * containing @child.
6414 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
6416 const gchar *tab_text)
6418 GtkWidget *tab_label = NULL;
6420 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6423 tab_label = gtk_label_new (tab_text);
6424 gtk_notebook_set_tab_label (notebook, child, tab_label);
6425 gtk_widget_child_notify (child, "tab-label");
6429 * gtk_notebook_get_tab_label_text:
6430 * @notebook: a #GtkNotebook
6431 * @child: a widget contained in a page of @notebook
6433 * Retrieves the text of the tab label for the page containing
6436 * Returns value: the text of the tab label, or %NULL if the
6437 * tab label widget is not a #GtkLabel. The
6438 * string is owned by the widget and must not
6441 G_CONST_RETURN gchar *
6442 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
6445 GtkWidget *tab_label;
6447 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6448 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6450 tab_label = gtk_notebook_get_tab_label (notebook, child);
6452 if (tab_label && GTK_IS_LABEL (tab_label))
6453 return gtk_label_get_text (GTK_LABEL (tab_label));
6459 * gtk_notebook_get_menu_label:
6460 * @notebook: a #GtkNotebook
6461 * @child: a widget contained in a page of @notebook
6463 * Retrieves the menu label widget of the page containing @child.
6465 * Return value: the menu label, or %NULL if the
6466 * notebook page does not have a menu label other
6467 * than the default (the tab label).
6470 gtk_notebook_get_menu_label (GtkNotebook *notebook,
6475 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6476 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6478 list = CHECK_FIND_CHILD (notebook, child);
6482 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
6485 return GTK_NOTEBOOK_PAGE (list)->menu_label;
6489 * gtk_notebook_set_menu_label:
6490 * @notebook: a #GtkNotebook
6491 * @child: the child widget
6492 * @menu_label: the menu label, or NULL for default
6494 * Changes the menu label for the page containing @child.
6497 gtk_notebook_set_menu_label (GtkNotebook *notebook,
6499 GtkWidget *menu_label)
6501 GtkNotebookPage *page;
6504 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6505 g_return_if_fail (GTK_IS_WIDGET (child));
6507 list = CHECK_FIND_CHILD (notebook, child);
6512 if (page->menu_label)
6515 gtk_container_remove (GTK_CONTAINER (notebook->menu),
6516 page->menu_label->parent);
6518 if (!page->default_menu)
6519 g_object_unref (page->menu_label);
6524 page->menu_label = menu_label;
6525 g_object_ref_sink (page->menu_label);
6526 page->default_menu = FALSE;
6529 page->default_menu = TRUE;
6532 gtk_notebook_menu_item_create (notebook, list);
6533 gtk_widget_child_notify (child, "menu-label");
6537 * gtk_notebook_set_menu_label_text:
6538 * @notebook: a #GtkNotebook
6539 * @child: the child widget
6540 * @menu_text: the label text
6542 * Creates a new label and sets it as the menu label of @child.
6545 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
6547 const gchar *menu_text)
6549 GtkWidget *menu_label = NULL;
6551 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6554 menu_label = gtk_label_new (menu_text);
6555 gtk_notebook_set_menu_label (notebook, child, menu_label);
6556 gtk_widget_child_notify (child, "menu-label");
6560 * gtk_notebook_get_menu_label_text:
6561 * @notebook: a #GtkNotebook
6562 * @child: the child widget of a page of the notebook.
6564 * Retrieves the text of the menu label for the page containing
6567 * Returns value: the text of the tab label, or %NULL if the
6568 * widget does not have a menu label other than
6569 * the default menu label, or the menu label widget
6570 * is not a #GtkLabel. The string is owned by
6571 * the widget and must not be freed.
6573 G_CONST_RETURN gchar *
6574 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
6577 GtkWidget *menu_label;
6579 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6580 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6582 menu_label = gtk_notebook_get_menu_label (notebook, child);
6584 if (menu_label && GTK_IS_LABEL (menu_label))
6585 return gtk_label_get_text (GTK_LABEL (menu_label));
6590 /* Helper function called when pages are reordered
6593 gtk_notebook_child_reordered (GtkNotebook *notebook,
6594 GtkNotebookPage *page)
6598 GtkWidget *menu_item;
6600 menu_item = page->menu_label->parent;
6601 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
6602 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
6603 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
6606 gtk_notebook_update_tab_states (notebook);
6607 gtk_notebook_update_labels (notebook);
6611 * gtk_notebook_set_tab_label_packing:
6612 * @notebook: a #GtkNotebook
6613 * @child: the child widget
6614 * @expand: whether to expand the bookmark or not
6615 * @fill: whether the bookmark should fill the allocated area or not
6616 * @pack_type: the position of the bookmark
6618 * Sets the packing parameters for the tab label of the page
6619 * containing @child. See gtk_box_pack_start() for the exact meaning
6620 * of the parameters.
6623 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
6627 GtkPackType pack_type)
6629 GtkNotebookPage *page;
6632 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6633 g_return_if_fail (GTK_IS_WIDGET (child));
6635 list = CHECK_FIND_CHILD (notebook, child);
6640 expand = expand != FALSE;
6641 fill = fill != FALSE;
6642 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
6645 gtk_widget_freeze_child_notify (child);
6646 page->expand = expand;
6647 gtk_widget_child_notify (child, "tab-expand");
6649 gtk_widget_child_notify (child, "tab-fill");
6650 if (page->pack != pack_type)
6652 page->pack = pack_type;
6653 gtk_notebook_child_reordered (notebook, page);
6655 gtk_widget_child_notify (child, "tab-pack");
6656 gtk_widget_child_notify (child, "position");
6657 if (notebook->show_tabs)
6658 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6659 gtk_widget_thaw_child_notify (child);
6663 * gtk_notebook_query_tab_label_packing:
6664 * @notebook: a #GtkNotebook
6666 * @expand: location to store the expand value (or NULL)
6667 * @fill: location to store the fill value (or NULL)
6668 * @pack_type: location to store the pack_type (or NULL)
6670 * Query the packing attributes for the tab label of the page
6671 * containing @child.
6674 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
6678 GtkPackType *pack_type)
6682 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6683 g_return_if_fail (GTK_IS_WIDGET (child));
6685 list = CHECK_FIND_CHILD (notebook, child);
6690 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
6692 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
6694 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
6698 * gtk_notebook_reorder_child:
6699 * @notebook: a #GtkNotebook
6700 * @child: the child to move
6701 * @position: the new position, or -1 to move to the end
6703 * Reorders the page containing @child, so that it appears in position
6704 * @position. If @position is greater than or equal to the number of
6705 * children in the list or negative, @child will be moved to the end
6709 gtk_notebook_reorder_child (GtkNotebook *notebook,
6713 GList *list, *new_list;
6714 GtkNotebookPage *page;
6718 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6719 g_return_if_fail (GTK_IS_WIDGET (child));
6721 list = CHECK_FIND_CHILD (notebook, child);
6725 max_pos = g_list_length (notebook->children) - 1;
6726 if (position < 0 || position > max_pos)
6729 old_pos = g_list_position (notebook->children, list);
6731 if (old_pos == position)
6735 notebook->children = g_list_delete_link (notebook->children, list);
6737 notebook->children = g_list_insert (notebook->children, page, position);
6738 new_list = g_list_nth (notebook->children, position);
6740 /* Fix up GList references in GtkNotebook structure */
6741 if (notebook->first_tab == list)
6742 notebook->first_tab = new_list;
6743 if (notebook->focus_tab == list)
6744 notebook->focus_tab = new_list;
6746 gtk_widget_freeze_child_notify (child);
6748 /* Move around the menu items if necessary */
6749 gtk_notebook_child_reordered (notebook, page);
6750 gtk_widget_child_notify (child, "tab-pack");
6751 gtk_widget_child_notify (child, "position");
6753 if (notebook->show_tabs)
6754 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6756 gtk_widget_thaw_child_notify (child);
6758 g_signal_emit (notebook,
6759 notebook_signals[PAGE_REORDERED],
6766 * gtk_notebook_set_window_creation_hook:
6767 * @func: the #GtkNotebookWindowCreationFunc, or NULL
6768 * @data: user data for @func.
6770 * Installs a global function used to create a window
6771 * when a detached tab is dropped in an empty area.
6776 gtk_notebook_set_window_creation_hook (GtkNotebookWindowCreationFunc func,
6779 window_creation_hook = func;
6780 window_creation_hook_data = data;
6784 * gtk_notebook_set_group_id:
6785 * @notebook: a #GtkNotebook
6786 * @group_id: a group identificator, or -1 to unset it
6788 * Sets an group identificator for @notebook, notebooks sharing
6789 * the same group identificator will be able to exchange tabs
6790 * via drag and drop. A notebook with group identificator -1 will
6791 * not be able to exchange tabs with any other notebook.
6796 gtk_notebook_set_group_id (GtkNotebook *notebook,
6799 GtkNotebookPrivate *priv;
6801 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6803 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6805 if (priv->group_id != group_id)
6807 priv->group_id = group_id;
6808 g_object_notify (G_OBJECT (notebook), "group-id");
6813 * gtk_notebook_get_group_id:
6814 * @notebook: a #GtkNotebook
6816 * Gets the current group identificator for @notebook.
6818 * Return Value: the group identificator, or -1 if none is set.
6823 gtk_notebook_get_group_id (GtkNotebook *notebook)
6825 GtkNotebookPrivate *priv;
6827 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
6829 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6830 return priv->group_id;
6834 * gtk_notebook_get_tab_reorderable:
6835 * @notebook: a #GtkNotebook
6836 * @child: a child #GtkWidget
6838 * Gets whether the tab can be reordered via drag and drop or not.
6840 * Return Value: TRUE if the tab is reorderable.
6843 gtk_notebook_get_tab_reorderable (GtkNotebook *notebook,
6848 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6849 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
6851 list = CHECK_FIND_CHILD (notebook, child);
6855 return GTK_NOTEBOOK_PAGE (list)->reorderable;
6859 * gtk_notebook_set_tab_reorderable:
6860 * @notebook: a #GtkNotebook
6861 * @child: a child #GtkWidget
6862 * @reorderable: whether the tab is reorderable or not.
6864 * Sets whether the notebook tab can be reordered
6865 * via drag and drop or not.
6870 gtk_notebook_set_tab_reorderable (GtkNotebook *notebook,
6872 gboolean reorderable)
6876 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6877 g_return_if_fail (GTK_IS_WIDGET (child));
6879 list = CHECK_FIND_CHILD (notebook, child);
6883 if (GTK_NOTEBOOK_PAGE (list)->reorderable != reorderable)
6885 GTK_NOTEBOOK_PAGE (list)->reorderable = (reorderable == TRUE);
6886 gtk_widget_child_notify (child, "reorderable");
6891 * gtk_notebook_get_tab_detachable:
6892 * @notebook: a #GtkNotebook
6893 * @child: a child #GtkWidget
6895 * Returns whether the tab contents can be detached from @notebook.
6897 * Return Value: TRUE if the tab is detachable.
6902 gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
6907 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6908 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
6910 list = CHECK_FIND_CHILD (notebook, child);
6914 return GTK_NOTEBOOK_PAGE (list)->detachable;
6918 * gtk_notebook_set_tab_detachable:
6919 * @notebook: a #GtkNotebook
6920 * @child: a child #GtkWidget
6921 * @detachable: whether the tab is detachable or not
6923 * Sets whether the tab can be detached from @notebook to another notebook.
6925 * Note that 2 notebooks must share a common group identificator
6926 * (see gtk_notebook_set_group_id ()) to allow tabs interchange between them.
6931 gtk_notebook_set_tab_detachable (GtkNotebook *notebook,
6933 gboolean detachable)
6937 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6938 g_return_if_fail (GTK_IS_WIDGET (child));
6940 list = CHECK_FIND_CHILD (notebook, child);
6944 if (GTK_NOTEBOOK_PAGE (list)->detachable != detachable)
6946 GTK_NOTEBOOK_PAGE (list)->detachable = (detachable == TRUE);
6947 gtk_widget_child_notify (child, "detachable");
6951 #define __GTK_NOTEBOOK_C__
6952 #include "gtkaliasdef.c"