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 gboolean destroying);
309 static void gtk_notebook_update_labels (GtkNotebook *notebook);
310 static gint gtk_notebook_timer (GtkNotebook *notebook);
311 static gint gtk_notebook_page_compare (gconstpointer a,
313 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
315 const gchar *function);
316 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
318 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
321 gboolean find_visible);
323 /*** GtkNotebook Drawing Functions ***/
324 static void gtk_notebook_paint (GtkWidget *widget,
326 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
327 GtkNotebookPage *page,
329 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
330 GtkNotebookArrow arrow);
332 /*** GtkNotebook Size Allocate Functions ***/
333 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
334 GtkNotebookDragOperation operation);
335 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
336 GtkNotebookPage *page,
337 GtkAllocation *allocation);
338 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
344 /*** GtkNotebook Page Switch Methods ***/
345 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
346 GtkNotebookPage *page,
349 /*** GtkNotebook Page Switch Functions ***/
350 static void gtk_notebook_switch_page (GtkNotebook *notebook,
351 GtkNotebookPage *page,
353 static gint gtk_notebook_page_select (GtkNotebook *notebook,
354 gboolean move_focus);
355 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
357 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
358 GtkNotebookPage *page);
360 /*** GtkNotebook Menu Functions ***/
361 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
363 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
365 static void gtk_notebook_menu_detacher (GtkWidget *widget,
368 /*** GtkNotebook Private Setters ***/
369 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
370 gboolean homogeneous);
371 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
373 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
375 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
378 static void gtk_notebook_update_tab_states (GtkNotebook *notebook);
379 static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
383 static gboolean focus_tabs_in (GtkNotebook *notebook);
384 static gboolean focus_child_in (GtkNotebook *notebook,
385 GtkDirectionType direction);
387 static void stop_scrolling (GtkNotebook *notebook);
390 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
391 static gpointer window_creation_hook_data;
393 static GtkContainerClass *parent_class = NULL;
394 static guint notebook_signals[LAST_SIGNAL] = { 0 };
397 gtk_notebook_get_type (void)
399 static GType notebook_type = 0;
403 static const GTypeInfo notebook_info =
405 sizeof (GtkNotebookClass),
406 NULL, /* base_init */
407 NULL, /* base_finalize */
408 (GClassInitFunc) gtk_notebook_class_init,
409 NULL, /* class_finalize */
410 NULL, /* class_data */
411 sizeof (GtkNotebook),
413 (GInstanceInitFunc) gtk_notebook_init,
416 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkNotebook"),
420 return notebook_type;
424 add_tab_bindings (GtkBindingSet *binding_set,
425 GdkModifierType modifiers,
426 GtkDirectionType direction)
428 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
430 GTK_TYPE_DIRECTION_TYPE, direction);
431 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
433 GTK_TYPE_DIRECTION_TYPE, direction);
437 add_arrow_bindings (GtkBindingSet *binding_set,
439 GtkDirectionType direction)
441 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
443 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
445 GTK_TYPE_DIRECTION_TYPE, direction);
446 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
448 GTK_TYPE_DIRECTION_TYPE, direction);
452 add_reorder_bindings (GtkBindingSet *binding_set,
454 GtkDirectionType direction,
455 gboolean move_to_last)
457 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
459 gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
461 GTK_TYPE_DIRECTION_TYPE, direction,
462 G_TYPE_BOOLEAN, move_to_last);
463 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
465 GTK_TYPE_DIRECTION_TYPE, direction,
466 G_TYPE_BOOLEAN, move_to_last);
470 gtk_notebook_class_init (GtkNotebookClass *class)
472 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
473 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
474 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
475 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
476 GtkBindingSet *binding_set;
478 parent_class = g_type_class_peek_parent (class);
480 gobject_class->set_property = gtk_notebook_set_property;
481 gobject_class->get_property = gtk_notebook_get_property;
482 object_class->destroy = gtk_notebook_destroy;
484 widget_class->map = gtk_notebook_map;
485 widget_class->unmap = gtk_notebook_unmap;
486 widget_class->realize = gtk_notebook_realize;
487 widget_class->unrealize = gtk_notebook_unrealize;
488 widget_class->size_request = gtk_notebook_size_request;
489 widget_class->size_allocate = gtk_notebook_size_allocate;
490 widget_class->expose_event = gtk_notebook_expose;
491 widget_class->scroll_event = gtk_notebook_scroll;
492 widget_class->button_press_event = gtk_notebook_button_press;
493 widget_class->button_release_event = gtk_notebook_button_release;
494 widget_class->popup_menu = gtk_notebook_popup_menu;
495 widget_class->enter_notify_event = gtk_notebook_enter_notify;
496 widget_class->leave_notify_event = gtk_notebook_leave_notify;
497 widget_class->motion_notify_event = gtk_notebook_motion_notify;
498 widget_class->grab_notify = gtk_notebook_grab_notify;
499 widget_class->state_changed = gtk_notebook_state_changed;
500 widget_class->focus_in_event = gtk_notebook_focus_in;
501 widget_class->focus_out_event = gtk_notebook_focus_out;
502 widget_class->focus = gtk_notebook_focus;
503 widget_class->style_set = gtk_notebook_style_set;
504 widget_class->drag_begin = gtk_notebook_drag_begin;
505 widget_class->drag_motion = gtk_notebook_drag_motion;
506 widget_class->drag_drop = gtk_notebook_drag_drop;
507 widget_class->drag_data_get = gtk_notebook_drag_data_get;
508 widget_class->drag_data_received = gtk_notebook_drag_data_received;
510 container_class->add = gtk_notebook_add;
511 container_class->remove = gtk_notebook_remove;
512 container_class->forall = gtk_notebook_forall;
513 container_class->set_focus_child = gtk_notebook_set_focus_child;
514 container_class->get_child_property = gtk_notebook_get_child_property;
515 container_class->set_child_property = gtk_notebook_set_child_property;
516 container_class->child_type = gtk_notebook_child_type;
518 class->switch_page = gtk_notebook_real_switch_page;
519 class->insert_page = gtk_notebook_real_insert_page;
521 class->focus_tab = gtk_notebook_focus_tab;
522 class->select_page = gtk_notebook_select_page;
523 class->change_current_page = gtk_notebook_change_current_page;
524 class->move_focus_out = gtk_notebook_move_focus_out;
525 class->reorder_tab = gtk_notebook_reorder_tab;
527 g_object_class_install_property (gobject_class,
529 g_param_spec_int ("page",
531 P_("The index of the current page"),
535 GTK_PARAM_READWRITE));
536 g_object_class_install_property (gobject_class,
538 g_param_spec_enum ("tab-pos",
540 P_("Which side of the notebook holds the tabs"),
541 GTK_TYPE_POSITION_TYPE,
543 GTK_PARAM_READWRITE));
544 g_object_class_install_property (gobject_class,
546 g_param_spec_uint ("tab-border",
548 P_("Width of the border around the tab labels"),
552 GTK_PARAM_WRITABLE));
553 g_object_class_install_property (gobject_class,
555 g_param_spec_uint ("tab-hborder",
556 P_("Horizontal Tab Border"),
557 P_("Width of the horizontal border of tab labels"),
561 GTK_PARAM_READWRITE));
562 g_object_class_install_property (gobject_class,
564 g_param_spec_uint ("tab-vborder",
565 P_("Vertical Tab Border"),
566 P_("Width of the vertical border of tab labels"),
570 GTK_PARAM_READWRITE));
571 g_object_class_install_property (gobject_class,
573 g_param_spec_boolean ("show-tabs",
575 P_("Whether tabs should be shown or not"),
577 GTK_PARAM_READWRITE));
578 g_object_class_install_property (gobject_class,
580 g_param_spec_boolean ("show-border",
582 P_("Whether the border should be shown or not"),
584 GTK_PARAM_READWRITE));
585 g_object_class_install_property (gobject_class,
587 g_param_spec_boolean ("scrollable",
589 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
591 GTK_PARAM_READWRITE));
592 g_object_class_install_property (gobject_class,
594 g_param_spec_boolean ("enable-popup",
596 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
598 GTK_PARAM_READWRITE));
599 g_object_class_install_property (gobject_class,
601 g_param_spec_boolean ("homogeneous",
603 P_("Whether tabs should have homogeneous sizes"),
605 GTK_PARAM_READWRITE));
606 g_object_class_install_property (gobject_class,
608 g_param_spec_int ("group-id",
610 P_("Group ID for tabs drag and drop"),
614 GTK_PARAM_READWRITE));
616 gtk_container_class_install_child_property (container_class,
617 CHILD_PROP_TAB_LABEL,
618 g_param_spec_string ("tab-label",
620 P_("The string displayed on the child's tab label"),
622 GTK_PARAM_READWRITE));
623 gtk_container_class_install_child_property (container_class,
624 CHILD_PROP_MENU_LABEL,
625 g_param_spec_string ("menu-label",
627 P_("The string displayed in the child's menu entry"),
629 GTK_PARAM_READWRITE));
630 gtk_container_class_install_child_property (container_class,
632 g_param_spec_int ("position",
634 P_("The index of the child in the parent"),
636 GTK_PARAM_READWRITE));
637 gtk_container_class_install_child_property (container_class,
638 CHILD_PROP_TAB_EXPAND,
639 g_param_spec_boolean ("tab-expand",
641 P_("Whether to expand the child's tab or not"),
643 GTK_PARAM_READWRITE));
644 gtk_container_class_install_child_property (container_class,
646 g_param_spec_boolean ("tab-fill",
648 P_("Whether the child's tab should fill the allocated area or not"),
650 GTK_PARAM_READWRITE));
651 gtk_container_class_install_child_property (container_class,
653 g_param_spec_enum ("tab-pack",
655 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
656 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
657 GTK_PARAM_READWRITE));
658 gtk_container_class_install_child_property (container_class,
659 CHILD_PROP_REORDERABLE,
660 g_param_spec_boolean ("reorderable",
661 P_("Tab reorderable"),
662 P_("Whether the tab is reorderable by user action or not"),
664 GTK_PARAM_READWRITE));
665 gtk_container_class_install_child_property (container_class,
666 CHILD_PROP_DETACHABLE,
667 g_param_spec_boolean ("detachable",
668 P_("Tab detachable"),
669 P_("Whether the tab is detachable"),
671 GTK_PARAM_READWRITE));
674 * GtkNotebook:has-secondary-backward-stepper:
676 * The "has-secondary-backward-stepper" property determines whether
677 * a second backward arrow button is displayed on the opposite end
682 gtk_widget_class_install_style_property (widget_class,
683 g_param_spec_boolean ("has-secondary-backward-stepper",
684 P_("Secondary backward stepper"),
685 P_("Display a second backward arrow button on the opposite end of the tab area"),
687 GTK_PARAM_READABLE));
690 * GtkNotebook:has-secondary-forward-stepper:
692 * The "has-secondary-forward-stepper" property determines whether
693 * a second forward arrow button is displayed on the opposite end
698 gtk_widget_class_install_style_property (widget_class,
699 g_param_spec_boolean ("has-secondary-forward-stepper",
700 P_("Secondary forward stepper"),
701 P_("Display a second forward arrow button on the opposite end of the tab area"),
703 GTK_PARAM_READABLE));
706 * GtkNotebook:has-backward-stepper:
708 * The "has-backward-stepper" property determines whether
709 * the standard backward arrow button is displayed.
713 gtk_widget_class_install_style_property (widget_class,
714 g_param_spec_boolean ("has-backward-stepper",
715 P_("Backward stepper"),
716 P_("Display the standard backward arrow button"),
718 GTK_PARAM_READABLE));
721 * GtkNotebook:has-forward-stepper:
723 * The "has-forward-stepper" property determines whether
724 * the standard forward arrow button is displayed.
728 gtk_widget_class_install_style_property (widget_class,
729 g_param_spec_boolean ("has-forward-stepper",
730 P_("Forward stepper"),
731 P_("Display the standard forward arrow button"),
733 GTK_PARAM_READABLE));
736 * GtkNotebook:tab-overlap:
738 * The "tab-overlap" property defines size of tab overlap
743 gtk_widget_class_install_style_property (widget_class,
744 g_param_spec_int ("tab-overlap",
746 P_("Size of tab overlap area"),
750 GTK_PARAM_READABLE));
753 * GtkNotebook:tab-curvature:
755 * The "tab-curvature" property defines size of tab curvature.
759 gtk_widget_class_install_style_property (widget_class,
760 g_param_spec_int ("tab-curvature",
762 P_("Size of tab curvature"),
766 GTK_PARAM_READABLE));
768 notebook_signals[SWITCH_PAGE] =
769 g_signal_new (I_("switch_page"),
770 G_TYPE_FROM_CLASS (gobject_class),
772 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
774 _gtk_marshal_VOID__POINTER_UINT,
778 notebook_signals[FOCUS_TAB] =
779 g_signal_new (I_("focus_tab"),
780 G_TYPE_FROM_CLASS (gobject_class),
781 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
782 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
784 _gtk_marshal_BOOLEAN__ENUM,
786 GTK_TYPE_NOTEBOOK_TAB);
787 notebook_signals[SELECT_PAGE] =
788 g_signal_new (I_("select_page"),
789 G_TYPE_FROM_CLASS (gobject_class),
790 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
791 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
793 _gtk_marshal_BOOLEAN__BOOLEAN,
796 notebook_signals[CHANGE_CURRENT_PAGE] =
797 g_signal_new (I_("change_current_page"),
798 G_TYPE_FROM_CLASS (gobject_class),
799 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
800 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
802 _gtk_marshal_VOID__INT,
805 notebook_signals[MOVE_FOCUS_OUT] =
806 g_signal_new (I_("move_focus_out"),
807 G_TYPE_FROM_CLASS (gobject_class),
808 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
809 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
811 _gtk_marshal_VOID__ENUM,
813 GTK_TYPE_DIRECTION_TYPE);
814 notebook_signals[REORDER_TAB] =
815 g_signal_new (I_("reorder_tab"),
816 G_TYPE_FROM_CLASS (gobject_class),
817 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
818 G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
820 _gtk_marshal_VOID__ENUM_BOOLEAN,
822 GTK_TYPE_DIRECTION_TYPE,
825 * GtkNotebook::tab-reordered:
826 * @notebook: the #GtkNotebook
827 * @child: the child #GtkWidget affected
828 * @page_num: the new page number for @child
830 * the ::tab-reordered signal is emitted in the notebook
831 * right after a tab has been reordered by the user.
835 notebook_signals[TAB_REORDERED] =
836 g_signal_new (I_("tab_reordered"),
837 G_TYPE_FROM_CLASS (gobject_class),
838 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
840 _gtk_marshal_VOID__POINTER_UINT,
845 * GtkNotebook::tab-removed:
846 * @notebook: the #GtkNotebook
847 * @child: the child #GtkWidget affected
848 * @page_num: the @child page number
850 * the ::tab-removed signal is emitted in the notebook
851 * right before a tab is removed from the notebook.
855 notebook_signals[TAB_REMOVED] =
856 g_signal_new (I_("tab_removed"),
857 G_TYPE_FROM_CLASS (gobject_class),
858 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
860 _gtk_marshal_VOID__POINTER_UINT,
865 * GtkNotebook::tab-attached:
866 * @notebook: the #GtkNotebook
867 * @child: the child #GtkWidget affected
868 * @page_num: the new page number for @child
870 * the ::tab-added signal is emitted in the notebook
871 * right after a tab is added to the notebook.
875 notebook_signals[TAB_ADDED] =
876 g_signal_new (I_("tab_added"),
877 G_TYPE_FROM_CLASS (gobject_class),
878 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
880 _gtk_marshal_VOID__POINTER_UINT,
885 binding_set = gtk_binding_set_by_class (class);
886 gtk_binding_entry_add_signal (binding_set,
889 G_TYPE_BOOLEAN, FALSE);
890 gtk_binding_entry_add_signal (binding_set,
893 G_TYPE_BOOLEAN, FALSE);
895 gtk_binding_entry_add_signal (binding_set,
898 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
899 gtk_binding_entry_add_signal (binding_set,
902 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
903 gtk_binding_entry_add_signal (binding_set,
906 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
907 gtk_binding_entry_add_signal (binding_set,
910 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
912 gtk_binding_entry_add_signal (binding_set,
913 GDK_Page_Up, GDK_CONTROL_MASK,
914 "change_current_page", 1,
916 gtk_binding_entry_add_signal (binding_set,
917 GDK_Page_Down, GDK_CONTROL_MASK,
918 "change_current_page", 1,
921 gtk_binding_entry_add_signal (binding_set,
922 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
923 "change_current_page", 1,
925 gtk_binding_entry_add_signal (binding_set,
926 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
927 "change_current_page", 1,
930 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
931 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
932 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
933 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
935 add_reorder_bindings (binding_set, GDK_Up, GTK_DIR_UP, FALSE);
936 add_reorder_bindings (binding_set, GDK_Down, GTK_DIR_DOWN, FALSE);
937 add_reorder_bindings (binding_set, GDK_Left, GTK_DIR_LEFT, FALSE);
938 add_reorder_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT, FALSE);
939 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_LEFT, TRUE);
940 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_UP, TRUE);
941 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_RIGHT, TRUE);
942 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_DOWN, TRUE);
944 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
945 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
947 g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
951 gtk_notebook_init (GtkNotebook *notebook)
953 GtkNotebookPrivate *priv;
955 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
956 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
958 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
960 notebook->cur_page = NULL;
961 notebook->children = NULL;
962 notebook->first_tab = NULL;
963 notebook->focus_tab = NULL;
964 notebook->event_window = NULL;
965 notebook->menu = NULL;
967 notebook->tab_hborder = 2;
968 notebook->tab_vborder = 2;
970 notebook->show_tabs = TRUE;
971 notebook->show_border = TRUE;
972 notebook->tab_pos = GTK_POS_TOP;
973 notebook->scrollable = FALSE;
974 notebook->in_child = 0;
975 notebook->click_child = 0;
976 notebook->button = 0;
977 notebook->need_timer = 0;
978 notebook->child_has_focus = FALSE;
979 notebook->have_visible_child = FALSE;
980 notebook->focus_out = FALSE;
982 notebook->has_before_previous = 1;
983 notebook->has_before_next = 0;
984 notebook->has_after_previous = 0;
985 notebook->has_after_next = 1;
988 priv->pressed_button = -1;
990 priv->source_targets = gtk_target_list_new (notebook_targets,
991 G_N_ELEMENTS (notebook_targets));
993 gtk_drag_dest_set (GTK_WIDGET (notebook),
994 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
995 notebook_targets, G_N_ELEMENTS (notebook_targets),
1000 gtk_notebook_select_page (GtkNotebook *notebook,
1001 gboolean move_focus)
1003 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1005 gtk_notebook_page_select (notebook, move_focus);
1013 gtk_notebook_focus_tab (GtkNotebook *notebook,
1014 GtkNotebookTab type)
1018 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1022 case GTK_NOTEBOOK_TAB_FIRST:
1023 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1025 gtk_notebook_switch_focus_tab (notebook, list);
1027 case GTK_NOTEBOOK_TAB_LAST:
1028 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
1030 gtk_notebook_switch_focus_tab (notebook, list);
1041 gtk_notebook_change_current_page (GtkNotebook *notebook,
1044 GList *current = NULL;
1046 if (notebook->cur_page)
1047 current = g_list_find (notebook->children, notebook->cur_page);
1051 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
1052 offset += offset < 0 ? 1 : -1;
1056 gtk_notebook_switch_page (notebook, current->data, -1);
1058 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1061 static GtkDirectionType
1062 get_effective_direction (GtkNotebook *notebook,
1063 GtkDirectionType direction)
1065 /* Remap the directions into the effective direction it would be for a
1066 * GTK_POS_TOP notebook
1069 #define D(rest) GTK_DIR_##rest
1071 static const GtkDirectionType translate_direction[2][4][6] = {
1072 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1073 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1074 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1075 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
1076 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1077 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1078 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
1079 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
1084 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
1086 return translate_direction[text_dir][notebook->tab_pos][direction];
1090 get_effective_tab_pos (GtkNotebook *notebook)
1092 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
1094 switch (notebook->tab_pos)
1097 return GTK_POS_RIGHT;
1099 return GTK_POS_LEFT;
1104 return notebook->tab_pos;
1108 gtk_notebook_move_focus_out (GtkNotebook *notebook,
1109 GtkDirectionType direction_type)
1111 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1112 GtkWidget *toplevel;
1114 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
1115 if (focus_tabs_in (notebook))
1117 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
1118 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
1121 /* At this point, we know we should be focusing out of the notebook entirely. We
1122 * do this by setting a flag, then propagating the focus motion to the notebook.
1124 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
1125 if (!GTK_WIDGET_TOPLEVEL (toplevel))
1128 g_object_ref (notebook);
1130 notebook->focus_out = TRUE;
1131 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
1132 notebook->focus_out = FALSE;
1134 g_object_unref (notebook);
1138 reorder_tab (GtkNotebook *notebook, GList *position, GList *tab)
1142 /* check that we aren't inserting the tab in the
1143 * same relative position, taking packing into account */
1144 elem = (position) ? position->prev : g_list_last (notebook->children);
1146 while (elem && GTK_NOTEBOOK_PAGE (elem)->pack != GTK_NOTEBOOK_PAGE (tab)->pack)
1150 return g_list_position (notebook->children, tab);
1152 /* now actually reorder the tab */
1153 if (notebook->first_tab == tab)
1154 notebook->first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
1157 notebook->children = g_list_remove_link (notebook->children, tab);
1160 elem = g_list_last (notebook->children);
1163 elem = position->prev;
1164 position->prev = tab;
1170 notebook->children = tab;
1173 tab->next = position;
1175 return g_list_position (notebook->children, tab);
1179 gtk_notebook_reorder_tab (GtkNotebook *notebook,
1180 GtkDirectionType direction_type,
1181 gboolean move_to_last)
1183 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1184 GtkNotebookPage *page;
1185 GList *last, *child;
1188 if (!notebook->cur_page ||
1189 !notebook->cur_page->reorderable)
1192 if (effective_direction != GTK_DIR_LEFT &&
1193 effective_direction != GTK_DIR_RIGHT)
1198 child = notebook->focus_tab;
1203 child = gtk_notebook_search_page (notebook, last,
1204 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1207 while (child && GTK_NOTEBOOK_PAGE (last)->pack == GTK_NOTEBOOK_PAGE (child)->pack);
1212 child = gtk_notebook_search_page (notebook, notebook->focus_tab,
1213 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1216 if (!child || child->data == notebook->cur_page)
1221 if (page->pack == notebook->cur_page->pack)
1223 if (effective_direction == GTK_DIR_RIGHT)
1224 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child->next : child, notebook->focus_tab);
1226 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child : child->next, notebook->focus_tab);
1228 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1230 g_signal_emit (notebook,
1231 notebook_signals[TAB_REORDERED],
1233 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
1241 * Creates a new #GtkNotebook widget with no pages.
1243 * Return value: the newly created #GtkNotebook
1246 gtk_notebook_new (void)
1248 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
1251 /* Private GtkObject Methods :
1253 * gtk_notebook_destroy
1254 * gtk_notebook_set_arg
1255 * gtk_notebook_get_arg
1258 gtk_notebook_destroy (GtkObject *object)
1261 GtkNotebook *notebook = GTK_NOTEBOOK (object);
1262 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1265 gtk_notebook_popup_disable (notebook);
1267 children = notebook->children;
1270 GList *child = children;
1271 children = child->next;
1273 gtk_notebook_real_remove (notebook, child, TRUE);
1276 if (priv->source_targets)
1278 gtk_target_list_unref (priv->source_targets);
1279 priv->source_targets = NULL;
1282 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1286 gtk_notebook_set_property (GObject *object,
1288 const GValue *value,
1291 GtkNotebook *notebook;
1293 notebook = GTK_NOTEBOOK (object);
1297 case PROP_SHOW_TABS:
1298 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
1300 case PROP_SHOW_BORDER:
1301 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
1303 case PROP_SCROLLABLE:
1304 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
1306 case PROP_ENABLE_POPUP:
1307 if (g_value_get_boolean (value))
1308 gtk_notebook_popup_enable (notebook);
1310 gtk_notebook_popup_disable (notebook);
1312 case PROP_HOMOGENEOUS:
1313 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
1316 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
1319 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
1321 case PROP_TAB_BORDER:
1322 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
1324 case PROP_TAB_HBORDER:
1325 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
1327 case PROP_TAB_VBORDER:
1328 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
1331 gtk_notebook_set_group_id (notebook, g_value_get_int (value));
1339 gtk_notebook_get_property (GObject *object,
1344 GtkNotebook *notebook;
1345 GtkNotebookPrivate *priv;
1347 notebook = GTK_NOTEBOOK (object);
1348 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1352 case PROP_SHOW_TABS:
1353 g_value_set_boolean (value, notebook->show_tabs);
1355 case PROP_SHOW_BORDER:
1356 g_value_set_boolean (value, notebook->show_border);
1358 case PROP_SCROLLABLE:
1359 g_value_set_boolean (value, notebook->scrollable);
1361 case PROP_ENABLE_POPUP:
1362 g_value_set_boolean (value, notebook->menu != NULL);
1364 case PROP_HOMOGENEOUS:
1365 g_value_set_boolean (value, notebook->homogeneous);
1368 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
1371 g_value_set_enum (value, notebook->tab_pos);
1373 case PROP_TAB_HBORDER:
1374 g_value_set_uint (value, notebook->tab_hborder);
1376 case PROP_TAB_VBORDER:
1377 g_value_set_uint (value, notebook->tab_vborder);
1380 g_value_set_int (value, priv->group_id);
1383 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1388 /* Private GtkWidget Methods :
1391 * gtk_notebook_unmap
1392 * gtk_notebook_realize
1393 * gtk_notebook_size_request
1394 * gtk_notebook_size_allocate
1395 * gtk_notebook_expose
1396 * gtk_notebook_scroll
1397 * gtk_notebook_button_press
1398 * gtk_notebook_button_release
1399 * gtk_notebook_popup_menu
1400 * gtk_notebook_enter_notify
1401 * gtk_notebook_leave_notify
1402 * gtk_notebook_motion_notify
1403 * gtk_notebook_focus_in
1404 * gtk_notebook_focus_out
1405 * gtk_notebook_draw_focus
1406 * gtk_notebook_style_set
1407 * gtk_notebook_drag_begin
1408 * gtk_notebook_drag_motion
1409 * gtk_notebook_drag_drop
1410 * gtk_notebook_drag_data_get
1411 * gtk_notebook_drag_data_received
1414 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1415 GdkRectangle *rectangle)
1417 GtkWidget *widget = GTK_WIDGET (notebook);
1418 gint border_width = GTK_CONTAINER (notebook)->border_width;
1419 GtkNotebookPage *visible_page = NULL;
1421 gint tab_pos = get_effective_tab_pos (notebook);
1423 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1425 GtkNotebookPage *page = tmp_list->data;
1426 if (GTK_WIDGET_VISIBLE (page->child))
1428 visible_page = page;
1433 if (notebook->show_tabs && visible_page)
1437 rectangle->x = widget->allocation.x + border_width;
1438 rectangle->y = widget->allocation.y + border_width;
1443 case GTK_POS_BOTTOM:
1444 rectangle->width = widget->allocation.width - 2 * border_width;
1445 rectangle->height = visible_page->requisition.height;
1446 if (tab_pos == GTK_POS_BOTTOM)
1447 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1451 rectangle->width = visible_page->requisition.width;
1452 rectangle->height = widget->allocation.height - 2 * border_width;
1453 if (tab_pos == GTK_POS_RIGHT)
1454 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1465 rectangle->x = rectangle->y = 0;
1466 rectangle->width = rectangle->height = 10;
1474 gtk_notebook_map (GtkWidget *widget)
1476 GtkNotebook *notebook;
1477 GtkNotebookPage *page;
1480 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1482 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1484 notebook = GTK_NOTEBOOK (widget);
1486 if (notebook->cur_page &&
1487 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1488 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1489 gtk_widget_map (notebook->cur_page->child);
1491 if (notebook->scrollable)
1492 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1495 children = notebook->children;
1499 page = children->data;
1500 children = children->next;
1502 if (page->tab_label &&
1503 GTK_WIDGET_VISIBLE (page->tab_label) &&
1504 !GTK_WIDGET_MAPPED (page->tab_label))
1505 gtk_widget_map (page->tab_label);
1509 if (gtk_notebook_get_event_window_position (notebook, NULL))
1510 gdk_window_show_unraised (notebook->event_window);
1514 gtk_notebook_unmap (GtkWidget *widget)
1516 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1518 stop_scrolling (GTK_NOTEBOOK (widget));
1520 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1522 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1524 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1528 gtk_notebook_realize (GtkWidget *widget)
1530 GtkNotebook *notebook;
1531 GdkWindowAttr attributes;
1532 gint attributes_mask;
1533 GdkRectangle event_window_pos;
1535 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1537 notebook = GTK_NOTEBOOK (widget);
1538 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1540 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1542 widget->window = gtk_widget_get_parent_window (widget);
1543 g_object_ref (widget->window);
1545 attributes.window_type = GDK_WINDOW_CHILD;
1546 attributes.x = event_window_pos.x;
1547 attributes.y = event_window_pos.y;
1548 attributes.width = event_window_pos.width;
1549 attributes.height = event_window_pos.height;
1550 attributes.wclass = GDK_INPUT_ONLY;
1551 attributes.event_mask = gtk_widget_get_events (widget);
1552 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1553 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1554 GDK_BUTTON1_MOTION_MASK |
1556 attributes_mask = GDK_WA_X | GDK_WA_Y;
1558 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1559 &attributes, attributes_mask);
1560 gdk_window_set_user_data (notebook->event_window, notebook);
1562 widget->style = gtk_style_attach (widget->style, widget->window);
1566 gtk_notebook_unrealize (GtkWidget *widget)
1568 GtkNotebook *notebook;
1570 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1572 notebook = GTK_NOTEBOOK (widget);
1574 gdk_window_set_user_data (notebook->event_window, NULL);
1575 gdk_window_destroy (notebook->event_window);
1576 notebook->event_window = NULL;
1578 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1579 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1583 gtk_notebook_size_request (GtkWidget *widget,
1584 GtkRequisition *requisition)
1586 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1587 GtkNotebookPage *page;
1589 GtkRequisition child_requisition;
1590 gboolean switch_page = FALSE;
1596 gtk_widget_style_get (widget,
1597 "focus-line-width", &focus_width,
1598 "tab-overlap", &tab_overlap,
1599 "tab-curvature", &tab_curvature,
1602 widget->requisition.width = 0;
1603 widget->requisition.height = 0;
1605 for (children = notebook->children, vis_pages = 0; children;
1606 children = children->next)
1608 page = children->data;
1610 if (GTK_WIDGET_VISIBLE (page->child))
1613 gtk_widget_size_request (page->child, &child_requisition);
1615 widget->requisition.width = MAX (widget->requisition.width,
1616 child_requisition.width);
1617 widget->requisition.height = MAX (widget->requisition.height,
1618 child_requisition.height);
1620 if (notebook->menu && page->menu_label->parent &&
1621 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1622 gtk_widget_show (page->menu_label->parent);
1626 if (page == notebook->cur_page)
1628 if (notebook->menu && page->menu_label->parent &&
1629 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1630 gtk_widget_hide (page->menu_label->parent);
1634 if (notebook->show_border || notebook->show_tabs)
1636 widget->requisition.width += widget->style->xthickness * 2;
1637 widget->requisition.height += widget->style->ythickness * 2;
1639 if (notebook->show_tabs)
1642 gint tab_height = 0;
1646 for (children = notebook->children; children;
1647 children = children->next)
1649 page = children->data;
1651 if (GTK_WIDGET_VISIBLE (page->child))
1653 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1654 gtk_widget_show (page->tab_label);
1656 gtk_widget_size_request (page->tab_label,
1657 &child_requisition);
1659 page->requisition.width =
1660 child_requisition.width +
1661 2 * widget->style->xthickness;
1662 page->requisition.height =
1663 child_requisition.height +
1664 2 * widget->style->ythickness;
1666 switch (notebook->tab_pos)
1669 case GTK_POS_BOTTOM:
1670 page->requisition.height += 2 * (notebook->tab_vborder +
1672 tab_height = MAX (tab_height, page->requisition.height);
1673 tab_max = MAX (tab_max, page->requisition.width);
1677 page->requisition.width += 2 * (notebook->tab_hborder +
1679 tab_width = MAX (tab_width, page->requisition.width);
1680 tab_max = MAX (tab_max, page->requisition.height);
1684 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1685 gtk_widget_hide (page->tab_label);
1688 children = notebook->children;
1692 switch (notebook->tab_pos)
1695 case GTK_POS_BOTTOM:
1696 if (tab_height == 0)
1699 if (notebook->scrollable && vis_pages > 1 &&
1700 widget->requisition.width < tab_width)
1701 tab_height = MAX (tab_height, ARROW_SIZE);
1703 padding = 2 * (tab_curvature + focus_width +
1704 notebook->tab_hborder) - tab_overlap;
1708 page = children->data;
1709 children = children->next;
1711 if (!GTK_WIDGET_VISIBLE (page->child))
1714 if (notebook->homogeneous)
1715 page->requisition.width = tab_max;
1717 page->requisition.width += padding;
1719 tab_width += page->requisition.width;
1720 page->requisition.height = tab_height;
1723 if (notebook->scrollable && vis_pages > 1 &&
1724 widget->requisition.width < tab_width)
1725 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1727 if (notebook->homogeneous && !notebook->scrollable)
1728 widget->requisition.width = MAX (widget->requisition.width,
1729 vis_pages * tab_max +
1732 widget->requisition.width = MAX (widget->requisition.width,
1733 tab_width + tab_overlap);
1735 widget->requisition.height += tab_height;
1742 if (notebook->scrollable && vis_pages > 1 &&
1743 widget->requisition.height < tab_height)
1744 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1746 padding = 2 * (tab_curvature + focus_width +
1747 notebook->tab_vborder) - tab_overlap;
1752 page = children->data;
1753 children = children->next;
1755 if (!GTK_WIDGET_VISIBLE (page->child))
1758 page->requisition.width = tab_width;
1760 if (notebook->homogeneous)
1761 page->requisition.height = tab_max;
1763 page->requisition.height += padding;
1765 tab_height += page->requisition.height;
1768 if (notebook->scrollable && vis_pages > 1 &&
1769 widget->requisition.height < tab_height)
1770 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1772 widget->requisition.width += tab_width;
1774 if (notebook->homogeneous && !notebook->scrollable)
1775 widget->requisition.height =
1776 MAX (widget->requisition.height,
1777 vis_pages * tab_max + tab_overlap);
1779 widget->requisition.height =
1780 MAX (widget->requisition.height,
1781 tab_height + tab_overlap);
1783 if (!notebook->homogeneous || notebook->scrollable)
1785 widget->requisition.height = MAX (widget->requisition.height,
1786 vis_pages * tab_max +
1794 for (children = notebook->children; children;
1795 children = children->next)
1797 page = children->data;
1799 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1800 gtk_widget_hide (page->tab_label);
1805 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1806 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1812 for (children = notebook->children; children;
1813 children = children->next)
1815 page = children->data;
1816 if (GTK_WIDGET_VISIBLE (page->child))
1818 gtk_notebook_switch_page (notebook, page, -1);
1823 else if (GTK_WIDGET_VISIBLE (widget))
1825 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1826 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1829 if (vis_pages && !notebook->cur_page)
1831 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1834 notebook->first_tab = children;
1835 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1841 gtk_notebook_size_allocate (GtkWidget *widget,
1842 GtkAllocation *allocation)
1844 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1846 gint tab_pos = get_effective_tab_pos (notebook);
1848 widget->allocation = *allocation;
1849 if (GTK_WIDGET_REALIZED (widget))
1851 GdkRectangle position;
1853 if (gtk_notebook_get_event_window_position (notebook, &position))
1855 gdk_window_move_resize (notebook->event_window,
1856 position.x, position.y,
1857 position.width, position.height);
1858 if (GTK_WIDGET_MAPPED (notebook))
1859 gdk_window_show_unraised (notebook->event_window);
1862 gdk_window_hide (notebook->event_window);
1865 if (notebook->children)
1867 gint border_width = GTK_CONTAINER (widget)->border_width;
1868 GtkNotebookPage *page;
1869 GtkAllocation child_allocation;
1872 child_allocation.x = widget->allocation.x + border_width;
1873 child_allocation.y = widget->allocation.y + border_width;
1874 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1875 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1877 if (notebook->show_tabs || notebook->show_border)
1879 child_allocation.x += widget->style->xthickness;
1880 child_allocation.y += widget->style->ythickness;
1881 child_allocation.width = MAX (1, child_allocation.width -
1882 widget->style->xthickness * 2);
1883 child_allocation.height = MAX (1, child_allocation.height -
1884 widget->style->ythickness * 2);
1886 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1891 child_allocation.y += notebook->cur_page->requisition.height;
1892 case GTK_POS_BOTTOM:
1893 child_allocation.height =
1894 MAX (1, child_allocation.height -
1895 notebook->cur_page->requisition.height);
1898 child_allocation.x += notebook->cur_page->requisition.width;
1900 child_allocation.width =
1901 MAX (1, child_allocation.width -
1902 notebook->cur_page->requisition.width);
1908 children = notebook->children;
1911 page = children->data;
1912 children = children->next;
1914 if (GTK_WIDGET_VISIBLE (page->child))
1916 gtk_widget_size_allocate (page->child, &child_allocation);
1921 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1926 gtk_notebook_expose (GtkWidget *widget,
1927 GdkEventExpose *event)
1929 GtkNotebook *notebook;
1930 GdkRectangle child_area;
1932 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1933 g_return_val_if_fail (event != NULL, FALSE);
1935 if (GTK_WIDGET_DRAWABLE (widget))
1937 notebook = GTK_NOTEBOOK (widget);
1939 gtk_notebook_paint (widget, &event->area);
1940 if (notebook->show_tabs)
1942 if (notebook->cur_page &&
1943 gtk_widget_intersect (notebook->cur_page->tab_label,
1944 &event->area, &child_area))
1945 gtk_notebook_draw_focus (widget);
1949 if (notebook->cur_page)
1950 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1951 notebook->cur_page->child,
1959 gtk_notebook_show_arrows (GtkNotebook *notebook)
1961 gboolean show_arrow = FALSE;
1964 if (!notebook->scrollable)
1967 children = notebook->children;
1970 GtkNotebookPage *page = children->data;
1972 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1975 children = children->next;
1982 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1983 GdkRectangle *rectangle,
1984 GtkNotebookArrow arrow)
1986 GdkRectangle event_window_pos;
1987 gboolean before = ARROW_IS_BEFORE (arrow);
1988 gboolean left = ARROW_IS_LEFT (arrow);
1990 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1992 rectangle->width = ARROW_SIZE;
1993 rectangle->height = ARROW_SIZE;
1995 switch (notebook->tab_pos)
1999 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
2000 (!before && (notebook->has_after_previous != notebook->has_after_next)))
2001 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
2003 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
2005 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
2006 rectangle->y = event_window_pos.y;
2008 rectangle->y += event_window_pos.height - rectangle->height;
2011 case GTK_POS_BOTTOM:
2014 if (left || !notebook->has_before_previous)
2015 rectangle->x = event_window_pos.x;
2017 rectangle->x = event_window_pos.x + rectangle->width;
2021 if (!left || !notebook->has_after_next)
2022 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
2024 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
2026 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
2032 static GtkNotebookArrow
2033 gtk_notebook_get_arrow (GtkNotebook *notebook,
2037 GdkRectangle arrow_rect;
2038 GdkRectangle event_window_pos;
2041 GtkNotebookArrow arrow[4];
2043 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2044 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2045 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2046 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2048 if (gtk_notebook_show_arrows (notebook))
2050 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
2051 for (i = 0; i < 4; i++)
2053 if (arrow[i] == ARROW_NONE)
2056 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
2058 x0 = x - arrow_rect.x;
2059 y0 = y - arrow_rect.y;
2061 if (y0 >= 0 && y0 < arrow_rect.height &&
2062 x0 >= 0 && x0 < arrow_rect.width)
2071 gtk_notebook_do_arrow (GtkNotebook *notebook,
2072 GtkNotebookArrow arrow)
2074 GtkWidget *widget = GTK_WIDGET (notebook);
2075 GtkDirectionType dir;
2076 gboolean is_rtl, left;
2078 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2079 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2080 (!ARROW_IS_LEFT (arrow) && is_rtl);
2082 if (!notebook->focus_tab ||
2083 gtk_notebook_search_page (notebook, notebook->focus_tab,
2084 left ? STEP_PREV : STEP_NEXT,
2087 if (notebook->tab_pos == GTK_POS_LEFT ||
2088 notebook->tab_pos == GTK_POS_RIGHT)
2089 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
2091 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
2092 gtk_widget_child_focus (widget, dir);
2097 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
2098 GtkNotebookArrow arrow,
2099 GdkEventButton *event)
2101 GtkWidget *widget = GTK_WIDGET (notebook);
2102 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2103 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2104 (!ARROW_IS_LEFT (arrow) && is_rtl);
2106 if (!GTK_WIDGET_HAS_FOCUS (widget))
2107 gtk_widget_grab_focus (widget);
2109 notebook->button = event->button;
2110 notebook->click_child = arrow;
2112 if (event->button == 1)
2114 gtk_notebook_do_arrow (notebook, arrow);
2116 if (!notebook->timer)
2118 GtkSettings *settings = gtk_widget_get_settings (widget);
2121 g_object_get (settings, "gtk-timeout-initial", &timeout, NULL);
2123 notebook->timer = g_timeout_add (timeout,
2124 (GSourceFunc) gtk_notebook_timer,
2125 (gpointer) notebook);
2126 notebook->need_timer = TRUE;
2129 else if (event->button == 2)
2130 gtk_notebook_page_select (notebook, TRUE);
2131 else if (event->button == 3)
2132 gtk_notebook_switch_focus_tab (notebook,
2133 gtk_notebook_search_page (notebook,
2135 left ? STEP_NEXT : STEP_PREV,
2137 gtk_notebook_redraw_arrows (notebook);
2143 get_widget_coordinates (GtkWidget *widget,
2148 GdkWindow *window = ((GdkEventAny *)event)->window;
2151 if (!gdk_event_get_coords (event, &tx, &ty))
2154 while (window && window != widget->window)
2156 gint window_x, window_y;
2158 gdk_window_get_position (window, &window_x, &window_y);
2162 window = gdk_window_get_parent (window);
2177 gtk_notebook_scroll (GtkWidget *widget,
2178 GdkEventScroll *event)
2180 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2183 GtkWidget* originator;
2185 if (!notebook->cur_page)
2188 child = notebook->cur_page->child;
2189 originator = gtk_get_event_widget ((GdkEvent *)event);
2191 /* ignore scroll events from the content of the page */
2192 if (!originator || gtk_widget_is_ancestor (originator, child))
2195 switch (event->direction)
2197 case GDK_SCROLL_RIGHT:
2198 case GDK_SCROLL_DOWN:
2199 gtk_notebook_next_page (notebook);
2201 case GDK_SCROLL_LEFT:
2203 gtk_notebook_prev_page (notebook);
2211 gtk_notebook_button_press (GtkWidget *widget,
2212 GdkEventButton *event)
2214 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2215 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2216 GtkNotebookPage *page;
2218 GtkNotebookArrow arrow;
2222 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
2226 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2229 arrow = gtk_notebook_get_arrow (notebook, x, y);
2231 return gtk_notebook_arrow_button_press (notebook, arrow, event);
2233 if (event->button == 3 && notebook->menu)
2235 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2236 NULL, NULL, 3, event->time);
2240 if (event->button != 1)
2243 notebook->button = event->button;
2245 children = notebook->children;
2249 page = children->data;
2251 if (GTK_WIDGET_VISIBLE (page->child) &&
2252 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
2253 (x >= page->allocation.x) &&
2254 (y >= page->allocation.y) &&
2255 (x <= (page->allocation.x + page->allocation.width)) &&
2256 (y <= (page->allocation.y + page->allocation.height)))
2258 gboolean page_changed = page != notebook->cur_page;
2259 gboolean was_focus = gtk_widget_is_focus (widget);
2261 gtk_notebook_switch_focus_tab (notebook, children);
2262 gtk_widget_grab_focus (widget);
2264 if (page_changed && !was_focus)
2265 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
2267 /* save press to possibly begin a drag */
2268 if (page->reorderable || page->detachable)
2270 priv->during_detach = FALSE;
2271 priv->pressed_button = event->button;
2272 gtk_grab_add (widget);
2277 children = children->next;
2285 popup_position_func (GtkMenu *menu,
2291 GtkNotebook *notebook = data;
2293 GtkRequisition requisition;
2295 if (notebook->focus_tab)
2297 GtkNotebookPage *page;
2299 page = notebook->focus_tab->data;
2300 w = page->tab_label;
2304 w = GTK_WIDGET (notebook);
2307 gdk_window_get_origin (w->window, x, y);
2308 gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
2310 if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
2311 *x += w->allocation.x + w->allocation.width - requisition.width;
2313 *x += w->allocation.x;
2315 *y += w->allocation.y + w->allocation.height;
2321 gtk_notebook_popup_menu (GtkWidget *widget)
2323 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2327 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2328 popup_position_func, notebook,
2329 0, gtk_get_current_event_time ());
2330 gtk_menu_shell_select_first (GTK_MENU_SHELL (notebook->menu), FALSE);
2338 stop_scrolling (GtkNotebook *notebook)
2340 if (notebook->timer)
2342 g_source_remove (notebook->timer);
2343 notebook->timer = 0;
2344 notebook->need_timer = FALSE;
2346 notebook->click_child = 0;
2347 notebook->button = 0;
2348 gtk_notebook_redraw_arrows (notebook);
2352 get_drop_position (GtkNotebook *notebook,
2358 GtkNotebookPage *page;
2361 is_rtl = gtk_widget_get_direction ((GtkWidget *) notebook) == GTK_TEXT_DIR_RTL;
2362 children = notebook->children;
2366 page = children->data;
2368 if (GTK_WIDGET_VISIBLE (page->child) &&
2370 GTK_WIDGET_MAPPED (page->tab_label) &&
2373 switch (notebook->tab_pos)
2376 case GTK_POS_BOTTOM:
2379 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) > x) ||
2380 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) < x))
2385 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) < x) ||
2386 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) > x))
2393 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_Y (page) > y) ||
2394 (page->pack == GTK_PACK_END && PAGE_MIDDLE_Y (page) < y))
2401 children = children->next;
2408 gtk_notebook_button_release (GtkWidget *widget,
2409 GdkEventButton *event)
2411 GtkNotebook *notebook;
2412 GtkNotebookPrivate *priv;
2414 gint old_page_num, page_num;
2416 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2417 g_return_val_if_fail (event != NULL, FALSE);
2419 if (event->type != GDK_BUTTON_RELEASE)
2422 notebook = GTK_NOTEBOOK (widget);
2423 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2425 if (notebook->cur_page->reorderable &&
2426 event->button == priv->pressed_button)
2428 gtk_grab_remove (widget);
2429 priv->pressed_button = -1;
2431 if (!priv->during_detach)
2433 element = get_drop_position (notebook,
2434 notebook->cur_page->pack,
2435 PAGE_MIDDLE_X (notebook->cur_page),
2436 PAGE_MIDDLE_Y (notebook->cur_page));
2437 old_page_num = g_list_position (notebook->children, notebook->focus_tab);
2438 page_num = reorder_tab (notebook, element, notebook->focus_tab);
2440 if (priv->has_scrolled ||
2441 old_page_num != page_num)
2442 g_signal_emit (notebook,
2443 notebook_signals[TAB_REORDERED], 0,
2444 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
2447 priv->has_scrolled = FALSE;
2450 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
2452 if (priv->dnd_timer)
2454 g_source_remove (priv->dnd_timer);
2455 priv->dnd_timer = 0;
2459 if (event->button == notebook->button)
2461 stop_scrolling (notebook);
2470 gtk_notebook_enter_notify (GtkWidget *widget,
2471 GdkEventCrossing *event)
2473 GtkNotebook *notebook;
2474 GtkNotebookArrow arrow;
2477 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2478 g_return_val_if_fail (event != NULL, FALSE);
2480 notebook = GTK_NOTEBOOK (widget);
2482 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2485 arrow = gtk_notebook_get_arrow (notebook, x, y);
2487 if (arrow != notebook->in_child)
2489 notebook->in_child = arrow;
2490 gtk_notebook_redraw_arrows (notebook);
2499 gtk_notebook_leave_notify (GtkWidget *widget,
2500 GdkEventCrossing *event)
2502 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2505 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2508 if (notebook->in_child)
2510 notebook->in_child = 0;
2511 gtk_notebook_redraw_arrows (notebook);
2517 static GtkNotebookPointerPosition
2518 get_pointer_position (GtkNotebook *notebook)
2520 GtkWidget *widget = (GtkWidget *) notebook;
2521 GtkContainer *container = (GtkContainer *) notebook;
2522 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2525 if (!notebook->scrollable)
2526 return POINTER_BETWEEN;
2528 if (notebook->tab_pos == GTK_POS_TOP ||
2529 notebook->tab_pos == GTK_POS_BOTTOM)
2531 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2533 if (priv->mouse_x > widget->allocation.width - 2 * container->border_width - SCROLL_THRESHOLD)
2534 return (is_rtl) ? POINTER_BEFORE : POINTER_AFTER;
2535 else if (priv->mouse_x < SCROLL_THRESHOLD + container->border_width)
2536 return (is_rtl) ? POINTER_AFTER : POINTER_BEFORE;
2538 return POINTER_BETWEEN;
2542 if (priv->mouse_y > widget->allocation.height - 2 * container->border_width - SCROLL_THRESHOLD)
2543 return POINTER_AFTER;
2544 else if (priv->mouse_y < SCROLL_THRESHOLD + container->border_width)
2545 return POINTER_BEFORE;
2547 return POINTER_BETWEEN;
2552 scroll_notebook_timer (gpointer data)
2554 GtkNotebook *notebook = (GtkNotebook *) data;
2555 GtkNotebookPrivate *priv;
2556 GtkNotebookPointerPosition pointer_position;
2557 GList *element, *first_tab;
2559 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2560 pointer_position = get_pointer_position (notebook);
2562 element = get_drop_position (notebook,
2563 notebook->cur_page->pack,
2564 PAGE_MIDDLE_X (notebook->cur_page),
2565 PAGE_MIDDLE_Y (notebook->cur_page));
2567 reorder_tab (notebook, element, notebook->focus_tab);
2569 first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
2570 (pointer_position == POINTER_BEFORE) ? STEP_PREV : STEP_NEXT,
2574 notebook->first_tab = first_tab;
2575 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2582 check_threshold (GtkNotebook *notebook,
2587 gint dnd_threshold, width, height;
2588 GdkRectangle rectangle = { 0, }; /* shut up gcc */
2589 GtkSettings *settings;
2591 widget = GTK_WIDGET (notebook);
2592 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2593 g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &dnd_threshold, NULL);
2595 gdk_drawable_get_size (GDK_DRAWABLE (notebook->event_window), &width, &height);
2597 /* we want a large threshold */
2598 dnd_threshold *= DND_THRESHOLD_MULTIPLIER;
2600 rectangle.x = - dnd_threshold;
2601 rectangle.width = width + 2 * dnd_threshold;
2602 rectangle.y = - dnd_threshold;
2603 rectangle.height = height + 2 * dnd_threshold;
2605 return (current_x < rectangle.x ||
2606 current_x > rectangle.x + rectangle.width ||
2607 current_y < rectangle.y ||
2608 current_y > rectangle.y + rectangle.height);
2612 gtk_notebook_motion_notify (GtkWidget *widget,
2613 GdkEventMotion *event)
2615 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2616 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2617 GtkNotebookPointerPosition pointer_position;
2618 GtkSettings *settings;
2622 if (priv->pressed_button == -1)
2625 if (!notebook->cur_page)
2628 priv->mouse_x = (gint) event->x;
2629 priv->mouse_y = (gint) event->y;
2631 if (notebook->cur_page->detachable &&
2632 check_threshold (notebook, priv->mouse_x, priv->mouse_y))
2634 /* move the page to the current position */
2635 element = get_drop_position (notebook,
2636 notebook->cur_page->pack,
2637 PAGE_MIDDLE_X (notebook->cur_page),
2638 PAGE_MIDDLE_Y (notebook->cur_page));
2639 reorder_tab (notebook, element, notebook->focus_tab);
2640 priv->during_detach = TRUE;
2642 gtk_drag_begin (widget, priv->source_targets, GDK_ACTION_MOVE,
2643 priv->pressed_button, (GdkEvent*) event);
2647 if (notebook->cur_page->reorderable)
2649 pointer_position = get_pointer_position (notebook);
2651 if (pointer_position != POINTER_BETWEEN &&
2652 gtk_notebook_show_arrows (notebook))
2654 if (!priv->dnd_timer)
2656 priv->has_scrolled = TRUE;
2657 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2658 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
2660 priv->dnd_timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
2661 (GSourceFunc) scroll_notebook_timer,
2662 (gpointer) notebook);
2667 if (priv->dnd_timer)
2669 g_source_remove (priv->dnd_timer);
2670 priv->dnd_timer = 0;
2674 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2681 gtk_notebook_grab_notify (GtkWidget *widget,
2682 gboolean was_grabbed)
2685 stop_scrolling (GTK_NOTEBOOK (widget));
2689 gtk_notebook_state_changed (GtkWidget *widget,
2690 GtkStateType previous_state)
2692 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2693 stop_scrolling (GTK_NOTEBOOK (widget));
2697 gtk_notebook_focus_in (GtkWidget *widget,
2698 GdkEventFocus *event)
2700 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2702 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2708 gtk_notebook_focus_out (GtkWidget *widget,
2709 GdkEventFocus *event)
2711 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2717 gtk_notebook_draw_focus (GtkWidget *widget)
2719 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2721 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2722 notebook->focus_tab)
2724 GtkNotebookPage *page;
2728 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2730 page = notebook->focus_tab->data;
2732 area.x = page->tab_label->allocation.x - focus_width;
2733 area.y = page->tab_label->allocation.y - focus_width;
2734 area.width = page->tab_label->allocation.width + 2 * focus_width;
2735 area.height = page->tab_label->allocation.height + 2 * focus_width;
2737 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2742 gtk_notebook_style_set (GtkWidget *widget,
2745 GtkNotebook *notebook;
2747 gboolean has_before_previous;
2748 gboolean has_before_next;
2749 gboolean has_after_previous;
2750 gboolean has_after_next;
2752 notebook = GTK_NOTEBOOK (widget);
2754 gtk_widget_style_get (widget,
2755 "has-backward-stepper", &has_before_previous,
2756 "has-secondary-forward-stepper", &has_before_next,
2757 "has-secondary-backward-stepper", &has_after_previous,
2758 "has-forward-stepper", &has_after_next,
2761 notebook->has_before_previous = has_before_previous;
2762 notebook->has_before_next = has_before_next;
2763 notebook->has_after_previous = has_after_previous;
2764 notebook->has_after_next = has_after_next;
2766 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2770 gtk_notebook_drag_begin (GtkWidget *widget,
2771 GdkDragContext *context)
2773 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
2774 GtkNotebook *notebook = (GtkNotebook*) widget;
2775 GtkWidget *tab_label;
2778 if (priv->dnd_timer)
2780 g_source_remove (priv->dnd_timer);
2781 priv->dnd_timer = 0;
2784 tab_label = notebook->cur_page->tab_label;
2786 pixmap = gdk_pixmap_new (tab_label->window,
2787 tab_label->allocation.width + 2,
2788 tab_label->allocation.height + 2,
2791 gdk_draw_drawable (pixmap,
2792 tab_label->style->base_gc [GTK_WIDGET_STATE (widget)],
2794 tab_label->allocation.x,
2795 tab_label->allocation.y,
2798 gdk_draw_rectangle (pixmap,
2799 widget->style->black_gc,
2802 tab_label->allocation.width + 1,
2803 tab_label->allocation.height + 1);
2805 gtk_drag_set_icon_pixmap (context,
2806 gdk_drawable_get_colormap (pixmap),
2811 gtk_notebook_pages_allocate (GTK_NOTEBOOK (widget), DRAG_OPERATION_DETACH);
2815 gtk_notebook_drag_motion (GtkWidget *widget,
2816 GdkDragContext *context,
2821 GtkWidget *source_widget;
2822 gint widget_group, source_widget_group;
2824 source_widget = gtk_drag_get_source_widget (context);
2826 g_assert (source_widget);
2828 widget_group = gtk_notebook_get_group_id (GTK_NOTEBOOK (widget));
2829 source_widget_group = gtk_notebook_get_group_id (GTK_NOTEBOOK (source_widget));
2831 if (widget_group != -1 &&
2832 source_widget_group != -1 &&
2833 widget_group == source_widget_group)
2836 gdk_drag_status (context, 0, time);
2842 gtk_notebook_drag_drop (GtkWidget *widget,
2843 GdkDragContext *context,
2850 target = gtk_drag_dest_find_target (widget, context, NULL);
2852 if (target == GDK_NONE)
2853 gtk_drag_finish (context, FALSE, FALSE, time);
2859 do_detach_tab (GtkNotebook *from,
2861 GtkNotebookPage *page_info,
2865 GtkWidget *child, *tab_label, *menu_label;
2866 gboolean tab_expand, tab_fill, reorderable, detachable;
2871 menu_label = tab_label = child = NULL;
2873 if (page_info->menu_label)
2874 menu_label = g_object_ref (page_info->menu_label);
2876 if (page_info->tab_label)
2877 tab_label = g_object_ref (page_info->tab_label);
2879 if (page_info->child)
2880 child = g_object_ref (page_info->child);
2882 /* preserve properties */
2883 tab_expand = page_info->expand;
2884 tab_fill = page_info->fill;
2885 tab_pack = page_info->pack;
2886 reorderable = page_info->reorderable;
2887 detachable = page_info->detachable;
2889 gtk_container_remove (GTK_CONTAINER (from), child);
2891 element = get_drop_position (to,
2893 GTK_WIDGET (to)->allocation.x + x,
2894 GTK_WIDGET (to)->allocation.y + y);
2896 page_num = g_list_position (to->children, element);
2897 gtk_notebook_insert_page_menu (to, child, tab_label, menu_label, page_num);
2899 gtk_container_child_set (GTK_CONTAINER (to), child,
2900 "tab-pack", tab_pack,
2901 "tab-expand", tab_expand,
2902 "tab-fill", tab_fill,
2903 "reorderable", reorderable,
2904 "detachable", detachable,
2907 g_object_unref (child);
2910 g_object_unref (tab_label);
2913 g_object_unref (menu_label);
2915 gtk_notebook_set_current_page (to, page_num);
2919 gtk_notebook_drag_data_get (GtkWidget *widget,
2920 GdkDragContext *context,
2921 GtkSelectionData *data,
2925 GtkNotebook *dest_notebook, *notebook;
2928 if (data->target != gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB") &&
2929 (data->target != gdk_atom_intern_static_string ("application/x-rootwindow-drop") ||
2930 !window_creation_hook))
2933 notebook = GTK_NOTEBOOK (widget);
2934 page_num = g_list_index (notebook->children, notebook->cur_page);
2936 if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
2938 gtk_selection_data_set (data,
2941 (void*) notebook->cur_page,
2942 sizeof (GtkNotebookPage));
2946 GdkDisplay *display;
2949 display = gtk_widget_get_display (widget);
2950 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
2952 dest_notebook = (* window_creation_hook) (notebook,
2953 notebook->cur_page->child,
2955 window_creation_hook_data);
2958 do_detach_tab (notebook, dest_notebook, notebook->cur_page, 0, 0);
2963 gtk_notebook_drag_data_received (GtkWidget *widget,
2964 GdkDragContext *context,
2967 GtkSelectionData *data,
2971 GtkNotebook *notebook;
2972 GtkWidget *source_widget;
2973 GtkNotebookPage *page_info;
2975 notebook = GTK_NOTEBOOK (widget);
2976 source_widget = gtk_drag_get_source_widget (context);
2978 if (source_widget &&
2979 data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
2981 page_info = (void*) data->data;
2983 do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, page_info, x, y);
2984 gtk_drag_finish (context, TRUE, FALSE, time);
2987 gtk_drag_finish (context, FALSE, FALSE, time);
2990 /* Private GtkContainer Methods :
2992 * gtk_notebook_set_child_arg
2993 * gtk_notebook_get_child_arg
2995 * gtk_notebook_remove
2996 * gtk_notebook_focus
2997 * gtk_notebook_set_focus_child
2998 * gtk_notebook_child_type
2999 * gtk_notebook_forall
3002 gtk_notebook_set_child_property (GtkContainer *container,
3005 const GValue *value,
3010 GtkPackType pack_type;
3012 /* not finding child's page is valid for menus or labels */
3013 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
3016 switch (property_id)
3018 case CHILD_PROP_TAB_LABEL:
3019 /* a NULL pointer indicates a default_tab setting, otherwise
3020 * we need to set the associated label
3022 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
3023 g_value_get_string (value));
3025 case CHILD_PROP_MENU_LABEL:
3026 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
3027 g_value_get_string (value));
3029 case CHILD_PROP_POSITION:
3030 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
3031 g_value_get_int (value));
3033 case CHILD_PROP_TAB_EXPAND:
3034 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3035 &expand, &fill, &pack_type);
3036 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3037 g_value_get_boolean (value),
3040 case CHILD_PROP_TAB_FILL:
3041 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3042 &expand, &fill, &pack_type);
3043 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3045 g_value_get_boolean (value),
3048 case CHILD_PROP_TAB_PACK:
3049 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3050 &expand, &fill, &pack_type);
3051 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3053 g_value_get_enum (value));
3055 case CHILD_PROP_REORDERABLE:
3056 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (container), child,
3057 g_value_get_boolean (value));
3059 case CHILD_PROP_DETACHABLE:
3060 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (container), child,
3061 g_value_get_boolean (value));
3064 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3070 gtk_notebook_get_child_property (GtkContainer *container,
3077 GtkNotebook *notebook;
3081 GtkPackType pack_type;
3083 notebook = GTK_NOTEBOOK (container);
3085 /* not finding child's page is valid for menus or labels */
3086 list = gtk_notebook_find_child (notebook, child, NULL);
3089 /* nothing to set on labels or menus */
3090 g_param_value_set_default (pspec, value);
3094 switch (property_id)
3096 case CHILD_PROP_TAB_LABEL:
3097 label = gtk_notebook_get_tab_label (notebook, child);
3099 if (label && GTK_IS_LABEL (label))
3100 g_value_set_string (value, GTK_LABEL (label)->label);
3102 g_value_set_string (value, NULL);
3104 case CHILD_PROP_MENU_LABEL:
3105 label = gtk_notebook_get_menu_label (notebook, child);
3107 if (label && GTK_IS_LABEL (label))
3108 g_value_set_string (value, GTK_LABEL (label)->label);
3110 g_value_set_string (value, NULL);
3112 case CHILD_PROP_POSITION:
3113 g_value_set_int (value, g_list_position (notebook->children, list));
3115 case CHILD_PROP_TAB_EXPAND:
3116 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3117 &expand, NULL, NULL);
3118 g_value_set_boolean (value, expand);
3120 case CHILD_PROP_TAB_FILL:
3121 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3123 g_value_set_boolean (value, fill);
3125 case CHILD_PROP_TAB_PACK:
3126 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3127 NULL, NULL, &pack_type);
3128 g_value_set_enum (value, pack_type);
3130 case CHILD_PROP_REORDERABLE:
3131 g_value_set_boolean (value,
3132 gtk_notebook_get_tab_reorderable (GTK_NOTEBOOK (container), child));
3134 case CHILD_PROP_DETACHABLE:
3135 g_value_set_boolean (value,
3136 gtk_notebook_get_tab_detachable (GTK_NOTEBOOK (container), child));
3139 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3145 gtk_notebook_add (GtkContainer *container,
3148 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3150 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
3155 gtk_notebook_remove (GtkContainer *container,
3158 GtkNotebook *notebook;
3159 GtkNotebookPage *page;
3163 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3164 g_return_if_fail (widget != NULL);
3166 notebook = GTK_NOTEBOOK (container);
3168 children = notebook->children;
3171 page = children->data;
3173 if (page->child == widget)
3177 children = children->next;
3180 g_signal_emit (notebook,
3181 notebook_signals[TAB_REMOVED],
3186 gtk_notebook_real_remove (notebook, children, FALSE);
3190 focus_tabs_in (GtkNotebook *notebook)
3192 if (notebook->show_tabs && notebook->cur_page)
3194 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3196 gtk_notebook_switch_focus_tab (notebook,
3197 g_list_find (notebook->children,
3198 notebook->cur_page));
3207 focus_tabs_move (GtkNotebook *notebook,
3208 GtkDirectionType direction,
3209 gint search_direction)
3213 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
3214 search_direction, TRUE);
3216 gtk_notebook_switch_focus_tab (notebook, new_page);
3218 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
3224 focus_child_in (GtkNotebook *notebook,
3225 GtkDirectionType direction)
3227 if (notebook->cur_page)
3228 return gtk_widget_child_focus (notebook->cur_page->child, direction);
3233 /* Focus in the notebook can either be on the pages, or on
3237 gtk_notebook_focus (GtkWidget *widget,
3238 GtkDirectionType direction)
3240 GtkWidget *old_focus_child;
3241 GtkNotebook *notebook;
3242 GtkDirectionType effective_direction;
3244 gboolean widget_is_focus;
3245 GtkContainer *container;
3247 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3249 container = GTK_CONTAINER (widget);
3250 notebook = GTK_NOTEBOOK (container);
3252 if (notebook->focus_out)
3254 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
3258 widget_is_focus = gtk_widget_is_focus (widget);
3259 old_focus_child = container->focus_child;
3261 effective_direction = get_effective_direction (notebook, direction);
3263 if (old_focus_child) /* Focus on page child */
3265 if (gtk_widget_child_focus (old_focus_child, direction))
3268 switch (effective_direction)
3270 case GTK_DIR_TAB_BACKWARD:
3272 /* Focus onto the tabs */
3273 return focus_tabs_in (notebook);
3275 case GTK_DIR_TAB_FORWARD:
3281 else if (widget_is_focus) /* Focus was on tabs */
3283 switch (effective_direction)
3285 case GTK_DIR_TAB_BACKWARD:
3288 case GTK_DIR_TAB_FORWARD:
3290 /* We use TAB_FORWARD rather than direction so that we focus a more
3291 * predictable widget for the user; users may be using arrow focusing
3292 * in this situation even if they don't usually use arrow focusing.
3294 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
3296 return focus_tabs_move (notebook, direction, STEP_PREV);
3298 return focus_tabs_move (notebook, direction, STEP_NEXT);
3301 else /* Focus was not on widget */
3303 switch (effective_direction)
3305 case GTK_DIR_TAB_FORWARD:
3307 if (focus_tabs_in (notebook))
3309 if (focus_child_in (notebook, direction))
3312 case GTK_DIR_TAB_BACKWARD:
3314 if (focus_child_in (notebook, direction))
3316 if (focus_tabs_in (notebook))
3321 return focus_child_in (notebook, direction);
3325 g_assert_not_reached ();
3330 gtk_notebook_set_focus_child (GtkContainer *container,
3333 GtkNotebook *notebook = GTK_NOTEBOOK (container);
3334 GtkWidget *page_child;
3335 GtkWidget *toplevel;
3337 /* If the old focus widget was within a page of the notebook,
3338 * (child may either be NULL or not in this case), record it
3339 * for future use if we switch to the page with a mnemonic.
3342 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
3343 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
3345 page_child = GTK_WINDOW (toplevel)->focus_widget;
3348 if (page_child->parent == GTK_WIDGET (container))
3350 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
3353 GtkNotebookPage *page = list->data;
3355 if (page->last_focus_child)
3356 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3358 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
3359 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3365 page_child = page_child->parent;
3371 g_return_if_fail (GTK_IS_WIDGET (child));
3373 notebook->child_has_focus = TRUE;
3374 if (!notebook->focus_tab)
3377 GtkNotebookPage *page;
3379 children = notebook->children;
3382 page = children->data;
3383 if (page->child == child || page->tab_label == child)
3384 gtk_notebook_switch_focus_tab (notebook, children);
3385 children = children->next;
3390 parent_class->set_focus_child (container, child);
3394 gtk_notebook_forall (GtkContainer *container,
3395 gboolean include_internals,
3396 GtkCallback callback,
3397 gpointer callback_data)
3399 GtkNotebook *notebook;
3402 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3403 g_return_if_fail (callback != NULL);
3405 notebook = GTK_NOTEBOOK (container);
3407 children = notebook->children;
3410 GtkNotebookPage *page;
3412 page = children->data;
3413 children = children->next;
3414 (* callback) (page->child, callback_data);
3415 if (include_internals)
3417 if (page->tab_label)
3418 (* callback) (page->tab_label, callback_data);
3424 gtk_notebook_child_type (GtkContainer *container)
3426 return GTK_TYPE_WIDGET;
3429 /* Private GtkNotebook Methods:
3431 * gtk_notebook_real_insert_page
3434 page_visible_cb (GtkWidget *page,
3438 GtkNotebook *notebook = (GtkNotebook *)data;
3442 if (notebook->cur_page &&
3443 notebook->cur_page->child == page &&
3444 !GTK_WIDGET_VISIBLE (page))
3446 list = g_list_find (notebook->children, notebook->cur_page);
3449 next = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3451 next = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3455 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next), -1);
3460 gtk_notebook_real_insert_page (GtkNotebook *notebook,
3462 GtkWidget *tab_label,
3463 GtkWidget *menu_label,
3466 GtkNotebookPage *page;
3469 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3470 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
3471 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
3472 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
3474 gtk_widget_freeze_child_notify (child);
3476 page = g_new (GtkNotebookPage, 1);
3477 page->child = child;
3478 page->last_focus_child = NULL;
3479 page->requisition.width = 0;
3480 page->requisition.height = 0;
3481 page->allocation.x = 0;
3482 page->allocation.y = 0;
3483 page->allocation.width = 0;
3484 page->allocation.height = 0;
3485 page->default_menu = FALSE;
3486 page->default_tab = FALSE;
3487 page->mnemonic_activate_signal = 0;
3488 page->reorderable = FALSE;
3489 page->detachable = FALSE;
3491 nchildren = g_list_length (notebook->children);
3492 if ((position < 0) || (position > nchildren))
3493 position = nchildren;
3495 notebook->children = g_list_insert (notebook->children, page, position);
3499 page->default_tab = TRUE;
3500 if (notebook->show_tabs)
3501 tab_label = gtk_label_new ("");
3503 page->tab_label = tab_label;
3504 page->menu_label = menu_label;
3505 page->expand = FALSE;
3507 page->pack = GTK_PACK_START;
3510 page->default_menu = TRUE;
3513 g_object_ref_sink (page->menu_label);
3517 gtk_notebook_menu_item_create (notebook,
3518 g_list_find (notebook->children, page));
3520 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3522 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3524 gtk_notebook_update_labels (notebook);
3526 if (!notebook->first_tab)
3527 notebook->first_tab = notebook->children;
3529 /* child visible will be turned on by switch_page below */
3530 gtk_widget_set_child_visible (child, FALSE);
3534 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3535 gtk_widget_show (tab_label);
3537 gtk_widget_hide (tab_label);
3540 if (!notebook->cur_page)
3542 gtk_notebook_switch_page (notebook, page, 0);
3543 gtk_notebook_switch_focus_tab (notebook, NULL);
3546 page->notify_visible_handler = g_signal_connect (G_OBJECT (child), "notify::visible",
3547 G_CALLBACK (page_visible_cb), notebook);
3548 gtk_notebook_update_tab_states (notebook);
3551 page->mnemonic_activate_signal =
3552 g_signal_connect (tab_label,
3553 "mnemonic_activate",
3554 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
3557 gtk_widget_child_notify (child, "tab-expand");
3558 gtk_widget_child_notify (child, "tab-fill");
3559 gtk_widget_child_notify (child, "tab-pack");
3560 gtk_widget_child_notify (child, "tab-label");
3561 gtk_widget_child_notify (child, "menu-label");
3562 gtk_widget_child_notify (child, "position");
3563 gtk_widget_thaw_child_notify (child);
3565 g_signal_emit (notebook,
3566 notebook_signals[TAB_ADDED],
3574 /* Private GtkNotebook Functions:
3576 * gtk_notebook_redraw_tabs
3577 * gtk_notebook_real_remove
3578 * gtk_notebook_update_labels
3579 * gtk_notebook_timer
3580 * gtk_notebook_page_compare
3581 * gtk_notebook_real_page_position
3582 * gtk_notebook_search_page
3585 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
3588 GtkNotebookPage *page;
3589 GdkRectangle redraw_rect;
3591 gint tab_pos = get_effective_tab_pos (notebook);
3593 widget = GTK_WIDGET (notebook);
3594 border = GTK_CONTAINER (notebook)->border_width;
3596 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
3599 page = notebook->first_tab->data;
3601 redraw_rect.x = border;
3602 redraw_rect.y = border;
3606 case GTK_POS_BOTTOM:
3607 redraw_rect.y = (widget->allocation.height - border -
3608 page->allocation.height -
3609 widget->style->ythickness);
3610 if (page != notebook->cur_page)
3611 redraw_rect.y -= widget->style->ythickness;
3614 redraw_rect.width = widget->allocation.width - 2 * border;
3615 redraw_rect.height = (page->allocation.height +
3616 widget->style->ythickness);
3617 if (page != notebook->cur_page)
3618 redraw_rect.height += widget->style->ythickness;
3621 redraw_rect.x = (widget->allocation.width - border -
3622 page->allocation.width -
3623 widget->style->xthickness);
3624 if (page != notebook->cur_page)
3625 redraw_rect.x -= widget->style->xthickness;
3628 redraw_rect.width = (page->allocation.width +
3629 widget->style->xthickness);
3630 redraw_rect.height = widget->allocation.height - 2 * border;
3631 if (page != notebook->cur_page)
3632 redraw_rect.width += widget->style->xthickness;
3636 redraw_rect.x += widget->allocation.x;
3637 redraw_rect.y += widget->allocation.y;
3639 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
3643 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
3645 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
3649 GtkNotebookArrow arrow[4];
3651 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
3652 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
3653 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
3654 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
3656 for (i = 0; i < 4; i++)
3658 if (arrow[i] == ARROW_NONE)
3661 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
3662 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
3669 gtk_notebook_timer (GtkNotebook *notebook)
3671 gboolean retval = FALSE;
3673 GDK_THREADS_ENTER ();
3675 if (notebook->timer)
3677 gtk_notebook_do_arrow (notebook, notebook->click_child);
3679 if (notebook->need_timer)
3681 GtkSettings *settings;
3684 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
3685 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
3687 notebook->need_timer = FALSE;
3688 notebook->timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
3689 (GSourceFunc) gtk_notebook_timer,
3690 (gpointer) notebook);
3696 GDK_THREADS_LEAVE ();
3702 gtk_notebook_page_compare (gconstpointer a,
3705 return (((GtkNotebookPage *) a)->child != b);
3709 gtk_notebook_find_child (GtkNotebook *notebook,
3711 const gchar *function)
3713 GList *list = g_list_find_custom (notebook->children, child,
3714 gtk_notebook_page_compare);
3716 #ifndef G_DISABLE_CHECKS
3717 if (!list && function)
3718 g_warning ("%s: unable to find child %p in notebook %p",
3719 function, child, notebook);
3726 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
3727 GtkNotebookPage *page)
3729 if (page->tab_label)
3731 if (page->mnemonic_activate_signal)
3732 g_signal_handler_disconnect (page->tab_label,
3733 page->mnemonic_activate_signal);
3734 page->mnemonic_activate_signal = 0;
3736 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3737 gtk_widget_unparent (page->tab_label);
3742 gtk_notebook_real_remove (GtkNotebook *notebook,
3744 gboolean destroying)
3746 GtkNotebookPage *page;
3748 gint need_resize = FALSE;
3750 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3752 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3754 if (notebook->cur_page == list->data)
3756 notebook->cur_page = NULL;
3757 if (next_list && !destroying)
3758 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
3761 if (list == notebook->first_tab)
3762 notebook->first_tab = next_list;
3763 if (list == notebook->focus_tab && !destroying)
3764 gtk_notebook_switch_focus_tab (notebook, next_list);
3768 g_signal_handler_disconnect (page->child, page->notify_visible_handler);
3770 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
3773 gtk_widget_unparent (page->child);
3775 gtk_notebook_remove_tab_label (notebook, page);
3779 gtk_container_remove (GTK_CONTAINER (notebook->menu),
3780 page->menu_label->parent);
3781 gtk_widget_queue_resize (notebook->menu);
3783 if (!page->default_menu)
3784 g_object_unref (page->menu_label);
3786 notebook->children = g_list_remove_link (notebook->children, list);
3789 if (page->last_focus_child)
3791 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3792 page->last_focus_child = NULL;
3797 gtk_notebook_update_labels (notebook);
3799 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3803 gtk_notebook_update_labels (GtkNotebook *notebook)
3805 GtkNotebookPage *page;
3810 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
3812 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
3815 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
3816 if (notebook->show_tabs)
3818 if (page->default_tab)
3820 if (!page->tab_label)
3822 page->tab_label = gtk_label_new (string);
3823 gtk_widget_set_parent (page->tab_label,
3824 GTK_WIDGET (notebook));
3827 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
3830 if (GTK_WIDGET_VISIBLE (page->child) &&
3831 !GTK_WIDGET_VISIBLE (page->tab_label))
3832 gtk_widget_show (page->tab_label);
3833 else if (!GTK_WIDGET_VISIBLE (page->child) &&
3834 GTK_WIDGET_VISIBLE (page->tab_label))
3835 gtk_widget_hide (page->tab_label);
3837 if (notebook->menu && page->default_menu)
3839 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3840 gtk_label_set_text (GTK_LABEL (page->menu_label),
3841 GTK_LABEL (page->tab_label)->label);
3843 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
3849 gtk_notebook_real_page_position (GtkNotebook *notebook,
3855 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3856 g_return_val_if_fail (list != NULL, -1);
3858 for (work = notebook->children, count_start = 0;
3859 work && work != list; work = work->next)
3860 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
3866 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
3869 return (count_start + g_list_length (list) - 1);
3873 gtk_notebook_search_page (GtkNotebook *notebook,
3876 gboolean find_visible)
3878 GtkNotebookPage *page = NULL;
3879 GList *old_list = NULL;
3882 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3887 flag = GTK_PACK_END;
3891 flag = GTK_PACK_START;
3898 if (!page || page->pack == flag)
3906 list = notebook->children;
3911 if (page->pack == flag &&
3912 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
3927 if (page->pack != flag &&
3928 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
3936 /* Private GtkNotebook Drawing Functions:
3938 * gtk_notebook_paint
3939 * gtk_notebook_draw_tab
3940 * gtk_notebook_draw_arrow
3943 gtk_notebook_paint (GtkWidget *widget,
3946 GtkNotebook *notebook;
3947 GtkNotebookPage *page;
3952 gint border_width = GTK_CONTAINER (widget)->border_width;
3953 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
3957 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3958 g_return_if_fail (area != NULL);
3960 if (!GTK_WIDGET_DRAWABLE (widget))
3963 notebook = GTK_NOTEBOOK (widget);
3964 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
3965 tab_pos = get_effective_tab_pos (notebook);
3967 if ((!notebook->show_tabs && !notebook->show_border) ||
3968 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
3971 x = widget->allocation.x + border_width;
3972 y = widget->allocation.y + border_width;
3973 width = widget->allocation.width - border_width * 2;
3974 height = widget->allocation.height - border_width * 2;
3976 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
3978 gtk_paint_box (widget->style, widget->window,
3979 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
3980 area, widget, "notebook",
3981 x, y, width, height);
3986 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
3988 page = notebook->first_tab->data;
3993 y += page->allocation.height + widget->style->ythickness;
3994 case GTK_POS_BOTTOM:
3995 height -= page->allocation.height + widget->style->ythickness;
3998 x += page->allocation.width + widget->style->xthickness;
4000 width -= page->allocation.width + widget->style->xthickness;
4003 gtk_paint_box (widget->style, widget->window,
4004 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4005 area, widget, "notebook",
4006 x, y, width, height);
4013 y += notebook->cur_page->allocation.height;
4014 case GTK_POS_BOTTOM:
4015 height -= notebook->cur_page->allocation.height;
4018 x += notebook->cur_page->allocation.width;
4020 width -= notebook->cur_page->allocation.width;
4027 case GTK_POS_BOTTOM:
4028 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
4029 gap_width = notebook->cur_page->allocation.width;
4030 step = is_rtl ? STEP_NEXT : STEP_PREV;
4034 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
4035 gap_width = notebook->cur_page->allocation.height;
4039 gtk_paint_box_gap (widget->style, widget->window,
4040 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4041 area, widget, "notebook",
4042 x, y, width, height,
4043 tab_pos, gap_x, gap_width);
4047 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
4050 page = children->data;
4051 children = gtk_notebook_search_page (notebook, children,
4053 if (!GTK_WIDGET_VISIBLE (page->child))
4055 if (!GTK_WIDGET_MAPPED (page->tab_label))
4057 else if (page != notebook->cur_page)
4058 gtk_notebook_draw_tab (notebook, page, area);
4061 if (showarrow && notebook->scrollable)
4063 if (notebook->has_before_previous)
4064 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
4065 if (notebook->has_before_next)
4066 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
4067 if (notebook->has_after_previous)
4068 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
4069 if (notebook->has_after_next)
4070 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
4072 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
4076 gtk_notebook_draw_tab (GtkNotebook *notebook,
4077 GtkNotebookPage *page,
4080 GdkRectangle child_area;
4081 GdkRectangle page_area;
4082 GtkStateType state_type;
4083 GtkPositionType gap_side;
4084 gint tab_pos = get_effective_tab_pos (notebook);
4086 g_return_if_fail (notebook != NULL);
4087 g_return_if_fail (page != NULL);
4088 g_return_if_fail (area != NULL);
4090 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
4091 (page->allocation.width == 0) || (page->allocation.height == 0))
4094 page_area.x = page->allocation.x;
4095 page_area.y = page->allocation.y;
4096 page_area.width = page->allocation.width;
4097 page_area.height = page->allocation.height;
4099 if (gdk_rectangle_intersect (&page_area, area, &child_area))
4103 widget = GTK_WIDGET (notebook);
4108 gap_side = GTK_POS_BOTTOM;
4110 case GTK_POS_BOTTOM:
4111 gap_side = GTK_POS_TOP;
4114 gap_side = GTK_POS_RIGHT;
4117 gap_side = GTK_POS_LEFT;
4121 if (notebook->cur_page == page)
4122 state_type = GTK_STATE_NORMAL;
4124 state_type = GTK_STATE_ACTIVE;
4125 gtk_paint_extension(widget->style, widget->window,
4126 state_type, GTK_SHADOW_OUT,
4127 area, widget, "tab",
4128 page_area.x, page_area.y,
4129 page_area.width, page_area.height,
4131 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
4132 notebook->focus_tab && (notebook->focus_tab->data == page))
4136 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
4138 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
4139 area, widget, "tab",
4140 page->tab_label->allocation.x - focus_width,
4141 page->tab_label->allocation.y - focus_width,
4142 page->tab_label->allocation.width + 2 * focus_width,
4143 page->tab_label->allocation.height + 2 * focus_width);
4145 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
4146 GTK_WIDGET_DRAWABLE (page->tab_label))
4148 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
4150 /* This is a lame hack since all this code needs rewriting anyhow */
4152 expose_event->expose.window = g_object_ref (page->tab_label->window);
4153 expose_event->expose.area = child_area;
4154 expose_event->expose.region = gdk_region_rectangle (&child_area);
4155 expose_event->expose.send_event = TRUE;
4156 expose_event->expose.count = 0;
4158 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
4160 gdk_event_free (expose_event);
4166 gtk_notebook_draw_arrow (GtkNotebook *notebook,
4167 GtkNotebookArrow nbarrow)
4169 GtkStateType state_type;
4170 GtkShadowType shadow_type;
4172 GdkRectangle arrow_rect;
4174 gboolean is_rtl, left;
4176 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
4178 widget = GTK_WIDGET (notebook);
4180 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
4181 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
4182 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
4184 if (GTK_WIDGET_DRAWABLE (notebook))
4186 if (notebook->in_child == nbarrow)
4188 if (notebook->click_child == nbarrow)
4189 state_type = GTK_STATE_ACTIVE;
4191 state_type = GTK_STATE_PRELIGHT;
4194 state_type = GTK_WIDGET_STATE (widget);
4196 if (notebook->click_child == nbarrow)
4197 shadow_type = GTK_SHADOW_IN;
4199 shadow_type = GTK_SHADOW_OUT;
4201 if (notebook->focus_tab &&
4202 !gtk_notebook_search_page (notebook, notebook->focus_tab,
4203 left? STEP_PREV : STEP_NEXT, TRUE))
4205 shadow_type = GTK_SHADOW_ETCHED_IN;
4206 state_type = GTK_STATE_INSENSITIVE;
4209 if (notebook->tab_pos == GTK_POS_LEFT ||
4210 notebook->tab_pos == GTK_POS_RIGHT)
4211 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
4213 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
4215 gtk_paint_arrow (widget->style, widget->window, state_type,
4216 shadow_type, NULL, widget, "notebook",
4217 arrow, TRUE, arrow_rect.x, arrow_rect.y,
4218 ARROW_SIZE, ARROW_SIZE);
4223 get_notebook_tabs_space (GtkNotebook *notebook, gint *min, gint *max)
4225 GtkWidget *widget = (GtkWidget *) notebook;
4226 GtkContainer *container = (GtkContainer *) notebook;
4228 if (notebook->tab_pos == GTK_POS_TOP ||
4229 notebook->tab_pos == GTK_POS_BOTTOM)
4231 *min = widget->allocation.x + container->border_width;
4232 *max = widget->allocation.x + widget->allocation.width - container->border_width;
4234 if (gtk_notebook_show_arrows (notebook))
4236 if (notebook->has_after_previous)
4237 *max -= ARROW_SPACING + ARROW_SIZE;
4238 if (notebook->has_after_next)
4239 *max -= ARROW_SPACING + ARROW_SIZE;
4240 if (notebook->has_before_previous)
4241 *min += ARROW_SPACING + ARROW_SIZE;
4242 if (notebook->has_before_next)
4243 *min += ARROW_SPACING + ARROW_SIZE;
4248 *min = widget->allocation.y + container->border_width;
4249 *max = widget->allocation.y + widget->allocation.height - container->border_width;
4251 if (gtk_notebook_show_arrows (notebook))
4253 if (notebook->has_after_previous || notebook->has_after_next)
4254 *max -= ARROW_SPACING + ARROW_SIZE;
4255 if (notebook->has_before_previous || notebook->has_before_next)
4256 *min += ARROW_SPACING + ARROW_SIZE;
4261 /* Private GtkNotebook Size Allocate Functions:
4263 * gtk_notebook_pages_allocate
4264 * gtk_notebook_page_allocate
4265 * gtk_notebook_calc_tabs
4268 gtk_notebook_pages_allocate (GtkNotebook *notebook,
4269 GtkNotebookDragOperation operation)
4271 GtkWidget *widget = GTK_WIDGET (notebook);
4272 GtkContainer *container = GTK_CONTAINER (notebook);
4273 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
4274 GtkNotebookPage *page = NULL;
4275 GtkAllocation *allocation = &widget->allocation;
4276 GtkAllocation child_allocation;
4277 GList *children = NULL;
4278 GList *last_child = NULL;
4279 gboolean showarrow = FALSE;
4286 gint tab_pos = get_effective_tab_pos (notebook);
4287 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
4288 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
4290 gint memo_x, anchor_x, anchor_y;
4291 gint min, max, top_y, bottom_y, left_x, right_x;
4292 gboolean packing_changed = FALSE;
4293 gboolean gap_left = FALSE;
4295 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
4298 gtk_widget_style_get (widget, "tab-overlap", &tab_overlap, NULL);
4300 child_allocation.x = widget->allocation.x + container->border_width;
4301 child_allocation.y = widget->allocation.y + container->border_width;
4305 case GTK_POS_BOTTOM:
4306 child_allocation.y = (widget->allocation.y +
4307 allocation->height -
4308 notebook->cur_page->requisition.height -
4309 container->border_width);
4312 child_allocation.height = notebook->cur_page->requisition.height;
4316 child_allocation.x = (widget->allocation.x +
4318 notebook->cur_page->requisition.width -
4319 container->border_width);
4322 child_allocation.width = notebook->cur_page->requisition.width;
4326 if (notebook->scrollable)
4330 children = notebook->children;
4332 if (notebook->focus_tab)
4333 focus_tab = notebook->focus_tab;
4334 else if (notebook->first_tab)
4335 focus_tab = notebook->first_tab;
4337 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
4342 case GTK_POS_BOTTOM:
4345 page = children->data;
4346 children = children->next;
4348 if (GTK_WIDGET_VISIBLE (page->child))
4349 tab_space += page->requisition.width;
4353 allocation->width - 2 * container->border_width - tab_overlap)
4356 page = focus_tab->data;
4358 tab_space = allocation->width - tab_overlap -
4359 page->requisition.width - 2 * container->border_width;
4360 if (notebook->has_after_previous)
4361 tab_space -= ARROW_SPACING + ARROW_SIZE;
4362 if (notebook->has_after_next)
4363 tab_space -= ARROW_SPACING + ARROW_SIZE;
4364 if (notebook->has_before_previous)
4366 tab_space -= ARROW_SPACING + ARROW_SIZE;
4367 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4369 if (notebook->has_before_next)
4371 tab_space -= ARROW_SPACING + ARROW_SIZE;
4372 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4380 page = children->data;
4381 children = children->next;
4383 if (GTK_WIDGET_VISIBLE (page->child))
4384 tab_space += page->requisition.height;
4387 (allocation->height - 2 * container->border_width - tab_overlap))
4390 page = focus_tab->data;
4391 tab_space = allocation->height
4392 - tab_overlap - 2 * container->border_width
4393 - page->requisition.height;
4394 if (notebook->has_after_previous || notebook->has_after_next)
4395 tab_space -= ARROW_SPACING + ARROW_SIZE;
4396 if (notebook->has_before_previous || notebook->has_before_next)
4398 tab_space -= ARROW_SPACING + ARROW_SIZE;
4399 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
4404 if (showarrow) /* first_tab <- focus_tab */
4408 notebook->first_tab = focus_tab;
4409 last_child = gtk_notebook_search_page (notebook, focus_tab,
4415 if (notebook->first_tab && notebook->first_tab != focus_tab)
4417 /* Is first_tab really predecessor of focus_tab ? */
4418 page = notebook->first_tab->data;
4419 if (GTK_WIDGET_VISIBLE (page->child))
4420 for (children = focus_tab;
4421 children && children != notebook->first_tab;
4422 children = gtk_notebook_search_page (notebook,
4428 notebook->first_tab = focus_tab;
4430 gtk_notebook_calc_tabs (notebook,
4431 gtk_notebook_search_page (notebook,
4435 &(notebook->first_tab), &tab_space,
4440 notebook->first_tab =
4441 gtk_notebook_search_page (notebook, notebook->first_tab,
4443 if (!notebook->first_tab)
4444 notebook->first_tab = focus_tab;
4445 last_child = gtk_notebook_search_page (notebook, focus_tab,
4448 else /* focus_tab -> end */
4450 if (!notebook->first_tab)
4451 notebook->first_tab = gtk_notebook_search_page (notebook,
4456 gtk_notebook_calc_tabs (notebook,
4457 gtk_notebook_search_page (notebook,
4461 &children, &tab_space, STEP_NEXT);
4464 last_child = children;
4465 else /* start <- first_tab */
4469 gtk_notebook_calc_tabs
4471 gtk_notebook_search_page (notebook,
4472 notebook->first_tab,
4475 &children, &tab_space, STEP_PREV);
4476 notebook->first_tab = gtk_notebook_search_page(notebook,
4486 tab_space = -tab_space;
4488 for (children = notebook->first_tab;
4489 children && children != last_child;
4490 children = gtk_notebook_search_page (notebook, children,
4497 /*unmap all non-visible tabs*/
4498 for (children = gtk_notebook_search_page (notebook, NULL,
4500 children && children != notebook->first_tab;
4501 children = gtk_notebook_search_page (notebook, children,
4504 page = children->data;
4505 if (page->tab_label)
4506 gtk_widget_set_child_visible (page->tab_label, FALSE);
4508 for (children = last_child; children;
4509 children = gtk_notebook_search_page (notebook, children,
4512 page = children->data;
4513 if (page->tab_label)
4514 gtk_widget_set_child_visible (page->tab_label, FALSE);
4517 else /* !showarrow */
4519 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4530 children = notebook->children;
4534 case GTK_POS_BOTTOM:
4537 page = children->data;
4538 children = children->next;
4540 if (GTK_WIDGET_VISIBLE (page->child))
4543 tab_space += page->requisition.width;
4548 tab_space -= allocation->width;
4554 page = children->data;
4555 children = children->next;
4557 if (GTK_WIDGET_VISIBLE (page->child))
4560 tab_space += page->requisition.height;
4565 tab_space -= allocation->height;
4567 tab_space += 2 * container->border_width + tab_overlap;
4569 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4571 if (notebook->homogeneous && n)
4575 children = notebook->first_tab;
4578 memo_x = child_allocation.x;
4579 if (notebook->children && is_rtl)
4581 child_allocation.x = (allocation->x + allocation->width -
4582 container->border_width);
4585 if (notebook->has_after_previous)
4586 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4587 if (notebook->has_after_next)
4588 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4592 get_notebook_tabs_space (notebook, &min, &max);
4593 anchor_x = child_allocation.x;
4594 anchor_y = child_allocation.y;
4596 left_x = CLAMP (widget->allocation.x + priv->mouse_x - notebook->cur_page->allocation.width / 2,
4597 min, max - notebook->cur_page->allocation.width);
4598 top_y = CLAMP (widget->allocation.y + priv->mouse_y - notebook->cur_page->allocation.height / 2,
4599 min, max - notebook->cur_page->allocation.height);
4600 right_x = left_x + notebook->cur_page->allocation.width;
4601 bottom_y = top_y + notebook->cur_page->allocation.height;
4605 if (children == last_child)
4607 /* FIXME double check */
4611 page = children->data;
4613 if (page->pack != GTK_PACK_START)
4617 else if (operation == DRAG_OPERATION_REORDER)
4618 packing_changed = TRUE;
4621 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
4624 if (n && (showarrow || page->expand || notebook->homogeneous))
4626 new_fill = (tab_space * i++) / n;
4627 delta = new_fill - old_fill;
4628 old_fill = new_fill;
4634 case GTK_POS_BOTTOM:
4635 child_allocation.width = (page->requisition.width +
4636 tab_overlap + delta);
4638 /* make sure that the reordered tab doesn't go past the last position */
4639 if (operation == DRAG_OPERATION_REORDER &&
4640 !gap_left && packing_changed)
4644 if ((notebook->cur_page->pack == GTK_PACK_START && left_x >= anchor_x) ||
4645 (notebook->cur_page->pack == GTK_PACK_END && left_x < anchor_x))
4647 left_x = notebook->cur_page->allocation.x = anchor_x;
4648 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4649 ¬ebook->cur_page->allocation);
4651 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4656 if ((notebook->cur_page->pack == GTK_PACK_START && right_x <= anchor_x) ||
4657 (notebook->cur_page->pack == GTK_PACK_END && right_x > anchor_x))
4659 anchor_x -= notebook->cur_page->allocation.width;
4661 left_x = notebook->cur_page->allocation.x = anchor_x;
4662 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4663 ¬ebook->cur_page->allocation);
4665 anchor_x += tab_overlap;
4672 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4673 child_allocation.x = left_x;
4677 anchor_x -= child_allocation.width;
4679 if (operation == DRAG_OPERATION_REORDER && page->pack == notebook->cur_page->pack)
4682 left_x >= anchor_x &&
4683 left_x <= anchor_x + child_allocation.width / 2)
4684 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4686 right_x > anchor_x + child_allocation.width / 2 &&
4687 right_x <= anchor_x + child_allocation.width)
4688 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4691 child_allocation.x = anchor_x;
4697 child_allocation.height = (page->requisition.height +
4698 tab_overlap + delta);
4700 /* make sure that the reordered tab doesn't go past the last position */
4701 if (operation == DRAG_OPERATION_REORDER &&
4702 !gap_left && packing_changed)
4704 if ((notebook->cur_page->pack == GTK_PACK_START && top_y >= anchor_y) ||
4705 (notebook->cur_page->pack == GTK_PACK_END && top_y < anchor_y))
4707 top_y = notebook->cur_page->allocation.y = anchor_y;
4708 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4709 ¬ebook->cur_page->allocation);
4711 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4717 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4718 child_allocation.y = top_y;
4721 if (operation == DRAG_OPERATION_REORDER &&
4722 page->pack == notebook->cur_page->pack &&
4723 top_y >= anchor_y &&
4724 top_y <= anchor_y + child_allocation.height / 2)
4725 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4727 child_allocation.y = anchor_y;
4733 gtk_notebook_page_allocate (notebook, page, &child_allocation);
4738 case GTK_POS_BOTTOM:
4739 if (operation != DRAG_OPERATION_REORDER ||
4740 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4742 if (operation == DRAG_OPERATION_REORDER)
4744 if (page->pack == notebook->cur_page->pack &&
4746 left_x > anchor_x + child_allocation.width / 2 &&
4747 left_x <= anchor_x + child_allocation.width)
4748 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4749 else if (page->pack == notebook->cur_page->pack &&
4751 right_x >= anchor_x &&
4752 right_x <= anchor_x + child_allocation.width / 2)
4753 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4757 anchor_x += child_allocation.width - tab_overlap;
4759 anchor_x += tab_overlap;
4765 if (operation != DRAG_OPERATION_REORDER ||
4766 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4768 if (operation == DRAG_OPERATION_REORDER &&
4769 page->pack == notebook->cur_page->pack &&
4770 page != notebook->cur_page &&
4771 top_y > anchor_y + child_allocation.height / 2 &&
4772 top_y <= anchor_y + child_allocation.height)
4773 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4775 anchor_y += child_allocation.height - tab_overlap;
4781 if (page->tab_label)
4782 gtk_widget_set_child_visible (page->tab_label, TRUE);
4785 /* don't move the tab past the last position */
4786 if (operation == DRAG_OPERATION_REORDER &&
4787 notebook->cur_page->pack == GTK_PACK_START)
4792 case GTK_POS_BOTTOM:
4793 if ((!is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x) ||
4794 (is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x))
4797 anchor_x -= notebook->cur_page->allocation.width;
4799 notebook->cur_page->allocation.x = anchor_x;
4800 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4801 ¬ebook->cur_page->allocation);
4806 if (PAGE_TOP_Y (notebook->cur_page) > anchor_y)
4808 notebook->cur_page->allocation.y = anchor_y;
4809 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4810 ¬ebook->cur_page->allocation);
4818 children = notebook->children;
4823 case GTK_POS_BOTTOM:
4825 anchor_x = (allocation->x + allocation->width -
4826 container->border_width);
4832 anchor_y = (allocation->y + allocation->height -
4833 container->border_width);
4837 while (children != last_child)
4839 page = children->data;
4840 children = children->next;
4842 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
4846 if (n && (page->expand || notebook->homogeneous))
4848 new_fill = (tab_space * i++) / n;
4849 delta = new_fill - old_fill;
4850 old_fill = new_fill;
4856 case GTK_POS_BOTTOM:
4857 child_allocation.width = (page->requisition.width +
4858 tab_overlap + delta);
4860 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4861 child_allocation.x = left_x;
4865 anchor_x -= child_allocation.width;
4867 if (operation == DRAG_OPERATION_REORDER)
4869 if (page->pack == notebook->cur_page->pack &&
4871 left_x >= anchor_x &&
4872 left_x <= anchor_x + child_allocation.width / 2)
4873 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4874 else if (page->pack == notebook->cur_page->pack &&
4876 right_x > anchor_x + child_allocation.width / 2 &&
4877 right_x <= anchor_x + child_allocation.width)
4878 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4881 child_allocation.x = anchor_x;
4887 child_allocation.height = (page->requisition.height +
4888 tab_overlap + delta);
4890 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4891 child_allocation.y = top_y;
4894 anchor_y -= child_allocation.height;
4896 if (operation == DRAG_OPERATION_REORDER &&
4897 page->pack == notebook->cur_page->pack &&
4898 bottom_y > anchor_y + child_allocation.height / 2 &&
4899 bottom_y <= anchor_y + child_allocation.height)
4900 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
4902 child_allocation.y = anchor_y;
4908 gtk_notebook_page_allocate (notebook, page, &child_allocation);
4913 case GTK_POS_BOTTOM:
4914 if (operation != DRAG_OPERATION_REORDER ||
4915 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4917 if (operation == DRAG_OPERATION_REORDER)
4919 if (page->pack == notebook->cur_page->pack &&
4921 left_x > anchor_x + child_allocation.width / 2 &&
4922 left_x <= anchor_x + child_allocation.width)
4923 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4924 else if (page->pack == notebook->cur_page->pack &&
4926 right_x >= anchor_x &&
4927 right_x <= anchor_x + child_allocation.width / 2)
4928 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4932 anchor_x += tab_overlap;
4934 anchor_x += child_allocation.width - tab_overlap;
4940 if (operation != DRAG_OPERATION_REORDER ||
4941 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4943 if (operation == DRAG_OPERATION_REORDER &&
4944 page->pack == notebook->cur_page->pack &&
4945 page != notebook->cur_page &&
4946 bottom_y >= anchor_y &&
4947 bottom_y <= anchor_y + child_allocation.height / 2)
4948 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
4950 anchor_y += tab_overlap;
4956 if (page->tab_label)
4957 gtk_widget_set_child_visible (page->tab_label, TRUE);
4960 /* don't move the tab past the last position */
4961 if (operation == DRAG_OPERATION_REORDER &&
4962 notebook->cur_page->pack == GTK_PACK_END)
4967 case GTK_POS_BOTTOM:
4968 if ((!is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x) ||
4969 (is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x))
4972 anchor_x -= notebook->cur_page->allocation.width;
4974 notebook->cur_page->allocation.x = anchor_x;
4975 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4976 ¬ebook->cur_page->allocation);
4981 if (PAGE_BOTTOM_Y (notebook->cur_page) < anchor_y)
4983 anchor_y -= notebook->cur_page->allocation.height;
4984 notebook->cur_page->allocation.y = anchor_y;
4985 gtk_notebook_page_allocate (notebook, notebook->cur_page,
4986 ¬ebook->cur_page->allocation);
4994 gtk_notebook_redraw_tabs (notebook);
4998 gtk_notebook_page_allocate (GtkNotebook *notebook,
4999 GtkNotebookPage *page,
5000 GtkAllocation *allocation)
5002 GtkWidget *widget = GTK_WIDGET (notebook);
5003 GtkAllocation child_allocation;
5004 GtkRequisition tab_requisition;
5010 gint tab_pos = get_effective_tab_pos (notebook);
5012 gtk_widget_style_get (widget,
5013 "focus-line-width", &focus_width,
5014 "tab-curvature", &tab_curvature,
5017 xthickness = widget->style->xthickness;
5018 ythickness = widget->style->ythickness;
5020 page->allocation = *allocation;
5021 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
5023 if (notebook->cur_page != page)
5028 page->allocation.y += ythickness;
5029 case GTK_POS_BOTTOM:
5030 page->allocation.height = MAX (1, page->allocation.height - ythickness);
5033 page->allocation.x += xthickness;
5035 page->allocation.width = MAX (1, page->allocation.width - xthickness);
5043 case GTK_POS_BOTTOM:
5044 padding = tab_curvature + focus_width + notebook->tab_hborder;
5047 child_allocation.x = (xthickness + focus_width +
5048 notebook->tab_hborder);
5049 child_allocation.width = MAX (1, (page->allocation.width -
5050 2 * child_allocation.x));
5051 child_allocation.x += page->allocation.x;
5055 child_allocation.x = (page->allocation.x +
5056 (page->allocation.width -
5057 tab_requisition.width) / 2);
5058 child_allocation.width = tab_requisition.width;
5060 child_allocation.y = (notebook->tab_vborder + focus_width +
5061 page->allocation.y);
5062 if (tab_pos == GTK_POS_TOP)
5063 child_allocation.y += ythickness;
5064 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
5065 2 * (notebook->tab_vborder + focus_width)));
5069 padding = tab_curvature + focus_width + notebook->tab_vborder;
5072 child_allocation.y = ythickness + padding;
5073 child_allocation.height = MAX (1, (page->allocation.height -
5074 2 * child_allocation.y));
5075 child_allocation.y += page->allocation.y;
5079 child_allocation.y = (page->allocation.y + (page->allocation.height -
5080 tab_requisition.height) / 2);
5081 child_allocation.height = tab_requisition.height;
5083 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
5084 if (tab_pos == GTK_POS_LEFT)
5085 child_allocation.x += xthickness;
5086 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
5087 2 * (notebook->tab_hborder + focus_width)));
5091 if (page->tab_label)
5092 gtk_widget_size_allocate (page->tab_label, &child_allocation);
5096 gtk_notebook_calc_tabs (GtkNotebook *notebook,
5102 GtkNotebookPage *page = NULL;
5104 GList *last_list = NULL;
5106 gint tab_pos = get_effective_tab_pos (notebook);
5112 pack = GTK_NOTEBOOK_PAGE (start)->pack;
5113 if (pack == GTK_PACK_END)
5114 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
5121 case GTK_POS_BOTTOM:
5124 page = children->data;
5125 if (GTK_WIDGET_VISIBLE (page->child))
5127 if (page->pack == pack)
5129 *tab_space -= page->requisition.width;
5130 if (*tab_space < 0 || children == *end)
5134 *tab_space = - (*tab_space +
5135 page->requisition.width);
5141 last_list = children;
5143 if (direction == STEP_NEXT)
5144 children = children->next;
5146 children = children->prev;
5153 page = children->data;
5154 if (GTK_WIDGET_VISIBLE (page->child))
5156 if (page->pack == pack)
5158 *tab_space -= page->requisition.height;
5159 if (*tab_space < 0 || children == *end)
5163 *tab_space = - (*tab_space +
5164 page->requisition.height);
5170 last_list = children;
5172 if (direction == STEP_NEXT)
5173 children = children->next;
5175 children = children->prev;
5179 if (direction == STEP_PREV)
5181 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
5182 direction = STEP_PREV;
5183 children = last_list;
5188 gtk_notebook_update_tab_states (GtkNotebook *notebook)
5192 for (list = notebook->children; list != NULL; list = list->next)
5194 GtkNotebookPage *page = list->data;
5196 if (page->tab_label)
5198 if (page == notebook->cur_page)
5199 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
5201 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
5206 /* Private GtkNotebook Page Switch Methods:
5208 * gtk_notebook_real_switch_page
5211 gtk_notebook_real_switch_page (GtkNotebook *notebook,
5212 GtkNotebookPage *page,
5215 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5216 g_return_if_fail (page != NULL);
5218 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
5221 if (notebook->cur_page)
5222 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
5224 notebook->cur_page = page;
5226 if (!notebook->focus_tab ||
5227 notebook->focus_tab->data != (gpointer) notebook->cur_page)
5228 notebook->focus_tab =
5229 g_list_find (notebook->children, notebook->cur_page);
5231 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
5233 /* If the focus was on the previous page, move it to the first
5234 * element on the new page, if possible, or if not, to the
5237 if (notebook->child_has_focus)
5239 if (notebook->cur_page->last_focus_child &&
5240 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
5241 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
5243 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
5244 gtk_widget_grab_focus (GTK_WIDGET (notebook));
5247 gtk_notebook_update_tab_states (notebook);
5248 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5249 g_object_notify (G_OBJECT (notebook), "page");
5252 /* Private GtkNotebook Page Switch Functions:
5254 * gtk_notebook_switch_page
5255 * gtk_notebook_page_select
5256 * gtk_notebook_switch_focus_tab
5257 * gtk_notebook_menu_switch_page
5260 gtk_notebook_switch_page (GtkNotebook *notebook,
5261 GtkNotebookPage *page,
5264 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5265 g_return_if_fail (page != NULL);
5267 if (notebook->cur_page == page)
5271 page_num = g_list_index (notebook->children, page);
5273 g_signal_emit (notebook,
5274 notebook_signals[SWITCH_PAGE],
5281 gtk_notebook_page_select (GtkNotebook *notebook,
5282 gboolean move_focus)
5284 GtkNotebookPage *page;
5285 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
5286 gint tab_pos = get_effective_tab_pos (notebook);
5288 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
5290 if (!notebook->focus_tab)
5293 page = notebook->focus_tab->data;
5294 gtk_notebook_switch_page (notebook, page, -1);
5303 case GTK_POS_BOTTOM:
5307 dir = GTK_DIR_RIGHT;
5314 if (gtk_widget_child_focus (page->child, dir))
5321 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
5325 GtkNotebookPage *page;
5327 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5329 if (notebook->focus_tab == new_child)
5332 old_child = notebook->focus_tab;
5333 notebook->focus_tab = new_child;
5335 if (notebook->scrollable)
5336 gtk_notebook_redraw_arrows (notebook);
5338 if (!notebook->show_tabs || !notebook->focus_tab)
5341 page = notebook->focus_tab->data;
5342 if (GTK_WIDGET_MAPPED (page->tab_label))
5343 gtk_notebook_redraw_tabs (notebook);
5345 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
5347 gtk_notebook_switch_page (notebook, page,
5348 g_list_index (notebook->children, page));
5352 gtk_notebook_menu_switch_page (GtkWidget *widget,
5353 GtkNotebookPage *page)
5355 GtkNotebook *notebook;
5359 g_return_if_fail (widget != NULL);
5360 g_return_if_fail (page != NULL);
5362 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
5363 (GTK_MENU (widget->parent)));
5365 if (notebook->cur_page == page)
5369 children = notebook->children;
5370 while (children && children->data != page)
5372 children = children->next;
5376 g_signal_emit (notebook,
5377 notebook_signals[SWITCH_PAGE],
5383 /* Private GtkNotebook Menu Functions:
5385 * gtk_notebook_menu_item_create
5386 * gtk_notebook_menu_label_unparent
5387 * gtk_notebook_menu_detacher
5390 gtk_notebook_menu_item_create (GtkNotebook *notebook,
5393 GtkNotebookPage *page;
5394 GtkWidget *menu_item;
5397 if (page->default_menu)
5399 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
5400 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
5402 page->menu_label = gtk_label_new ("");
5403 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
5406 gtk_widget_show (page->menu_label);
5407 menu_item = gtk_menu_item_new ();
5408 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
5409 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
5410 gtk_notebook_real_page_position (notebook, list));
5411 g_signal_connect (menu_item, "activate",
5412 G_CALLBACK (gtk_notebook_menu_switch_page), page);
5413 if (GTK_WIDGET_VISIBLE (page->child))
5414 gtk_widget_show (menu_item);
5418 gtk_notebook_menu_label_unparent (GtkWidget *widget,
5421 gtk_widget_unparent (GTK_BIN(widget)->child);
5422 GTK_BIN(widget)->child = NULL;
5426 gtk_notebook_menu_detacher (GtkWidget *widget,
5429 GtkNotebook *notebook;
5431 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
5433 notebook = GTK_NOTEBOOK (widget);
5434 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
5436 notebook->menu = NULL;
5439 /* Private GtkNotebook Setter Functions:
5441 * gtk_notebook_set_homogeneous_tabs_internal
5442 * gtk_notebook_set_tab_border_internal
5443 * gtk_notebook_set_tab_hborder_internal
5444 * gtk_notebook_set_tab_vborder_internal
5447 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
5448 gboolean homogeneous)
5450 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5452 if (homogeneous == notebook->homogeneous)
5455 notebook->homogeneous = homogeneous;
5456 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5458 g_object_notify (G_OBJECT (notebook), "homogeneous");
5462 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
5465 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5467 notebook->tab_hborder = border_width;
5468 notebook->tab_vborder = border_width;
5470 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5471 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5473 g_object_freeze_notify (G_OBJECT (notebook));
5474 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5475 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5476 g_object_thaw_notify (G_OBJECT (notebook));
5480 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
5483 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5485 if (notebook->tab_hborder == tab_hborder)
5488 notebook->tab_hborder = tab_hborder;
5490 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5491 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5493 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5497 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
5500 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5502 if (notebook->tab_vborder == tab_vborder)
5505 notebook->tab_vborder = tab_vborder;
5507 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5508 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5510 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5513 /* Public GtkNotebook Page Insert/Remove Methods :
5515 * gtk_notebook_append_page
5516 * gtk_notebook_append_page_menu
5517 * gtk_notebook_prepend_page
5518 * gtk_notebook_prepend_page_menu
5519 * gtk_notebook_insert_page
5520 * gtk_notebook_insert_page_menu
5521 * gtk_notebook_remove_page
5524 * gtk_notebook_append_page:
5525 * @notebook: a #GtkNotebook
5526 * @child: the #GtkWidget to use as the contents of the page.
5527 * @tab_label: the #GtkWidget to be used as the label for the page,
5528 * or %NULL to use the default label, 'page N'.
5530 * Appends a page to @notebook.
5532 * Return value: the index (starting from 0) of the appended
5533 * page in the notebook, or -1 if function fails
5536 gtk_notebook_append_page (GtkNotebook *notebook,
5538 GtkWidget *tab_label)
5540 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5541 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5542 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5544 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
5548 * gtk_notebook_append_page_menu:
5549 * @notebook: a #GtkNotebook
5550 * @child: the #GtkWidget to use as the contents of the page.
5551 * @tab_label: the #GtkWidget to be used as the label for the page,
5552 * or %NULL to use the default label, 'page N'.
5553 * @menu_label: the widget to use as a label for the page-switch
5554 * menu, if that is enabled. If %NULL, and @tab_label
5555 * is a #GtkLabel or %NULL, then the menu label will be
5556 * a newly created label with the same text as @tab_label;
5557 * If @tab_label is not a #GtkLabel, @menu_label must be
5558 * specified if the page-switch menu is to be used.
5560 * Appends a page to @notebook, specifying the widget to use as the
5561 * label in the popup menu.
5563 * Return value: the index (starting from 0) of the appended
5564 * page in the notebook, or -1 if function fails
5567 gtk_notebook_append_page_menu (GtkNotebook *notebook,
5569 GtkWidget *tab_label,
5570 GtkWidget *menu_label)
5572 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5573 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5574 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5575 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5577 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
5581 * gtk_notebook_prepend_page:
5582 * @notebook: a #GtkNotebook
5583 * @child: the #GtkWidget to use as the contents of the page.
5584 * @tab_label: the #GtkWidget to be used as the label for the page,
5585 * or %NULL to use the default label, 'page N'.
5587 * Prepends a page to @notebook.
5589 * Return value: the index (starting from 0) of the prepended
5590 * page in the notebook, or -1 if function fails
5593 gtk_notebook_prepend_page (GtkNotebook *notebook,
5595 GtkWidget *tab_label)
5597 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5598 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5599 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5601 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
5605 * gtk_notebook_prepend_page_menu:
5606 * @notebook: a #GtkNotebook
5607 * @child: the #GtkWidget to use as the contents of the page.
5608 * @tab_label: the #GtkWidget to be used as the label for the page,
5609 * or %NULL to use the default label, 'page N'.
5610 * @menu_label: the widget to use as a label for the page-switch
5611 * menu, if that is enabled. If %NULL, and @tab_label
5612 * is a #GtkLabel or %NULL, then the menu label will be
5613 * a newly created label with the same text as @tab_label;
5614 * If @tab_label is not a #GtkLabel, @menu_label must be
5615 * specified if the page-switch menu is to be used.
5617 * Prepends a page to @notebook, specifying the widget to use as the
5618 * label in the popup menu.
5620 * Return value: the index (starting from 0) of the prepended
5621 * page in the notebook, or -1 if function fails
5624 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
5626 GtkWidget *tab_label,
5627 GtkWidget *menu_label)
5629 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5630 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5631 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5632 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5634 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
5638 * gtk_notebook_insert_page:
5639 * @notebook: a #GtkNotebook
5640 * @child: the #GtkWidget to use as the contents of the page.
5641 * @tab_label: the #GtkWidget to be used as the label for the page,
5642 * or %NULL to use the default label, 'page N'.
5643 * @position: the index (starting at 0) at which to insert the page,
5644 * or -1 to append the page after all other pages.
5646 * Insert a page into @notebook at the given position.
5648 * Return value: the index (starting from 0) of the inserted
5649 * page in the notebook, or -1 if function fails
5652 gtk_notebook_insert_page (GtkNotebook *notebook,
5654 GtkWidget *tab_label,
5657 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5658 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5659 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5661 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
5666 gtk_notebook_page_compare_tab (gconstpointer a,
5669 return (((GtkNotebookPage *) a)->tab_label != b);
5673 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
5677 GtkNotebook *notebook = GTK_NOTEBOOK (data);
5680 list = g_list_find_custom (notebook->children, child,
5681 gtk_notebook_page_compare_tab);
5684 GtkNotebookPage *page = list->data;
5686 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
5687 gtk_notebook_switch_page (notebook, page, -1);
5688 focus_tabs_in (notebook);
5695 * gtk_notebook_insert_page_menu:
5696 * @notebook: a #GtkNotebook
5697 * @child: the #GtkWidget to use as the contents of the page.
5698 * @tab_label: the #GtkWidget to be used as the label for the page,
5699 * or %NULL to use the default label, 'page N'.
5700 * @menu_label: the widget to use as a label for the page-switch
5701 * menu, if that is enabled. If %NULL, and @tab_label
5702 * is a #GtkLabel or %NULL, then the menu label will be
5703 * a newly created label with the same text as @tab_label;
5704 * If @tab_label is not a #GtkLabel, @menu_label must be
5705 * specified if the page-switch menu is to be used.
5706 * @position: the index (starting at 0) at which to insert the page,
5707 * or -1 to append the page after all other pages.
5709 * Insert a page into @notebook at the given position, specifying
5710 * the widget to use as the label in the popup menu.
5712 * Return value: the index (starting from 0) of the inserted
5713 * page in the notebook
5716 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
5718 GtkWidget *tab_label,
5719 GtkWidget *menu_label,
5722 GtkNotebookClass *class;
5724 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5725 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5726 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5727 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5729 class = GTK_NOTEBOOK_GET_CLASS (notebook);
5731 return (class->insert_page) (notebook, child, tab_label, menu_label, position);
5735 * gtk_notebook_remove_page:
5736 * @notebook: a #GtkNotebook.
5737 * @page_num: the index of a notebook page, starting
5738 * from 0. If -1, the last page will
5741 * Removes a page from the notebook given its index
5745 gtk_notebook_remove_page (GtkNotebook *notebook,
5750 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5753 list = g_list_nth (notebook->children, page_num);
5755 list = g_list_last (notebook->children);
5758 gtk_container_remove (GTK_CONTAINER (notebook),
5759 ((GtkNotebookPage *) list->data)->child);
5762 /* Public GtkNotebook Page Switch Methods :
5763 * gtk_notebook_get_current_page
5764 * gtk_notebook_page_num
5765 * gtk_notebook_set_current_page
5766 * gtk_notebook_next_page
5767 * gtk_notebook_prev_page
5770 * gtk_notebook_get_current_page:
5771 * @notebook: a #GtkNotebook
5773 * Returns the page number of the current page.
5775 * Return value: the index (starting from 0) of the current
5776 * page in the notebook. If the notebook has no pages, then
5777 * -1 will be returned.
5780 gtk_notebook_get_current_page (GtkNotebook *notebook)
5782 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5784 if (!notebook->cur_page)
5787 return g_list_index (notebook->children, notebook->cur_page);
5791 * gtk_notebook_get_nth_page:
5792 * @notebook: a #GtkNotebook
5793 * @page_num: the index of a page in the noteobok, or -1
5794 * to get the last page.
5796 * Returns the child widget contained in page number @page_num.
5798 * Return value: the child widget, or %NULL if @page_num is
5802 gtk_notebook_get_nth_page (GtkNotebook *notebook,
5805 GtkNotebookPage *page;
5808 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5811 list = g_list_nth (notebook->children, page_num);
5813 list = g_list_last (notebook->children);
5825 * gtk_notebook_get_n_pages:
5826 * @notebook: a #GtkNotebook
5828 * Gets the number of pages in a notebook.
5830 * Return value: the number of pages in the notebook.
5835 gtk_notebook_get_n_pages (GtkNotebook *notebook)
5837 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
5839 return g_list_length (notebook->children);
5843 * gtk_notebook_page_num:
5844 * @notebook: a #GtkNotebook
5845 * @child: a #GtkWidget
5847 * Finds the index of the page which contains the given child
5850 * Return value: the index of the page containing @child, or
5851 * -1 if @child is not in the notebook.
5854 gtk_notebook_page_num (GtkNotebook *notebook,
5860 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5863 children = notebook->children;
5866 GtkNotebookPage *page = children->data;
5868 if (page->child == child)
5871 children = children->next;
5879 * gtk_notebook_set_current_page:
5880 * @notebook: a #GtkNotebook
5881 * @page_num: index of the page to switch to, starting from 0.
5882 * If negative, the last page will be used. If greater
5883 * than the number of pages in the notebook, nothing
5886 * Switches to the page number @page_num.
5889 gtk_notebook_set_current_page (GtkNotebook *notebook,
5894 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5897 list = g_list_nth (notebook->children, page_num);
5899 list = g_list_last (notebook->children);
5901 page_num = g_list_index (notebook->children, list);
5904 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
5908 * gtk_notebook_next_page:
5909 * @notebook: a #GtkNotebook
5911 * Switches to the next page. Nothing happens if the current page is
5915 gtk_notebook_next_page (GtkNotebook *notebook)
5919 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5921 list = g_list_find (notebook->children, notebook->cur_page);
5925 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
5929 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
5933 * gtk_notebook_prev_page:
5934 * @notebook: a #GtkNotebook
5936 * Switches to the previous page. Nothing happens if the current page
5937 * is the first page.
5940 gtk_notebook_prev_page (GtkNotebook *notebook)
5944 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5946 list = g_list_find (notebook->children, notebook->cur_page);
5950 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
5954 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
5957 /* Public GtkNotebook/Tab Style Functions
5959 * gtk_notebook_set_show_border
5960 * gtk_notebook_set_show_tabs
5961 * gtk_notebook_set_tab_pos
5962 * gtk_notebook_set_homogeneous_tabs
5963 * gtk_notebook_set_tab_border
5964 * gtk_notebook_set_tab_hborder
5965 * gtk_notebook_set_tab_vborder
5966 * gtk_notebook_set_scrollable
5969 * gtk_notebook_set_show_border:
5970 * @notebook: a #GtkNotebook
5971 * @show_border: %TRUE if a bevel should be drawn around the notebook.
5973 * Sets whether a bevel will be drawn around the notebook pages.
5974 * This only has a visual effect when the tabs are not shown.
5975 * See gtk_notebook_set_show_tabs().
5978 gtk_notebook_set_show_border (GtkNotebook *notebook,
5979 gboolean show_border)
5981 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5983 if (notebook->show_border != show_border)
5985 notebook->show_border = show_border;
5987 if (GTK_WIDGET_VISIBLE (notebook))
5988 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5990 g_object_notify (G_OBJECT (notebook), "show-border");
5995 * gtk_notebook_get_show_border:
5996 * @notebook: a #GtkNotebook
5998 * Returns whether a bevel will be drawn around the notebook pages. See
5999 * gtk_notebook_set_show_border().
6001 * Return value: %TRUE if the bevel is drawn
6004 gtk_notebook_get_show_border (GtkNotebook *notebook)
6006 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6008 return notebook->show_border;
6012 * gtk_notebook_set_show_tabs:
6013 * @notebook: a #GtkNotebook
6014 * @show_tabs: %TRUE if the tabs should be shown.
6016 * Sets whether to show the tabs for the notebook or not.
6019 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
6022 GtkNotebookPage *page;
6025 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6027 show_tabs = show_tabs != FALSE;
6029 if (notebook->show_tabs == show_tabs)
6032 notebook->show_tabs = show_tabs;
6033 children = notebook->children;
6037 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
6041 page = children->data;
6042 children = children->next;
6043 if (page->default_tab)
6045 gtk_widget_destroy (page->tab_label);
6046 page->tab_label = NULL;
6049 gtk_widget_hide (page->tab_label);
6054 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
6055 gtk_notebook_update_labels (notebook);
6057 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6059 g_object_notify (G_OBJECT (notebook), "show-tabs");
6063 * gtk_notebook_get_show_tabs:
6064 * @notebook: a #GtkNotebook
6066 * Returns whether the tabs of the notebook are shown. See
6067 * gtk_notebook_set_show_tabs().
6069 * Return value: %TRUE if the tabs are shown
6072 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
6074 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6076 return notebook->show_tabs;
6080 * gtk_notebook_set_tab_pos:
6081 * @notebook: a #GtkNotebook.
6082 * @pos: the edge to draw the tabs at.
6084 * Sets the edge at which the tabs for switching pages in the
6085 * notebook are drawn.
6088 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
6089 GtkPositionType pos)
6091 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6093 if (notebook->tab_pos != pos)
6095 notebook->tab_pos = pos;
6096 if (GTK_WIDGET_VISIBLE (notebook))
6097 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6100 g_object_notify (G_OBJECT (notebook), "tab-pos");
6104 * gtk_notebook_get_tab_pos:
6105 * @notebook: a #GtkNotebook
6107 * Gets the edge at which the tabs for switching pages in the
6108 * notebook are drawn.
6110 * Return value: the edge at which the tabs are drawn
6113 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
6115 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
6117 return notebook->tab_pos;
6121 * gtk_notebook_set_homogeneous_tabs:
6122 * @notebook: a #GtkNotebook
6123 * @homogeneous: %TRUE if all tabs should be the same size.
6125 * Sets whether the tabs must have all the same size or not.
6128 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
6129 gboolean homogeneous)
6131 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6133 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
6137 * gtk_notebook_set_tab_border:
6138 * @notebook: a #GtkNotebook
6139 * @border_width: width of the border around the tab labels.
6141 * Sets the width the border around the tab labels
6142 * in a notebook. This is equivalent to calling
6143 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
6144 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
6147 gtk_notebook_set_tab_border (GtkNotebook *notebook,
6150 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6152 gtk_notebook_set_tab_border_internal (notebook, border_width);
6156 * gtk_notebook_set_tab_hborder:
6157 * @notebook: a #GtkNotebook
6158 * @tab_hborder: width of the horizontal border of tab labels.
6160 * Sets the width of the horizontal border of tab labels.
6163 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
6166 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6168 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
6172 * gtk_notebook_set_tab_vborder:
6173 * @notebook: a #GtkNotebook
6174 * @tab_vborder: width of the vertical border of tab labels.
6176 * Sets the width of the vertical border of tab labels.
6179 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
6182 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6184 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
6188 * gtk_notebook_set_scrollable:
6189 * @notebook: a #GtkNotebook
6190 * @scrollable: %TRUE if scroll arrows should be added
6192 * Sets whether the tab label area will have arrows for scrolling if
6193 * there are too many tabs to fit in the area.
6196 gtk_notebook_set_scrollable (GtkNotebook *notebook,
6197 gboolean scrollable)
6199 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6201 scrollable = (scrollable != FALSE);
6203 if (scrollable != notebook->scrollable)
6205 notebook->scrollable = scrollable;
6207 if (GTK_WIDGET_VISIBLE (notebook))
6208 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6210 g_object_notify (G_OBJECT (notebook), "scrollable");
6215 * gtk_notebook_get_scrollable:
6216 * @notebook: a #GtkNotebook
6218 * Returns whether the tab label area has arrows for scrolling. See
6219 * gtk_notebook_set_scrollable().
6221 * Return value: %TRUE if arrows for scrolling are present
6224 gtk_notebook_get_scrollable (GtkNotebook *notebook)
6226 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6228 return notebook->scrollable;
6231 /* Public GtkNotebook Popup Menu Methods:
6233 * gtk_notebook_popup_enable
6234 * gtk_notebook_popup_disable
6239 * gtk_notebook_popup_enable:
6240 * @notebook: a #GtkNotebook
6242 * Enables the popup menu: if the user clicks with the right mouse button on
6243 * the bookmarks, a menu with all the pages will be popped up.
6246 gtk_notebook_popup_enable (GtkNotebook *notebook)
6250 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6255 notebook->menu = gtk_menu_new ();
6256 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
6258 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
6259 gtk_notebook_menu_item_create (notebook, list);
6261 gtk_notebook_update_labels (notebook);
6262 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
6263 GTK_WIDGET (notebook),
6264 gtk_notebook_menu_detacher);
6266 g_object_notify (G_OBJECT (notebook), "enable-popup");
6270 * gtk_notebook_popup_disable:
6271 * @notebook: a #GtkNotebook
6273 * Disables the popup menu.
6276 gtk_notebook_popup_disable (GtkNotebook *notebook)
6278 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6280 if (!notebook->menu)
6283 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
6284 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
6285 gtk_widget_destroy (notebook->menu);
6287 g_object_notify (G_OBJECT (notebook), "enable-popup");
6290 /* Public GtkNotebook Page Properties Functions:
6292 * gtk_notebook_get_tab_label
6293 * gtk_notebook_set_tab_label
6294 * gtk_notebook_set_tab_label_text
6295 * gtk_notebook_get_menu_label
6296 * gtk_notebook_set_menu_label
6297 * gtk_notebook_set_menu_label_text
6298 * gtk_notebook_set_tab_label_packing
6299 * gtk_notebook_query_tab_label_packing
6300 * gtk_notebook_get_tab_reorderable
6301 * gtk_notebook_set_tab_reorderable
6302 * gtk_notebook_get_tab_detachable
6303 * gtk_notebook_set_tab_detachable
6307 * gtk_notebook_get_tab_label:
6308 * @notebook: a #GtkNotebook
6311 * Returns the tab label widget for the page @child. %NULL is returned
6312 * if @child is not in @notebook or if no tab label has specifically
6313 * been set for @child.
6315 * Return value: the tab label
6318 gtk_notebook_get_tab_label (GtkNotebook *notebook,
6323 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6324 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6326 list = CHECK_FIND_CHILD (notebook, child);
6330 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
6333 return GTK_NOTEBOOK_PAGE (list)->tab_label;
6337 * gtk_notebook_set_tab_label:
6338 * @notebook: a #GtkNotebook
6340 * @tab_label: the tab label widget to use, or %NULL for default tab
6343 * Changes the tab label for @child. If %NULL is specified
6344 * for @tab_label, then the page will have the label 'page N'.
6347 gtk_notebook_set_tab_label (GtkNotebook *notebook,
6349 GtkWidget *tab_label)
6351 GtkNotebookPage *page;
6354 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6355 g_return_if_fail (GTK_IS_WIDGET (child));
6357 list = CHECK_FIND_CHILD (notebook, child);
6361 /* a NULL pointer indicates a default_tab setting, otherwise
6362 * we need to set the associated label
6366 if (page->tab_label == tab_label)
6370 gtk_notebook_remove_tab_label (notebook, page);
6374 page->default_tab = FALSE;
6375 page->tab_label = tab_label;
6376 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6380 page->default_tab = TRUE;
6381 page->tab_label = NULL;
6383 if (notebook->show_tabs)
6387 g_snprintf (string, sizeof(string), _("Page %u"),
6388 gtk_notebook_real_page_position (notebook, list));
6389 page->tab_label = gtk_label_new (string);
6390 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6394 if (page->tab_label)
6395 page->mnemonic_activate_signal =
6396 g_signal_connect (page->tab_label,
6397 "mnemonic_activate",
6398 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
6401 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
6403 gtk_widget_show (page->tab_label);
6404 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6407 gtk_notebook_update_tab_states (notebook);
6408 gtk_widget_child_notify (child, "tab-label");
6412 * gtk_notebook_set_tab_label_text:
6413 * @notebook: a #GtkNotebook
6415 * @tab_text: the label text
6417 * Creates a new label and sets it as the tab label for the page
6418 * containing @child.
6421 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
6423 const gchar *tab_text)
6425 GtkWidget *tab_label = NULL;
6427 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6430 tab_label = gtk_label_new (tab_text);
6431 gtk_notebook_set_tab_label (notebook, child, tab_label);
6432 gtk_widget_child_notify (child, "tab-label");
6436 * gtk_notebook_get_tab_label_text:
6437 * @notebook: a #GtkNotebook
6438 * @child: a widget contained in a page of @notebook
6440 * Retrieves the text of the tab label for the page containing
6443 * Returns value: the text of the tab label, or %NULL if the
6444 * tab label widget is not a #GtkLabel. The
6445 * string is owned by the widget and must not
6448 G_CONST_RETURN gchar *
6449 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
6452 GtkWidget *tab_label;
6454 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6455 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6457 tab_label = gtk_notebook_get_tab_label (notebook, child);
6459 if (tab_label && GTK_IS_LABEL (tab_label))
6460 return gtk_label_get_text (GTK_LABEL (tab_label));
6466 * gtk_notebook_get_menu_label:
6467 * @notebook: a #GtkNotebook
6468 * @child: a widget contained in a page of @notebook
6470 * Retrieves the menu label widget of the page containing @child.
6472 * Return value: the menu label, or %NULL if the
6473 * notebook page does not have a menu label other
6474 * than the default (the tab label).
6477 gtk_notebook_get_menu_label (GtkNotebook *notebook,
6482 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6483 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6485 list = CHECK_FIND_CHILD (notebook, child);
6489 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
6492 return GTK_NOTEBOOK_PAGE (list)->menu_label;
6496 * gtk_notebook_set_menu_label:
6497 * @notebook: a #GtkNotebook
6498 * @child: the child widget
6499 * @menu_label: the menu label, or NULL for default
6501 * Changes the menu label for the page containing @child.
6504 gtk_notebook_set_menu_label (GtkNotebook *notebook,
6506 GtkWidget *menu_label)
6508 GtkNotebookPage *page;
6511 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6512 g_return_if_fail (GTK_IS_WIDGET (child));
6514 list = CHECK_FIND_CHILD (notebook, child);
6519 if (page->menu_label)
6522 gtk_container_remove (GTK_CONTAINER (notebook->menu),
6523 page->menu_label->parent);
6525 if (!page->default_menu)
6526 g_object_unref (page->menu_label);
6531 page->menu_label = menu_label;
6532 g_object_ref_sink (page->menu_label);
6533 page->default_menu = FALSE;
6536 page->default_menu = TRUE;
6539 gtk_notebook_menu_item_create (notebook, list);
6540 gtk_widget_child_notify (child, "menu-label");
6544 * gtk_notebook_set_menu_label_text:
6545 * @notebook: a #GtkNotebook
6546 * @child: the child widget
6547 * @menu_text: the label text
6549 * Creates a new label and sets it as the menu label of @child.
6552 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
6554 const gchar *menu_text)
6556 GtkWidget *menu_label = NULL;
6558 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6561 menu_label = gtk_label_new (menu_text);
6562 gtk_notebook_set_menu_label (notebook, child, menu_label);
6563 gtk_widget_child_notify (child, "menu-label");
6567 * gtk_notebook_get_menu_label_text:
6568 * @notebook: a #GtkNotebook
6569 * @child: the child widget of a page of the notebook.
6571 * Retrieves the text of the menu label for the page containing
6574 * Returns value: the text of the tab label, or %NULL if the
6575 * widget does not have a menu label other than
6576 * the default menu label, or the menu label widget
6577 * is not a #GtkLabel. The string is owned by
6578 * the widget and must not be freed.
6580 G_CONST_RETURN gchar *
6581 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
6584 GtkWidget *menu_label;
6586 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6587 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6589 menu_label = gtk_notebook_get_menu_label (notebook, child);
6591 if (menu_label && GTK_IS_LABEL (menu_label))
6592 return gtk_label_get_text (GTK_LABEL (menu_label));
6597 /* Helper function called when pages are reordered
6600 gtk_notebook_child_reordered (GtkNotebook *notebook,
6601 GtkNotebookPage *page)
6605 GtkWidget *menu_item;
6607 menu_item = page->menu_label->parent;
6608 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
6609 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
6610 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
6613 gtk_notebook_update_tab_states (notebook);
6614 gtk_notebook_update_labels (notebook);
6618 * gtk_notebook_set_tab_label_packing:
6619 * @notebook: a #GtkNotebook
6620 * @child: the child widget
6621 * @expand: whether to expand the bookmark or not
6622 * @fill: whether the bookmark should fill the allocated area or not
6623 * @pack_type: the position of the bookmark
6625 * Sets the packing parameters for the tab label of the page
6626 * containing @child. See gtk_box_pack_start() for the exact meaning
6627 * of the parameters.
6630 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
6634 GtkPackType pack_type)
6636 GtkNotebookPage *page;
6639 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6640 g_return_if_fail (GTK_IS_WIDGET (child));
6642 list = CHECK_FIND_CHILD (notebook, child);
6647 expand = expand != FALSE;
6648 fill = fill != FALSE;
6649 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
6652 gtk_widget_freeze_child_notify (child);
6653 page->expand = expand;
6654 gtk_widget_child_notify (child, "tab-expand");
6656 gtk_widget_child_notify (child, "tab-fill");
6657 if (page->pack != pack_type)
6659 page->pack = pack_type;
6660 gtk_notebook_child_reordered (notebook, page);
6662 gtk_widget_child_notify (child, "tab-pack");
6663 gtk_widget_child_notify (child, "position");
6664 if (notebook->show_tabs)
6665 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6666 gtk_widget_thaw_child_notify (child);
6670 * gtk_notebook_query_tab_label_packing:
6671 * @notebook: a #GtkNotebook
6673 * @expand: location to store the expand value (or NULL)
6674 * @fill: location to store the fill value (or NULL)
6675 * @pack_type: location to store the pack_type (or NULL)
6677 * Query the packing attributes for the tab label of the page
6678 * containing @child.
6681 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
6685 GtkPackType *pack_type)
6689 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6690 g_return_if_fail (GTK_IS_WIDGET (child));
6692 list = CHECK_FIND_CHILD (notebook, child);
6697 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
6699 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
6701 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
6705 * gtk_notebook_reorder_child:
6706 * @notebook: a #GtkNotebook
6707 * @child: the child to move
6708 * @position: the new position, or -1 to move to the end
6710 * Reorders the page containing @child, so that it appears in position
6711 * @position. If @position is greater than or equal to the number of
6712 * children in the list or negative, @child will be moved to the end
6716 gtk_notebook_reorder_child (GtkNotebook *notebook,
6720 GList *list, *new_list;
6721 GtkNotebookPage *page;
6725 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6726 g_return_if_fail (GTK_IS_WIDGET (child));
6728 list = CHECK_FIND_CHILD (notebook, child);
6732 max_pos = g_list_length (notebook->children) - 1;
6733 if (position < 0 || position > max_pos)
6736 old_pos = g_list_position (notebook->children, list);
6738 if (old_pos == position)
6742 notebook->children = g_list_delete_link (notebook->children, list);
6744 notebook->children = g_list_insert (notebook->children, page, position);
6745 new_list = g_list_nth (notebook->children, position);
6747 /* Fix up GList references in GtkNotebook structure */
6748 if (notebook->first_tab == list)
6749 notebook->first_tab = new_list;
6750 if (notebook->focus_tab == list)
6751 notebook->focus_tab = new_list;
6753 gtk_widget_freeze_child_notify (child);
6755 /* Move around the menu items if necessary */
6756 gtk_notebook_child_reordered (notebook, page);
6757 gtk_widget_child_notify (child, "tab-pack");
6758 gtk_widget_child_notify (child, "position");
6760 if (notebook->show_tabs)
6761 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6763 gtk_widget_thaw_child_notify (child);
6767 * gtk_notebook_set_window_creation_hook:
6768 * @func: the #GtkNotebookWindowCreationFunc, or NULL
6769 * @data: user data for @func.
6771 * Installs a global function used to create a window
6772 * when a detached tab is dropped in an empty area.
6777 gtk_notebook_set_window_creation_hook (GtkNotebookWindowCreationFunc func,
6780 window_creation_hook = func;
6781 window_creation_hook_data = data;
6785 * gtk_notebook_set_group_id:
6786 * @notebook: a #GtkNotebook
6787 * @group_id: a group identificator, or -1 to unset it
6789 * Sets an group identificator for @notebook, notebooks sharing
6790 * the same group identificator will be able to exchange tabs
6791 * via drag and drop. A notebook with group identificator -1 will
6792 * not be able to exchange tabs with any other notebook.
6797 gtk_notebook_set_group_id (GtkNotebook *notebook,
6800 GtkNotebookPrivate *priv;
6802 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6804 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6806 if (priv->group_id != group_id)
6808 priv->group_id = group_id;
6809 g_object_notify (G_OBJECT (notebook), "group-id");
6814 * gtk_notebook_get_group_id:
6815 * @notebook: a #GtkNotebook
6817 * Gets the current group identificator for @notebook.
6819 * Return Value: the group identificator, or -1 if none is set.
6824 gtk_notebook_get_group_id (GtkNotebook *notebook)
6826 GtkNotebookPrivate *priv;
6828 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
6830 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6831 return priv->group_id;
6835 * gtk_notebook_get_tab_reorderable:
6836 * @notebook: a #GtkNotebook
6837 * @child: a child #GtkWidget
6839 * Gets whether the tab can be reordered via drag and drop or not.
6841 * Return Value: TRUE if the tab is reorderable.
6844 gtk_notebook_get_tab_reorderable (GtkNotebook *notebook,
6849 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6850 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
6852 list = CHECK_FIND_CHILD (notebook, child);
6856 return GTK_NOTEBOOK_PAGE (list)->reorderable;
6860 * gtk_notebook_set_tab_reorderable:
6861 * @notebook: a #GtkNotebook
6862 * @child: a child #GtkWidget
6863 * @reorderable: whether the tab is reorderable or not.
6865 * Sets whether the notebook tab can be reordered
6866 * via drag and drop or not.
6871 gtk_notebook_set_tab_reorderable (GtkNotebook *notebook,
6873 gboolean reorderable)
6877 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6878 g_return_if_fail (GTK_IS_WIDGET (child));
6880 list = CHECK_FIND_CHILD (notebook, child);
6884 if (GTK_NOTEBOOK_PAGE (list)->reorderable != reorderable)
6886 GTK_NOTEBOOK_PAGE (list)->reorderable = (reorderable == TRUE);
6887 gtk_widget_child_notify (child, "reorderable");
6892 * gtk_notebook_get_tab_detachable:
6893 * @notebook: a #GtkNotebook
6894 * @child: a child #GtkWidget
6896 * Returns whether the tab contents can be detached from @notebook.
6898 * Return Value: TRUE if the tab is detachable.
6903 gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
6908 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6909 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
6911 list = CHECK_FIND_CHILD (notebook, child);
6915 return GTK_NOTEBOOK_PAGE (list)->detachable;
6919 * gtk_notebook_set_tab_detachable:
6920 * @notebook: a #GtkNotebook
6921 * @child: a child #GtkWidget
6922 * @detachable: whether the tab is detachable or not
6924 * Sets whether the tab can be detached from @notebook to another notebook.
6926 * Note that 2 notebooks must share a common group identificator
6927 * (see gtk_notebook_set_group_id ()) to allow tabs interchange between them.
6932 gtk_notebook_set_tab_detachable (GtkNotebook *notebook,
6934 gboolean detachable)
6938 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6939 g_return_if_fail (GTK_IS_WIDGET (child));
6941 list = CHECK_FIND_CHILD (notebook, child);
6945 if (GTK_NOTEBOOK_PAGE (list)->detachable != detachable)
6947 GTK_NOTEBOOK_PAGE (list)->detachable = (detachable == TRUE);
6948 gtk_widget_child_notify (child, "detachable");
6952 #define __GTK_NOTEBOOK_C__
6953 #include "gtkaliasdef.c"