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"
44 #define ARROW_SPACING 0
45 #define SCROLL_DELAY_FACTOR 5
46 #define SCROLL_THRESHOLD 12
47 #define DND_THRESHOLD_MULTIPLIER 4
81 } GtkNotebookPointerPosition;
86 DRAG_OPERATION_REORDER,
88 } GtkNotebookDragOperation;
90 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
91 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
110 CHILD_PROP_TAB_LABEL,
111 CHILD_PROP_MENU_LABEL,
113 CHILD_PROP_TAB_EXPAND,
116 CHILD_PROP_REORDERABLE,
117 CHILD_PROP_DETACHABLE
120 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
122 /* some useful defines for calculating coords */
123 #define PAGE_LEFT_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x)
124 #define PAGE_RIGHT_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width)
125 #define PAGE_MIDDLE_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width / 2)
126 #define PAGE_TOP_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y)
127 #define PAGE_BOTTOM_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height)
128 #define PAGE_MIDDLE_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height / 2)
130 struct _GtkNotebookPage
133 GtkWidget *tab_label;
134 GtkWidget *menu_label;
135 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
137 guint default_menu : 1; /* If true, we create the menu label ourself */
138 guint default_tab : 1; /* If true, we create the tab label ourself */
142 guint reorderable : 1;
143 guint detachable : 1;
145 GtkRequisition requisition;
146 GtkAllocation allocation;
148 gulong mnemonic_activate_signal;
149 gulong notify_visible_handler;
152 #define GTK_NOTEBOOK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_NOTEBOOK, GtkNotebookPrivate))
154 typedef struct _GtkNotebookPrivate GtkNotebookPrivate;
156 struct _GtkNotebookPrivate
163 guint switch_tab_timer;
164 GtkTargetList *source_targets;
165 gboolean during_detach;
166 gboolean has_scrolled;
169 static const GtkTargetEntry notebook_source_targets [] = {
170 { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
171 { "application/x-rootwindow-drop", 0, 1 }
174 static const GtkTargetEntry notebook_dest_targets[] = {
175 { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 }
178 #ifdef G_DISABLE_CHECKS
179 #define CHECK_FIND_CHILD(notebook, child) \
180 gtk_notebook_find_child (notebook, child, G_STRLOC)
182 #define CHECK_FIND_CHILD(notebook, child) \
183 gtk_notebook_find_child (notebook, child, NULL)
186 /*** GtkNotebook Methods ***/
187 static void gtk_notebook_class_init (GtkNotebookClass *klass);
188 static void gtk_notebook_init (GtkNotebook *notebook);
190 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
191 gboolean move_focus);
192 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
193 GtkNotebookTab type);
194 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
196 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
197 GtkDirectionType direction_type);
198 static void gtk_notebook_reorder_tab (GtkNotebook *notebook,
199 GtkDirectionType direction_type,
200 gboolean move_to_last);
202 /*** GtkObject Methods ***/
203 static void gtk_notebook_destroy (GtkObject *object);
204 static void gtk_notebook_set_property (GObject *object,
208 static void gtk_notebook_get_property (GObject *object,
213 /*** GtkWidget Methods ***/
214 static void gtk_notebook_map (GtkWidget *widget);
215 static void gtk_notebook_unmap (GtkWidget *widget);
216 static void gtk_notebook_realize (GtkWidget *widget);
217 static void gtk_notebook_unrealize (GtkWidget *widget);
218 static void gtk_notebook_size_request (GtkWidget *widget,
219 GtkRequisition *requisition);
220 static void gtk_notebook_size_allocate (GtkWidget *widget,
221 GtkAllocation *allocation);
222 static gint gtk_notebook_expose (GtkWidget *widget,
223 GdkEventExpose *event);
224 static gboolean gtk_notebook_scroll (GtkWidget *widget,
225 GdkEventScroll *event);
226 static gint gtk_notebook_button_press (GtkWidget *widget,
227 GdkEventButton *event);
228 static gint gtk_notebook_button_release (GtkWidget *widget,
229 GdkEventButton *event);
230 static gboolean gtk_notebook_popup_menu (GtkWidget *widget);
231 static gint gtk_notebook_enter_notify (GtkWidget *widget,
232 GdkEventCrossing *event);
233 static gint gtk_notebook_leave_notify (GtkWidget *widget,
234 GdkEventCrossing *event);
235 static gint gtk_notebook_motion_notify (GtkWidget *widget,
236 GdkEventMotion *event);
237 static gint gtk_notebook_focus_in (GtkWidget *widget,
238 GdkEventFocus *event);
239 static gint gtk_notebook_focus_out (GtkWidget *widget,
240 GdkEventFocus *event);
241 static void gtk_notebook_grab_notify (GtkWidget *widget,
242 gboolean was_grabbed);
243 static void gtk_notebook_state_changed (GtkWidget *widget,
244 GtkStateType previous_state);
245 static void gtk_notebook_draw_focus (GtkWidget *widget);
246 static gint gtk_notebook_focus (GtkWidget *widget,
247 GtkDirectionType direction);
248 static void gtk_notebook_style_set (GtkWidget *widget,
251 /*** Drag and drop Methods ***/
252 static void gtk_notebook_drag_begin (GtkWidget *widget,
253 GdkDragContext *context);
254 static gboolean gtk_notebook_drag_motion (GtkWidget *widget,
255 GdkDragContext *context,
259 static void gtk_notebook_drag_leave (GtkWidget *widget,
260 GdkDragContext *context,
262 static gboolean gtk_notebook_drag_drop (GtkWidget *widget,
263 GdkDragContext *context,
267 static void gtk_notebook_drag_data_get (GtkWidget *widget,
268 GdkDragContext *context,
269 GtkSelectionData *data,
272 static void gtk_notebook_drag_data_received (GtkWidget *widget,
273 GdkDragContext *context,
276 GtkSelectionData *data,
280 /*** GtkContainer Methods ***/
281 static void gtk_notebook_set_child_property (GtkContainer *container,
286 static void gtk_notebook_get_child_property (GtkContainer *container,
291 static void gtk_notebook_add (GtkContainer *container,
293 static void gtk_notebook_remove (GtkContainer *container,
295 static void gtk_notebook_set_focus_child (GtkContainer *container,
297 static GType gtk_notebook_child_type (GtkContainer *container);
298 static void gtk_notebook_forall (GtkContainer *container,
299 gboolean include_internals,
300 GtkCallback callback,
301 gpointer callback_data);
303 /*** GtkNotebook Methods ***/
304 static gint gtk_notebook_real_insert_page (GtkNotebook *notebook,
306 GtkWidget *tab_label,
307 GtkWidget *menu_label,
310 /*** GtkNotebook Private Functions ***/
311 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
312 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
313 static void gtk_notebook_real_remove (GtkNotebook *notebook,
315 static void gtk_notebook_update_labels (GtkNotebook *notebook);
316 static gint gtk_notebook_timer (GtkNotebook *notebook);
317 static gint gtk_notebook_page_compare (gconstpointer a,
319 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
321 const gchar *function);
322 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
324 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
327 gboolean find_visible);
329 /*** GtkNotebook Drawing Functions ***/
330 static void gtk_notebook_paint (GtkWidget *widget,
332 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
333 GtkNotebookPage *page,
335 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
336 GtkNotebookArrow arrow);
338 /*** GtkNotebook Size Allocate Functions ***/
339 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
340 GtkNotebookDragOperation operation);
341 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
342 GtkNotebookPage *page);
343 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
349 /*** GtkNotebook Page Switch Methods ***/
350 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
351 GtkNotebookPage *page,
354 /*** GtkNotebook Page Switch Functions ***/
355 static void gtk_notebook_switch_page (GtkNotebook *notebook,
356 GtkNotebookPage *page,
358 static gint gtk_notebook_page_select (GtkNotebook *notebook,
359 gboolean move_focus);
360 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
362 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
363 GtkNotebookPage *page);
365 /*** GtkNotebook Menu Functions ***/
366 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
368 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
370 static void gtk_notebook_menu_detacher (GtkWidget *widget,
373 /*** GtkNotebook Private Setters ***/
374 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
375 gboolean homogeneous);
376 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
378 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
380 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
383 static void gtk_notebook_update_tab_states (GtkNotebook *notebook);
384 static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
388 static gboolean focus_tabs_in (GtkNotebook *notebook);
389 static gboolean focus_child_in (GtkNotebook *notebook,
390 GtkDirectionType direction);
392 static void stop_scrolling (GtkNotebook *notebook);
395 static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
396 static gpointer window_creation_hook_data;
398 static GtkContainerClass *parent_class = NULL;
399 static guint notebook_signals[LAST_SIGNAL] = { 0 };
402 gtk_notebook_get_type (void)
404 static GType notebook_type = 0;
408 static const GTypeInfo notebook_info =
410 sizeof (GtkNotebookClass),
411 NULL, /* base_init */
412 NULL, /* base_finalize */
413 (GClassInitFunc) gtk_notebook_class_init,
414 NULL, /* class_finalize */
415 NULL, /* class_data */
416 sizeof (GtkNotebook),
418 (GInstanceInitFunc) gtk_notebook_init,
421 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, I_("GtkNotebook"),
425 return notebook_type;
429 add_tab_bindings (GtkBindingSet *binding_set,
430 GdkModifierType modifiers,
431 GtkDirectionType direction)
433 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
435 GTK_TYPE_DIRECTION_TYPE, direction);
436 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
438 GTK_TYPE_DIRECTION_TYPE, direction);
442 add_arrow_bindings (GtkBindingSet *binding_set,
444 GtkDirectionType direction)
446 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
448 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
450 GTK_TYPE_DIRECTION_TYPE, direction);
451 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
453 GTK_TYPE_DIRECTION_TYPE, direction);
457 add_reorder_bindings (GtkBindingSet *binding_set,
459 GtkDirectionType direction,
460 gboolean move_to_last)
462 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
464 gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
466 GTK_TYPE_DIRECTION_TYPE, direction,
467 G_TYPE_BOOLEAN, move_to_last);
468 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
470 GTK_TYPE_DIRECTION_TYPE, direction,
471 G_TYPE_BOOLEAN, move_to_last);
475 gtk_notebook_class_init (GtkNotebookClass *class)
477 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
478 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
479 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
480 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
481 GtkBindingSet *binding_set;
483 parent_class = g_type_class_peek_parent (class);
485 gobject_class->set_property = gtk_notebook_set_property;
486 gobject_class->get_property = gtk_notebook_get_property;
487 object_class->destroy = gtk_notebook_destroy;
489 widget_class->map = gtk_notebook_map;
490 widget_class->unmap = gtk_notebook_unmap;
491 widget_class->realize = gtk_notebook_realize;
492 widget_class->unrealize = gtk_notebook_unrealize;
493 widget_class->size_request = gtk_notebook_size_request;
494 widget_class->size_allocate = gtk_notebook_size_allocate;
495 widget_class->expose_event = gtk_notebook_expose;
496 widget_class->scroll_event = gtk_notebook_scroll;
497 widget_class->button_press_event = gtk_notebook_button_press;
498 widget_class->button_release_event = gtk_notebook_button_release;
499 widget_class->popup_menu = gtk_notebook_popup_menu;
500 widget_class->enter_notify_event = gtk_notebook_enter_notify;
501 widget_class->leave_notify_event = gtk_notebook_leave_notify;
502 widget_class->motion_notify_event = gtk_notebook_motion_notify;
503 widget_class->grab_notify = gtk_notebook_grab_notify;
504 widget_class->state_changed = gtk_notebook_state_changed;
505 widget_class->focus_in_event = gtk_notebook_focus_in;
506 widget_class->focus_out_event = gtk_notebook_focus_out;
507 widget_class->focus = gtk_notebook_focus;
508 widget_class->style_set = gtk_notebook_style_set;
509 widget_class->drag_begin = gtk_notebook_drag_begin;
510 widget_class->drag_motion = gtk_notebook_drag_motion;
511 widget_class->drag_leave = gtk_notebook_drag_leave;
512 widget_class->drag_drop = gtk_notebook_drag_drop;
513 widget_class->drag_data_get = gtk_notebook_drag_data_get;
514 widget_class->drag_data_received = gtk_notebook_drag_data_received;
516 container_class->add = gtk_notebook_add;
517 container_class->remove = gtk_notebook_remove;
518 container_class->forall = gtk_notebook_forall;
519 container_class->set_focus_child = gtk_notebook_set_focus_child;
520 container_class->get_child_property = gtk_notebook_get_child_property;
521 container_class->set_child_property = gtk_notebook_set_child_property;
522 container_class->child_type = gtk_notebook_child_type;
524 class->switch_page = gtk_notebook_real_switch_page;
525 class->insert_page = gtk_notebook_real_insert_page;
527 class->focus_tab = gtk_notebook_focus_tab;
528 class->select_page = gtk_notebook_select_page;
529 class->change_current_page = gtk_notebook_change_current_page;
530 class->move_focus_out = gtk_notebook_move_focus_out;
531 class->reorder_tab = gtk_notebook_reorder_tab;
533 g_object_class_install_property (gobject_class,
535 g_param_spec_int ("page",
537 P_("The index of the current page"),
541 GTK_PARAM_READWRITE));
542 g_object_class_install_property (gobject_class,
544 g_param_spec_enum ("tab-pos",
546 P_("Which side of the notebook holds the tabs"),
547 GTK_TYPE_POSITION_TYPE,
549 GTK_PARAM_READWRITE));
550 g_object_class_install_property (gobject_class,
552 g_param_spec_uint ("tab-border",
554 P_("Width of the border around the tab labels"),
558 GTK_PARAM_WRITABLE));
559 g_object_class_install_property (gobject_class,
561 g_param_spec_uint ("tab-hborder",
562 P_("Horizontal Tab Border"),
563 P_("Width of the horizontal border of tab labels"),
567 GTK_PARAM_READWRITE));
568 g_object_class_install_property (gobject_class,
570 g_param_spec_uint ("tab-vborder",
571 P_("Vertical Tab Border"),
572 P_("Width of the vertical border of tab labels"),
576 GTK_PARAM_READWRITE));
577 g_object_class_install_property (gobject_class,
579 g_param_spec_boolean ("show-tabs",
581 P_("Whether tabs should be shown or not"),
583 GTK_PARAM_READWRITE));
584 g_object_class_install_property (gobject_class,
586 g_param_spec_boolean ("show-border",
588 P_("Whether the border should be shown or not"),
590 GTK_PARAM_READWRITE));
591 g_object_class_install_property (gobject_class,
593 g_param_spec_boolean ("scrollable",
595 P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
597 GTK_PARAM_READWRITE));
598 g_object_class_install_property (gobject_class,
600 g_param_spec_boolean ("enable-popup",
602 P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
604 GTK_PARAM_READWRITE));
605 g_object_class_install_property (gobject_class,
607 g_param_spec_boolean ("homogeneous",
609 P_("Whether tabs should have homogeneous sizes"),
611 GTK_PARAM_READWRITE));
612 g_object_class_install_property (gobject_class,
614 g_param_spec_int ("group-id",
616 P_("Group ID for tabs drag and drop"),
620 GTK_PARAM_READWRITE));
622 gtk_container_class_install_child_property (container_class,
623 CHILD_PROP_TAB_LABEL,
624 g_param_spec_string ("tab-label",
626 P_("The string displayed on the child's tab label"),
628 GTK_PARAM_READWRITE));
629 gtk_container_class_install_child_property (container_class,
630 CHILD_PROP_MENU_LABEL,
631 g_param_spec_string ("menu-label",
633 P_("The string displayed in the child's menu entry"),
635 GTK_PARAM_READWRITE));
636 gtk_container_class_install_child_property (container_class,
638 g_param_spec_int ("position",
640 P_("The index of the child in the parent"),
642 GTK_PARAM_READWRITE));
643 gtk_container_class_install_child_property (container_class,
644 CHILD_PROP_TAB_EXPAND,
645 g_param_spec_boolean ("tab-expand",
647 P_("Whether to expand the child's tab or not"),
649 GTK_PARAM_READWRITE));
650 gtk_container_class_install_child_property (container_class,
652 g_param_spec_boolean ("tab-fill",
654 P_("Whether the child's tab should fill the allocated area or not"),
656 GTK_PARAM_READWRITE));
657 gtk_container_class_install_child_property (container_class,
659 g_param_spec_enum ("tab-pack",
661 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
662 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
663 GTK_PARAM_READWRITE));
664 gtk_container_class_install_child_property (container_class,
665 CHILD_PROP_REORDERABLE,
666 g_param_spec_boolean ("reorderable",
667 P_("Tab reorderable"),
668 P_("Whether the tab is reorderable by user action or not"),
670 GTK_PARAM_READWRITE));
671 gtk_container_class_install_child_property (container_class,
672 CHILD_PROP_DETACHABLE,
673 g_param_spec_boolean ("detachable",
674 P_("Tab detachable"),
675 P_("Whether the tab is detachable"),
677 GTK_PARAM_READWRITE));
680 * GtkNotebook:has-secondary-backward-stepper:
682 * The "has-secondary-backward-stepper" property determines whether
683 * a second backward arrow button is displayed on the opposite end
688 gtk_widget_class_install_style_property (widget_class,
689 g_param_spec_boolean ("has-secondary-backward-stepper",
690 P_("Secondary backward stepper"),
691 P_("Display a second backward arrow button on the opposite end of the tab area"),
693 GTK_PARAM_READABLE));
696 * GtkNotebook:has-secondary-forward-stepper:
698 * The "has-secondary-forward-stepper" property determines whether
699 * a second forward arrow button is displayed on the opposite end
704 gtk_widget_class_install_style_property (widget_class,
705 g_param_spec_boolean ("has-secondary-forward-stepper",
706 P_("Secondary forward stepper"),
707 P_("Display a second forward arrow button on the opposite end of the tab area"),
709 GTK_PARAM_READABLE));
712 * GtkNotebook:has-backward-stepper:
714 * The "has-backward-stepper" property determines whether
715 * the standard backward arrow button is displayed.
719 gtk_widget_class_install_style_property (widget_class,
720 g_param_spec_boolean ("has-backward-stepper",
721 P_("Backward stepper"),
722 P_("Display the standard backward arrow button"),
724 GTK_PARAM_READABLE));
727 * GtkNotebook:has-forward-stepper:
729 * The "has-forward-stepper" property determines whether
730 * the standard forward arrow button is displayed.
734 gtk_widget_class_install_style_property (widget_class,
735 g_param_spec_boolean ("has-forward-stepper",
736 P_("Forward stepper"),
737 P_("Display the standard forward arrow button"),
739 GTK_PARAM_READABLE));
742 * GtkNotebook:tab-overlap:
744 * The "tab-overlap" property defines size of tab overlap
749 gtk_widget_class_install_style_property (widget_class,
750 g_param_spec_int ("tab-overlap",
752 P_("Size of tab overlap area"),
756 GTK_PARAM_READABLE));
759 * GtkNotebook:tab-curvature:
761 * The "tab-curvature" property defines size of tab curvature.
765 gtk_widget_class_install_style_property (widget_class,
766 g_param_spec_int ("tab-curvature",
768 P_("Size of tab curvature"),
772 GTK_PARAM_READABLE));
774 notebook_signals[SWITCH_PAGE] =
775 g_signal_new (I_("switch_page"),
776 G_TYPE_FROM_CLASS (gobject_class),
778 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
780 _gtk_marshal_VOID__POINTER_UINT,
784 notebook_signals[FOCUS_TAB] =
785 g_signal_new (I_("focus_tab"),
786 G_TYPE_FROM_CLASS (gobject_class),
787 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
788 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
790 _gtk_marshal_BOOLEAN__ENUM,
792 GTK_TYPE_NOTEBOOK_TAB);
793 notebook_signals[SELECT_PAGE] =
794 g_signal_new (I_("select_page"),
795 G_TYPE_FROM_CLASS (gobject_class),
796 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
797 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
799 _gtk_marshal_BOOLEAN__BOOLEAN,
802 notebook_signals[CHANGE_CURRENT_PAGE] =
803 g_signal_new (I_("change_current_page"),
804 G_TYPE_FROM_CLASS (gobject_class),
805 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
806 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
808 _gtk_marshal_VOID__INT,
811 notebook_signals[MOVE_FOCUS_OUT] =
812 g_signal_new (I_("move_focus_out"),
813 G_TYPE_FROM_CLASS (gobject_class),
814 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
815 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
817 _gtk_marshal_VOID__ENUM,
819 GTK_TYPE_DIRECTION_TYPE);
820 notebook_signals[REORDER_TAB] =
821 g_signal_new (I_("reorder_tab"),
822 G_TYPE_FROM_CLASS (gobject_class),
823 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
824 G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
826 _gtk_marshal_VOID__ENUM_BOOLEAN,
828 GTK_TYPE_DIRECTION_TYPE,
831 * GtkNotebook::page-reordered:
832 * @notebook: the #GtkNotebook
833 * @child: the child #GtkWidget affected
834 * @page_num: the new page number for @child
836 * the ::page-reordered signal is emitted in the notebook
837 * right after a page has been reordered.
841 notebook_signals[PAGE_REORDERED] =
842 g_signal_new (I_("page_reordered"),
843 G_TYPE_FROM_CLASS (gobject_class),
846 _gtk_marshal_VOID__OBJECT_UINT,
851 * GtkNotebook::page-removed:
852 * @notebook: the #GtkNotebook
853 * @child: the child #GtkWidget affected
854 * @page_num: the @child page number
856 * the ::page-removed signal is emitted in the notebook
857 * right after a page is removed from the notebook.
861 notebook_signals[PAGE_REMOVED] =
862 g_signal_new (I_("page_removed"),
863 G_TYPE_FROM_CLASS (gobject_class),
866 _gtk_marshal_VOID__OBJECT_UINT,
871 * GtkNotebook::page-added:
872 * @notebook: the #GtkNotebook
873 * @child: the child #GtkWidget affected
874 * @page_num: the new page number for @child
876 * the ::page-added signal is emitted in the notebook
877 * right after a page is added to the notebook.
881 notebook_signals[PAGE_ADDED] =
882 g_signal_new (I_("page_added"),
883 G_TYPE_FROM_CLASS (gobject_class),
886 _gtk_marshal_VOID__OBJECT_UINT,
891 binding_set = gtk_binding_set_by_class (class);
892 gtk_binding_entry_add_signal (binding_set,
895 G_TYPE_BOOLEAN, FALSE);
896 gtk_binding_entry_add_signal (binding_set,
899 G_TYPE_BOOLEAN, FALSE);
901 gtk_binding_entry_add_signal (binding_set,
904 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
905 gtk_binding_entry_add_signal (binding_set,
908 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
909 gtk_binding_entry_add_signal (binding_set,
912 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
913 gtk_binding_entry_add_signal (binding_set,
916 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
918 gtk_binding_entry_add_signal (binding_set,
919 GDK_Page_Up, GDK_CONTROL_MASK,
920 "change_current_page", 1,
922 gtk_binding_entry_add_signal (binding_set,
923 GDK_Page_Down, GDK_CONTROL_MASK,
924 "change_current_page", 1,
927 gtk_binding_entry_add_signal (binding_set,
928 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
929 "change_current_page", 1,
931 gtk_binding_entry_add_signal (binding_set,
932 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
933 "change_current_page", 1,
936 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
937 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
938 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
939 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
941 add_reorder_bindings (binding_set, GDK_Up, GTK_DIR_UP, FALSE);
942 add_reorder_bindings (binding_set, GDK_Down, GTK_DIR_DOWN, FALSE);
943 add_reorder_bindings (binding_set, GDK_Left, GTK_DIR_LEFT, FALSE);
944 add_reorder_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT, FALSE);
945 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_LEFT, TRUE);
946 add_reorder_bindings (binding_set, GDK_Home, GTK_DIR_UP, TRUE);
947 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_RIGHT, TRUE);
948 add_reorder_bindings (binding_set, GDK_End, GTK_DIR_DOWN, TRUE);
950 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
951 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
953 g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
957 gtk_notebook_init (GtkNotebook *notebook)
959 GtkNotebookPrivate *priv;
961 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
962 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
964 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
966 notebook->cur_page = NULL;
967 notebook->children = NULL;
968 notebook->first_tab = NULL;
969 notebook->focus_tab = NULL;
970 notebook->event_window = NULL;
971 notebook->menu = NULL;
973 notebook->tab_hborder = 2;
974 notebook->tab_vborder = 2;
976 notebook->show_tabs = TRUE;
977 notebook->show_border = TRUE;
978 notebook->tab_pos = GTK_POS_TOP;
979 notebook->scrollable = FALSE;
980 notebook->in_child = 0;
981 notebook->click_child = 0;
982 notebook->button = 0;
983 notebook->need_timer = 0;
984 notebook->child_has_focus = FALSE;
985 notebook->have_visible_child = FALSE;
986 notebook->focus_out = FALSE;
988 notebook->has_before_previous = 1;
989 notebook->has_before_next = 0;
990 notebook->has_after_previous = 0;
991 notebook->has_after_next = 1;
994 priv->pressed_button = -1;
996 priv->switch_tab_timer = 0;
997 priv->source_targets = gtk_target_list_new (notebook_source_targets,
998 G_N_ELEMENTS (notebook_source_targets));
1000 gtk_drag_dest_set (GTK_WIDGET (notebook),
1001 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
1002 notebook_dest_targets, G_N_ELEMENTS (notebook_dest_targets),
1005 gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
1009 gtk_notebook_select_page (GtkNotebook *notebook,
1010 gboolean move_focus)
1012 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1014 gtk_notebook_page_select (notebook, move_focus);
1022 gtk_notebook_focus_tab (GtkNotebook *notebook,
1023 GtkNotebookTab type)
1027 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
1031 case GTK_NOTEBOOK_TAB_FIRST:
1032 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1034 gtk_notebook_switch_focus_tab (notebook, list);
1036 case GTK_NOTEBOOK_TAB_LAST:
1037 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
1039 gtk_notebook_switch_focus_tab (notebook, list);
1050 gtk_notebook_change_current_page (GtkNotebook *notebook,
1053 GList *current = NULL;
1055 if (notebook->cur_page)
1056 current = g_list_find (notebook->children, notebook->cur_page);
1060 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
1061 offset += offset < 0 ? 1 : -1;
1065 gtk_notebook_switch_page (notebook, current->data, -1);
1067 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1070 static GtkDirectionType
1071 get_effective_direction (GtkNotebook *notebook,
1072 GtkDirectionType direction)
1074 /* Remap the directions into the effective direction it would be for a
1075 * GTK_POS_TOP notebook
1078 #define D(rest) GTK_DIR_##rest
1080 static const GtkDirectionType translate_direction[2][4][6] = {
1081 /* LEFT */ {{ D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1082 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1083 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1084 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) }},
1085 /* LEFT */ {{ D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1086 /* RIGHT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1087 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(RIGHT), D(LEFT) },
1088 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(RIGHT), D(LEFT) }},
1093 int text_dir = gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL ? 1 : 0;
1095 return translate_direction[text_dir][notebook->tab_pos][direction];
1099 get_effective_tab_pos (GtkNotebook *notebook)
1101 if (gtk_widget_get_direction (GTK_WIDGET (notebook)) == GTK_TEXT_DIR_RTL)
1103 switch (notebook->tab_pos)
1106 return GTK_POS_RIGHT;
1108 return GTK_POS_LEFT;
1113 return notebook->tab_pos;
1117 gtk_notebook_move_focus_out (GtkNotebook *notebook,
1118 GtkDirectionType direction_type)
1120 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1121 GtkWidget *toplevel;
1123 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
1124 if (focus_tabs_in (notebook))
1126 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
1127 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
1130 /* At this point, we know we should be focusing out of the notebook entirely. We
1131 * do this by setting a flag, then propagating the focus motion to the notebook.
1133 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
1134 if (!GTK_WIDGET_TOPLEVEL (toplevel))
1137 g_object_ref (notebook);
1139 notebook->focus_out = TRUE;
1140 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
1141 notebook->focus_out = FALSE;
1143 g_object_unref (notebook);
1147 reorder_tab (GtkNotebook *notebook, GList *position, GList *tab)
1151 /* check that we aren't inserting the tab in the
1152 * same relative position, taking packing into account */
1153 elem = (position) ? position->prev : g_list_last (notebook->children);
1155 while (elem && GTK_NOTEBOOK_PAGE (elem)->pack != GTK_NOTEBOOK_PAGE (tab)->pack)
1159 return g_list_position (notebook->children, tab);
1161 /* now actually reorder the tab */
1162 if (notebook->first_tab == tab)
1163 notebook->first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
1166 notebook->children = g_list_remove_link (notebook->children, tab);
1169 elem = g_list_last (notebook->children);
1172 elem = position->prev;
1173 position->prev = tab;
1179 notebook->children = tab;
1182 tab->next = position;
1184 return g_list_position (notebook->children, tab);
1188 gtk_notebook_reorder_tab (GtkNotebook *notebook,
1189 GtkDirectionType direction_type,
1190 gboolean move_to_last)
1192 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
1193 GtkNotebookPage *page;
1194 GList *last, *child;
1197 if (!notebook->cur_page ||
1198 !notebook->cur_page->reorderable)
1201 if (effective_direction != GTK_DIR_LEFT &&
1202 effective_direction != GTK_DIR_RIGHT)
1207 child = notebook->focus_tab;
1212 child = gtk_notebook_search_page (notebook, last,
1213 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1216 while (child && GTK_NOTEBOOK_PAGE (last)->pack == GTK_NOTEBOOK_PAGE (child)->pack);
1221 child = gtk_notebook_search_page (notebook, notebook->focus_tab,
1222 (effective_direction == GTK_DIR_RIGHT) ? STEP_NEXT : STEP_PREV,
1225 if (!child || child->data == notebook->cur_page)
1230 if (page->pack == notebook->cur_page->pack)
1232 if (effective_direction == GTK_DIR_RIGHT)
1233 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child->next : child, notebook->focus_tab);
1235 page_num = reorder_tab (notebook, (page->pack == GTK_PACK_START) ? child : child->next, notebook->focus_tab);
1237 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1239 g_signal_emit (notebook,
1240 notebook_signals[PAGE_REORDERED],
1242 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
1250 * Creates a new #GtkNotebook widget with no pages.
1252 * Return value: the newly created #GtkNotebook
1255 gtk_notebook_new (void)
1257 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
1260 /* Private GtkObject Methods :
1262 * gtk_notebook_destroy
1263 * gtk_notebook_set_arg
1264 * gtk_notebook_get_arg
1267 gtk_notebook_destroy (GtkObject *object)
1269 GtkNotebook *notebook = GTK_NOTEBOOK (object);
1270 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1273 gtk_notebook_popup_disable (notebook);
1275 if (priv->source_targets)
1277 gtk_target_list_unref (priv->source_targets);
1278 priv->source_targets = NULL;
1281 if (priv->switch_tab_timer)
1283 g_source_remove (priv->switch_tab_timer);
1284 priv->switch_tab_timer = 0;
1287 GTK_OBJECT_CLASS (parent_class)->destroy (object);
1291 gtk_notebook_set_property (GObject *object,
1293 const GValue *value,
1296 GtkNotebook *notebook;
1298 notebook = GTK_NOTEBOOK (object);
1302 case PROP_SHOW_TABS:
1303 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
1305 case PROP_SHOW_BORDER:
1306 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
1308 case PROP_SCROLLABLE:
1309 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
1311 case PROP_ENABLE_POPUP:
1312 if (g_value_get_boolean (value))
1313 gtk_notebook_popup_enable (notebook);
1315 gtk_notebook_popup_disable (notebook);
1317 case PROP_HOMOGENEOUS:
1318 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
1321 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
1324 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
1326 case PROP_TAB_BORDER:
1327 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
1329 case PROP_TAB_HBORDER:
1330 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
1332 case PROP_TAB_VBORDER:
1333 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
1336 gtk_notebook_set_group_id (notebook, g_value_get_int (value));
1344 gtk_notebook_get_property (GObject *object,
1349 GtkNotebook *notebook;
1350 GtkNotebookPrivate *priv;
1352 notebook = GTK_NOTEBOOK (object);
1353 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
1357 case PROP_SHOW_TABS:
1358 g_value_set_boolean (value, notebook->show_tabs);
1360 case PROP_SHOW_BORDER:
1361 g_value_set_boolean (value, notebook->show_border);
1363 case PROP_SCROLLABLE:
1364 g_value_set_boolean (value, notebook->scrollable);
1366 case PROP_ENABLE_POPUP:
1367 g_value_set_boolean (value, notebook->menu != NULL);
1369 case PROP_HOMOGENEOUS:
1370 g_value_set_boolean (value, notebook->homogeneous);
1373 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
1376 g_value_set_enum (value, notebook->tab_pos);
1378 case PROP_TAB_HBORDER:
1379 g_value_set_uint (value, notebook->tab_hborder);
1381 case PROP_TAB_VBORDER:
1382 g_value_set_uint (value, notebook->tab_vborder);
1385 g_value_set_int (value, priv->group_id);
1388 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1393 /* Private GtkWidget Methods :
1396 * gtk_notebook_unmap
1397 * gtk_notebook_realize
1398 * gtk_notebook_size_request
1399 * gtk_notebook_size_allocate
1400 * gtk_notebook_expose
1401 * gtk_notebook_scroll
1402 * gtk_notebook_button_press
1403 * gtk_notebook_button_release
1404 * gtk_notebook_popup_menu
1405 * gtk_notebook_enter_notify
1406 * gtk_notebook_leave_notify
1407 * gtk_notebook_motion_notify
1408 * gtk_notebook_focus_in
1409 * gtk_notebook_focus_out
1410 * gtk_notebook_draw_focus
1411 * gtk_notebook_style_set
1412 * gtk_notebook_drag_begin
1413 * gtk_notebook_drag_motion
1414 * gtk_notebook_drag_drop
1415 * gtk_notebook_drag_data_get
1416 * gtk_notebook_drag_data_received
1419 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
1420 GdkRectangle *rectangle)
1422 GtkWidget *widget = GTK_WIDGET (notebook);
1423 gint border_width = GTK_CONTAINER (notebook)->border_width;
1424 GtkNotebookPage *visible_page = NULL;
1426 gint tab_pos = get_effective_tab_pos (notebook);
1428 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
1430 GtkNotebookPage *page = tmp_list->data;
1431 if (GTK_WIDGET_VISIBLE (page->child))
1433 visible_page = page;
1438 if (notebook->show_tabs && visible_page)
1442 rectangle->x = widget->allocation.x + border_width;
1443 rectangle->y = widget->allocation.y + border_width;
1448 case GTK_POS_BOTTOM:
1449 rectangle->width = widget->allocation.width - 2 * border_width;
1450 rectangle->height = visible_page->requisition.height;
1451 if (tab_pos == GTK_POS_BOTTOM)
1452 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
1456 rectangle->width = visible_page->requisition.width;
1457 rectangle->height = widget->allocation.height - 2 * border_width;
1458 if (tab_pos == GTK_POS_RIGHT)
1459 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1470 rectangle->x = rectangle->y = 0;
1471 rectangle->width = rectangle->height = 10;
1479 gtk_notebook_map (GtkWidget *widget)
1481 GtkNotebook *notebook;
1482 GtkNotebookPage *page;
1485 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1487 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1489 notebook = GTK_NOTEBOOK (widget);
1491 if (notebook->cur_page &&
1492 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1493 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1494 gtk_widget_map (notebook->cur_page->child);
1496 if (notebook->scrollable)
1497 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1500 children = notebook->children;
1504 page = children->data;
1505 children = children->next;
1507 if (page->tab_label &&
1508 GTK_WIDGET_VISIBLE (page->tab_label) &&
1509 !GTK_WIDGET_MAPPED (page->tab_label))
1510 gtk_widget_map (page->tab_label);
1514 if (gtk_notebook_get_event_window_position (notebook, NULL))
1515 gdk_window_show_unraised (notebook->event_window);
1519 gtk_notebook_unmap (GtkWidget *widget)
1521 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1523 stop_scrolling (GTK_NOTEBOOK (widget));
1525 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1527 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1529 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1533 gtk_notebook_realize (GtkWidget *widget)
1535 GtkNotebook *notebook;
1536 GdkWindowAttr attributes;
1537 gint attributes_mask;
1538 GdkRectangle event_window_pos;
1540 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1542 notebook = GTK_NOTEBOOK (widget);
1543 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1545 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1547 widget->window = gtk_widget_get_parent_window (widget);
1548 g_object_ref (widget->window);
1550 attributes.window_type = GDK_WINDOW_CHILD;
1551 attributes.x = event_window_pos.x;
1552 attributes.y = event_window_pos.y;
1553 attributes.width = event_window_pos.width;
1554 attributes.height = event_window_pos.height;
1555 attributes.wclass = GDK_INPUT_ONLY;
1556 attributes.event_mask = gtk_widget_get_events (widget);
1557 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1558 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
1559 GDK_BUTTON1_MOTION_MASK |
1561 attributes_mask = GDK_WA_X | GDK_WA_Y;
1563 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1564 &attributes, attributes_mask);
1565 gdk_window_set_user_data (notebook->event_window, notebook);
1567 widget->style = gtk_style_attach (widget->style, widget->window);
1571 gtk_notebook_unrealize (GtkWidget *widget)
1573 GtkNotebook *notebook;
1575 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1577 notebook = GTK_NOTEBOOK (widget);
1579 gdk_window_set_user_data (notebook->event_window, NULL);
1580 gdk_window_destroy (notebook->event_window);
1581 notebook->event_window = NULL;
1583 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1584 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1588 gtk_notebook_size_request (GtkWidget *widget,
1589 GtkRequisition *requisition)
1591 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1592 GtkNotebookPage *page;
1594 GtkRequisition child_requisition;
1595 gboolean switch_page = FALSE;
1601 gtk_widget_style_get (widget,
1602 "focus-line-width", &focus_width,
1603 "tab-overlap", &tab_overlap,
1604 "tab-curvature", &tab_curvature,
1607 widget->requisition.width = 0;
1608 widget->requisition.height = 0;
1610 for (children = notebook->children, vis_pages = 0; children;
1611 children = children->next)
1613 page = children->data;
1615 if (GTK_WIDGET_VISIBLE (page->child))
1618 gtk_widget_size_request (page->child, &child_requisition);
1620 widget->requisition.width = MAX (widget->requisition.width,
1621 child_requisition.width);
1622 widget->requisition.height = MAX (widget->requisition.height,
1623 child_requisition.height);
1625 if (notebook->menu && page->menu_label->parent &&
1626 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1627 gtk_widget_show (page->menu_label->parent);
1631 if (page == notebook->cur_page)
1633 if (notebook->menu && page->menu_label->parent &&
1634 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1635 gtk_widget_hide (page->menu_label->parent);
1639 if (notebook->show_border || notebook->show_tabs)
1641 widget->requisition.width += widget->style->xthickness * 2;
1642 widget->requisition.height += widget->style->ythickness * 2;
1644 if (notebook->show_tabs)
1647 gint tab_height = 0;
1651 for (children = notebook->children; children;
1652 children = children->next)
1654 page = children->data;
1656 if (GTK_WIDGET_VISIBLE (page->child))
1658 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1659 gtk_widget_show (page->tab_label);
1661 gtk_widget_size_request (page->tab_label,
1662 &child_requisition);
1664 page->requisition.width =
1665 child_requisition.width +
1666 2 * widget->style->xthickness;
1667 page->requisition.height =
1668 child_requisition.height +
1669 2 * widget->style->ythickness;
1671 switch (notebook->tab_pos)
1674 case GTK_POS_BOTTOM:
1675 page->requisition.height += 2 * (notebook->tab_vborder +
1677 tab_height = MAX (tab_height, page->requisition.height);
1678 tab_max = MAX (tab_max, page->requisition.width);
1682 page->requisition.width += 2 * (notebook->tab_hborder +
1684 tab_width = MAX (tab_width, page->requisition.width);
1685 tab_max = MAX (tab_max, page->requisition.height);
1689 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1690 gtk_widget_hide (page->tab_label);
1693 children = notebook->children;
1697 switch (notebook->tab_pos)
1700 case GTK_POS_BOTTOM:
1701 if (tab_height == 0)
1704 if (notebook->scrollable && vis_pages > 1 &&
1705 widget->requisition.width < tab_width)
1706 tab_height = MAX (tab_height, ARROW_SIZE);
1708 padding = 2 * (tab_curvature + focus_width +
1709 notebook->tab_hborder) - tab_overlap;
1713 page = children->data;
1714 children = children->next;
1716 if (!GTK_WIDGET_VISIBLE (page->child))
1719 if (notebook->homogeneous)
1720 page->requisition.width = tab_max;
1722 page->requisition.width += padding;
1724 tab_width += page->requisition.width;
1725 page->requisition.height = tab_height;
1728 if (notebook->scrollable && vis_pages > 1 &&
1729 widget->requisition.width < tab_width)
1730 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1732 if (notebook->homogeneous && !notebook->scrollable)
1733 widget->requisition.width = MAX (widget->requisition.width,
1734 vis_pages * tab_max +
1737 widget->requisition.width = MAX (widget->requisition.width,
1738 tab_width + tab_overlap);
1740 widget->requisition.height += tab_height;
1747 if (notebook->scrollable && vis_pages > 1 &&
1748 widget->requisition.height < tab_height)
1749 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1751 padding = 2 * (tab_curvature + focus_width +
1752 notebook->tab_vborder) - tab_overlap;
1757 page = children->data;
1758 children = children->next;
1760 if (!GTK_WIDGET_VISIBLE (page->child))
1763 page->requisition.width = tab_width;
1765 if (notebook->homogeneous)
1766 page->requisition.height = tab_max;
1768 page->requisition.height += padding;
1770 tab_height += page->requisition.height;
1773 if (notebook->scrollable && vis_pages > 1 &&
1774 widget->requisition.height < tab_height)
1775 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1777 widget->requisition.width += tab_width;
1779 if (notebook->homogeneous && !notebook->scrollable)
1780 widget->requisition.height =
1781 MAX (widget->requisition.height,
1782 vis_pages * tab_max + tab_overlap);
1784 widget->requisition.height =
1785 MAX (widget->requisition.height,
1786 tab_height + tab_overlap);
1788 if (!notebook->homogeneous || notebook->scrollable)
1790 widget->requisition.height = MAX (widget->requisition.height,
1791 vis_pages * tab_max +
1799 for (children = notebook->children; children;
1800 children = children->next)
1802 page = children->data;
1804 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1805 gtk_widget_hide (page->tab_label);
1810 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1811 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1817 for (children = notebook->children; children;
1818 children = children->next)
1820 page = children->data;
1821 if (GTK_WIDGET_VISIBLE (page->child))
1823 gtk_notebook_switch_page (notebook, page, -1);
1828 else if (GTK_WIDGET_VISIBLE (widget))
1830 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1831 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1834 if (vis_pages && !notebook->cur_page)
1836 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1839 notebook->first_tab = children;
1840 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1846 gtk_notebook_size_allocate (GtkWidget *widget,
1847 GtkAllocation *allocation)
1849 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1851 gint tab_pos = get_effective_tab_pos (notebook);
1853 widget->allocation = *allocation;
1854 if (GTK_WIDGET_REALIZED (widget))
1856 GdkRectangle position;
1858 if (gtk_notebook_get_event_window_position (notebook, &position))
1860 gdk_window_move_resize (notebook->event_window,
1861 position.x, position.y,
1862 position.width, position.height);
1863 if (GTK_WIDGET_MAPPED (notebook))
1864 gdk_window_show_unraised (notebook->event_window);
1867 gdk_window_hide (notebook->event_window);
1870 if (notebook->children)
1872 gint border_width = GTK_CONTAINER (widget)->border_width;
1873 GtkNotebookPage *page;
1874 GtkAllocation child_allocation;
1877 child_allocation.x = widget->allocation.x + border_width;
1878 child_allocation.y = widget->allocation.y + border_width;
1879 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1880 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1882 if (notebook->show_tabs || notebook->show_border)
1884 child_allocation.x += widget->style->xthickness;
1885 child_allocation.y += widget->style->ythickness;
1886 child_allocation.width = MAX (1, child_allocation.width -
1887 widget->style->xthickness * 2);
1888 child_allocation.height = MAX (1, child_allocation.height -
1889 widget->style->ythickness * 2);
1891 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1896 child_allocation.y += notebook->cur_page->requisition.height;
1897 case GTK_POS_BOTTOM:
1898 child_allocation.height =
1899 MAX (1, child_allocation.height -
1900 notebook->cur_page->requisition.height);
1903 child_allocation.x += notebook->cur_page->requisition.width;
1905 child_allocation.width =
1906 MAX (1, child_allocation.width -
1907 notebook->cur_page->requisition.width);
1913 children = notebook->children;
1916 page = children->data;
1917 children = children->next;
1919 if (GTK_WIDGET_VISIBLE (page->child))
1921 gtk_widget_size_allocate (page->child, &child_allocation);
1926 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
1931 gtk_notebook_expose (GtkWidget *widget,
1932 GdkEventExpose *event)
1934 GtkNotebook *notebook;
1935 GdkRectangle child_area;
1937 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1938 g_return_val_if_fail (event != NULL, FALSE);
1940 if (GTK_WIDGET_DRAWABLE (widget))
1942 notebook = GTK_NOTEBOOK (widget);
1944 gtk_notebook_paint (widget, &event->area);
1945 if (notebook->show_tabs)
1947 if (notebook->cur_page &&
1948 gtk_widget_intersect (notebook->cur_page->tab_label,
1949 &event->area, &child_area))
1950 gtk_notebook_draw_focus (widget);
1954 if (notebook->cur_page)
1955 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1956 notebook->cur_page->child,
1964 gtk_notebook_show_arrows (GtkNotebook *notebook)
1966 gboolean show_arrow = FALSE;
1969 if (!notebook->scrollable)
1972 children = notebook->children;
1975 GtkNotebookPage *page = children->data;
1977 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1980 children = children->next;
1987 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1988 GdkRectangle *rectangle,
1989 GtkNotebookArrow arrow)
1991 GdkRectangle event_window_pos;
1992 gboolean before = ARROW_IS_BEFORE (arrow);
1993 gboolean left = ARROW_IS_LEFT (arrow);
1995 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1997 rectangle->width = ARROW_SIZE;
1998 rectangle->height = ARROW_SIZE;
2000 switch (notebook->tab_pos)
2004 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
2005 (!before && (notebook->has_after_previous != notebook->has_after_next)))
2006 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
2008 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
2010 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
2011 rectangle->y = event_window_pos.y;
2013 rectangle->y += event_window_pos.height - rectangle->height;
2016 case GTK_POS_BOTTOM:
2019 if (left || !notebook->has_before_previous)
2020 rectangle->x = event_window_pos.x;
2022 rectangle->x = event_window_pos.x + rectangle->width;
2026 if (!left || !notebook->has_after_next)
2027 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
2029 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
2031 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
2037 static GtkNotebookArrow
2038 gtk_notebook_get_arrow (GtkNotebook *notebook,
2042 GdkRectangle arrow_rect;
2043 GdkRectangle event_window_pos;
2046 GtkNotebookArrow arrow[4];
2048 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2049 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2050 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2051 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2053 if (gtk_notebook_show_arrows (notebook))
2055 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
2056 for (i = 0; i < 4; i++)
2058 if (arrow[i] == ARROW_NONE)
2061 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
2063 x0 = x - arrow_rect.x;
2064 y0 = y - arrow_rect.y;
2066 if (y0 >= 0 && y0 < arrow_rect.height &&
2067 x0 >= 0 && x0 < arrow_rect.width)
2076 gtk_notebook_do_arrow (GtkNotebook *notebook,
2077 GtkNotebookArrow arrow)
2079 GtkWidget *widget = GTK_WIDGET (notebook);
2080 GtkDirectionType dir;
2081 gboolean is_rtl, left;
2083 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2084 left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2085 (!ARROW_IS_LEFT (arrow) && is_rtl);
2087 if (!notebook->focus_tab ||
2088 gtk_notebook_search_page (notebook, notebook->focus_tab,
2089 left ? STEP_PREV : STEP_NEXT,
2092 if (notebook->tab_pos == GTK_POS_LEFT ||
2093 notebook->tab_pos == GTK_POS_RIGHT)
2094 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_UP : GTK_DIR_DOWN;
2096 dir = ARROW_IS_LEFT (arrow) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
2097 gtk_widget_child_focus (widget, dir);
2102 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
2103 GtkNotebookArrow arrow,
2106 GtkWidget *widget = GTK_WIDGET (notebook);
2107 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2108 gboolean left = (ARROW_IS_LEFT (arrow) && !is_rtl) ||
2109 (!ARROW_IS_LEFT (arrow) && is_rtl);
2111 if (!GTK_WIDGET_HAS_FOCUS (widget))
2112 gtk_widget_grab_focus (widget);
2114 notebook->button = button;
2115 notebook->click_child = arrow;
2119 gtk_notebook_do_arrow (notebook, arrow);
2121 if (!notebook->timer)
2123 GtkSettings *settings = gtk_widget_get_settings (widget);
2126 g_object_get (settings, "gtk-timeout-initial", &timeout, NULL);
2128 notebook->timer = g_timeout_add (timeout,
2129 (GSourceFunc) gtk_notebook_timer,
2130 (gpointer) notebook);
2131 notebook->need_timer = TRUE;
2134 else if (button == 2)
2135 gtk_notebook_page_select (notebook, TRUE);
2136 else if (button == 3)
2137 gtk_notebook_switch_focus_tab (notebook,
2138 gtk_notebook_search_page (notebook,
2140 left ? STEP_NEXT : STEP_PREV,
2142 gtk_notebook_redraw_arrows (notebook);
2148 get_widget_coordinates (GtkWidget *widget,
2153 GdkWindow *window = ((GdkEventAny *)event)->window;
2156 if (!gdk_event_get_coords (event, &tx, &ty))
2159 while (window && window != widget->window)
2161 gint window_x, window_y;
2163 gdk_window_get_position (window, &window_x, &window_y);
2167 window = gdk_window_get_parent (window);
2182 gtk_notebook_scroll (GtkWidget *widget,
2183 GdkEventScroll *event)
2185 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2188 GtkWidget* originator;
2190 if (!notebook->cur_page)
2193 child = notebook->cur_page->child;
2194 originator = gtk_get_event_widget ((GdkEvent *)event);
2196 /* ignore scroll events from the content of the page */
2197 if (!originator || gtk_widget_is_ancestor (originator, child))
2200 switch (event->direction)
2202 case GDK_SCROLL_RIGHT:
2203 case GDK_SCROLL_DOWN:
2204 gtk_notebook_next_page (notebook);
2206 case GDK_SCROLL_LEFT:
2208 gtk_notebook_prev_page (notebook);
2216 get_tab_at_pos (GtkNotebook *notebook, gint x, gint y)
2218 GtkNotebookPage *page;
2219 GList *children = notebook->children;
2223 page = children->data;
2225 if (GTK_WIDGET_VISIBLE (page->child) &&
2226 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
2227 (x >= page->allocation.x) &&
2228 (y >= page->allocation.y) &&
2229 (x <= (page->allocation.x + page->allocation.width)) &&
2230 (y <= (page->allocation.y + page->allocation.height)))
2233 children = children->next;
2240 gtk_notebook_button_press (GtkWidget *widget,
2241 GdkEventButton *event)
2243 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2244 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2245 GtkNotebookPage *page;
2247 GtkNotebookArrow arrow;
2250 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
2254 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2257 arrow = gtk_notebook_get_arrow (notebook, x, y);
2259 return gtk_notebook_arrow_button_press (notebook, arrow, event->button);
2261 if (event->button == 3 && notebook->menu)
2263 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2264 NULL, NULL, 3, event->time);
2268 if (event->button != 1)
2271 notebook->button = event->button;
2273 if ((tab = get_tab_at_pos (notebook, x, y)) != NULL)
2275 gboolean page_changed, was_focus;
2278 page_changed = page != notebook->cur_page;
2279 was_focus = gtk_widget_is_focus (widget);
2281 gtk_notebook_switch_focus_tab (notebook, tab);
2282 gtk_widget_grab_focus (widget);
2284 if (page_changed && !was_focus)
2285 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
2287 /* save press to possibly begin a drag */
2288 if (page->reorderable || page->detachable)
2290 priv->during_detach = FALSE;
2291 priv->pressed_button = event->button;
2292 gtk_grab_add (widget);
2300 popup_position_func (GtkMenu *menu,
2306 GtkNotebook *notebook = data;
2308 GtkRequisition requisition;
2310 if (notebook->focus_tab)
2312 GtkNotebookPage *page;
2314 page = notebook->focus_tab->data;
2315 w = page->tab_label;
2319 w = GTK_WIDGET (notebook);
2322 gdk_window_get_origin (w->window, x, y);
2323 gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
2325 if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
2326 *x += w->allocation.x + w->allocation.width - requisition.width;
2328 *x += w->allocation.x;
2330 *y += w->allocation.y + w->allocation.height;
2336 gtk_notebook_popup_menu (GtkWidget *widget)
2338 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2342 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
2343 popup_position_func, notebook,
2344 0, gtk_get_current_event_time ());
2345 gtk_menu_shell_select_first (GTK_MENU_SHELL (notebook->menu), FALSE);
2353 stop_scrolling (GtkNotebook *notebook)
2355 if (notebook->timer)
2357 g_source_remove (notebook->timer);
2358 notebook->timer = 0;
2359 notebook->need_timer = FALSE;
2361 notebook->click_child = 0;
2362 notebook->button = 0;
2363 gtk_notebook_redraw_arrows (notebook);
2367 get_drop_position (GtkNotebook *notebook,
2373 GtkNotebookPage *page;
2376 is_rtl = gtk_widget_get_direction ((GtkWidget *) notebook) == GTK_TEXT_DIR_RTL;
2377 children = notebook->children;
2381 page = children->data;
2383 if (GTK_WIDGET_VISIBLE (page->child) &&
2385 GTK_WIDGET_MAPPED (page->tab_label) &&
2388 switch (notebook->tab_pos)
2391 case GTK_POS_BOTTOM:
2394 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) > x) ||
2395 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) < x))
2400 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_X (page) < x) ||
2401 (page->pack == GTK_PACK_END && PAGE_MIDDLE_X (page) > x))
2408 if ((page->pack == GTK_PACK_START && PAGE_MIDDLE_Y (page) > y) ||
2409 (page->pack == GTK_PACK_END && PAGE_MIDDLE_Y (page) < y))
2416 children = children->next;
2423 gtk_notebook_button_release (GtkWidget *widget,
2424 GdkEventButton *event)
2426 GtkNotebook *notebook;
2427 GtkNotebookPrivate *priv;
2429 gint old_page_num, page_num;
2431 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2432 g_return_val_if_fail (event != NULL, FALSE);
2434 if (event->type != GDK_BUTTON_RELEASE)
2437 notebook = GTK_NOTEBOOK (widget);
2438 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2440 if (notebook->cur_page->reorderable &&
2441 event->button == priv->pressed_button)
2443 gtk_grab_remove (widget);
2444 priv->pressed_button = -1;
2446 if (!priv->during_detach)
2448 element = get_drop_position (notebook,
2449 notebook->cur_page->pack,
2450 PAGE_MIDDLE_X (notebook->cur_page),
2451 PAGE_MIDDLE_Y (notebook->cur_page));
2452 old_page_num = g_list_position (notebook->children, notebook->focus_tab);
2453 page_num = reorder_tab (notebook, element, notebook->focus_tab);
2455 if (priv->has_scrolled ||
2456 old_page_num != page_num)
2457 g_signal_emit (notebook,
2458 notebook_signals[PAGE_REORDERED], 0,
2459 ((GtkNotebookPage *) notebook->focus_tab->data)->child,
2462 priv->has_scrolled = FALSE;
2465 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
2467 if (priv->dnd_timer)
2469 g_source_remove (priv->dnd_timer);
2470 priv->dnd_timer = 0;
2474 if (event->button == notebook->button)
2476 stop_scrolling (notebook);
2485 gtk_notebook_enter_notify (GtkWidget *widget,
2486 GdkEventCrossing *event)
2488 GtkNotebook *notebook;
2489 GtkNotebookArrow arrow;
2492 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2493 g_return_val_if_fail (event != NULL, FALSE);
2495 notebook = GTK_NOTEBOOK (widget);
2497 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2500 arrow = gtk_notebook_get_arrow (notebook, x, y);
2502 if (arrow != notebook->in_child)
2504 notebook->in_child = arrow;
2505 gtk_notebook_redraw_arrows (notebook);
2514 gtk_notebook_leave_notify (GtkWidget *widget,
2515 GdkEventCrossing *event)
2517 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2520 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
2523 if (notebook->in_child)
2525 notebook->in_child = 0;
2526 gtk_notebook_redraw_arrows (notebook);
2532 static GtkNotebookPointerPosition
2533 get_pointer_position (GtkNotebook *notebook)
2535 GtkWidget *widget = (GtkWidget *) notebook;
2536 GtkContainer *container = (GtkContainer *) notebook;
2537 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2540 if (!notebook->scrollable)
2541 return POINTER_BETWEEN;
2543 if (notebook->tab_pos == GTK_POS_TOP ||
2544 notebook->tab_pos == GTK_POS_BOTTOM)
2546 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2548 if (priv->mouse_x > widget->allocation.width - 2 * container->border_width - SCROLL_THRESHOLD)
2549 return (is_rtl) ? POINTER_BEFORE : POINTER_AFTER;
2550 else if (priv->mouse_x < SCROLL_THRESHOLD + container->border_width)
2551 return (is_rtl) ? POINTER_AFTER : POINTER_BEFORE;
2553 return POINTER_BETWEEN;
2557 if (priv->mouse_y > widget->allocation.height - 2 * container->border_width - SCROLL_THRESHOLD)
2558 return POINTER_AFTER;
2559 else if (priv->mouse_y < SCROLL_THRESHOLD + container->border_width)
2560 return POINTER_BEFORE;
2562 return POINTER_BETWEEN;
2567 scroll_notebook_timer (gpointer data)
2569 GtkNotebook *notebook = (GtkNotebook *) data;
2570 GtkNotebookPrivate *priv;
2571 GtkNotebookPointerPosition pointer_position;
2572 GList *element, *first_tab;
2574 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2575 pointer_position = get_pointer_position (notebook);
2577 element = get_drop_position (notebook,
2578 notebook->cur_page->pack,
2579 PAGE_MIDDLE_X (notebook->cur_page),
2580 PAGE_MIDDLE_Y (notebook->cur_page));
2582 reorder_tab (notebook, element, notebook->focus_tab);
2584 first_tab = gtk_notebook_search_page (notebook, notebook->first_tab,
2585 (pointer_position == POINTER_BEFORE) ? STEP_PREV : STEP_NEXT,
2589 notebook->first_tab = first_tab;
2590 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2597 check_threshold (GtkNotebook *notebook,
2602 gint dnd_threshold, width, height;
2603 GdkRectangle rectangle = { 0, }; /* shut up gcc */
2604 GtkSettings *settings;
2606 widget = GTK_WIDGET (notebook);
2607 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2608 g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &dnd_threshold, NULL);
2610 gdk_drawable_get_size (GDK_DRAWABLE (notebook->event_window), &width, &height);
2612 /* we want a large threshold */
2613 dnd_threshold *= DND_THRESHOLD_MULTIPLIER;
2615 rectangle.x = - dnd_threshold;
2616 rectangle.width = width + 2 * dnd_threshold;
2617 rectangle.y = - dnd_threshold;
2618 rectangle.height = height + 2 * dnd_threshold;
2620 return (current_x < rectangle.x ||
2621 current_x > rectangle.x + rectangle.width ||
2622 current_y < rectangle.y ||
2623 current_y > rectangle.y + rectangle.height);
2627 gtk_notebook_motion_notify (GtkWidget *widget,
2628 GdkEventMotion *event)
2630 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2631 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2632 GtkNotebookPointerPosition pointer_position;
2633 GtkSettings *settings;
2637 if (priv->pressed_button == -1)
2640 if (!notebook->cur_page)
2643 gdk_window_get_pointer (notebook->event_window,
2648 if (notebook->cur_page->detachable &&
2649 check_threshold (notebook, priv->mouse_x, priv->mouse_y))
2651 /* move the page to the current position */
2652 element = get_drop_position (notebook,
2653 notebook->cur_page->pack,
2654 PAGE_MIDDLE_X (notebook->cur_page),
2655 PAGE_MIDDLE_Y (notebook->cur_page));
2656 reorder_tab (notebook, element, notebook->focus_tab);
2657 priv->during_detach = TRUE;
2659 gtk_drag_begin (widget, priv->source_targets, GDK_ACTION_MOVE,
2660 priv->pressed_button, (GdkEvent*) event);
2664 if (notebook->cur_page->reorderable)
2666 pointer_position = get_pointer_position (notebook);
2668 if (pointer_position != POINTER_BETWEEN &&
2669 gtk_notebook_show_arrows (notebook))
2671 if (!priv->dnd_timer)
2673 priv->has_scrolled = TRUE;
2674 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
2675 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
2677 priv->dnd_timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
2678 (GSourceFunc) scroll_notebook_timer,
2679 (gpointer) notebook);
2684 if (priv->dnd_timer)
2686 g_source_remove (priv->dnd_timer);
2687 priv->dnd_timer = 0;
2691 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_REORDER);
2698 gtk_notebook_grab_notify (GtkWidget *widget,
2699 gboolean was_grabbed)
2702 stop_scrolling (GTK_NOTEBOOK (widget));
2706 gtk_notebook_state_changed (GtkWidget *widget,
2707 GtkStateType previous_state)
2709 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2710 stop_scrolling (GTK_NOTEBOOK (widget));
2714 gtk_notebook_focus_in (GtkWidget *widget,
2715 GdkEventFocus *event)
2717 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2719 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2725 gtk_notebook_focus_out (GtkWidget *widget,
2726 GdkEventFocus *event)
2728 gtk_notebook_redraw_tabs (GTK_NOTEBOOK (widget));
2734 gtk_notebook_draw_focus (GtkWidget *widget)
2736 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
2738 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2739 notebook->focus_tab)
2741 GtkNotebookPage *page;
2745 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2747 page = notebook->focus_tab->data;
2749 area.x = page->tab_label->allocation.x - focus_width;
2750 area.y = page->tab_label->allocation.y - focus_width;
2751 area.width = page->tab_label->allocation.width + 2 * focus_width;
2752 area.height = page->tab_label->allocation.height + 2 * focus_width;
2754 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
2759 gtk_notebook_style_set (GtkWidget *widget,
2762 GtkNotebook *notebook;
2764 gboolean has_before_previous;
2765 gboolean has_before_next;
2766 gboolean has_after_previous;
2767 gboolean has_after_next;
2769 notebook = GTK_NOTEBOOK (widget);
2771 gtk_widget_style_get (widget,
2772 "has-backward-stepper", &has_before_previous,
2773 "has-secondary-forward-stepper", &has_before_next,
2774 "has-secondary-backward-stepper", &has_after_previous,
2775 "has-forward-stepper", &has_after_next,
2778 notebook->has_before_previous = has_before_previous;
2779 notebook->has_before_next = has_before_next;
2780 notebook->has_after_previous = has_after_previous;
2781 notebook->has_after_next = has_after_next;
2783 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
2787 gtk_notebook_drag_begin (GtkWidget *widget,
2788 GdkDragContext *context)
2790 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
2791 GtkNotebook *notebook = (GtkNotebook*) widget;
2792 GtkWidget *tab_label;
2795 if (priv->dnd_timer)
2797 g_source_remove (priv->dnd_timer);
2798 priv->dnd_timer = 0;
2801 tab_label = notebook->cur_page->tab_label;
2803 pixmap = gdk_pixmap_new (tab_label->window,
2804 tab_label->allocation.width + 2,
2805 tab_label->allocation.height + 2,
2808 gdk_draw_drawable (pixmap,
2809 tab_label->style->base_gc [GTK_WIDGET_STATE (widget)],
2811 tab_label->allocation.x,
2812 tab_label->allocation.y,
2815 gdk_draw_rectangle (pixmap,
2816 widget->style->black_gc,
2819 tab_label->allocation.width + 1,
2820 tab_label->allocation.height + 1);
2822 gtk_drag_set_icon_pixmap (context,
2823 gdk_drawable_get_colormap (pixmap),
2828 gtk_notebook_pages_allocate (GTK_NOTEBOOK (widget), DRAG_OPERATION_DETACH);
2832 gtk_notebook_switch_tab_timeout (gpointer data)
2834 GtkNotebook *notebook;
2835 GtkNotebookPrivate *priv;
2839 notebook = GTK_NOTEBOOK (data);
2840 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
2842 priv->switch_tab_timer = 0;
2846 if ((tab = get_tab_at_pos (notebook, x, y)) != NULL)
2848 /* FIXME: hack, we don't want the
2849 * focus to move fom the source widget
2851 notebook->child_has_focus = FALSE;
2852 gtk_notebook_switch_focus_tab (notebook, tab);
2859 gtk_notebook_drag_motion (GtkWidget *widget,
2860 GdkDragContext *context,
2865 GtkNotebook *notebook;
2866 GtkNotebookPrivate *priv;
2867 GdkRectangle position;
2868 GtkSettings *settings;
2869 GtkNotebookArrow arrow;
2871 GdkAtom target, tab_target;
2873 notebook = GTK_NOTEBOOK (widget);
2874 target = gtk_drag_dest_find_target (widget, context, NULL);
2875 tab_target = gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB");
2877 if (target == tab_target)
2879 gint widget_group, source_widget_group;
2880 GtkWidget *source_widget;
2882 source_widget = gtk_drag_get_source_widget (context);
2884 g_assert (source_widget);
2886 widget_group = gtk_notebook_get_group_id (notebook);
2887 source_widget_group = gtk_notebook_get_group_id (GTK_NOTEBOOK (source_widget));
2889 if (widget_group != -1 &&
2890 source_widget_group != -1 &&
2891 widget_group == source_widget_group)
2893 gdk_drag_status (context, GDK_ACTION_MOVE, time);
2898 priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
2899 x += widget->allocation.x;
2900 y += widget->allocation.y;
2902 if (target == tab_target)
2904 /* it's a tab, but doesn't share
2905 * ID with this notebook */
2906 gdk_drag_status (context, 0, time);
2909 if (gtk_notebook_get_event_window_position (notebook, &position) &&
2910 x >= position.x && x <= position.x + position.width &&
2911 y >= position.y && y <= position.y + position.height)
2916 arrow = gtk_notebook_get_arrow (notebook, x, y);
2919 return gtk_notebook_arrow_button_press (notebook, arrow, 1);
2921 stop_scrolling (notebook);
2923 if (!priv->switch_tab_timer)
2925 settings = gtk_widget_get_settings (widget);
2927 g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
2928 priv->switch_tab_timer = g_timeout_add (timeout,
2929 (GSourceFunc) gtk_notebook_switch_tab_timeout,
2935 if (priv->switch_tab_timer)
2937 g_source_remove (priv->switch_tab_timer);
2938 priv->switch_tab_timer = 0;
2946 gtk_notebook_drag_leave (GtkWidget *widget,
2947 GdkDragContext *context,
2950 GtkNotebookPrivate *priv;
2952 priv = GTK_NOTEBOOK_GET_PRIVATE (widget);
2954 if (priv->switch_tab_timer)
2956 g_source_remove (priv->switch_tab_timer);
2957 priv->switch_tab_timer = 0;
2960 stop_scrolling (GTK_NOTEBOOK (widget));
2964 gtk_notebook_drag_drop (GtkWidget *widget,
2965 GdkDragContext *context,
2972 target = gtk_drag_dest_find_target (widget, context, NULL);
2974 if (target == GDK_NONE)
2975 gtk_drag_finish (context, FALSE, FALSE, time);
2981 do_detach_tab (GtkNotebook *from,
2987 GtkWidget *tab_label, *menu_label;
2988 gboolean tab_expand, tab_fill, reorderable, detachable;
2993 menu_label = gtk_notebook_get_menu_label (from, child);
2996 g_object_ref (menu_label);
2998 tab_label = gtk_notebook_get_tab_label (from, child);
3001 g_object_ref (tab_label);
3003 g_object_ref (child);
3005 gtk_container_child_get (GTK_CONTAINER (from),
3007 "tab-expand", &tab_expand,
3008 "tab-fill", &tab_fill,
3009 "tab-pack", &tab_pack,
3010 "reorderable", &reorderable,
3011 "detachable", &detachable,
3014 gtk_container_remove (GTK_CONTAINER (from), child);
3016 element = get_drop_position (to,
3018 GTK_WIDGET (to)->allocation.x + x,
3019 GTK_WIDGET (to)->allocation.y + y);
3021 page_num = g_list_position (to->children, element);
3022 gtk_notebook_insert_page_menu (to, child, tab_label, menu_label, page_num);
3024 gtk_container_child_set (GTK_CONTAINER (to), child,
3025 "tab-pack", tab_pack,
3026 "tab-expand", tab_expand,
3027 "tab-fill", tab_fill,
3028 "reorderable", reorderable,
3029 "detachable", detachable,
3032 g_object_unref (child);
3035 g_object_unref (tab_label);
3038 g_object_unref (menu_label);
3040 gtk_notebook_set_current_page (to, page_num);
3044 gtk_notebook_drag_data_get (GtkWidget *widget,
3045 GdkDragContext *context,
3046 GtkSelectionData *data,
3050 GtkNotebook *dest_notebook, *notebook;
3052 if (data->target != gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB") &&
3053 (data->target != gdk_atom_intern_static_string ("application/x-rootwindow-drop") ||
3054 !window_creation_hook))
3057 notebook = GTK_NOTEBOOK (widget);
3059 if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
3061 gtk_selection_data_set (data,
3064 (void*) ¬ebook->cur_page->child,
3069 GdkDisplay *display;
3072 display = gtk_widget_get_display (widget);
3073 gdk_display_get_pointer (display, NULL, &x, &y, NULL);
3075 dest_notebook = (* window_creation_hook) (notebook,
3076 notebook->cur_page->child,
3078 window_creation_hook_data);
3081 do_detach_tab (notebook, dest_notebook, notebook->cur_page->child, 0, 0);
3086 gtk_notebook_drag_data_received (GtkWidget *widget,
3087 GdkDragContext *context,
3090 GtkSelectionData *data,
3094 GtkNotebook *notebook;
3095 GtkWidget *source_widget;
3098 notebook = GTK_NOTEBOOK (widget);
3099 source_widget = gtk_drag_get_source_widget (context);
3101 if (source_widget &&
3102 data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
3104 child = (void*) data->data;
3106 do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child, x, y);
3107 gtk_drag_finish (context, TRUE, FALSE, time);
3110 gtk_drag_finish (context, FALSE, FALSE, time);
3113 /* Private GtkContainer Methods :
3115 * gtk_notebook_set_child_arg
3116 * gtk_notebook_get_child_arg
3118 * gtk_notebook_remove
3119 * gtk_notebook_focus
3120 * gtk_notebook_set_focus_child
3121 * gtk_notebook_child_type
3122 * gtk_notebook_forall
3125 gtk_notebook_set_child_property (GtkContainer *container,
3128 const GValue *value,
3133 GtkPackType pack_type;
3135 /* not finding child's page is valid for menus or labels */
3136 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
3139 switch (property_id)
3141 case CHILD_PROP_TAB_LABEL:
3142 /* a NULL pointer indicates a default_tab setting, otherwise
3143 * we need to set the associated label
3145 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
3146 g_value_get_string (value));
3148 case CHILD_PROP_MENU_LABEL:
3149 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
3150 g_value_get_string (value));
3152 case CHILD_PROP_POSITION:
3153 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
3154 g_value_get_int (value));
3156 case CHILD_PROP_TAB_EXPAND:
3157 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3158 &expand, &fill, &pack_type);
3159 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3160 g_value_get_boolean (value),
3163 case CHILD_PROP_TAB_FILL:
3164 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3165 &expand, &fill, &pack_type);
3166 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3168 g_value_get_boolean (value),
3171 case CHILD_PROP_TAB_PACK:
3172 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3173 &expand, &fill, &pack_type);
3174 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
3176 g_value_get_enum (value));
3178 case CHILD_PROP_REORDERABLE:
3179 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (container), child,
3180 g_value_get_boolean (value));
3182 case CHILD_PROP_DETACHABLE:
3183 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (container), child,
3184 g_value_get_boolean (value));
3187 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3193 gtk_notebook_get_child_property (GtkContainer *container,
3200 GtkNotebook *notebook;
3204 GtkPackType pack_type;
3206 notebook = GTK_NOTEBOOK (container);
3208 /* not finding child's page is valid for menus or labels */
3209 list = gtk_notebook_find_child (notebook, child, NULL);
3212 /* nothing to set on labels or menus */
3213 g_param_value_set_default (pspec, value);
3217 switch (property_id)
3219 case CHILD_PROP_TAB_LABEL:
3220 label = gtk_notebook_get_tab_label (notebook, child);
3222 if (label && GTK_IS_LABEL (label))
3223 g_value_set_string (value, GTK_LABEL (label)->label);
3225 g_value_set_string (value, NULL);
3227 case CHILD_PROP_MENU_LABEL:
3228 label = gtk_notebook_get_menu_label (notebook, child);
3230 if (label && GTK_IS_LABEL (label))
3231 g_value_set_string (value, GTK_LABEL (label)->label);
3233 g_value_set_string (value, NULL);
3235 case CHILD_PROP_POSITION:
3236 g_value_set_int (value, g_list_position (notebook->children, list));
3238 case CHILD_PROP_TAB_EXPAND:
3239 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3240 &expand, NULL, NULL);
3241 g_value_set_boolean (value, expand);
3243 case CHILD_PROP_TAB_FILL:
3244 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3246 g_value_set_boolean (value, fill);
3248 case CHILD_PROP_TAB_PACK:
3249 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
3250 NULL, NULL, &pack_type);
3251 g_value_set_enum (value, pack_type);
3253 case CHILD_PROP_REORDERABLE:
3254 g_value_set_boolean (value,
3255 gtk_notebook_get_tab_reorderable (GTK_NOTEBOOK (container), child));
3257 case CHILD_PROP_DETACHABLE:
3258 g_value_set_boolean (value,
3259 gtk_notebook_get_tab_detachable (GTK_NOTEBOOK (container), child));
3262 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
3268 gtk_notebook_add (GtkContainer *container,
3271 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3273 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
3278 gtk_notebook_remove (GtkContainer *container,
3281 GtkNotebook *notebook;
3282 GtkNotebookPage *page;
3286 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3287 g_return_if_fail (widget != NULL);
3289 notebook = GTK_NOTEBOOK (container);
3291 children = notebook->children;
3294 page = children->data;
3296 if (page->child == widget)
3300 children = children->next;
3303 g_object_ref (widget);
3305 gtk_notebook_real_remove (notebook, children);
3307 g_signal_emit (notebook,
3308 notebook_signals[PAGE_REMOVED],
3313 g_object_unref (widget);
3317 focus_tabs_in (GtkNotebook *notebook)
3319 if (notebook->show_tabs && notebook->cur_page)
3321 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3323 gtk_notebook_switch_focus_tab (notebook,
3324 g_list_find (notebook->children,
3325 notebook->cur_page));
3334 focus_tabs_move (GtkNotebook *notebook,
3335 GtkDirectionType direction,
3336 gint search_direction)
3340 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
3341 search_direction, TRUE);
3343 gtk_notebook_switch_focus_tab (notebook, new_page);
3345 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
3351 focus_child_in (GtkNotebook *notebook,
3352 GtkDirectionType direction)
3354 if (notebook->cur_page)
3355 return gtk_widget_child_focus (notebook->cur_page->child, direction);
3360 /* Focus in the notebook can either be on the pages, or on
3364 gtk_notebook_focus (GtkWidget *widget,
3365 GtkDirectionType direction)
3367 GtkWidget *old_focus_child;
3368 GtkNotebook *notebook;
3369 GtkDirectionType effective_direction;
3371 gboolean widget_is_focus;
3372 GtkContainer *container;
3374 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3376 container = GTK_CONTAINER (widget);
3377 notebook = GTK_NOTEBOOK (container);
3379 if (notebook->focus_out)
3381 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
3385 widget_is_focus = gtk_widget_is_focus (widget);
3386 old_focus_child = container->focus_child;
3388 effective_direction = get_effective_direction (notebook, direction);
3390 if (old_focus_child) /* Focus on page child */
3392 if (gtk_widget_child_focus (old_focus_child, direction))
3395 switch (effective_direction)
3397 case GTK_DIR_TAB_BACKWARD:
3399 /* Focus onto the tabs */
3400 return focus_tabs_in (notebook);
3402 case GTK_DIR_TAB_FORWARD:
3408 else if (widget_is_focus) /* Focus was on tabs */
3410 switch (effective_direction)
3412 case GTK_DIR_TAB_BACKWARD:
3415 case GTK_DIR_TAB_FORWARD:
3417 /* We use TAB_FORWARD rather than direction so that we focus a more
3418 * predictable widget for the user; users may be using arrow focusing
3419 * in this situation even if they don't usually use arrow focusing.
3421 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
3423 return focus_tabs_move (notebook, direction, STEP_PREV);
3425 return focus_tabs_move (notebook, direction, STEP_NEXT);
3428 else /* Focus was not on widget */
3430 switch (effective_direction)
3432 case GTK_DIR_TAB_FORWARD:
3434 if (focus_tabs_in (notebook))
3436 if (focus_child_in (notebook, direction))
3439 case GTK_DIR_TAB_BACKWARD:
3441 if (focus_child_in (notebook, direction))
3443 if (focus_tabs_in (notebook))
3448 return focus_child_in (notebook, direction);
3452 g_assert_not_reached ();
3457 gtk_notebook_set_focus_child (GtkContainer *container,
3460 GtkNotebook *notebook = GTK_NOTEBOOK (container);
3461 GtkWidget *page_child;
3462 GtkWidget *toplevel;
3464 /* If the old focus widget was within a page of the notebook,
3465 * (child may either be NULL or not in this case), record it
3466 * for future use if we switch to the page with a mnemonic.
3469 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
3470 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
3472 page_child = GTK_WINDOW (toplevel)->focus_widget;
3475 if (page_child->parent == GTK_WIDGET (container))
3477 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
3480 GtkNotebookPage *page = list->data;
3482 if (page->last_focus_child)
3483 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3485 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
3486 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3492 page_child = page_child->parent;
3498 g_return_if_fail (GTK_IS_WIDGET (child));
3500 notebook->child_has_focus = TRUE;
3501 if (!notebook->focus_tab)
3504 GtkNotebookPage *page;
3506 children = notebook->children;
3509 page = children->data;
3510 if (page->child == child || page->tab_label == child)
3511 gtk_notebook_switch_focus_tab (notebook, children);
3512 children = children->next;
3517 parent_class->set_focus_child (container, child);
3521 gtk_notebook_forall (GtkContainer *container,
3522 gboolean include_internals,
3523 GtkCallback callback,
3524 gpointer callback_data)
3526 GtkNotebook *notebook;
3529 g_return_if_fail (GTK_IS_NOTEBOOK (container));
3530 g_return_if_fail (callback != NULL);
3532 notebook = GTK_NOTEBOOK (container);
3534 children = notebook->children;
3537 GtkNotebookPage *page;
3539 page = children->data;
3540 children = children->next;
3541 (* callback) (page->child, callback_data);
3542 if (include_internals)
3544 if (page->tab_label)
3545 (* callback) (page->tab_label, callback_data);
3551 gtk_notebook_child_type (GtkContainer *container)
3553 return GTK_TYPE_WIDGET;
3556 /* Private GtkNotebook Methods:
3558 * gtk_notebook_real_insert_page
3561 page_visible_cb (GtkWidget *page,
3565 GtkNotebook *notebook = (GtkNotebook *)data;
3569 if (notebook->cur_page &&
3570 notebook->cur_page->child == page &&
3571 !GTK_WIDGET_VISIBLE (page))
3573 list = g_list_find (notebook->children, notebook->cur_page);
3576 next = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3578 next = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3582 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next), -1);
3587 gtk_notebook_real_insert_page (GtkNotebook *notebook,
3589 GtkWidget *tab_label,
3590 GtkWidget *menu_label,
3593 GtkNotebookPage *page;
3596 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3597 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
3598 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
3599 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
3601 gtk_widget_freeze_child_notify (child);
3603 page = g_new (GtkNotebookPage, 1);
3604 page->child = child;
3605 page->last_focus_child = NULL;
3606 page->requisition.width = 0;
3607 page->requisition.height = 0;
3608 page->allocation.x = 0;
3609 page->allocation.y = 0;
3610 page->allocation.width = 0;
3611 page->allocation.height = 0;
3612 page->default_menu = FALSE;
3613 page->default_tab = FALSE;
3614 page->mnemonic_activate_signal = 0;
3615 page->reorderable = FALSE;
3616 page->detachable = FALSE;
3618 nchildren = g_list_length (notebook->children);
3619 if ((position < 0) || (position > nchildren))
3620 position = nchildren;
3622 notebook->children = g_list_insert (notebook->children, page, position);
3626 page->default_tab = TRUE;
3627 if (notebook->show_tabs)
3628 tab_label = gtk_label_new ("");
3630 page->tab_label = tab_label;
3631 page->menu_label = menu_label;
3632 page->expand = FALSE;
3634 page->pack = GTK_PACK_START;
3637 page->default_menu = TRUE;
3640 g_object_ref_sink (page->menu_label);
3644 gtk_notebook_menu_item_create (notebook,
3645 g_list_find (notebook->children, page));
3647 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3649 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3651 gtk_notebook_update_labels (notebook);
3653 if (!notebook->first_tab)
3654 notebook->first_tab = notebook->children;
3656 /* child visible will be turned on by switch_page below */
3657 gtk_widget_set_child_visible (child, FALSE);
3661 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3662 gtk_widget_show (tab_label);
3664 gtk_widget_hide (tab_label);
3667 if (!notebook->cur_page)
3669 gtk_notebook_switch_page (notebook, page, 0);
3670 gtk_notebook_switch_focus_tab (notebook, NULL);
3673 page->notify_visible_handler = g_signal_connect (G_OBJECT (child), "notify::visible",
3674 G_CALLBACK (page_visible_cb), notebook);
3675 gtk_notebook_update_tab_states (notebook);
3678 page->mnemonic_activate_signal =
3679 g_signal_connect (tab_label,
3680 "mnemonic_activate",
3681 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
3684 gtk_widget_child_notify (child, "tab-expand");
3685 gtk_widget_child_notify (child, "tab-fill");
3686 gtk_widget_child_notify (child, "tab-pack");
3687 gtk_widget_child_notify (child, "tab-label");
3688 gtk_widget_child_notify (child, "menu-label");
3689 gtk_widget_child_notify (child, "position");
3690 gtk_widget_thaw_child_notify (child);
3692 g_signal_emit (notebook,
3693 notebook_signals[PAGE_ADDED],
3701 /* Private GtkNotebook Functions:
3703 * gtk_notebook_redraw_tabs
3704 * gtk_notebook_real_remove
3705 * gtk_notebook_update_labels
3706 * gtk_notebook_timer
3707 * gtk_notebook_page_compare
3708 * gtk_notebook_real_page_position
3709 * gtk_notebook_search_page
3712 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
3715 GtkNotebookPage *page;
3716 GdkRectangle redraw_rect;
3718 gint tab_pos = get_effective_tab_pos (notebook);
3720 widget = GTK_WIDGET (notebook);
3721 border = GTK_CONTAINER (notebook)->border_width;
3723 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
3726 page = notebook->first_tab->data;
3728 redraw_rect.x = border;
3729 redraw_rect.y = border;
3733 case GTK_POS_BOTTOM:
3734 redraw_rect.y = (widget->allocation.height - border -
3735 page->allocation.height -
3736 widget->style->ythickness);
3737 if (page != notebook->cur_page)
3738 redraw_rect.y -= widget->style->ythickness;
3741 redraw_rect.width = widget->allocation.width - 2 * border;
3742 redraw_rect.height = (page->allocation.height +
3743 widget->style->ythickness);
3744 if (page != notebook->cur_page)
3745 redraw_rect.height += widget->style->ythickness;
3748 redraw_rect.x = (widget->allocation.width - border -
3749 page->allocation.width -
3750 widget->style->xthickness);
3751 if (page != notebook->cur_page)
3752 redraw_rect.x -= widget->style->xthickness;
3755 redraw_rect.width = (page->allocation.width +
3756 widget->style->xthickness);
3757 redraw_rect.height = widget->allocation.height - 2 * border;
3758 if (page != notebook->cur_page)
3759 redraw_rect.width += widget->style->xthickness;
3763 redraw_rect.x += widget->allocation.x;
3764 redraw_rect.y += widget->allocation.y;
3766 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
3770 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
3772 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
3776 GtkNotebookArrow arrow[4];
3778 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
3779 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
3780 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
3781 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
3783 for (i = 0; i < 4; i++)
3785 if (arrow[i] == ARROW_NONE)
3788 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
3789 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
3796 gtk_notebook_timer (GtkNotebook *notebook)
3798 gboolean retval = FALSE;
3800 GDK_THREADS_ENTER ();
3802 if (notebook->timer)
3804 gtk_notebook_do_arrow (notebook, notebook->click_child);
3806 if (notebook->need_timer)
3808 GtkSettings *settings;
3811 settings = gtk_widget_get_settings (GTK_WIDGET (notebook));
3812 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
3814 notebook->need_timer = FALSE;
3815 notebook->timer = g_timeout_add (timeout * SCROLL_DELAY_FACTOR,
3816 (GSourceFunc) gtk_notebook_timer,
3817 (gpointer) notebook);
3823 GDK_THREADS_LEAVE ();
3829 gtk_notebook_page_compare (gconstpointer a,
3832 return (((GtkNotebookPage *) a)->child != b);
3836 gtk_notebook_find_child (GtkNotebook *notebook,
3838 const gchar *function)
3840 GList *list = g_list_find_custom (notebook->children, child,
3841 gtk_notebook_page_compare);
3843 #ifndef G_DISABLE_CHECKS
3844 if (!list && function)
3845 g_warning ("%s: unable to find child %p in notebook %p",
3846 function, child, notebook);
3853 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
3854 GtkNotebookPage *page)
3856 if (page->tab_label)
3858 if (page->mnemonic_activate_signal)
3859 g_signal_handler_disconnect (page->tab_label,
3860 page->mnemonic_activate_signal);
3861 page->mnemonic_activate_signal = 0;
3863 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3864 gtk_widget_unparent (page->tab_label);
3865 page->tab_label = NULL;
3870 gtk_notebook_real_remove (GtkNotebook *notebook,
3873 GtkNotebookPage *page;
3875 gint need_resize = FALSE;
3877 gboolean destroying;
3879 destroying = GTK_OBJECT_FLAGS (notebook) & GTK_IN_DESTRUCTION;
3881 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3883 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3885 if (notebook->cur_page == list->data)
3887 notebook->cur_page = NULL;
3888 if (next_list && !destroying)
3889 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
3892 if (list == notebook->first_tab)
3893 notebook->first_tab = next_list;
3894 if (list == notebook->focus_tab && !destroying)
3895 gtk_notebook_switch_focus_tab (notebook, next_list);
3899 g_signal_handler_disconnect (page->child, page->notify_visible_handler);
3901 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
3904 gtk_widget_unparent (page->child);
3906 gtk_notebook_remove_tab_label (notebook, page);
3910 gtk_container_remove (GTK_CONTAINER (notebook->menu),
3911 page->menu_label->parent);
3912 gtk_widget_queue_resize (notebook->menu);
3914 if (!page->default_menu)
3915 g_object_unref (page->menu_label);
3917 notebook->children = g_list_remove_link (notebook->children, list);
3920 if (page->last_focus_child)
3922 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
3923 page->last_focus_child = NULL;
3928 gtk_notebook_update_labels (notebook);
3930 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3934 gtk_notebook_update_labels (GtkNotebook *notebook)
3936 GtkNotebookPage *page;
3941 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
3943 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
3946 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
3947 if (notebook->show_tabs)
3949 if (page->default_tab)
3951 if (!page->tab_label)
3953 page->tab_label = gtk_label_new (string);
3954 gtk_widget_set_parent (page->tab_label,
3955 GTK_WIDGET (notebook));
3958 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
3961 if (GTK_WIDGET_VISIBLE (page->child) &&
3962 !GTK_WIDGET_VISIBLE (page->tab_label))
3963 gtk_widget_show (page->tab_label);
3964 else if (!GTK_WIDGET_VISIBLE (page->child) &&
3965 GTK_WIDGET_VISIBLE (page->tab_label))
3966 gtk_widget_hide (page->tab_label);
3968 if (notebook->menu && page->default_menu)
3970 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3971 gtk_label_set_text (GTK_LABEL (page->menu_label),
3972 GTK_LABEL (page->tab_label)->label);
3974 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
3980 gtk_notebook_real_page_position (GtkNotebook *notebook,
3986 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3987 g_return_val_if_fail (list != NULL, -1);
3989 for (work = notebook->children, count_start = 0;
3990 work && work != list; work = work->next)
3991 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
3997 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
4000 return (count_start + g_list_length (list) - 1);
4004 gtk_notebook_search_page (GtkNotebook *notebook,
4007 gboolean find_visible)
4009 GtkNotebookPage *page = NULL;
4010 GList *old_list = NULL;
4013 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4018 flag = GTK_PACK_END;
4022 flag = GTK_PACK_START;
4029 if (!page || page->pack == flag)
4037 list = notebook->children;
4042 if (page->pack == flag &&
4043 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
4058 if (page->pack != flag &&
4059 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
4067 /* Private GtkNotebook Drawing Functions:
4069 * gtk_notebook_paint
4070 * gtk_notebook_draw_tab
4071 * gtk_notebook_draw_arrow
4074 gtk_notebook_paint (GtkWidget *widget,
4077 GtkNotebook *notebook;
4078 GtkNotebookPage *page;
4083 gint border_width = GTK_CONTAINER (widget)->border_width;
4084 gint gap_x = 0, gap_width = 0, step = STEP_PREV;
4088 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
4089 g_return_if_fail (area != NULL);
4091 if (!GTK_WIDGET_DRAWABLE (widget))
4094 notebook = GTK_NOTEBOOK (widget);
4095 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
4096 tab_pos = get_effective_tab_pos (notebook);
4098 if ((!notebook->show_tabs && !notebook->show_border) ||
4099 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
4102 x = widget->allocation.x + border_width;
4103 y = widget->allocation.y + border_width;
4104 width = widget->allocation.width - border_width * 2;
4105 height = widget->allocation.height - border_width * 2;
4107 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
4109 gtk_paint_box (widget->style, widget->window,
4110 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4111 area, widget, "notebook",
4112 x, y, width, height);
4117 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
4119 page = notebook->first_tab->data;
4124 y += page->allocation.height + widget->style->ythickness;
4125 case GTK_POS_BOTTOM:
4126 height -= page->allocation.height + widget->style->ythickness;
4129 x += page->allocation.width + widget->style->xthickness;
4131 width -= page->allocation.width + widget->style->xthickness;
4134 gtk_paint_box (widget->style, widget->window,
4135 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4136 area, widget, "notebook",
4137 x, y, width, height);
4144 y += notebook->cur_page->allocation.height;
4145 case GTK_POS_BOTTOM:
4146 height -= notebook->cur_page->allocation.height;
4149 x += notebook->cur_page->allocation.width;
4151 width -= notebook->cur_page->allocation.width;
4158 case GTK_POS_BOTTOM:
4159 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
4160 gap_width = notebook->cur_page->allocation.width;
4161 step = is_rtl ? STEP_NEXT : STEP_PREV;
4165 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
4166 gap_width = notebook->cur_page->allocation.height;
4170 gtk_paint_box_gap (widget->style, widget->window,
4171 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
4172 area, widget, "notebook",
4173 x, y, width, height,
4174 tab_pos, gap_x, gap_width);
4178 children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
4181 page = children->data;
4182 children = gtk_notebook_search_page (notebook, children,
4184 if (!GTK_WIDGET_VISIBLE (page->child))
4186 if (!GTK_WIDGET_MAPPED (page->tab_label))
4188 else if (page != notebook->cur_page)
4189 gtk_notebook_draw_tab (notebook, page, area);
4192 if (showarrow && notebook->scrollable)
4194 if (notebook->has_before_previous)
4195 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
4196 if (notebook->has_before_next)
4197 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
4198 if (notebook->has_after_previous)
4199 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
4200 if (notebook->has_after_next)
4201 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
4203 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
4207 gtk_notebook_draw_tab (GtkNotebook *notebook,
4208 GtkNotebookPage *page,
4211 GdkRectangle child_area;
4212 GdkRectangle page_area;
4213 GtkStateType state_type;
4214 GtkPositionType gap_side;
4215 gint tab_pos = get_effective_tab_pos (notebook);
4217 g_return_if_fail (notebook != NULL);
4218 g_return_if_fail (page != NULL);
4219 g_return_if_fail (area != NULL);
4221 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
4222 (page->allocation.width == 0) || (page->allocation.height == 0))
4225 page_area.x = page->allocation.x;
4226 page_area.y = page->allocation.y;
4227 page_area.width = page->allocation.width;
4228 page_area.height = page->allocation.height;
4230 if (gdk_rectangle_intersect (&page_area, area, &child_area))
4234 widget = GTK_WIDGET (notebook);
4239 gap_side = GTK_POS_BOTTOM;
4241 case GTK_POS_BOTTOM:
4242 gap_side = GTK_POS_TOP;
4245 gap_side = GTK_POS_RIGHT;
4248 gap_side = GTK_POS_LEFT;
4252 if (notebook->cur_page == page)
4253 state_type = GTK_STATE_NORMAL;
4255 state_type = GTK_STATE_ACTIVE;
4256 gtk_paint_extension(widget->style, widget->window,
4257 state_type, GTK_SHADOW_OUT,
4258 area, widget, "tab",
4259 page_area.x, page_area.y,
4260 page_area.width, page_area.height,
4262 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
4263 notebook->focus_tab && (notebook->focus_tab->data == page))
4267 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
4269 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
4270 area, widget, "tab",
4271 page->tab_label->allocation.x - focus_width,
4272 page->tab_label->allocation.y - focus_width,
4273 page->tab_label->allocation.width + 2 * focus_width,
4274 page->tab_label->allocation.height + 2 * focus_width);
4276 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
4277 GTK_WIDGET_DRAWABLE (page->tab_label))
4279 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
4281 /* This is a lame hack since all this code needs rewriting anyhow */
4283 expose_event->expose.window = g_object_ref (page->tab_label->window);
4284 expose_event->expose.area = child_area;
4285 expose_event->expose.region = gdk_region_rectangle (&child_area);
4286 expose_event->expose.send_event = TRUE;
4287 expose_event->expose.count = 0;
4289 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
4291 gdk_event_free (expose_event);
4297 gtk_notebook_draw_arrow (GtkNotebook *notebook,
4298 GtkNotebookArrow nbarrow)
4300 GtkStateType state_type;
4301 GtkShadowType shadow_type;
4303 GdkRectangle arrow_rect;
4305 gboolean is_rtl, left;
4307 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
4309 widget = GTK_WIDGET (notebook);
4311 is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
4312 left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
4313 (!ARROW_IS_LEFT (nbarrow) && is_rtl);
4315 if (GTK_WIDGET_DRAWABLE (notebook))
4317 if (notebook->in_child == nbarrow)
4319 if (notebook->click_child == nbarrow)
4320 state_type = GTK_STATE_ACTIVE;
4322 state_type = GTK_STATE_PRELIGHT;
4325 state_type = GTK_WIDGET_STATE (widget);
4327 if (notebook->click_child == nbarrow)
4328 shadow_type = GTK_SHADOW_IN;
4330 shadow_type = GTK_SHADOW_OUT;
4332 if (notebook->focus_tab &&
4333 !gtk_notebook_search_page (notebook, notebook->focus_tab,
4334 left? STEP_PREV : STEP_NEXT, TRUE))
4336 shadow_type = GTK_SHADOW_ETCHED_IN;
4337 state_type = GTK_STATE_INSENSITIVE;
4340 if (notebook->tab_pos == GTK_POS_LEFT ||
4341 notebook->tab_pos == GTK_POS_RIGHT)
4342 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
4344 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
4346 gtk_paint_arrow (widget->style, widget->window, state_type,
4347 shadow_type, NULL, widget, "notebook",
4348 arrow, TRUE, arrow_rect.x, arrow_rect.y,
4349 ARROW_SIZE, ARROW_SIZE);
4354 get_notebook_tabs_space (GtkNotebook *notebook, gint *min, gint *max)
4356 GtkWidget *widget = (GtkWidget *) notebook;
4357 GtkContainer *container = (GtkContainer *) notebook;
4359 if (notebook->tab_pos == GTK_POS_TOP ||
4360 notebook->tab_pos == GTK_POS_BOTTOM)
4362 *min = widget->allocation.x + container->border_width;
4363 *max = widget->allocation.x + widget->allocation.width - container->border_width;
4365 if (gtk_notebook_show_arrows (notebook))
4367 if (notebook->has_after_previous)
4368 *max -= ARROW_SPACING + ARROW_SIZE;
4369 if (notebook->has_after_next)
4370 *max -= ARROW_SPACING + ARROW_SIZE;
4371 if (notebook->has_before_previous)
4372 *min += ARROW_SPACING + ARROW_SIZE;
4373 if (notebook->has_before_next)
4374 *min += ARROW_SPACING + ARROW_SIZE;
4379 *min = widget->allocation.y + container->border_width;
4380 *max = widget->allocation.y + widget->allocation.height - container->border_width;
4382 if (gtk_notebook_show_arrows (notebook))
4384 if (notebook->has_after_previous || notebook->has_after_next)
4385 *max -= ARROW_SPACING + ARROW_SIZE;
4386 if (notebook->has_before_previous || notebook->has_before_next)
4387 *min += ARROW_SPACING + ARROW_SIZE;
4392 /* Private GtkNotebook Size Allocate Functions:
4394 * gtk_notebook_pages_allocate
4395 * gtk_notebook_page_allocate
4396 * gtk_notebook_calc_tabs
4399 gtk_notebook_pages_allocate (GtkNotebook *notebook,
4400 GtkNotebookDragOperation operation)
4402 GtkWidget *widget = GTK_WIDGET (notebook);
4403 GtkContainer *container = GTK_CONTAINER (notebook);
4404 GtkNotebookPrivate *priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
4405 GtkNotebookPage *page = NULL;
4406 GtkAllocation *allocation = &widget->allocation;
4407 GtkAllocation child_allocation;
4408 GList *children = NULL;
4409 GList *last_child = NULL;
4410 gboolean showarrow = FALSE;
4417 gint tab_pos = get_effective_tab_pos (notebook);
4418 gboolean is_rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL &&
4419 (tab_pos == GTK_POS_TOP || tab_pos == GTK_POS_BOTTOM));
4421 gint memo_x, anchor_x, anchor_y;
4422 gint min, max, top_y, bottom_y, left_x, right_x;
4423 gboolean packing_changed = FALSE;
4424 gboolean gap_left = FALSE;
4426 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
4429 gtk_widget_style_get (widget, "tab-overlap", &tab_overlap, NULL);
4431 child_allocation.x = widget->allocation.x + container->border_width;
4432 child_allocation.y = widget->allocation.y + container->border_width;
4436 case GTK_POS_BOTTOM:
4437 child_allocation.y = (widget->allocation.y +
4438 allocation->height -
4439 notebook->cur_page->requisition.height -
4440 container->border_width);
4443 child_allocation.height = notebook->cur_page->requisition.height;
4447 child_allocation.x = (widget->allocation.x +
4449 notebook->cur_page->requisition.width -
4450 container->border_width);
4453 child_allocation.width = notebook->cur_page->requisition.width;
4457 if (notebook->scrollable)
4461 children = notebook->children;
4463 if (notebook->focus_tab)
4464 focus_tab = notebook->focus_tab;
4465 else if (notebook->first_tab)
4466 focus_tab = notebook->first_tab;
4468 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
4473 case GTK_POS_BOTTOM:
4476 page = children->data;
4477 children = children->next;
4479 if (GTK_WIDGET_VISIBLE (page->child))
4480 tab_space += page->requisition.width;
4484 allocation->width - 2 * container->border_width - tab_overlap)
4487 page = focus_tab->data;
4489 tab_space = allocation->width - tab_overlap -
4490 page->requisition.width - 2 * container->border_width;
4491 if (notebook->has_after_previous)
4492 tab_space -= ARROW_SPACING + ARROW_SIZE;
4493 if (notebook->has_after_next)
4494 tab_space -= ARROW_SPACING + ARROW_SIZE;
4495 if (notebook->has_before_previous)
4497 tab_space -= ARROW_SPACING + ARROW_SIZE;
4498 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4500 if (notebook->has_before_next)
4502 tab_space -= ARROW_SPACING + ARROW_SIZE;
4503 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
4511 page = children->data;
4512 children = children->next;
4514 if (GTK_WIDGET_VISIBLE (page->child))
4515 tab_space += page->requisition.height;
4518 (allocation->height - 2 * container->border_width - tab_overlap))
4521 page = focus_tab->data;
4522 tab_space = allocation->height
4523 - tab_overlap - 2 * container->border_width
4524 - page->requisition.height;
4525 if (notebook->has_after_previous || notebook->has_after_next)
4526 tab_space -= ARROW_SPACING + ARROW_SIZE;
4527 if (notebook->has_before_previous || notebook->has_before_next)
4529 tab_space -= ARROW_SPACING + ARROW_SIZE;
4530 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
4535 if (showarrow) /* first_tab <- focus_tab */
4539 notebook->first_tab = focus_tab;
4540 last_child = gtk_notebook_search_page (notebook, focus_tab,
4546 if (notebook->first_tab && notebook->first_tab != focus_tab)
4548 /* Is first_tab really predecessor of focus_tab ? */
4549 page = notebook->first_tab->data;
4550 if (GTK_WIDGET_VISIBLE (page->child))
4551 for (children = focus_tab;
4552 children && children != notebook->first_tab;
4553 children = gtk_notebook_search_page (notebook,
4559 notebook->first_tab = focus_tab;
4561 gtk_notebook_calc_tabs (notebook,
4562 gtk_notebook_search_page (notebook,
4566 &(notebook->first_tab), &tab_space,
4571 notebook->first_tab =
4572 gtk_notebook_search_page (notebook, notebook->first_tab,
4574 if (!notebook->first_tab)
4575 notebook->first_tab = focus_tab;
4576 last_child = gtk_notebook_search_page (notebook, focus_tab,
4579 else /* focus_tab -> end */
4581 if (!notebook->first_tab)
4582 notebook->first_tab = gtk_notebook_search_page (notebook,
4587 gtk_notebook_calc_tabs (notebook,
4588 gtk_notebook_search_page (notebook,
4592 &children, &tab_space, STEP_NEXT);
4595 last_child = children;
4596 else /* start <- first_tab */
4600 gtk_notebook_calc_tabs
4602 gtk_notebook_search_page (notebook,
4603 notebook->first_tab,
4606 &children, &tab_space, STEP_PREV);
4607 notebook->first_tab = gtk_notebook_search_page(notebook,
4617 tab_space = -tab_space;
4619 for (children = notebook->first_tab;
4620 children && children != last_child;
4621 children = gtk_notebook_search_page (notebook, children,
4628 /*unmap all non-visible tabs*/
4629 for (children = gtk_notebook_search_page (notebook, NULL,
4631 children && children != notebook->first_tab;
4632 children = gtk_notebook_search_page (notebook, children,
4635 page = children->data;
4636 if (page->tab_label)
4637 gtk_widget_set_child_visible (page->tab_label, FALSE);
4639 for (children = last_child; children;
4640 children = gtk_notebook_search_page (notebook, children,
4643 page = children->data;
4644 if (page->tab_label)
4645 gtk_widget_set_child_visible (page->tab_label, FALSE);
4648 else /* !showarrow */
4650 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4661 children = notebook->children;
4665 case GTK_POS_BOTTOM:
4668 page = children->data;
4669 children = children->next;
4671 if (GTK_WIDGET_VISIBLE (page->child))
4674 tab_space += page->requisition.width;
4679 tab_space -= allocation->width;
4685 page = children->data;
4686 children = children->next;
4688 if (GTK_WIDGET_VISIBLE (page->child))
4691 tab_space += page->requisition.height;
4696 tab_space -= allocation->height;
4698 tab_space += 2 * container->border_width + tab_overlap;
4700 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
4702 if (notebook->homogeneous && n)
4706 children = notebook->first_tab;
4709 memo_x = child_allocation.x;
4710 if (notebook->children && is_rtl)
4712 child_allocation.x = (allocation->x + allocation->width -
4713 container->border_width);
4716 if (notebook->has_after_previous)
4717 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4718 if (notebook->has_after_next)
4719 child_allocation.x -= ARROW_SPACING + ARROW_SIZE;
4723 get_notebook_tabs_space (notebook, &min, &max);
4724 anchor_x = child_allocation.x;
4725 anchor_y = child_allocation.y;
4727 left_x = CLAMP (widget->allocation.x + priv->mouse_x - notebook->cur_page->allocation.width / 2,
4728 min, max - notebook->cur_page->allocation.width);
4729 top_y = CLAMP (widget->allocation.y + priv->mouse_y - notebook->cur_page->allocation.height / 2,
4730 min, max - notebook->cur_page->allocation.height);
4731 right_x = left_x + notebook->cur_page->allocation.width;
4732 bottom_y = top_y + notebook->cur_page->allocation.height;
4736 if (children == last_child)
4738 /* FIXME double check */
4742 page = children->data;
4744 if (page->pack != GTK_PACK_START)
4748 else if (operation == DRAG_OPERATION_REORDER)
4749 packing_changed = TRUE;
4752 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
4755 if (n && (showarrow || page->expand || notebook->homogeneous))
4757 new_fill = (tab_space * i++) / n;
4758 delta = new_fill - old_fill;
4759 old_fill = new_fill;
4765 case GTK_POS_BOTTOM:
4766 child_allocation.width = (page->requisition.width +
4767 tab_overlap + delta);
4769 /* make sure that the reordered tab doesn't go past the last position */
4770 if (operation == DRAG_OPERATION_REORDER &&
4771 !gap_left && packing_changed)
4775 if ((notebook->cur_page->pack == GTK_PACK_START && left_x >= anchor_x) ||
4776 (notebook->cur_page->pack == GTK_PACK_END && left_x < anchor_x))
4778 left_x = notebook->cur_page->allocation.x = anchor_x;
4779 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4784 if ((notebook->cur_page->pack == GTK_PACK_START && right_x <= anchor_x) ||
4785 (notebook->cur_page->pack == GTK_PACK_END && right_x > anchor_x))
4787 anchor_x -= notebook->cur_page->allocation.width;
4788 left_x = notebook->cur_page->allocation.x = anchor_x;
4789 anchor_x += tab_overlap;
4796 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4797 child_allocation.x = left_x;
4801 anchor_x -= child_allocation.width;
4803 if (operation == DRAG_OPERATION_REORDER && page->pack == notebook->cur_page->pack)
4806 left_x >= anchor_x &&
4807 left_x <= anchor_x + child_allocation.width / 2)
4808 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4810 right_x > anchor_x + child_allocation.width / 2 &&
4811 right_x <= anchor_x + child_allocation.width)
4812 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4815 child_allocation.x = anchor_x;
4821 child_allocation.height = (page->requisition.height +
4822 tab_overlap + delta);
4824 /* make sure that the reordered tab doesn't go past the last position */
4825 if (operation == DRAG_OPERATION_REORDER &&
4826 !gap_left && packing_changed)
4828 if ((notebook->cur_page->pack == GTK_PACK_START && top_y >= anchor_y) ||
4829 (notebook->cur_page->pack == GTK_PACK_END && top_y < anchor_y))
4831 top_y = notebook->cur_page->allocation.y = anchor_y;
4832 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4838 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4839 child_allocation.y = top_y;
4842 if (operation == DRAG_OPERATION_REORDER &&
4843 page->pack == notebook->cur_page->pack &&
4844 top_y >= anchor_y &&
4845 top_y <= anchor_y + child_allocation.height / 2)
4846 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4848 child_allocation.y = anchor_y;
4854 page->allocation = child_allocation;
4859 case GTK_POS_BOTTOM:
4860 if (operation != DRAG_OPERATION_REORDER ||
4861 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4863 if (operation == DRAG_OPERATION_REORDER)
4865 if (page->pack == notebook->cur_page->pack &&
4867 left_x > anchor_x + child_allocation.width / 2 &&
4868 left_x <= anchor_x + child_allocation.width)
4869 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4870 else if (page->pack == notebook->cur_page->pack &&
4872 right_x >= anchor_x &&
4873 right_x <= anchor_x + child_allocation.width / 2)
4874 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4878 anchor_x += child_allocation.width - tab_overlap;
4880 anchor_x += tab_overlap;
4886 if (operation != DRAG_OPERATION_REORDER ||
4887 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
4889 if (operation == DRAG_OPERATION_REORDER &&
4890 page->pack == notebook->cur_page->pack &&
4891 page != notebook->cur_page &&
4892 top_y > anchor_y + child_allocation.height / 2 &&
4893 top_y <= anchor_y + child_allocation.height)
4894 anchor_y += notebook->cur_page->allocation.height - tab_overlap;
4896 anchor_y += child_allocation.height - tab_overlap;
4902 if (page->tab_label)
4903 gtk_widget_set_child_visible (page->tab_label, TRUE);
4906 /* don't move the tab past the last position */
4907 if (operation == DRAG_OPERATION_REORDER &&
4908 notebook->cur_page->pack == GTK_PACK_START)
4913 case GTK_POS_BOTTOM:
4914 if ((!is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x) ||
4915 (is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x))
4918 anchor_x -= notebook->cur_page->allocation.width;
4920 notebook->cur_page->allocation.x = anchor_x;
4925 if (PAGE_TOP_Y (notebook->cur_page) > anchor_y)
4926 notebook->cur_page->allocation.y = anchor_y;
4934 children = notebook->children;
4939 case GTK_POS_BOTTOM:
4941 anchor_x = (allocation->x + allocation->width -
4942 container->border_width);
4948 anchor_y = (allocation->y + allocation->height -
4949 container->border_width);
4953 while (children != last_child)
4955 page = children->data;
4956 children = children->next;
4958 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
4962 if (n && (page->expand || notebook->homogeneous))
4964 new_fill = (tab_space * i++) / n;
4965 delta = new_fill - old_fill;
4966 old_fill = new_fill;
4972 case GTK_POS_BOTTOM:
4973 child_allocation.width = (page->requisition.width +
4974 tab_overlap + delta);
4976 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
4977 child_allocation.x = left_x;
4981 anchor_x -= child_allocation.width;
4983 if (operation == DRAG_OPERATION_REORDER)
4985 if (page->pack == notebook->cur_page->pack &&
4987 left_x >= anchor_x &&
4988 left_x <= anchor_x + child_allocation.width / 2)
4989 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
4990 else if (page->pack == notebook->cur_page->pack &&
4992 right_x > anchor_x + child_allocation.width / 2 &&
4993 right_x <= anchor_x + child_allocation.width)
4994 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
4997 child_allocation.x = anchor_x;
5003 child_allocation.height = (page->requisition.height +
5004 tab_overlap + delta);
5006 if (operation == DRAG_OPERATION_REORDER && page == notebook->cur_page)
5007 child_allocation.y = top_y;
5010 anchor_y -= child_allocation.height;
5012 if (operation == DRAG_OPERATION_REORDER &&
5013 page->pack == notebook->cur_page->pack &&
5014 bottom_y > anchor_y + child_allocation.height / 2 &&
5015 bottom_y <= anchor_y + child_allocation.height)
5016 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
5018 child_allocation.y = anchor_y;
5024 page->allocation = child_allocation;
5029 case GTK_POS_BOTTOM:
5030 if (operation != DRAG_OPERATION_REORDER ||
5031 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
5033 if (operation == DRAG_OPERATION_REORDER)
5035 if (page->pack == notebook->cur_page->pack &&
5037 left_x > anchor_x + child_allocation.width / 2 &&
5038 left_x <= anchor_x + child_allocation.width)
5039 anchor_x += notebook->cur_page->allocation.width - tab_overlap;
5040 else if (page->pack == notebook->cur_page->pack &&
5042 right_x >= anchor_x &&
5043 right_x <= anchor_x + child_allocation.width / 2)
5044 anchor_x -= notebook->cur_page->allocation.width - tab_overlap;
5048 anchor_x += tab_overlap;
5050 anchor_x += child_allocation.width - tab_overlap;
5056 if (operation != DRAG_OPERATION_REORDER ||
5057 (operation == DRAG_OPERATION_REORDER && page != notebook->cur_page))
5059 if (operation == DRAG_OPERATION_REORDER &&
5060 page->pack == notebook->cur_page->pack &&
5061 page != notebook->cur_page &&
5062 bottom_y >= anchor_y &&
5063 bottom_y <= anchor_y + child_allocation.height / 2)
5064 anchor_y -= notebook->cur_page->allocation.height - tab_overlap;
5066 anchor_y += tab_overlap;
5072 if (page->tab_label)
5073 gtk_widget_set_child_visible (page->tab_label, TRUE);
5076 /* don't move the tab past the last position */
5077 if (operation == DRAG_OPERATION_REORDER &&
5078 notebook->cur_page->pack == GTK_PACK_END)
5083 case GTK_POS_BOTTOM:
5084 if ((!is_rtl && PAGE_RIGHT_X (notebook->cur_page) < anchor_x) ||
5085 (is_rtl && PAGE_LEFT_X (notebook->cur_page) > anchor_x))
5088 anchor_x -= notebook->cur_page->allocation.width;
5090 notebook->cur_page->allocation.x = anchor_x;
5095 if (PAGE_BOTTOM_Y (notebook->cur_page) < anchor_y)
5097 anchor_y -= notebook->cur_page->allocation.height;
5098 notebook->cur_page->allocation.y = anchor_y;
5106 children = notebook->children;
5110 page = children->data;
5111 children = children->next;
5113 if (GTK_WIDGET_DRAWABLE (page->tab_label))
5114 gtk_notebook_page_allocate (notebook, page);
5117 gtk_notebook_redraw_tabs (notebook);
5121 gtk_notebook_page_allocate (GtkNotebook *notebook,
5122 GtkNotebookPage *page)
5124 GtkWidget *widget = GTK_WIDGET (notebook);
5125 GtkAllocation child_allocation;
5126 GtkRequisition tab_requisition;
5132 gint tab_pos = get_effective_tab_pos (notebook);
5134 gtk_widget_style_get (widget,
5135 "focus-line-width", &focus_width,
5136 "tab-curvature", &tab_curvature,
5139 xthickness = widget->style->xthickness;
5140 ythickness = widget->style->ythickness;
5142 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
5144 if (notebook->cur_page != page)
5149 page->allocation.y += ythickness;
5150 case GTK_POS_BOTTOM:
5151 page->allocation.height = MAX (1, page->allocation.height - ythickness);
5154 page->allocation.x += xthickness;
5156 page->allocation.width = MAX (1, page->allocation.width - xthickness);
5164 case GTK_POS_BOTTOM:
5165 padding = tab_curvature + focus_width + notebook->tab_hborder;
5168 child_allocation.x = (xthickness + focus_width +
5169 notebook->tab_hborder);
5170 child_allocation.width = MAX (1, (page->allocation.width -
5171 2 * child_allocation.x));
5172 child_allocation.x += page->allocation.x;
5176 child_allocation.x = (page->allocation.x +
5177 (page->allocation.width -
5178 tab_requisition.width) / 2);
5179 child_allocation.width = tab_requisition.width;
5181 child_allocation.y = (notebook->tab_vborder + focus_width +
5182 page->allocation.y);
5183 if (tab_pos == GTK_POS_TOP)
5184 child_allocation.y += ythickness;
5185 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
5186 2 * (notebook->tab_vborder + focus_width)));
5190 padding = tab_curvature + focus_width + notebook->tab_vborder;
5193 child_allocation.y = ythickness + padding;
5194 child_allocation.height = MAX (1, (page->allocation.height -
5195 2 * child_allocation.y));
5196 child_allocation.y += page->allocation.y;
5200 child_allocation.y = (page->allocation.y + (page->allocation.height -
5201 tab_requisition.height) / 2);
5202 child_allocation.height = tab_requisition.height;
5204 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
5205 if (tab_pos == GTK_POS_LEFT)
5206 child_allocation.x += xthickness;
5207 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
5208 2 * (notebook->tab_hborder + focus_width)));
5212 if (page->tab_label)
5213 gtk_widget_size_allocate (page->tab_label, &child_allocation);
5217 gtk_notebook_calc_tabs (GtkNotebook *notebook,
5223 GtkNotebookPage *page = NULL;
5225 GList *last_list = NULL;
5227 gint tab_pos = get_effective_tab_pos (notebook);
5233 pack = GTK_NOTEBOOK_PAGE (start)->pack;
5234 if (pack == GTK_PACK_END)
5235 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
5242 case GTK_POS_BOTTOM:
5245 page = children->data;
5246 if (GTK_WIDGET_VISIBLE (page->child))
5248 if (page->pack == pack)
5250 *tab_space -= page->requisition.width;
5251 if (*tab_space < 0 || children == *end)
5255 *tab_space = - (*tab_space +
5256 page->requisition.width);
5262 last_list = children;
5264 if (direction == STEP_NEXT)
5265 children = children->next;
5267 children = children->prev;
5274 page = children->data;
5275 if (GTK_WIDGET_VISIBLE (page->child))
5277 if (page->pack == pack)
5279 *tab_space -= page->requisition.height;
5280 if (*tab_space < 0 || children == *end)
5284 *tab_space = - (*tab_space +
5285 page->requisition.height);
5291 last_list = children;
5293 if (direction == STEP_NEXT)
5294 children = children->next;
5296 children = children->prev;
5300 if (direction == STEP_PREV)
5302 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
5303 direction = STEP_PREV;
5304 children = last_list;
5309 gtk_notebook_update_tab_states (GtkNotebook *notebook)
5313 for (list = notebook->children; list != NULL; list = list->next)
5315 GtkNotebookPage *page = list->data;
5317 if (page->tab_label)
5319 if (page == notebook->cur_page)
5320 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
5322 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
5327 /* Private GtkNotebook Page Switch Methods:
5329 * gtk_notebook_real_switch_page
5332 gtk_notebook_real_switch_page (GtkNotebook *notebook,
5333 GtkNotebookPage *page,
5336 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5337 g_return_if_fail (page != NULL);
5339 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
5342 if (notebook->cur_page)
5343 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
5345 notebook->cur_page = page;
5347 if (!notebook->focus_tab ||
5348 notebook->focus_tab->data != (gpointer) notebook->cur_page)
5349 notebook->focus_tab =
5350 g_list_find (notebook->children, notebook->cur_page);
5352 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
5354 /* If the focus was on the previous page, move it to the first
5355 * element on the new page, if possible, or if not, to the
5358 if (notebook->child_has_focus)
5360 if (notebook->cur_page->last_focus_child &&
5361 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
5362 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
5364 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
5365 gtk_widget_grab_focus (GTK_WIDGET (notebook));
5368 gtk_notebook_update_tab_states (notebook);
5369 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5370 g_object_notify (G_OBJECT (notebook), "page");
5373 /* Private GtkNotebook Page Switch Functions:
5375 * gtk_notebook_switch_page
5376 * gtk_notebook_page_select
5377 * gtk_notebook_switch_focus_tab
5378 * gtk_notebook_menu_switch_page
5381 gtk_notebook_switch_page (GtkNotebook *notebook,
5382 GtkNotebookPage *page,
5385 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5386 g_return_if_fail (page != NULL);
5388 if (notebook->cur_page == page)
5392 page_num = g_list_index (notebook->children, page);
5394 g_signal_emit (notebook,
5395 notebook_signals[SWITCH_PAGE],
5402 gtk_notebook_page_select (GtkNotebook *notebook,
5403 gboolean move_focus)
5405 GtkNotebookPage *page;
5406 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
5407 gint tab_pos = get_effective_tab_pos (notebook);
5409 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
5411 if (!notebook->focus_tab)
5414 page = notebook->focus_tab->data;
5415 gtk_notebook_switch_page (notebook, page, -1);
5424 case GTK_POS_BOTTOM:
5428 dir = GTK_DIR_RIGHT;
5435 if (gtk_widget_child_focus (page->child, dir))
5442 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
5446 GtkNotebookPage *page;
5448 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5450 if (notebook->focus_tab == new_child)
5453 old_child = notebook->focus_tab;
5454 notebook->focus_tab = new_child;
5456 if (notebook->scrollable)
5457 gtk_notebook_redraw_arrows (notebook);
5459 if (!notebook->show_tabs || !notebook->focus_tab)
5462 page = notebook->focus_tab->data;
5463 if (GTK_WIDGET_MAPPED (page->tab_label))
5464 gtk_notebook_redraw_tabs (notebook);
5466 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
5468 gtk_notebook_switch_page (notebook, page,
5469 g_list_index (notebook->children, page));
5473 gtk_notebook_menu_switch_page (GtkWidget *widget,
5474 GtkNotebookPage *page)
5476 GtkNotebook *notebook;
5480 g_return_if_fail (widget != NULL);
5481 g_return_if_fail (page != NULL);
5483 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
5484 (GTK_MENU (widget->parent)));
5486 if (notebook->cur_page == page)
5490 children = notebook->children;
5491 while (children && children->data != page)
5493 children = children->next;
5497 g_signal_emit (notebook,
5498 notebook_signals[SWITCH_PAGE],
5504 /* Private GtkNotebook Menu Functions:
5506 * gtk_notebook_menu_item_create
5507 * gtk_notebook_menu_label_unparent
5508 * gtk_notebook_menu_detacher
5511 gtk_notebook_menu_item_create (GtkNotebook *notebook,
5514 GtkNotebookPage *page;
5515 GtkWidget *menu_item;
5518 if (page->default_menu)
5520 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
5521 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
5523 page->menu_label = gtk_label_new ("");
5524 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
5527 gtk_widget_show (page->menu_label);
5528 menu_item = gtk_menu_item_new ();
5529 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
5530 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
5531 gtk_notebook_real_page_position (notebook, list));
5532 g_signal_connect (menu_item, "activate",
5533 G_CALLBACK (gtk_notebook_menu_switch_page), page);
5534 if (GTK_WIDGET_VISIBLE (page->child))
5535 gtk_widget_show (menu_item);
5539 gtk_notebook_menu_label_unparent (GtkWidget *widget,
5542 gtk_widget_unparent (GTK_BIN(widget)->child);
5543 GTK_BIN(widget)->child = NULL;
5547 gtk_notebook_menu_detacher (GtkWidget *widget,
5550 GtkNotebook *notebook;
5552 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
5554 notebook = GTK_NOTEBOOK (widget);
5555 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
5557 notebook->menu = NULL;
5560 /* Private GtkNotebook Setter Functions:
5562 * gtk_notebook_set_homogeneous_tabs_internal
5563 * gtk_notebook_set_tab_border_internal
5564 * gtk_notebook_set_tab_hborder_internal
5565 * gtk_notebook_set_tab_vborder_internal
5568 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
5569 gboolean homogeneous)
5571 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5573 if (homogeneous == notebook->homogeneous)
5576 notebook->homogeneous = homogeneous;
5577 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5579 g_object_notify (G_OBJECT (notebook), "homogeneous");
5583 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
5586 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5588 notebook->tab_hborder = border_width;
5589 notebook->tab_vborder = border_width;
5591 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5592 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5594 g_object_freeze_notify (G_OBJECT (notebook));
5595 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5596 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5597 g_object_thaw_notify (G_OBJECT (notebook));
5601 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
5604 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5606 if (notebook->tab_hborder == tab_hborder)
5609 notebook->tab_hborder = tab_hborder;
5611 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5612 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5614 g_object_notify (G_OBJECT (notebook), "tab-hborder");
5618 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
5621 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5623 if (notebook->tab_vborder == tab_vborder)
5626 notebook->tab_vborder = tab_vborder;
5628 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
5629 gtk_widget_queue_resize (GTK_WIDGET (notebook));
5631 g_object_notify (G_OBJECT (notebook), "tab-vborder");
5634 /* Public GtkNotebook Page Insert/Remove Methods :
5636 * gtk_notebook_append_page
5637 * gtk_notebook_append_page_menu
5638 * gtk_notebook_prepend_page
5639 * gtk_notebook_prepend_page_menu
5640 * gtk_notebook_insert_page
5641 * gtk_notebook_insert_page_menu
5642 * gtk_notebook_remove_page
5645 * gtk_notebook_append_page:
5646 * @notebook: a #GtkNotebook
5647 * @child: the #GtkWidget to use as the contents of the page.
5648 * @tab_label: the #GtkWidget to be used as the label for the page,
5649 * or %NULL to use the default label, 'page N'.
5651 * Appends a page to @notebook.
5653 * Return value: the index (starting from 0) of the appended
5654 * page in the notebook, or -1 if function fails
5657 gtk_notebook_append_page (GtkNotebook *notebook,
5659 GtkWidget *tab_label)
5661 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5662 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5663 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5665 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
5669 * gtk_notebook_append_page_menu:
5670 * @notebook: a #GtkNotebook
5671 * @child: the #GtkWidget to use as the contents of the page.
5672 * @tab_label: the #GtkWidget to be used as the label for the page,
5673 * or %NULL to use the default label, 'page N'.
5674 * @menu_label: the widget to use as a label for the page-switch
5675 * menu, if that is enabled. If %NULL, and @tab_label
5676 * is a #GtkLabel or %NULL, then the menu label will be
5677 * a newly created label with the same text as @tab_label;
5678 * If @tab_label is not a #GtkLabel, @menu_label must be
5679 * specified if the page-switch menu is to be used.
5681 * Appends a page to @notebook, specifying the widget to use as the
5682 * label in the popup menu.
5684 * Return value: the index (starting from 0) of the appended
5685 * page in the notebook, or -1 if function fails
5688 gtk_notebook_append_page_menu (GtkNotebook *notebook,
5690 GtkWidget *tab_label,
5691 GtkWidget *menu_label)
5693 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5694 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5695 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5696 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5698 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
5702 * gtk_notebook_prepend_page:
5703 * @notebook: a #GtkNotebook
5704 * @child: the #GtkWidget to use as the contents of the page.
5705 * @tab_label: the #GtkWidget to be used as the label for the page,
5706 * or %NULL to use the default label, 'page N'.
5708 * Prepends a page to @notebook.
5710 * Return value: the index (starting from 0) of the prepended
5711 * page in the notebook, or -1 if function fails
5714 gtk_notebook_prepend_page (GtkNotebook *notebook,
5716 GtkWidget *tab_label)
5718 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5719 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5720 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5722 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
5726 * gtk_notebook_prepend_page_menu:
5727 * @notebook: a #GtkNotebook
5728 * @child: the #GtkWidget to use as the contents of the page.
5729 * @tab_label: the #GtkWidget to be used as the label for the page,
5730 * or %NULL to use the default label, 'page N'.
5731 * @menu_label: the widget to use as a label for the page-switch
5732 * menu, if that is enabled. If %NULL, and @tab_label
5733 * is a #GtkLabel or %NULL, then the menu label will be
5734 * a newly created label with the same text as @tab_label;
5735 * If @tab_label is not a #GtkLabel, @menu_label must be
5736 * specified if the page-switch menu is to be used.
5738 * Prepends a page to @notebook, specifying the widget to use as the
5739 * label in the popup menu.
5741 * Return value: the index (starting from 0) of the prepended
5742 * page in the notebook, or -1 if function fails
5745 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
5747 GtkWidget *tab_label,
5748 GtkWidget *menu_label)
5750 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5751 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5752 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5753 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5755 return gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
5759 * gtk_notebook_insert_page:
5760 * @notebook: a #GtkNotebook
5761 * @child: the #GtkWidget to use as the contents of the page.
5762 * @tab_label: the #GtkWidget to be used as the label for the page,
5763 * or %NULL to use the default label, 'page N'.
5764 * @position: the index (starting at 0) at which to insert the page,
5765 * or -1 to append the page after all other pages.
5767 * Insert a page into @notebook at the given position.
5769 * Return value: the index (starting from 0) of the inserted
5770 * page in the notebook, or -1 if function fails
5773 gtk_notebook_insert_page (GtkNotebook *notebook,
5775 GtkWidget *tab_label,
5778 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5779 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5780 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5782 return gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
5787 gtk_notebook_page_compare_tab (gconstpointer a,
5790 return (((GtkNotebookPage *) a)->tab_label != b);
5794 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
5798 GtkNotebook *notebook = GTK_NOTEBOOK (data);
5801 list = g_list_find_custom (notebook->children, child,
5802 gtk_notebook_page_compare_tab);
5805 GtkNotebookPage *page = list->data;
5807 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
5808 gtk_notebook_switch_page (notebook, page, -1);
5809 focus_tabs_in (notebook);
5816 * gtk_notebook_insert_page_menu:
5817 * @notebook: a #GtkNotebook
5818 * @child: the #GtkWidget to use as the contents of the page.
5819 * @tab_label: the #GtkWidget to be used as the label for the page,
5820 * or %NULL to use the default label, 'page N'.
5821 * @menu_label: the widget to use as a label for the page-switch
5822 * menu, if that is enabled. If %NULL, and @tab_label
5823 * is a #GtkLabel or %NULL, then the menu label will be
5824 * a newly created label with the same text as @tab_label;
5825 * If @tab_label is not a #GtkLabel, @menu_label must be
5826 * specified if the page-switch menu is to be used.
5827 * @position: the index (starting at 0) at which to insert the page,
5828 * or -1 to append the page after all other pages.
5830 * Insert a page into @notebook at the given position, specifying
5831 * the widget to use as the label in the popup menu.
5833 * Return value: the index (starting from 0) of the inserted
5834 * page in the notebook
5837 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
5839 GtkWidget *tab_label,
5840 GtkWidget *menu_label,
5843 GtkNotebookClass *class;
5845 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5846 g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
5847 g_return_val_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label), -1);
5848 g_return_val_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label), -1);
5850 class = GTK_NOTEBOOK_GET_CLASS (notebook);
5852 return (class->insert_page) (notebook, child, tab_label, menu_label, position);
5856 * gtk_notebook_remove_page:
5857 * @notebook: a #GtkNotebook.
5858 * @page_num: the index of a notebook page, starting
5859 * from 0. If -1, the last page will
5862 * Removes a page from the notebook given its index
5866 gtk_notebook_remove_page (GtkNotebook *notebook,
5871 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5874 list = g_list_nth (notebook->children, page_num);
5876 list = g_list_last (notebook->children);
5879 gtk_container_remove (GTK_CONTAINER (notebook),
5880 ((GtkNotebookPage *) list->data)->child);
5883 /* Public GtkNotebook Page Switch Methods :
5884 * gtk_notebook_get_current_page
5885 * gtk_notebook_page_num
5886 * gtk_notebook_set_current_page
5887 * gtk_notebook_next_page
5888 * gtk_notebook_prev_page
5891 * gtk_notebook_get_current_page:
5892 * @notebook: a #GtkNotebook
5894 * Returns the page number of the current page.
5896 * Return value: the index (starting from 0) of the current
5897 * page in the notebook. If the notebook has no pages, then
5898 * -1 will be returned.
5901 gtk_notebook_get_current_page (GtkNotebook *notebook)
5903 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5905 if (!notebook->cur_page)
5908 return g_list_index (notebook->children, notebook->cur_page);
5912 * gtk_notebook_get_nth_page:
5913 * @notebook: a #GtkNotebook
5914 * @page_num: the index of a page in the noteobok, or -1
5915 * to get the last page.
5917 * Returns the child widget contained in page number @page_num.
5919 * Return value: the child widget, or %NULL if @page_num is
5923 gtk_notebook_get_nth_page (GtkNotebook *notebook,
5926 GtkNotebookPage *page;
5929 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5932 list = g_list_nth (notebook->children, page_num);
5934 list = g_list_last (notebook->children);
5946 * gtk_notebook_get_n_pages:
5947 * @notebook: a #GtkNotebook
5949 * Gets the number of pages in a notebook.
5951 * Return value: the number of pages in the notebook.
5956 gtk_notebook_get_n_pages (GtkNotebook *notebook)
5958 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
5960 return g_list_length (notebook->children);
5964 * gtk_notebook_page_num:
5965 * @notebook: a #GtkNotebook
5966 * @child: a #GtkWidget
5968 * Finds the index of the page which contains the given child
5971 * Return value: the index of the page containing @child, or
5972 * -1 if @child is not in the notebook.
5975 gtk_notebook_page_num (GtkNotebook *notebook,
5981 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
5984 children = notebook->children;
5987 GtkNotebookPage *page = children->data;
5989 if (page->child == child)
5992 children = children->next;
6000 * gtk_notebook_set_current_page:
6001 * @notebook: a #GtkNotebook
6002 * @page_num: index of the page to switch to, starting from 0.
6003 * If negative, the last page will be used. If greater
6004 * than the number of pages in the notebook, nothing
6007 * Switches to the page number @page_num.
6010 gtk_notebook_set_current_page (GtkNotebook *notebook,
6015 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6018 list = g_list_nth (notebook->children, page_num);
6020 list = g_list_last (notebook->children);
6022 page_num = g_list_index (notebook->children, list);
6025 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
6029 * gtk_notebook_next_page:
6030 * @notebook: a #GtkNotebook
6032 * Switches to the next page. Nothing happens if the current page is
6036 gtk_notebook_next_page (GtkNotebook *notebook)
6040 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6042 list = g_list_find (notebook->children, notebook->cur_page);
6046 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
6050 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
6054 * gtk_notebook_prev_page:
6055 * @notebook: a #GtkNotebook
6057 * Switches to the previous page. Nothing happens if the current page
6058 * is the first page.
6061 gtk_notebook_prev_page (GtkNotebook *notebook)
6065 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6067 list = g_list_find (notebook->children, notebook->cur_page);
6071 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
6075 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
6078 /* Public GtkNotebook/Tab Style Functions
6080 * gtk_notebook_set_show_border
6081 * gtk_notebook_set_show_tabs
6082 * gtk_notebook_set_tab_pos
6083 * gtk_notebook_set_homogeneous_tabs
6084 * gtk_notebook_set_tab_border
6085 * gtk_notebook_set_tab_hborder
6086 * gtk_notebook_set_tab_vborder
6087 * gtk_notebook_set_scrollable
6090 * gtk_notebook_set_show_border:
6091 * @notebook: a #GtkNotebook
6092 * @show_border: %TRUE if a bevel should be drawn around the notebook.
6094 * Sets whether a bevel will be drawn around the notebook pages.
6095 * This only has a visual effect when the tabs are not shown.
6096 * See gtk_notebook_set_show_tabs().
6099 gtk_notebook_set_show_border (GtkNotebook *notebook,
6100 gboolean show_border)
6102 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6104 if (notebook->show_border != show_border)
6106 notebook->show_border = show_border;
6108 if (GTK_WIDGET_VISIBLE (notebook))
6109 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6111 g_object_notify (G_OBJECT (notebook), "show-border");
6116 * gtk_notebook_get_show_border:
6117 * @notebook: a #GtkNotebook
6119 * Returns whether a bevel will be drawn around the notebook pages. See
6120 * gtk_notebook_set_show_border().
6122 * Return value: %TRUE if the bevel is drawn
6125 gtk_notebook_get_show_border (GtkNotebook *notebook)
6127 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6129 return notebook->show_border;
6133 * gtk_notebook_set_show_tabs:
6134 * @notebook: a #GtkNotebook
6135 * @show_tabs: %TRUE if the tabs should be shown.
6137 * Sets whether to show the tabs for the notebook or not.
6140 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
6143 GtkNotebookPage *page;
6146 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6148 show_tabs = show_tabs != FALSE;
6150 if (notebook->show_tabs == show_tabs)
6153 notebook->show_tabs = show_tabs;
6154 children = notebook->children;
6158 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
6162 page = children->data;
6163 children = children->next;
6164 if (page->default_tab)
6166 gtk_widget_destroy (page->tab_label);
6167 page->tab_label = NULL;
6170 gtk_widget_hide (page->tab_label);
6175 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
6176 gtk_notebook_update_labels (notebook);
6178 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6180 g_object_notify (G_OBJECT (notebook), "show-tabs");
6184 * gtk_notebook_get_show_tabs:
6185 * @notebook: a #GtkNotebook
6187 * Returns whether the tabs of the notebook are shown. See
6188 * gtk_notebook_set_show_tabs().
6190 * Return value: %TRUE if the tabs are shown
6193 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
6195 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6197 return notebook->show_tabs;
6201 * gtk_notebook_set_tab_pos:
6202 * @notebook: a #GtkNotebook.
6203 * @pos: the edge to draw the tabs at.
6205 * Sets the edge at which the tabs for switching pages in the
6206 * notebook are drawn.
6209 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
6210 GtkPositionType pos)
6212 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6214 if (notebook->tab_pos != pos)
6216 notebook->tab_pos = pos;
6217 if (GTK_WIDGET_VISIBLE (notebook))
6218 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6221 g_object_notify (G_OBJECT (notebook), "tab-pos");
6225 * gtk_notebook_get_tab_pos:
6226 * @notebook: a #GtkNotebook
6228 * Gets the edge at which the tabs for switching pages in the
6229 * notebook are drawn.
6231 * Return value: the edge at which the tabs are drawn
6234 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
6236 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
6238 return notebook->tab_pos;
6242 * gtk_notebook_set_homogeneous_tabs:
6243 * @notebook: a #GtkNotebook
6244 * @homogeneous: %TRUE if all tabs should be the same size.
6246 * Sets whether the tabs must have all the same size or not.
6249 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
6250 gboolean homogeneous)
6252 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6254 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
6258 * gtk_notebook_set_tab_border:
6259 * @notebook: a #GtkNotebook
6260 * @border_width: width of the border around the tab labels.
6262 * Sets the width the border around the tab labels
6263 * in a notebook. This is equivalent to calling
6264 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
6265 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
6268 gtk_notebook_set_tab_border (GtkNotebook *notebook,
6271 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6273 gtk_notebook_set_tab_border_internal (notebook, border_width);
6277 * gtk_notebook_set_tab_hborder:
6278 * @notebook: a #GtkNotebook
6279 * @tab_hborder: width of the horizontal border of tab labels.
6281 * Sets the width of the horizontal border of tab labels.
6284 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
6287 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6289 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
6293 * gtk_notebook_set_tab_vborder:
6294 * @notebook: a #GtkNotebook
6295 * @tab_vborder: width of the vertical border of tab labels.
6297 * Sets the width of the vertical border of tab labels.
6300 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
6303 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6305 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
6309 * gtk_notebook_set_scrollable:
6310 * @notebook: a #GtkNotebook
6311 * @scrollable: %TRUE if scroll arrows should be added
6313 * Sets whether the tab label area will have arrows for scrolling if
6314 * there are too many tabs to fit in the area.
6317 gtk_notebook_set_scrollable (GtkNotebook *notebook,
6318 gboolean scrollable)
6320 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6322 scrollable = (scrollable != FALSE);
6324 if (scrollable != notebook->scrollable)
6326 notebook->scrollable = scrollable;
6328 if (GTK_WIDGET_VISIBLE (notebook))
6329 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6331 g_object_notify (G_OBJECT (notebook), "scrollable");
6336 * gtk_notebook_get_scrollable:
6337 * @notebook: a #GtkNotebook
6339 * Returns whether the tab label area has arrows for scrolling. See
6340 * gtk_notebook_set_scrollable().
6342 * Return value: %TRUE if arrows for scrolling are present
6345 gtk_notebook_get_scrollable (GtkNotebook *notebook)
6347 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6349 return notebook->scrollable;
6352 /* Public GtkNotebook Popup Menu Methods:
6354 * gtk_notebook_popup_enable
6355 * gtk_notebook_popup_disable
6360 * gtk_notebook_popup_enable:
6361 * @notebook: a #GtkNotebook
6363 * Enables the popup menu: if the user clicks with the right mouse button on
6364 * the bookmarks, a menu with all the pages will be popped up.
6367 gtk_notebook_popup_enable (GtkNotebook *notebook)
6371 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6376 notebook->menu = gtk_menu_new ();
6377 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
6379 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
6380 gtk_notebook_menu_item_create (notebook, list);
6382 gtk_notebook_update_labels (notebook);
6383 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
6384 GTK_WIDGET (notebook),
6385 gtk_notebook_menu_detacher);
6387 g_object_notify (G_OBJECT (notebook), "enable-popup");
6391 * gtk_notebook_popup_disable:
6392 * @notebook: a #GtkNotebook
6394 * Disables the popup menu.
6397 gtk_notebook_popup_disable (GtkNotebook *notebook)
6399 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6401 if (!notebook->menu)
6404 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
6405 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
6406 gtk_widget_destroy (notebook->menu);
6408 g_object_notify (G_OBJECT (notebook), "enable-popup");
6411 /* Public GtkNotebook Page Properties Functions:
6413 * gtk_notebook_get_tab_label
6414 * gtk_notebook_set_tab_label
6415 * gtk_notebook_set_tab_label_text
6416 * gtk_notebook_get_menu_label
6417 * gtk_notebook_set_menu_label
6418 * gtk_notebook_set_menu_label_text
6419 * gtk_notebook_set_tab_label_packing
6420 * gtk_notebook_query_tab_label_packing
6421 * gtk_notebook_get_tab_reorderable
6422 * gtk_notebook_set_tab_reorderable
6423 * gtk_notebook_get_tab_detachable
6424 * gtk_notebook_set_tab_detachable
6428 * gtk_notebook_get_tab_label:
6429 * @notebook: a #GtkNotebook
6432 * Returns the tab label widget for the page @child. %NULL is returned
6433 * if @child is not in @notebook or if no tab label has specifically
6434 * been set for @child.
6436 * Return value: the tab label
6439 gtk_notebook_get_tab_label (GtkNotebook *notebook,
6444 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6445 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6447 list = CHECK_FIND_CHILD (notebook, child);
6451 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
6454 return GTK_NOTEBOOK_PAGE (list)->tab_label;
6458 * gtk_notebook_set_tab_label:
6459 * @notebook: a #GtkNotebook
6461 * @tab_label: the tab label widget to use, or %NULL for default tab
6464 * Changes the tab label for @child. If %NULL is specified
6465 * for @tab_label, then the page will have the label 'page N'.
6468 gtk_notebook_set_tab_label (GtkNotebook *notebook,
6470 GtkWidget *tab_label)
6472 GtkNotebookPage *page;
6475 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6476 g_return_if_fail (GTK_IS_WIDGET (child));
6478 list = CHECK_FIND_CHILD (notebook, child);
6482 /* a NULL pointer indicates a default_tab setting, otherwise
6483 * we need to set the associated label
6487 if (page->tab_label == tab_label)
6491 gtk_notebook_remove_tab_label (notebook, page);
6495 page->default_tab = FALSE;
6496 page->tab_label = tab_label;
6497 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6501 page->default_tab = TRUE;
6502 page->tab_label = NULL;
6504 if (notebook->show_tabs)
6508 g_snprintf (string, sizeof(string), _("Page %u"),
6509 gtk_notebook_real_page_position (notebook, list));
6510 page->tab_label = gtk_label_new (string);
6511 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
6515 if (page->tab_label)
6516 page->mnemonic_activate_signal =
6517 g_signal_connect (page->tab_label,
6518 "mnemonic_activate",
6519 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
6522 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
6524 gtk_widget_show (page->tab_label);
6525 gtk_widget_queue_resize (GTK_WIDGET (notebook));
6528 gtk_notebook_update_tab_states (notebook);
6529 gtk_widget_child_notify (child, "tab-label");
6533 * gtk_notebook_set_tab_label_text:
6534 * @notebook: a #GtkNotebook
6536 * @tab_text: the label text
6538 * Creates a new label and sets it as the tab label for the page
6539 * containing @child.
6542 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
6544 const gchar *tab_text)
6546 GtkWidget *tab_label = NULL;
6548 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6551 tab_label = gtk_label_new (tab_text);
6552 gtk_notebook_set_tab_label (notebook, child, tab_label);
6553 gtk_widget_child_notify (child, "tab-label");
6557 * gtk_notebook_get_tab_label_text:
6558 * @notebook: a #GtkNotebook
6559 * @child: a widget contained in a page of @notebook
6561 * Retrieves the text of the tab label for the page containing
6564 * Returns value: the text of the tab label, or %NULL if the
6565 * tab label widget is not a #GtkLabel. The
6566 * string is owned by the widget and must not
6569 G_CONST_RETURN gchar *
6570 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
6573 GtkWidget *tab_label;
6575 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6576 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6578 tab_label = gtk_notebook_get_tab_label (notebook, child);
6580 if (tab_label && GTK_IS_LABEL (tab_label))
6581 return gtk_label_get_text (GTK_LABEL (tab_label));
6587 * gtk_notebook_get_menu_label:
6588 * @notebook: a #GtkNotebook
6589 * @child: a widget contained in a page of @notebook
6591 * Retrieves the menu label widget of the page containing @child.
6593 * Return value: the menu label, or %NULL if the
6594 * notebook page does not have a menu label other
6595 * than the default (the tab label).
6598 gtk_notebook_get_menu_label (GtkNotebook *notebook,
6603 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6604 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6606 list = CHECK_FIND_CHILD (notebook, child);
6610 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
6613 return GTK_NOTEBOOK_PAGE (list)->menu_label;
6617 * gtk_notebook_set_menu_label:
6618 * @notebook: a #GtkNotebook
6619 * @child: the child widget
6620 * @menu_label: the menu label, or NULL for default
6622 * Changes the menu label for the page containing @child.
6625 gtk_notebook_set_menu_label (GtkNotebook *notebook,
6627 GtkWidget *menu_label)
6629 GtkNotebookPage *page;
6632 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6633 g_return_if_fail (GTK_IS_WIDGET (child));
6635 list = CHECK_FIND_CHILD (notebook, child);
6640 if (page->menu_label)
6643 gtk_container_remove (GTK_CONTAINER (notebook->menu),
6644 page->menu_label->parent);
6646 if (!page->default_menu)
6647 g_object_unref (page->menu_label);
6652 page->menu_label = menu_label;
6653 g_object_ref_sink (page->menu_label);
6654 page->default_menu = FALSE;
6657 page->default_menu = TRUE;
6660 gtk_notebook_menu_item_create (notebook, list);
6661 gtk_widget_child_notify (child, "menu-label");
6665 * gtk_notebook_set_menu_label_text:
6666 * @notebook: a #GtkNotebook
6667 * @child: the child widget
6668 * @menu_text: the label text
6670 * Creates a new label and sets it as the menu label of @child.
6673 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
6675 const gchar *menu_text)
6677 GtkWidget *menu_label = NULL;
6679 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6682 menu_label = gtk_label_new (menu_text);
6683 gtk_notebook_set_menu_label (notebook, child, menu_label);
6684 gtk_widget_child_notify (child, "menu-label");
6688 * gtk_notebook_get_menu_label_text:
6689 * @notebook: a #GtkNotebook
6690 * @child: the child widget of a page of the notebook.
6692 * Retrieves the text of the menu label for the page containing
6695 * Returns value: the text of the tab label, or %NULL if the
6696 * widget does not have a menu label other than
6697 * the default menu label, or the menu label widget
6698 * is not a #GtkLabel. The string is owned by
6699 * the widget and must not be freed.
6701 G_CONST_RETURN gchar *
6702 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
6705 GtkWidget *menu_label;
6707 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
6708 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
6710 menu_label = gtk_notebook_get_menu_label (notebook, child);
6712 if (menu_label && GTK_IS_LABEL (menu_label))
6713 return gtk_label_get_text (GTK_LABEL (menu_label));
6718 /* Helper function called when pages are reordered
6721 gtk_notebook_child_reordered (GtkNotebook *notebook,
6722 GtkNotebookPage *page)
6726 GtkWidget *menu_item;
6728 menu_item = page->menu_label->parent;
6729 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
6730 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
6731 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
6734 gtk_notebook_update_tab_states (notebook);
6735 gtk_notebook_update_labels (notebook);
6739 * gtk_notebook_set_tab_label_packing:
6740 * @notebook: a #GtkNotebook
6741 * @child: the child widget
6742 * @expand: whether to expand the bookmark or not
6743 * @fill: whether the bookmark should fill the allocated area or not
6744 * @pack_type: the position of the bookmark
6746 * Sets the packing parameters for the tab label of the page
6747 * containing @child. See gtk_box_pack_start() for the exact meaning
6748 * of the parameters.
6751 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
6755 GtkPackType pack_type)
6757 GtkNotebookPage *page;
6760 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6761 g_return_if_fail (GTK_IS_WIDGET (child));
6763 list = CHECK_FIND_CHILD (notebook, child);
6768 expand = expand != FALSE;
6769 fill = fill != FALSE;
6770 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
6773 gtk_widget_freeze_child_notify (child);
6774 page->expand = expand;
6775 gtk_widget_child_notify (child, "tab-expand");
6777 gtk_widget_child_notify (child, "tab-fill");
6778 if (page->pack != pack_type)
6780 page->pack = pack_type;
6781 gtk_notebook_child_reordered (notebook, page);
6783 gtk_widget_child_notify (child, "tab-pack");
6784 gtk_widget_child_notify (child, "position");
6785 if (notebook->show_tabs)
6786 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6787 gtk_widget_thaw_child_notify (child);
6791 * gtk_notebook_query_tab_label_packing:
6792 * @notebook: a #GtkNotebook
6794 * @expand: location to store the expand value (or NULL)
6795 * @fill: location to store the fill value (or NULL)
6796 * @pack_type: location to store the pack_type (or NULL)
6798 * Query the packing attributes for the tab label of the page
6799 * containing @child.
6802 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
6806 GtkPackType *pack_type)
6810 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6811 g_return_if_fail (GTK_IS_WIDGET (child));
6813 list = CHECK_FIND_CHILD (notebook, child);
6818 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
6820 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
6822 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
6826 * gtk_notebook_reorder_child:
6827 * @notebook: a #GtkNotebook
6828 * @child: the child to move
6829 * @position: the new position, or -1 to move to the end
6831 * Reorders the page containing @child, so that it appears in position
6832 * @position. If @position is greater than or equal to the number of
6833 * children in the list or negative, @child will be moved to the end
6837 gtk_notebook_reorder_child (GtkNotebook *notebook,
6841 GList *list, *new_list;
6842 GtkNotebookPage *page;
6846 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6847 g_return_if_fail (GTK_IS_WIDGET (child));
6849 list = CHECK_FIND_CHILD (notebook, child);
6853 max_pos = g_list_length (notebook->children) - 1;
6854 if (position < 0 || position > max_pos)
6857 old_pos = g_list_position (notebook->children, list);
6859 if (old_pos == position)
6863 notebook->children = g_list_delete_link (notebook->children, list);
6865 notebook->children = g_list_insert (notebook->children, page, position);
6866 new_list = g_list_nth (notebook->children, position);
6868 /* Fix up GList references in GtkNotebook structure */
6869 if (notebook->first_tab == list)
6870 notebook->first_tab = new_list;
6871 if (notebook->focus_tab == list)
6872 notebook->focus_tab = new_list;
6874 gtk_widget_freeze_child_notify (child);
6876 /* Move around the menu items if necessary */
6877 gtk_notebook_child_reordered (notebook, page);
6878 gtk_widget_child_notify (child, "tab-pack");
6879 gtk_widget_child_notify (child, "position");
6881 if (notebook->show_tabs)
6882 gtk_notebook_pages_allocate (notebook, DRAG_OPERATION_NONE);
6884 gtk_widget_thaw_child_notify (child);
6886 g_signal_emit (notebook,
6887 notebook_signals[PAGE_REORDERED],
6894 * gtk_notebook_set_window_creation_hook:
6895 * @func: the #GtkNotebookWindowCreationFunc, or NULL
6896 * @data: user data for @func.
6898 * Installs a global function used to create a window
6899 * when a detached tab is dropped in an empty area.
6904 gtk_notebook_set_window_creation_hook (GtkNotebookWindowCreationFunc func,
6907 window_creation_hook = func;
6908 window_creation_hook_data = data;
6912 * gtk_notebook_set_group_id:
6913 * @notebook: a #GtkNotebook
6914 * @group_id: a group identificator, or -1 to unset it
6916 * Sets an group identificator for @notebook, notebooks sharing
6917 * the same group identificator will be able to exchange tabs
6918 * via drag and drop. A notebook with group identificator -1 will
6919 * not be able to exchange tabs with any other notebook.
6924 gtk_notebook_set_group_id (GtkNotebook *notebook,
6927 GtkNotebookPrivate *priv;
6929 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
6931 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6933 if (priv->group_id != group_id)
6935 priv->group_id = group_id;
6936 g_object_notify (G_OBJECT (notebook), "group-id");
6941 * gtk_notebook_get_group_id:
6942 * @notebook: a #GtkNotebook
6944 * Gets the current group identificator for @notebook.
6946 * Return Value: the group identificator, or -1 if none is set.
6951 gtk_notebook_get_group_id (GtkNotebook *notebook)
6953 GtkNotebookPrivate *priv;
6955 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
6957 priv = GTK_NOTEBOOK_GET_PRIVATE (notebook);
6958 return priv->group_id;
6962 * gtk_notebook_get_tab_reorderable:
6963 * @notebook: a #GtkNotebook
6964 * @child: a child #GtkWidget
6966 * Gets whether the tab can be reordered via drag and drop or not.
6968 * Return Value: TRUE if the tab is reorderable.
6971 gtk_notebook_get_tab_reorderable (GtkNotebook *notebook,
6976 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
6977 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
6979 list = CHECK_FIND_CHILD (notebook, child);
6983 return GTK_NOTEBOOK_PAGE (list)->reorderable;
6987 * gtk_notebook_set_tab_reorderable:
6988 * @notebook: a #GtkNotebook
6989 * @child: a child #GtkWidget
6990 * @reorderable: whether the tab is reorderable or not.
6992 * Sets whether the notebook tab can be reordered
6993 * via drag and drop or not.
6998 gtk_notebook_set_tab_reorderable (GtkNotebook *notebook,
7000 gboolean reorderable)
7004 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
7005 g_return_if_fail (GTK_IS_WIDGET (child));
7007 list = CHECK_FIND_CHILD (notebook, child);
7011 if (GTK_NOTEBOOK_PAGE (list)->reorderable != reorderable)
7013 GTK_NOTEBOOK_PAGE (list)->reorderable = (reorderable == TRUE);
7014 gtk_widget_child_notify (child, "reorderable");
7019 * gtk_notebook_get_tab_detachable:
7020 * @notebook: a #GtkNotebook
7021 * @child: a child #GtkWidget
7023 * Returns whether the tab contents can be detached from @notebook.
7025 * Return Value: TRUE if the tab is detachable.
7030 gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
7035 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
7036 g_return_val_if_fail (GTK_IS_WIDGET (child), FALSE);
7038 list = CHECK_FIND_CHILD (notebook, child);
7042 return GTK_NOTEBOOK_PAGE (list)->detachable;
7046 * gtk_notebook_set_tab_detachable:
7047 * @notebook: a #GtkNotebook
7048 * @child: a child #GtkWidget
7049 * @detachable: whether the tab is detachable or not
7051 * Sets whether the tab can be detached from @notebook to another
7052 * notebook or widget.
7054 * Note that 2 notebooks must share a common group identificator
7055 * (see gtk_notebook_set_group_id ()) to allow automatic tabs
7056 * interchange between them.
7058 * If you want a widget to interact with a notebook through DnD
7059 * (i.e.: accept dragged tabs from it) it must be set as a drop
7060 * destination and accept the target "GTK_NOTEBOOK_TAB". The notebook
7061 * will fill the selection with a GtkWidget** pointing to the child
7062 * widget that corresponds to the dropped tab.
7064 * <informalexample><programlisting>
7066 * on_drop_zone_drag_data_received (GtkWidget *widget,
7067 * GdkDragContext *context,
7070 * GtkSelectionData *selection_data,
7073 * gpointer user_data)
7075 * GtkWidget *notebook;
7076 * GtkWidget **child;
7078 * notebook = gtk_drag_get_source_widget (context);
7079 * child = (void*) selection_data->data;
7081 * process_widget (*child);
7082 * gtk_container_remove (GTK_CONTAINER (notebook), *child);
7084 * </programlisting></informalexample>
7086 * If you want a notebook to accept drags from other widgets,
7087 * you will have to set your own DnD code to do it.
7092 gtk_notebook_set_tab_detachable (GtkNotebook *notebook,
7094 gboolean detachable)
7098 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
7099 g_return_if_fail (GTK_IS_WIDGET (child));
7101 list = CHECK_FIND_CHILD (notebook, child);
7105 if (GTK_NOTEBOOK_PAGE (list)->detachable != detachable)
7107 GTK_NOTEBOOK_PAGE (list)->detachable = (detachable == TRUE);
7108 gtk_widget_child_notify (child, "detachable");
7112 #define __GTK_NOTEBOOK_C__
7113 #include "gtkaliasdef.c"