1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtknotebook.h"
28 #include "gtksignal.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
36 #include "gtkbindings.h"
40 #define TAB_CURVATURE 1
42 #define ARROW_SPACING 0
44 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
45 #define NOTEBOOK_SCROLL_DELAY (100)
77 CHILD_PROP_MENU_LABEL,
79 CHILD_PROP_TAB_EXPAND,
84 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
86 struct _GtkNotebookPage
90 GtkWidget *menu_label;
92 guint default_menu : 1; /* If true, we create the menu label ourself */
93 guint default_tab : 1; /* If true, we create the tab label ourself */
98 GtkRequisition requisition;
99 GtkAllocation allocation;
101 guint mnemonic_activate_signal;
104 #ifdef G_DISABLE_CHECKS
105 #define CHECK_FIND_CHILD(notebook, child) \
106 gtk_notebook_find_child(notebook, child, \
107 G_GNUC_PRETTY_FUNCTION)
109 #define CHECK_FIND_CHILD(notebook, child) \
110 gtk_notebook_find_child(notebook, child, NULL)
113 /*** GtkNotebook Methods ***/
114 static void gtk_notebook_class_init (GtkNotebookClass *klass);
115 static void gtk_notebook_init (GtkNotebook *notebook);
117 static void gtk_notebook_select_page (GtkNotebook *notebook,
118 gboolean move_focus);
119 static void gtk_notebook_focus_tab (GtkNotebook *notebook,
120 GtkNotebookTab type);
122 /*** GtkObject Methods ***/
123 static void gtk_notebook_destroy (GtkObject *object);
124 static void gtk_notebook_set_property (GObject *object,
128 static void gtk_notebook_get_property (GObject *object,
133 /*** GtkWidget Methods ***/
134 static void gtk_notebook_map (GtkWidget *widget);
135 static void gtk_notebook_unmap (GtkWidget *widget);
136 static void gtk_notebook_realize (GtkWidget *widget);
137 static void gtk_notebook_unrealize (GtkWidget *widget);
138 static void gtk_notebook_size_request (GtkWidget *widget,
139 GtkRequisition *requisition);
140 static void gtk_notebook_size_allocate (GtkWidget *widget,
141 GtkAllocation *allocation);
142 static gint gtk_notebook_expose (GtkWidget *widget,
143 GdkEventExpose *event);
144 static gint gtk_notebook_button_press (GtkWidget *widget,
145 GdkEventButton *event);
146 static gint gtk_notebook_button_release (GtkWidget *widget,
147 GdkEventButton *event);
148 static gint gtk_notebook_enter_notify (GtkWidget *widget,
149 GdkEventCrossing *event);
150 static gint gtk_notebook_leave_notify (GtkWidget *widget,
151 GdkEventCrossing *event);
152 static gint gtk_notebook_motion_notify (GtkWidget *widget,
153 GdkEventMotion *event);
154 static gint gtk_notebook_focus_in (GtkWidget *widget,
155 GdkEventFocus *event);
156 static void gtk_notebook_draw_focus (GtkWidget *widget);
157 static void gtk_notebook_style_set (GtkWidget *widget,
158 GtkStyle *previous_style);
159 static gint gtk_notebook_focus (GtkWidget *widget,
160 GtkDirectionType direction);
162 /*** GtkContainer Methods ***/
163 static void gtk_notebook_set_child_property (GtkContainer *container,
168 static void gtk_notebook_get_child_property (GtkContainer *container,
173 static void gtk_notebook_add (GtkContainer *container,
175 static void gtk_notebook_remove (GtkContainer *container,
177 static void gtk_notebook_set_focus_child (GtkContainer *container,
179 static GtkType gtk_notebook_child_type (GtkContainer *container);
180 static void gtk_notebook_forall (GtkContainer *container,
181 gboolean include_internals,
182 GtkCallback callback,
183 gpointer callback_data);
185 /*** GtkNotebook Private Functions ***/
186 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
187 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
188 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
189 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
190 GtkNotebookPage *old_page);
191 static void gtk_notebook_real_remove (GtkNotebook *notebook,
193 static void gtk_notebook_update_labels (GtkNotebook *notebook);
194 static gint gtk_notebook_timer (GtkNotebook *notebook);
195 static gint gtk_notebook_page_compare (gconstpointer a,
197 static GList *gtk_notebook_find_child (GtkNotebook *notebook,
199 const gchar *function);
200 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
202 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
205 gboolean find_visible);
207 /*** GtkNotebook Drawing Functions ***/
208 static void gtk_notebook_paint (GtkWidget *widget,
210 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
211 GtkNotebookPage *page,
213 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
215 static void gtk_notebook_set_shape (GtkNotebook *notebook);
217 /*** GtkNotebook Size Allocate Functions ***/
218 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
219 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
220 GtkNotebookPage *page,
221 GtkAllocation *allocation);
222 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
228 /*** GtkNotebook Page Switch Methods ***/
229 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
230 GtkNotebookPage *page,
233 /*** GtkNotebook Page Switch Functions ***/
234 static void gtk_notebook_switch_page (GtkNotebook *notebook,
235 GtkNotebookPage *page,
237 static gint gtk_notebook_page_select (GtkNotebook *notebook,
238 gboolean move_focus);
239 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
241 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
242 GtkNotebookPage *page);
244 /*** GtkNotebook Menu Functions ***/
245 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
247 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
249 static void gtk_notebook_menu_detacher (GtkWidget *widget,
253 static GtkContainerClass *parent_class = NULL;
254 static guint notebook_signals[LAST_SIGNAL] = { 0 };
257 gtk_notebook_get_type (void)
259 static GtkType notebook_type = 0;
263 static const GtkTypeInfo notebook_info =
266 sizeof (GtkNotebook),
267 sizeof (GtkNotebookClass),
268 (GtkClassInitFunc) gtk_notebook_class_init,
269 (GtkObjectInitFunc) gtk_notebook_init,
270 /* reserved_1 */ NULL,
271 /* reserved_2 */ NULL,
272 (GtkClassInitFunc) NULL,
275 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
278 return notebook_type;
282 gtk_notebook_class_init (GtkNotebookClass *class)
284 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
285 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
286 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
287 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
288 GtkBindingSet *binding_set;
290 parent_class = g_type_class_peek_parent (class);
292 gobject_class->set_property = gtk_notebook_set_property;
293 gobject_class->get_property = gtk_notebook_get_property;
294 object_class->destroy = gtk_notebook_destroy;
296 widget_class->map = gtk_notebook_map;
297 widget_class->unmap = gtk_notebook_unmap;
298 widget_class->realize = gtk_notebook_realize;
299 widget_class->unrealize = gtk_notebook_unrealize;
300 widget_class->size_request = gtk_notebook_size_request;
301 widget_class->size_allocate = gtk_notebook_size_allocate;
302 widget_class->expose_event = gtk_notebook_expose;
303 widget_class->button_press_event = gtk_notebook_button_press;
304 widget_class->button_release_event = gtk_notebook_button_release;
305 widget_class->enter_notify_event = gtk_notebook_enter_notify;
306 widget_class->leave_notify_event = gtk_notebook_leave_notify;
307 widget_class->motion_notify_event = gtk_notebook_motion_notify;
308 widget_class->focus_in_event = gtk_notebook_focus_in;
309 widget_class->style_set = gtk_notebook_style_set;
310 widget_class->focus = gtk_notebook_focus;
312 container_class->add = gtk_notebook_add;
313 container_class->remove = gtk_notebook_remove;
314 container_class->forall = gtk_notebook_forall;
315 container_class->set_focus_child = gtk_notebook_set_focus_child;
316 container_class->get_child_property = gtk_notebook_get_child_property;
317 container_class->set_child_property = gtk_notebook_set_child_property;
318 container_class->child_type = gtk_notebook_child_type;
320 class->switch_page = gtk_notebook_real_switch_page;
322 class->focus_tab = gtk_notebook_focus_tab;
323 class->select_page = gtk_notebook_select_page;
325 g_object_class_install_property (gobject_class,
327 g_param_spec_int ("page",
329 _("The index of the current page"),
334 g_object_class_install_property (gobject_class,
336 g_param_spec_enum ("tab_pos",
338 _("Which side of the notebook holds the tabs"),
339 GTK_TYPE_POSITION_TYPE,
342 g_object_class_install_property (gobject_class,
344 g_param_spec_uint ("tab_border",
346 _("Width of the border around the tab labels"),
351 g_object_class_install_property (gobject_class,
353 g_param_spec_uint ("tab_hborder",
354 _("Horizontal Tab Border"),
355 _("Width of the horizontal border of tab labels"),
360 g_object_class_install_property (gobject_class,
362 g_param_spec_uint ("tab_vborder",
363 _("Vertical Tab Border"),
364 _("Width of the vertical border of tab labels"),
369 g_object_class_install_property (gobject_class,
371 g_param_spec_boolean ("show_tabs",
373 _("Whether tabs should be shown or not"),
376 g_object_class_install_property (gobject_class,
378 g_param_spec_boolean ("show_border",
380 _("Whether the border should be shown or not"),
383 g_object_class_install_property (gobject_class,
385 g_param_spec_boolean ("scrollable",
387 _("If TRUE, scroll arrows are added if there are to many tabs to fit"),
390 g_object_class_install_property (gobject_class,
392 g_param_spec_boolean ("enable_popup",
394 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
397 g_object_class_install_property (gobject_class,
399 g_param_spec_boolean ("homogeneous",
401 _("Whether tabs should have homogeneous sizes"),
405 gtk_container_class_install_child_property (container_class,
406 CHILD_PROP_TAB_LABEL,
407 g_param_spec_string ("tab_label", NULL, NULL,
410 gtk_container_class_install_child_property (container_class,
411 CHILD_PROP_MENU_LABEL,
412 g_param_spec_string ("menu_label", NULL, NULL,
415 gtk_container_class_install_child_property (container_class,
417 g_param_spec_int ("position", NULL, NULL,
420 gtk_container_class_install_child_property (container_class,
421 CHILD_PROP_TAB_EXPAND,
422 g_param_spec_boolean ("tab_expand", NULL, NULL,
425 gtk_container_class_install_child_property (container_class,
427 g_param_spec_boolean ("tab_fill", NULL, NULL,
430 gtk_container_class_install_child_property (container_class,
432 g_param_spec_boolean ("tab_pack", NULL, NULL,
436 notebook_signals[SWITCH_PAGE] =
437 gtk_signal_new ("switch_page",
439 GTK_CLASS_TYPE (object_class),
440 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
441 gtk_marshal_VOID__POINTER_UINT,
445 notebook_signals[FOCUS_TAB] =
446 g_signal_new ("focus_tab",
447 G_TYPE_FROM_CLASS (object_class),
448 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
449 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
451 gtk_marshal_VOID__ENUM,
453 GTK_TYPE_NOTEBOOK_TAB);
454 notebook_signals[SELECT_PAGE] =
455 g_signal_new ("select_page",
456 G_TYPE_FROM_CLASS (object_class),
457 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
458 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
460 gtk_marshal_VOID__BOOLEAN,
464 binding_set = gtk_binding_set_by_class (object_class);
465 gtk_binding_entry_add_signal (binding_set,
468 G_TYPE_BOOLEAN, TRUE);
469 gtk_binding_entry_add_signal (binding_set,
472 G_TYPE_BOOLEAN, TRUE);
473 gtk_binding_entry_add_signal (binding_set,
476 G_TYPE_BOOLEAN, FALSE);
477 gtk_binding_entry_add_signal (binding_set,
480 G_TYPE_BOOLEAN, FALSE);
482 gtk_binding_entry_add_signal (binding_set,
485 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
486 gtk_binding_entry_add_signal (binding_set,
489 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
490 gtk_binding_entry_add_signal (binding_set,
493 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
494 gtk_binding_entry_add_signal (binding_set,
497 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
501 gtk_notebook_init (GtkNotebook *notebook)
503 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
504 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_NO_WINDOW);
506 notebook->cur_page = NULL;
507 notebook->children = NULL;
508 notebook->first_tab = NULL;
509 notebook->focus_tab = NULL;
510 notebook->panel = NULL;
511 notebook->menu = NULL;
513 notebook->tab_hborder = 2;
514 notebook->tab_vborder = 2;
516 notebook->show_tabs = TRUE;
517 notebook->show_border = TRUE;
518 notebook->tab_pos = GTK_POS_TOP;
519 notebook->scrollable = FALSE;
520 notebook->in_child = 0;
521 notebook->click_child = 0;
522 notebook->button = 0;
523 notebook->need_timer = 0;
524 notebook->child_has_focus = FALSE;
525 notebook->have_visible_child = FALSE;
529 gtk_notebook_select_page (GtkNotebook *notebook,
532 gtk_notebook_page_select (notebook, move_focus);
536 gtk_notebook_focus_tab (GtkNotebook *notebook,
543 case GTK_NOTEBOOK_TAB_FIRST:
544 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
546 gtk_notebook_switch_focus_tab (notebook, list);
548 case GTK_NOTEBOOK_TAB_LAST:
549 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
551 gtk_notebook_switch_focus_tab (notebook, list);
559 * Creates a new #GtkNotebook widget with no pages.
561 * Return value: the newly created #GtkNotebook
564 gtk_notebook_new (void)
566 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
569 /* Private GtkObject Methods :
571 * gtk_notebook_destroy
572 * gtk_notebook_set_arg
573 * gtk_notebook_get_arg
576 gtk_notebook_destroy (GtkObject *object)
578 GtkNotebook *notebook;
580 g_return_if_fail (object != NULL);
581 g_return_if_fail (GTK_IS_NOTEBOOK (object));
583 notebook = GTK_NOTEBOOK (object);
586 gtk_notebook_popup_disable (notebook);
588 GTK_OBJECT_CLASS (parent_class)->destroy (object);
592 gtk_notebook_set_property (GObject *object,
597 GtkNotebook *notebook;
599 notebook = GTK_NOTEBOOK (object);
604 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
606 case PROP_SHOW_BORDER:
607 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
609 case PROP_SCROLLABLE:
610 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
612 case PROP_ENABLE_POPUP:
613 if (g_value_get_boolean (value))
614 gtk_notebook_popup_enable (notebook);
616 gtk_notebook_popup_disable (notebook);
618 case PROP_HOMOGENEOUS:
619 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
622 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
625 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
627 case PROP_TAB_BORDER:
628 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
630 case PROP_TAB_HBORDER:
631 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
633 case PROP_TAB_VBORDER:
634 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
642 gtk_notebook_get_property (GObject *object,
647 GtkNotebook *notebook;
649 notebook = GTK_NOTEBOOK (object);
654 g_value_set_boolean (value, notebook->show_tabs);
656 case PROP_SHOW_BORDER:
657 g_value_set_boolean (value, notebook->show_border);
659 case PROP_SCROLLABLE:
660 g_value_set_boolean (value, notebook->scrollable);
662 case PROP_ENABLE_POPUP:
663 g_value_set_boolean (value, notebook->menu != NULL);
665 case PROP_HOMOGENEOUS:
666 g_value_set_boolean (value, notebook->homogeneous);
669 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
672 g_value_set_enum (value, notebook->tab_pos);
674 case PROP_TAB_HBORDER:
675 g_value_set_uint (value, notebook->tab_hborder);
677 case PROP_TAB_VBORDER:
678 g_value_set_uint (value, notebook->tab_vborder);
681 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
686 /* Private GtkWidget Methods :
690 * gtk_notebook_realize
691 * gtk_notebook_size_request
692 * gtk_notebook_size_allocate
693 * gtk_notebook_expose
694 * gtk_notebook_button_press
695 * gtk_notebook_button_release
696 * gtk_notebook_enter_notify
697 * gtk_notebook_leave_notify
698 * gtk_notebook_motion_notify
699 * gtk_notebook_focus_in
700 * gtk_notebook_focus_out
701 * gtk_notebook_draw_focus
702 * gtk_notebook_style_set
705 gtk_notebook_map (GtkWidget *widget)
707 GtkNotebook *notebook;
708 GtkNotebookPage *page;
711 g_return_if_fail (widget != NULL);
712 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
714 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
716 notebook = GTK_NOTEBOOK (widget);
718 if (notebook->cur_page &&
719 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
720 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
721 gtk_widget_map (notebook->cur_page->child);
723 if (notebook->scrollable)
724 gtk_notebook_pages_allocate (notebook);
727 children = notebook->children;
731 page = children->data;
732 children = children->next;
734 if (page->tab_label &&
735 GTK_WIDGET_VISIBLE (page->tab_label) &&
736 !GTK_WIDGET_MAPPED (page->tab_label))
737 gtk_widget_map (page->tab_label);
741 gdk_window_show (widget->window);
745 gtk_notebook_unmap (GtkWidget *widget)
747 g_return_if_fail (widget != NULL);
748 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
750 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
751 gdk_window_hide (widget->window);
752 if (GTK_NOTEBOOK (widget)->panel)
753 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
757 gtk_notebook_realize (GtkWidget *widget)
759 GtkNotebook *notebook;
760 GdkWindowAttr attributes;
761 gint attributes_mask;
763 g_return_if_fail (widget != NULL);
764 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
766 notebook = GTK_NOTEBOOK (widget);
767 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
769 attributes.window_type = GDK_WINDOW_CHILD;
770 attributes.x = widget->allocation.x;
771 attributes.y = widget->allocation.y;
772 attributes.width = widget->allocation.width;
773 attributes.height = widget->allocation.height;
774 attributes.wclass = GDK_INPUT_OUTPUT;
775 attributes.visual = gtk_widget_get_visual (widget);
776 attributes.colormap = gtk_widget_get_colormap (widget);
777 attributes.event_mask = gtk_widget_get_events (widget);
778 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
779 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
781 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
783 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
784 gdk_window_set_user_data (widget->window, notebook);
786 widget->style = gtk_style_attach (widget->style, widget->window);
787 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
789 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
790 if (notebook->scrollable)
791 gtk_notebook_panel_realize (notebook);
795 gtk_notebook_unrealize (GtkWidget *widget)
797 GtkNotebook *notebook;
799 g_return_if_fail (widget != NULL);
800 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
802 notebook = GTK_NOTEBOOK (widget);
806 gdk_window_set_user_data (notebook->panel, NULL);
807 gdk_window_destroy (notebook->panel);
808 notebook->panel = NULL;
811 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
812 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
816 gtk_notebook_size_request (GtkWidget *widget,
817 GtkRequisition *requisition)
819 GtkNotebook *notebook;
820 GtkNotebookPage *page;
822 GtkRequisition child_requisition;
823 gboolean switch_page = FALSE;
826 g_return_if_fail (widget != NULL);
827 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
828 g_return_if_fail (requisition != NULL);
830 notebook = GTK_NOTEBOOK (widget);
831 widget->requisition.width = 0;
832 widget->requisition.height = 0;
834 for (children = notebook->children, vis_pages = 0; children;
835 children = children->next)
837 page = children->data;
839 if (GTK_WIDGET_VISIBLE (page->child))
842 gtk_widget_size_request (page->child, &child_requisition);
844 widget->requisition.width = MAX (widget->requisition.width,
845 child_requisition.width);
846 widget->requisition.height = MAX (widget->requisition.height,
847 child_requisition.height);
849 if (GTK_WIDGET_MAPPED (page->child) && page != notebook->cur_page)
850 gtk_widget_unmap (page->child);
851 if (notebook->menu && page->menu_label->parent &&
852 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
853 gtk_widget_show (page->menu_label->parent);
857 if (page == notebook->cur_page)
859 if (notebook->menu && page->menu_label->parent &&
860 GTK_WIDGET_VISIBLE (page->menu_label->parent))
861 gtk_widget_hide (page->menu_label->parent);
865 if (notebook->show_border || notebook->show_tabs)
867 widget->requisition.width += widget->style->xthickness * 2;
868 widget->requisition.height += widget->style->ythickness * 2;
870 if (notebook->show_tabs)
877 for (children = notebook->children; children;
878 children = children->next)
880 page = children->data;
882 if (GTK_WIDGET_VISIBLE (page->child))
884 if (!GTK_WIDGET_VISIBLE (page->tab_label))
885 gtk_widget_show (page->tab_label);
887 gtk_widget_size_request (page->tab_label,
890 page->requisition.width =
891 child_requisition.width +
892 2 * widget->style->xthickness;
893 page->requisition.height =
894 child_requisition.height +
895 2 * widget->style->ythickness;
897 switch (notebook->tab_pos)
901 page->requisition.height += 2 * (notebook->tab_vborder +
903 tab_height = MAX (tab_height, page->requisition.height);
904 tab_max = MAX (tab_max, page->requisition.width);
908 page->requisition.width += 2 * (notebook->tab_hborder +
910 tab_width = MAX (tab_width, page->requisition.width);
911 tab_max = MAX (tab_max, page->requisition.height);
915 else if (GTK_WIDGET_VISIBLE (page->tab_label))
916 gtk_widget_hide (page->tab_label);
919 children = notebook->children;
923 switch (notebook->tab_pos)
930 if (notebook->scrollable && vis_pages > 1 &&
931 widget->requisition.width < tab_width)
932 tab_height = MAX (tab_height, ARROW_SIZE);
934 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
935 notebook->tab_hborder) - TAB_OVERLAP;
939 page = children->data;
940 children = children->next;
942 if (!GTK_WIDGET_VISIBLE (page->child))
945 if (notebook->homogeneous)
946 page->requisition.width = tab_max;
948 page->requisition.width += padding;
950 tab_width += page->requisition.width;
951 page->requisition.height = tab_height;
954 if (notebook->scrollable && vis_pages > 1 &&
955 widget->requisition.width < tab_width)
956 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
958 if (notebook->homogeneous && !notebook->scrollable)
959 widget->requisition.width = MAX (widget->requisition.width,
960 vis_pages * tab_max +
963 widget->requisition.width = MAX (widget->requisition.width,
964 tab_width + TAB_OVERLAP);
966 widget->requisition.height += tab_height;
973 if (notebook->scrollable && vis_pages > 1 &&
974 widget->requisition.height < tab_height)
975 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
977 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
978 notebook->tab_vborder) - TAB_OVERLAP;
983 page = children->data;
984 children = children->next;
986 if (!GTK_WIDGET_VISIBLE (page->child))
989 page->requisition.width = tab_width;
991 if (notebook->homogeneous)
992 page->requisition.height = tab_max;
994 page->requisition.height += padding;
996 tab_height += page->requisition.height;
999 if (notebook->scrollable && vis_pages > 1 &&
1000 widget->requisition.height < tab_height)
1001 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1003 widget->requisition.width += tab_width;
1005 if (notebook->homogeneous && !notebook->scrollable)
1006 widget->requisition.height =
1007 MAX (widget->requisition.height,
1008 vis_pages * tab_max + TAB_OVERLAP);
1010 widget->requisition.height =
1011 MAX (widget->requisition.height,
1012 tab_height + TAB_OVERLAP);
1014 if (!notebook->homogeneous || notebook->scrollable)
1016 widget->requisition.height = MAX (widget->requisition.height,
1017 vis_pages * tab_max +
1025 for (children = notebook->children; children;
1026 children = children->next)
1028 page = children->data;
1030 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1031 gtk_widget_hide (page->tab_label);
1036 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1037 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1043 for (children = notebook->children; children;
1044 children = children->next)
1046 page = children->data;
1047 if (GTK_WIDGET_VISIBLE (page->child))
1049 gtk_notebook_switch_page (notebook, page, -1);
1054 else if (GTK_WIDGET_VISIBLE (widget))
1056 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1057 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1060 if (vis_pages && !notebook->cur_page)
1062 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1065 notebook->first_tab = children;
1066 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1072 gtk_notebook_size_allocate (GtkWidget *widget,
1073 GtkAllocation *allocation)
1075 GtkNotebook *notebook;
1076 GtkNotebookPage *page;
1077 GtkAllocation child_allocation;
1080 g_return_if_fail (widget != NULL);
1081 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1082 g_return_if_fail (allocation != NULL);
1084 widget->allocation = *allocation;
1085 if (GTK_WIDGET_REALIZED (widget))
1086 gdk_window_move_resize (widget->window,
1087 allocation->x, allocation->y,
1088 allocation->width, allocation->height);
1090 notebook = GTK_NOTEBOOK (widget);
1091 if (notebook->children)
1093 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1094 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1095 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
1096 child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
1098 if (notebook->show_tabs || notebook->show_border)
1100 child_allocation.x += widget->style->xthickness;
1101 child_allocation.y += widget->style->ythickness;
1102 child_allocation.width = MAX (1, (gint)child_allocation.width -
1103 (gint) widget->style->xthickness * 2);
1104 child_allocation.height = MAX (1, (gint)child_allocation.height -
1105 (gint) widget->style->ythickness * 2);
1107 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1109 switch (notebook->tab_pos)
1112 child_allocation.y += notebook->cur_page->requisition.height;
1113 case GTK_POS_BOTTOM:
1114 child_allocation.height =
1115 MAX (1, (gint)child_allocation.height -
1116 (gint)notebook->cur_page->requisition.height);
1119 child_allocation.x += notebook->cur_page->requisition.width;
1121 child_allocation.width =
1122 MAX (1, (gint)child_allocation.width -
1123 (gint)notebook->cur_page->requisition.width);
1129 children = notebook->children;
1132 page = children->data;
1133 children = children->next;
1135 if (GTK_WIDGET_VISIBLE (page->child))
1136 gtk_widget_size_allocate (page->child, &child_allocation);
1139 gtk_notebook_pages_allocate (notebook);
1141 gtk_notebook_set_shape (notebook);
1145 gtk_notebook_expose (GtkWidget *widget,
1146 GdkEventExpose *event)
1148 GtkNotebook *notebook;
1149 GdkRectangle child_area;
1151 g_return_val_if_fail (widget != NULL, FALSE);
1152 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1153 g_return_val_if_fail (event != NULL, FALSE);
1155 if (GTK_WIDGET_DRAWABLE (widget))
1157 notebook = GTK_NOTEBOOK (widget);
1159 gtk_notebook_paint (widget, &event->area);
1160 if (notebook->show_tabs)
1162 if (notebook->cur_page &&
1163 gtk_widget_intersect (notebook->cur_page->tab_label,
1164 &event->area, &child_area))
1165 gtk_notebook_draw_focus (widget);
1169 if (notebook->cur_page)
1170 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1171 notebook->cur_page->child,
1179 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1180 GdkEventButton *event)
1182 GtkWidget *widget = GTK_WIDGET (notebook);
1184 GtkArrowType arrow = event->x <= ARROW_SIZE + ARROW_SPACING / 2 ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT;
1186 if (!GTK_WIDGET_HAS_FOCUS (widget))
1187 gtk_widget_grab_focus (widget);
1189 notebook->button = event->button;
1190 notebook->click_child = arrow;
1192 if (event->button == 1)
1194 GtkDirectionType dir;
1195 if (!notebook->focus_tab ||
1196 gtk_notebook_search_page (notebook, notebook->focus_tab,
1197 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1200 if (notebook->tab_pos == GTK_POS_LEFT ||
1201 notebook->tab_pos == GTK_POS_RIGHT)
1202 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1204 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1205 gtk_widget_child_focus (widget, dir);
1208 if (!notebook->timer)
1210 notebook->timer = gtk_timeout_add
1211 (NOTEBOOK_INIT_SCROLL_DELAY,
1212 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1213 notebook->need_timer = TRUE;
1216 else if (event->button == 2)
1217 gtk_notebook_page_select (notebook, TRUE);
1218 else if (event->button == 3)
1219 gtk_notebook_switch_focus_tab (notebook,
1220 gtk_notebook_search_page (notebook,
1222 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1224 gtk_notebook_redraw_arrows (notebook);
1230 gtk_notebook_button_press (GtkWidget *widget,
1231 GdkEventButton *event)
1233 GtkNotebook *notebook;
1234 GtkNotebookPage *page;
1238 g_return_val_if_fail (widget != NULL, FALSE);
1239 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1240 g_return_val_if_fail (event != NULL, FALSE);
1242 notebook = GTK_NOTEBOOK (widget);
1244 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1248 if (event->window == notebook->panel)
1250 return gtk_notebook_arrow_button_press (notebook, event);
1252 else if (event->window == widget->window)
1254 if (event->button == 3 && notebook->menu)
1256 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1257 NULL, NULL, 3, event->time);
1262 children = notebook->children;
1265 page = children->data;
1267 if (GTK_WIDGET_VISIBLE (page->child) &&
1268 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1269 (event->x >= page->allocation.x) &&
1270 (event->y >= page->allocation.y) &&
1271 (event->x <= (page->allocation.x + page->allocation.width)) &&
1272 (event->y <= (page->allocation.y + page->allocation.height)))
1274 if (page == notebook->cur_page && notebook->focus_tab &&
1275 notebook->focus_tab != children &&
1276 GTK_WIDGET_HAS_FOCUS (notebook))
1278 GtkNotebookPage *old_page;
1280 notebook->child_has_focus = FALSE;
1281 old_page = (GtkNotebookPage *)
1282 (notebook->focus_tab->data);
1283 gtk_notebook_switch_focus_tab (notebook, children);
1284 gtk_notebook_focus_changed (notebook, old_page);
1288 gtk_notebook_switch_focus_tab (notebook, children);
1289 gtk_widget_grab_focus (widget);
1290 gtk_notebook_switch_page (notebook, page, num);
1294 children = children->next;
1297 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1298 gtk_widget_grab_focus (widget);
1306 gtk_notebook_button_release (GtkWidget *widget,
1307 GdkEventButton *event)
1309 GtkNotebook *notebook;
1311 g_return_val_if_fail (widget != NULL, FALSE);
1312 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1313 g_return_val_if_fail (event != NULL, FALSE);
1315 if (event->type != GDK_BUTTON_RELEASE)
1318 notebook = GTK_NOTEBOOK (widget);
1320 if (event->button == notebook->button)
1324 if (notebook->timer)
1326 gtk_timeout_remove (notebook->timer);
1327 notebook->timer = 0;
1328 notebook->need_timer = FALSE;
1330 click_child = notebook->click_child;
1331 notebook->click_child = 0;
1332 notebook->button = 0;
1333 gtk_notebook_redraw_arrows (notebook);
1342 gtk_notebook_enter_notify (GtkWidget *widget,
1343 GdkEventCrossing *event)
1345 GtkNotebook *notebook;
1347 g_return_val_if_fail (widget != NULL, FALSE);
1348 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1349 g_return_val_if_fail (event != NULL, FALSE);
1351 notebook = GTK_NOTEBOOK (widget);
1353 if (event->window == notebook->panel)
1358 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1360 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1361 notebook->in_child = GTK_ARROW_LEFT;
1363 notebook->in_child = GTK_ARROW_RIGHT;
1365 gtk_notebook_redraw_arrows (notebook);
1372 gtk_notebook_leave_notify (GtkWidget *widget,
1373 GdkEventCrossing *event)
1375 GtkNotebook *notebook;
1377 g_return_val_if_fail (widget != NULL, FALSE);
1378 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1379 g_return_val_if_fail (event != NULL, FALSE);
1381 notebook = GTK_NOTEBOOK (widget);
1383 if (event->window == notebook->panel)
1384 gtk_notebook_redraw_arrows (notebook);
1390 gtk_notebook_motion_notify (GtkWidget *widget,
1391 GdkEventMotion *event)
1393 GtkNotebook *notebook;
1395 g_return_val_if_fail (widget != NULL, FALSE);
1396 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1397 g_return_val_if_fail (event != NULL, FALSE);
1399 notebook = GTK_NOTEBOOK (widget);
1401 if (notebook->button)
1404 if (event->window == notebook->panel)
1407 GtkArrowType old_child = notebook->in_child;
1411 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1413 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1414 notebook->in_child = GTK_ARROW_LEFT;
1416 notebook->in_child = GTK_ARROW_RIGHT;
1418 if (old_child != notebook->in_child)
1419 gtk_notebook_redraw_arrows (notebook);
1426 gtk_notebook_focus_in (GtkWidget *widget,
1427 GdkEventFocus *event)
1429 g_return_val_if_fail (widget != NULL, FALSE);
1430 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1431 g_return_val_if_fail (event != NULL, FALSE);
1433 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1435 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1439 gtk_notebook_draw_focus (GtkWidget *widget)
1441 GtkNotebook *notebook;
1443 g_return_if_fail (widget != NULL);
1444 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1446 notebook = GTK_NOTEBOOK (widget);
1448 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1449 notebook->focus_tab)
1451 GtkNotebookPage *page;
1454 page = notebook->focus_tab->data;
1456 area.x = page->tab_label->allocation.x - 1;
1457 area.y = page->tab_label->allocation.y - 1;
1458 area.width = page->tab_label->allocation.width + 2;
1459 area.height = page->tab_label->allocation.height + 2;
1461 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1466 gtk_notebook_style_set (GtkWidget *widget,
1467 GtkStyle *previous_style)
1469 if (GTK_WIDGET_REALIZED (widget) &&
1470 !GTK_WIDGET_NO_WINDOW (widget))
1472 gtk_style_set_background (widget->style, widget->window, widget->state);
1473 if (GTK_WIDGET_DRAWABLE (widget))
1474 gdk_window_clear (widget->window);
1477 gtk_notebook_set_shape (GTK_NOTEBOOK(widget));
1480 /* Private GtkContainer Methods :
1482 * gtk_notebook_set_child_arg
1483 * gtk_notebook_get_child_arg
1485 * gtk_notebook_remove
1486 * gtk_notebook_focus
1487 * gtk_notebook_set_focus_child
1488 * gtk_notebook_child_type
1489 * gtk_notebook_forall
1492 gtk_notebook_set_child_property (GtkContainer *container,
1495 const GValue *value,
1500 GtkPackType pack_type;
1502 switch (property_id)
1504 case CHILD_PROP_TAB_LABEL:
1505 /* a NULL pointer indicates a default_tab setting, otherwise
1506 * we need to set the associated label
1508 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1509 g_value_get_string (value));
1511 case CHILD_PROP_MENU_LABEL:
1512 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1513 g_value_get_string (value));
1515 case CHILD_PROP_POSITION:
1516 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1517 g_value_get_int (value));
1519 case CHILD_PROP_TAB_EXPAND:
1520 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1521 &expand, &fill, &pack_type);
1522 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1523 g_value_get_boolean (value),
1526 case CHILD_PROP_TAB_FILL:
1527 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1528 &expand, &fill, &pack_type);
1529 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1531 g_value_get_boolean (value),
1534 case CHILD_PROP_TAB_PACK:
1535 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1536 &expand, &fill, &pack_type);
1537 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1539 g_value_get_enum (value));
1542 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1548 gtk_notebook_get_child_property (GtkContainer *container,
1555 GtkNotebook *notebook;
1559 GtkPackType pack_type;
1561 notebook = GTK_NOTEBOOK (container);
1563 list = CHECK_FIND_CHILD (notebook, child);
1566 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1570 switch (property_id)
1572 case CHILD_PROP_TAB_LABEL:
1573 label = gtk_notebook_get_tab_label (notebook, child);
1575 if (label && GTK_IS_LABEL (label))
1576 g_value_set_string (value, GTK_LABEL (label)->label);
1578 g_value_set_string (value, NULL);
1580 case CHILD_PROP_MENU_LABEL:
1581 label = gtk_notebook_get_menu_label (notebook, child);
1583 if (label && GTK_IS_LABEL (label))
1584 g_value_set_string (value, GTK_LABEL (label)->label);
1586 g_value_set_string (value, NULL);
1588 case CHILD_PROP_POSITION:
1589 g_value_set_int (value, g_list_position (notebook->children, list));
1591 case CHILD_PROP_TAB_EXPAND:
1592 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1593 &expand, NULL, NULL);
1594 g_value_set_boolean (value, expand);
1596 case CHILD_PROP_TAB_FILL:
1597 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1599 g_value_set_boolean (value, fill);
1601 case CHILD_PROP_TAB_PACK:
1602 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1603 NULL, NULL, &pack_type);
1604 g_value_set_enum (value, pack_type);
1607 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1613 gtk_notebook_add (GtkContainer *container,
1616 g_return_if_fail (container != NULL);
1617 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1619 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1624 gtk_notebook_remove (GtkContainer *container,
1627 GtkNotebook *notebook;
1628 GtkNotebookPage *page;
1632 g_return_if_fail (container != NULL);
1633 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1634 g_return_if_fail (widget != NULL);
1636 notebook = GTK_NOTEBOOK (container);
1638 children = notebook->children;
1642 page = children->data;
1643 if (page->child == widget)
1645 gtk_notebook_real_remove (notebook, children);
1649 children = children->next;
1654 focus_tabs_in (GtkNotebook *notebook)
1656 if (notebook->cur_page)
1658 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1660 gtk_notebook_switch_focus_tab (notebook,
1661 g_list_find (notebook->children,
1662 notebook->cur_page));
1671 focus_tabs_move (GtkNotebook *notebook,
1672 GtkDirectionType direction,
1673 gint search_direction)
1677 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1678 search_direction, TRUE);
1680 new_page = (search_direction == STEP_NEXT) ?
1681 notebook->children :
1682 g_list_last (notebook->children);
1684 gtk_notebook_switch_focus_tab (notebook, new_page);
1690 focus_child_in (GtkNotebook *notebook,
1691 GtkDirectionType direction)
1693 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1696 /* Focus in the notebook can either be on the pages, or on
1700 gtk_notebook_focus (GtkWidget *widget,
1701 GtkDirectionType direction)
1703 GtkWidget *old_focus_child;
1704 GtkNotebook *notebook;
1705 GtkDirectionType effective_direction;
1707 /* Remap the directions into the effective direction it would be for a
1708 * GTK_POS_TOP notebook
1710 #define D(rest) GTK_DIR_##rest
1712 static const GtkDirectionType translate_direction[4][6] = {
1713 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
1714 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
1715 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
1716 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
1721 gboolean widget_is_focus;
1722 GtkContainer *container;
1724 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1726 container = GTK_CONTAINER (widget);
1727 notebook = GTK_NOTEBOOK (container);
1729 widget_is_focus = gtk_widget_is_focus (widget);
1730 old_focus_child = container->focus_child;
1732 effective_direction = translate_direction[notebook->tab_pos][direction];
1734 if (old_focus_child) /* Focus on page child */
1736 if (gtk_widget_child_focus (old_focus_child, direction))
1739 switch (effective_direction)
1741 case GTK_DIR_TAB_BACKWARD:
1743 /* Focus onto the tabs */
1744 if (notebook->show_tabs)
1745 return focus_tabs_in (notebook);
1749 case GTK_DIR_TAB_FORWARD:
1755 else if (widget_is_focus) /* Focus was on tabs */
1757 switch (effective_direction)
1759 case GTK_DIR_TAB_BACKWARD:
1762 case GTK_DIR_TAB_FORWARD:
1764 return focus_child_in (notebook, direction);
1766 return focus_tabs_move (notebook, direction, STEP_PREV);
1768 return focus_tabs_move (notebook, direction, STEP_NEXT);
1771 else /* Focus was not on widget */
1773 switch (effective_direction)
1775 case GTK_DIR_TAB_FORWARD:
1777 if (focus_tabs_in (notebook))
1779 if (focus_child_in (notebook, direction))
1782 case GTK_DIR_TAB_BACKWARD:
1784 if (focus_child_in (notebook, direction))
1786 if (focus_tabs_in (notebook))
1791 return focus_child_in (notebook, direction);
1795 g_assert_not_reached ();
1800 gtk_notebook_set_focus_child (GtkContainer *container,
1803 GtkNotebook *notebook;
1805 g_return_if_fail (container != NULL);
1806 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1810 g_return_if_fail (GTK_IS_WIDGET (child));
1812 notebook = GTK_NOTEBOOK (container);
1814 notebook->child_has_focus = TRUE;
1815 if (!notebook->focus_tab)
1818 GtkNotebookPage *page;
1820 children = notebook->children;
1823 page = children->data;
1824 if (page->child == child || page->tab_label == child)
1825 gtk_notebook_switch_focus_tab (notebook, children);
1826 children = children->next;
1830 parent_class->set_focus_child (container, child);
1834 gtk_notebook_forall (GtkContainer *container,
1835 gboolean include_internals,
1836 GtkCallback callback,
1837 gpointer callback_data)
1839 GtkNotebook *notebook;
1842 g_return_if_fail (container != NULL);
1843 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1844 g_return_if_fail (callback != NULL);
1846 notebook = GTK_NOTEBOOK (container);
1848 children = notebook->children;
1851 GtkNotebookPage *page;
1853 page = children->data;
1854 children = children->next;
1855 (* callback) (page->child, callback_data);
1856 if (include_internals)
1858 if (page->tab_label)
1859 (* callback) (page->tab_label, callback_data);
1860 if (page->menu_label)
1861 (* callback) (page->menu_label, callback_data);
1867 gtk_notebook_child_type (GtkContainer *container)
1869 return GTK_TYPE_WIDGET;
1872 /* Private GtkNotebook Functions:
1874 * gtk_notebook_panel_realize
1875 * gtk_notebook_redraw_tabs
1876 * gtk_notebook_focus_changed
1877 * gtk_notebook_real_remove
1878 * gtk_notebook_update_labels
1879 * gtk_notebook_timer
1880 * gtk_notebook_page_compare
1881 * gtk_notebook_real_page_position
1882 * gtk_notebook_search_page
1885 gtk_notebook_panel_realize (GtkNotebook *notebook)
1888 GdkWindowAttr attributes;
1889 gint attributes_mask;
1891 g_return_if_fail (notebook != NULL);
1892 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1894 widget = GTK_WIDGET (notebook);
1896 attributes.window_type = GDK_WINDOW_CHILD;
1897 attributes.wclass = GDK_INPUT_OUTPUT;
1898 attributes.visual = gtk_widget_get_visual (widget);
1899 attributes.colormap = gtk_widget_get_colormap (widget);
1900 attributes.event_mask = gtk_widget_get_events (widget);
1901 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1902 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1903 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1905 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1907 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1908 attributes.height = ARROW_SIZE;
1910 attributes.x = (widget->allocation.width - attributes.width -
1911 GTK_CONTAINER (notebook)->border_width);
1912 attributes.y = (widget->allocation.height - ARROW_SIZE -
1913 GTK_CONTAINER (notebook)->border_width);
1914 if (notebook->tab_pos == GTK_POS_TOP)
1915 attributes.y = GTK_CONTAINER (notebook)->border_width;
1916 else if (notebook->tab_pos == GTK_POS_LEFT)
1917 attributes.x = (widget->allocation.x +
1918 GTK_CONTAINER (notebook)->border_width);
1920 notebook->panel = gdk_window_new (widget->window, &attributes,
1922 gtk_style_set_background (widget->style, notebook->panel,
1924 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
1925 gdk_window_set_user_data (notebook->panel, widget);
1929 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
1932 GtkNotebookPage *page;
1933 GdkRectangle redraw_rect;
1936 widget = GTK_WIDGET (notebook);
1937 border = GTK_CONTAINER (notebook)->border_width;
1939 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
1942 page = notebook->first_tab->data;
1944 redraw_rect.x = border;
1945 redraw_rect.y = border;
1947 switch (notebook->tab_pos)
1949 case GTK_POS_BOTTOM:
1950 redraw_rect.y = (widget->allocation.height - border -
1951 page->allocation.height -
1952 widget->style->ythickness);
1953 if (page != notebook->cur_page)
1954 redraw_rect.y -= widget->style->ythickness;
1957 redraw_rect.width = widget->allocation.width - 2 * border;
1958 redraw_rect.height = (page->allocation.height +
1959 widget->style->ythickness);
1960 if (page != notebook->cur_page)
1961 redraw_rect.height += widget->style->ythickness;
1964 redraw_rect.x = (widget->allocation.width - border -
1965 page->allocation.width -
1966 widget->style->xthickness);
1967 if (page != notebook->cur_page)
1968 redraw_rect.x -= widget->style->xthickness;
1971 redraw_rect.width = (page->allocation.width +
1972 widget->style->xthickness);
1973 redraw_rect.height = widget->allocation.height - 2 * border;
1974 if (page != notebook->cur_page)
1975 redraw_rect.width += widget->style->xthickness;
1979 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
1983 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
1985 if (GTK_WIDGET_MAPPED (notebook) && notebook->panel)
1986 gdk_window_invalidate_rect (notebook->panel, NULL, FALSE);
1990 gtk_notebook_focus_changed (GtkNotebook *notebook,
1991 GtkNotebookPage *old_page)
1993 g_return_if_fail (notebook != NULL);
1994 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1996 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2000 if (notebook->focus_tab)
2002 GtkNotebookPage *page;
2004 page = notebook->focus_tab->data;
2006 area.x = page->tab_label->allocation.x - 1;
2007 area.y = page->tab_label->allocation.y - 1;
2008 area.width = page->tab_label->allocation.width + 2;
2009 area.height = page->tab_label->allocation.height + 2;
2011 gtk_notebook_draw_tab (notebook, page, &area);
2016 area.x = old_page->tab_label->allocation.x - 1;
2017 area.y = old_page->tab_label->allocation.y - 1;
2018 area.width = old_page->tab_label->allocation.width + 2;
2019 area.height = old_page->tab_label->allocation.height + 2;
2021 gtk_notebook_draw_tab (notebook, old_page, &area);
2027 gtk_notebook_timer (GtkNotebook *notebook)
2029 gboolean retval = FALSE;
2031 GDK_THREADS_ENTER ();
2033 if (notebook->timer)
2035 if (notebook->click_child == GTK_ARROW_LEFT)
2037 if (!notebook->focus_tab ||
2038 gtk_notebook_search_page (notebook, notebook->focus_tab,
2040 gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_LEFT);
2042 else if (notebook->click_child == GTK_ARROW_RIGHT)
2044 if (!notebook->focus_tab ||
2045 gtk_notebook_search_page (notebook, notebook->focus_tab,
2047 gtk_widget_child_focus (GTK_WIDGET (notebook), GTK_DIR_RIGHT);
2049 if (notebook->need_timer)
2051 notebook->need_timer = FALSE;
2052 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2053 (GtkFunction) gtk_notebook_timer,
2054 (gpointer) notebook);
2060 GDK_THREADS_LEAVE ();
2066 gtk_notebook_page_compare (gconstpointer a,
2069 return (((GtkNotebookPage *) a)->child != b);
2073 gtk_notebook_find_child (GtkNotebook *notebook,
2075 const gchar *function)
2077 GList *list = g_list_find_custom (notebook->children, child,
2078 gtk_notebook_page_compare);
2080 #ifndef G_DISABLE_CHECKS
2082 g_warning ("child argument to '%s' does not refer to the contents of a notebook page",
2090 gtk_notebook_real_remove (GtkNotebook *notebook,
2093 GtkNotebookPage *page;
2095 gint need_resize = FALSE;
2097 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2099 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2101 if (notebook->cur_page == list->data)
2103 notebook->cur_page = NULL;
2105 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2108 if (list == notebook->first_tab)
2109 notebook->first_tab = next_list;
2110 if (list == notebook->focus_tab)
2111 gtk_notebook_switch_focus_tab (notebook, next_list);
2115 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2118 if (page->tab_label && page->mnemonic_activate_signal)
2119 gtk_signal_disconnect (page->tab_label,
2120 page->mnemonic_activate_signal);
2122 gtk_widget_unparent (page->child);
2124 if (page->tab_label)
2125 gtk_widget_unparent (page->tab_label);
2129 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2130 page->menu_label->parent);
2131 gtk_widget_queue_resize (notebook->menu);
2133 if (!page->default_menu)
2134 gtk_widget_unref (page->menu_label);
2136 notebook->children = g_list_remove_link (notebook->children, list);
2140 gtk_notebook_update_labels (notebook);
2142 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2146 gtk_notebook_update_labels (GtkNotebook *notebook)
2148 GtkNotebookPage *page;
2153 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2155 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2158 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2159 if (notebook->show_tabs)
2161 if (page->default_tab)
2163 if (!page->tab_label)
2165 page->tab_label = gtk_label_new (string);
2166 gtk_widget_set_parent (page->tab_label,
2167 GTK_WIDGET (notebook));
2170 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2173 if (GTK_WIDGET_VISIBLE (page->child) &&
2174 !GTK_WIDGET_VISIBLE (page->tab_label))
2175 gtk_widget_show (page->tab_label);
2176 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2177 GTK_WIDGET_VISIBLE (page->tab_label))
2178 gtk_widget_hide (page->tab_label);
2180 if (notebook->menu && page->default_menu)
2182 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2183 gtk_label_set_text (GTK_LABEL (page->menu_label),
2184 GTK_LABEL (page->tab_label)->label);
2186 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2192 gtk_notebook_real_page_position (GtkNotebook *notebook,
2198 g_return_val_if_fail (notebook != NULL, -1);
2199 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2200 g_return_val_if_fail (list != NULL, -1);
2202 for (work = notebook->children, count_start = 0;
2203 work && work != list; work = work->next)
2204 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2210 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2213 return (count_start + g_list_length (list) - 1);
2217 gtk_notebook_search_page (GtkNotebook *notebook,
2220 gboolean find_visible)
2222 GtkNotebookPage *page = NULL;
2223 GList *old_list = NULL;
2226 g_return_val_if_fail (notebook != NULL, NULL);
2227 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2232 flag = GTK_PACK_END;
2236 flag = GTK_PACK_START;
2243 if (!page || page->pack == flag)
2251 list = notebook->children;
2256 if (page->pack == flag &&
2257 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2272 if (page->pack != flag &&
2273 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2281 /* Private GtkNotebook Drawing Functions:
2283 * gtk_notebook_paint
2284 * gtk_notebook_draw_tab
2285 * gtk_notebook_draw_arrow
2286 * gtk_notebook_set_shape
2289 gtk_notebook_paint (GtkWidget *widget,
2292 GtkNotebook *notebook;
2293 GtkNotebookPage *page;
2298 gint gap_x = 0, gap_width = 0;
2300 g_return_if_fail (widget != NULL);
2301 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2302 g_return_if_fail (area != NULL);
2304 if (!GTK_WIDGET_DRAWABLE (widget))
2307 notebook = GTK_NOTEBOOK (widget);
2309 if ((!notebook->show_tabs && !notebook->show_border) ||
2310 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2312 gdk_window_clear_area (widget->window,
2314 area->width, area->height);
2318 x = GTK_CONTAINER (widget)->border_width;
2319 y = GTK_CONTAINER (widget)->border_width;
2320 width = widget->allocation.width - x * 2;
2321 height = widget->allocation.height - y * 2;
2323 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2325 gtk_paint_box (widget->style, widget->window,
2326 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2327 area, widget, "notebook",
2328 x, y, width, height);
2333 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2335 page = notebook->first_tab->data;
2337 switch (notebook->tab_pos)
2340 y += page->allocation.height + widget->style->ythickness;
2341 case GTK_POS_BOTTOM:
2342 height -= page->allocation.height + widget->style->ythickness;
2345 x += page->allocation.width + widget->style->xthickness;
2347 width -= page->allocation.width + widget->style->xthickness;
2350 gtk_paint_box (widget->style, widget->window,
2351 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2352 area, widget, "notebook",
2353 x, y, width, height);
2357 switch (notebook->tab_pos)
2360 y += notebook->cur_page->allocation.height;
2361 case GTK_POS_BOTTOM:
2362 height -= notebook->cur_page->allocation.height;
2365 x += notebook->cur_page->allocation.width;
2367 width -= notebook->cur_page->allocation.width;
2371 switch (notebook->tab_pos)
2374 gap_x = (notebook->cur_page->allocation.x -
2375 GTK_CONTAINER(notebook)->border_width);
2376 gap_width = notebook->cur_page->allocation.width;
2378 case GTK_POS_BOTTOM:
2379 gap_x = (notebook->cur_page->allocation.x -
2380 GTK_CONTAINER(notebook)->border_width);
2381 gap_width = notebook->cur_page->allocation.width;
2384 gap_x = (notebook->cur_page->allocation.y -
2385 GTK_CONTAINER(notebook)->border_width);
2386 gap_width = notebook->cur_page->allocation.height;
2389 gap_x = (notebook->cur_page->allocation.y -
2390 GTK_CONTAINER(notebook)->border_width);
2391 gap_width = notebook->cur_page->allocation.height;
2394 gtk_paint_box_gap(widget->style, widget->window,
2395 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2396 area, widget, "notebook",
2397 x, y, width, height,
2398 notebook->tab_pos, gap_x, gap_width);
2402 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2405 page = children->data;
2406 children = gtk_notebook_search_page (notebook, children,
2408 if (!GTK_WIDGET_VISIBLE (page->child))
2410 if (!GTK_WIDGET_MAPPED (page->tab_label))
2412 else if (page != notebook->cur_page)
2413 gtk_notebook_draw_tab (notebook, page, area);
2416 if (showarrow && notebook->scrollable)
2418 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2419 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2421 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2425 gtk_notebook_draw_tab (GtkNotebook *notebook,
2426 GtkNotebookPage *page,
2429 GdkRectangle child_area;
2430 GdkRectangle page_area;
2431 GtkStateType state_type;
2432 GtkPositionType gap_side;
2434 g_return_if_fail (notebook != NULL);
2435 g_return_if_fail (page != NULL);
2436 g_return_if_fail (area != NULL);
2438 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2439 (page->allocation.width == 0) || (page->allocation.height == 0))
2442 page_area.x = page->allocation.x;
2443 page_area.y = page->allocation.y;
2444 page_area.width = page->allocation.width;
2445 page_area.height = page->allocation.height;
2447 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2451 widget = GTK_WIDGET (notebook);
2453 switch (notebook->tab_pos)
2456 gap_side = GTK_POS_BOTTOM;
2458 case GTK_POS_BOTTOM:
2459 gap_side = GTK_POS_TOP;
2462 gap_side = GTK_POS_RIGHT;
2465 gap_side = GTK_POS_LEFT;
2469 if (notebook->cur_page == page)
2470 state_type = GTK_STATE_NORMAL;
2472 state_type = GTK_STATE_ACTIVE;
2473 gtk_paint_extension(widget->style, widget->window,
2474 state_type, GTK_SHADOW_OUT,
2475 area, widget, "tab",
2476 page_area.x, page_area.y,
2477 page_area.width, page_area.height,
2479 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2480 notebook->focus_tab && (notebook->focus_tab->data == page))
2482 gtk_paint_focus (widget->style, widget->window,
2483 area, widget, "tab",
2484 page->tab_label->allocation.x - 1,
2485 page->tab_label->allocation.y - 1,
2486 page->tab_label->allocation.width + 1,
2487 page->tab_label->allocation.height + 1);
2489 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2490 GTK_WIDGET_DRAWABLE (page->tab_label))
2492 GdkEventExpose expose_event;
2494 /* This is a lame hack since all this code needs rewriting anyhow */
2496 expose_event.window = page->tab_label->window;
2497 expose_event.area = child_area;
2498 expose_event.region = gdk_region_rectangle (&child_area);
2499 expose_event.send_event = TRUE;
2500 expose_event.type = GDK_EXPOSE;
2501 expose_event.count = 0;
2503 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
2505 gdk_region_destroy (expose_event.region);
2511 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2514 GtkStateType state_type;
2515 GtkShadowType shadow_type;
2518 g_return_if_fail (notebook != NULL);
2519 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2521 widget = GTK_WIDGET(notebook);
2523 if (GTK_WIDGET_DRAWABLE (notebook))
2525 if (notebook->in_child == arrow)
2527 if (notebook->click_child == arrow)
2528 state_type = GTK_STATE_ACTIVE;
2530 state_type = GTK_STATE_PRELIGHT;
2533 state_type = GTK_STATE_NORMAL;
2535 if (notebook->click_child == arrow)
2536 shadow_type = GTK_SHADOW_IN;
2538 shadow_type = GTK_SHADOW_OUT;
2540 if (arrow == GTK_ARROW_LEFT)
2542 if (notebook->focus_tab &&
2543 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2546 shadow_type = GTK_SHADOW_ETCHED_IN;
2547 state_type = GTK_STATE_NORMAL;
2550 if (notebook->tab_pos == GTK_POS_LEFT ||
2551 notebook->tab_pos == GTK_POS_RIGHT)
2552 arrow = GTK_ARROW_UP;
2554 gdk_window_clear_area (notebook->panel, 0, 0, ARROW_SIZE, ARROW_SIZE);
2555 gtk_paint_arrow (widget->style, notebook->panel, state_type,
2556 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2558 0, 0, ARROW_SIZE, ARROW_SIZE);
2562 if (notebook->focus_tab &&
2563 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2566 shadow_type = GTK_SHADOW_ETCHED_IN;
2567 state_type = GTK_STATE_NORMAL;
2570 if (notebook->tab_pos == GTK_POS_LEFT ||
2571 notebook->tab_pos == GTK_POS_RIGHT)
2572 arrow = GTK_ARROW_DOWN;
2574 gdk_window_clear_area(notebook->panel, ARROW_SIZE + ARROW_SPACING,
2575 0, ARROW_SIZE, ARROW_SIZE);
2576 gtk_paint_arrow (widget->style, notebook->panel, state_type,
2577 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2578 arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2579 0, ARROW_SIZE, ARROW_SIZE);
2585 gtk_notebook_set_shape (GtkNotebook *notebook)
2587 GtkWidget *widget = NULL;
2588 GdkPixmap *pm = NULL;
2591 gint x, y, width, height, w, h, depth;
2592 GtkNotebookPage *page;
2595 if (!GTK_WIDGET(notebook)->window)
2598 widget = GTK_WIDGET(notebook);
2600 w = widget->allocation.width;
2601 h = widget->allocation.height;
2603 pm = gdk_pixmap_new (widget->window, w, h, 1);
2604 pmgc = gdk_gc_new (pm);
2606 /* clear the shape mask */
2608 gdk_gc_set_foreground(pmgc, &col);
2609 gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, w, h);
2612 gdk_gc_set_foreground(pmgc, &col);
2614 /* draw the shape for the notebook page itself */
2615 x = GTK_CONTAINER(notebook)->border_width;
2616 y = GTK_CONTAINER(notebook)->border_width;
2617 width = widget->allocation.width - x * 2;
2618 height = widget->allocation.height - y * 2;
2620 if (notebook->show_tabs && notebook->children)
2622 if (!(notebook->show_tabs))
2624 page = notebook->first_tab->data;
2625 switch (notebook->tab_pos)
2628 y += page->allocation.height +
2629 widget->style->ythickness;
2630 case GTK_POS_BOTTOM:
2631 height -= page->allocation.height +
2632 widget->style->ythickness;
2635 x += page->allocation.width +
2636 widget->style->xthickness;
2638 width -= page->allocation.width +
2639 widget->style->xthickness;
2645 if (notebook->cur_page)
2646 page = notebook->cur_page;
2648 page = notebook->children->data;
2650 if (!GTK_WIDGET_MAPPED (page->tab_label))
2652 if (notebook->tab_pos == GTK_POS_LEFT)
2654 x -= widget->style->xthickness * 2;
2655 width += widget->style->xthickness * 2;
2657 else if (notebook->tab_pos == GTK_POS_RIGHT)
2658 width += widget->style->xthickness * 2;
2660 switch (notebook->tab_pos)
2663 y += page->allocation.height;
2664 case GTK_POS_BOTTOM:
2665 height -= page->allocation.height;
2668 x += page->allocation.width;
2670 width -= page->allocation.width;
2675 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2677 /* if theres an area for scrolling arrows draw the shape for them */
2678 if (notebook->panel && gdk_window_is_visible (notebook->panel))
2680 gdk_window_get_geometry(notebook->panel, &x, &y, &width, &height, &depth);
2681 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2684 /* draw the shapes of all the children */
2685 if (notebook->show_tabs)
2687 children = notebook->children;
2690 page = children->data;
2691 if (GTK_WIDGET_MAPPED (page->tab_label))
2693 x = page->allocation.x;
2694 y = page->allocation.y;
2695 width = page->allocation.width;
2696 height = page->allocation.height;
2697 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2699 children = children->next;
2704 gdk_window_shape_combine_mask(widget->window, pm, 0, 0);
2705 gdk_pixmap_unref(pm);
2706 gdk_gc_destroy(pmgc);
2709 /* Private GtkNotebook Size Allocate Functions:
2711 * gtk_notebook_pages_allocate
2712 * gtk_notebook_page_allocate
2713 * gtk_notebook_calc_tabs
2716 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2718 GtkWidget *widget = GTK_WIDGET (notebook);
2719 GtkContainer *container = GTK_CONTAINER (notebook);
2720 GtkNotebookPage *page = NULL;
2721 GtkAllocation *allocation = &widget->allocation;
2722 GtkAllocation child_allocation;
2723 GList *children = NULL;
2724 GList *last_child = NULL;
2725 gboolean showarrow = FALSE;
2735 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2738 child_allocation.x = container->border_width;
2739 child_allocation.y = container->border_width;
2741 switch (notebook->tab_pos)
2743 case GTK_POS_BOTTOM:
2744 child_allocation.y = (allocation->height -
2745 notebook->cur_page->requisition.height -
2746 container->border_width);
2749 child_allocation.height = notebook->cur_page->requisition.height;
2753 child_allocation.x = (allocation->width -
2754 notebook->cur_page->requisition.width -
2755 container->border_width);
2758 child_allocation.width = notebook->cur_page->requisition.width;
2762 if (notebook->scrollable)
2766 children = notebook->children;
2768 if (notebook->focus_tab)
2769 focus_tab = notebook->focus_tab;
2770 else if (notebook->first_tab)
2771 focus_tab = notebook->first_tab;
2773 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2775 switch (notebook->tab_pos)
2778 case GTK_POS_BOTTOM:
2781 page = children->data;
2782 children = children->next;
2784 if (GTK_WIDGET_VISIBLE (page->child))
2785 tab_space += page->requisition.width;
2788 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2791 page = focus_tab->data;
2793 tab_space = (allocation->width - TAB_OVERLAP -
2794 page->requisition.width -
2795 2 * (container->border_width + ARROW_SPACING +
2797 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2798 container->border_width);
2800 page = notebook->children->data;
2801 if (notebook->tab_pos == GTK_POS_TOP)
2802 y = (container->border_width +
2803 (page->requisition.height - ARROW_SIZE) / 2);
2805 y = (allocation->height - container->border_width -
2806 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2813 page = children->data;
2814 children = children->next;
2816 if (GTK_WIDGET_VISIBLE (page->child))
2817 tab_space += page->requisition.height;
2820 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2823 page = focus_tab->data;
2824 tab_space = (allocation->height -
2825 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2826 2 * container->border_width -
2827 page->requisition.height);
2828 y = allocation->height - container->border_width - ARROW_SIZE;
2830 page = notebook->children->data;
2831 if (notebook->tab_pos == GTK_POS_LEFT)
2832 x = (container->border_width +
2833 (page->requisition.width -
2834 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2836 x = (allocation->width - container->border_width -
2837 (2 * ARROW_SIZE - ARROW_SPACING) -
2838 (page->requisition.width -
2839 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2843 if (showarrow) /* first_tab <- focus_tab */
2847 notebook->first_tab = focus_tab;
2848 last_child = gtk_notebook_search_page (notebook, focus_tab,
2854 if (notebook->first_tab && notebook->first_tab != focus_tab)
2856 /* Is first_tab really predecessor of focus_tab ? */
2857 page = notebook->first_tab->data;
2858 if (GTK_WIDGET_VISIBLE (page->child))
2859 for (children = focus_tab;
2860 children && children != notebook->first_tab;
2861 children = gtk_notebook_search_page (notebook,
2867 notebook->first_tab = focus_tab;
2869 gtk_notebook_calc_tabs (notebook,
2870 gtk_notebook_search_page (notebook,
2874 &(notebook->first_tab), &tab_space,
2879 notebook->first_tab =
2880 gtk_notebook_search_page (notebook, notebook->first_tab,
2882 if (!notebook->first_tab)
2883 notebook->first_tab = focus_tab;
2884 last_child = gtk_notebook_search_page (notebook, focus_tab,
2887 else /* focus_tab -> end */
2889 if (!notebook->first_tab)
2890 notebook->first_tab = gtk_notebook_search_page (notebook,
2895 gtk_notebook_calc_tabs (notebook,
2896 gtk_notebook_search_page (notebook,
2900 &children, &tab_space, STEP_NEXT);
2903 last_child = children;
2904 else /* start <- first_tab */
2908 gtk_notebook_calc_tabs
2910 gtk_notebook_search_page (notebook,
2911 notebook->first_tab,
2914 &children, &tab_space, STEP_PREV);
2915 notebook->first_tab = gtk_notebook_search_page(notebook,
2923 if (GTK_WIDGET_REALIZED (notebook))
2925 gdk_window_move (notebook->panel, x, y);
2926 gdk_window_show (notebook->panel);
2931 tab_space = -tab_space;
2933 for (children = notebook->first_tab;
2934 children && children != last_child;
2935 children = gtk_notebook_search_page (notebook, children,
2942 /*unmap all non-visible tabs*/
2943 for (children = gtk_notebook_search_page (notebook, NULL,
2945 children && children != notebook->first_tab;
2946 children = gtk_notebook_search_page (notebook, children,
2949 page = children->data;
2950 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2951 gtk_widget_unmap (page->tab_label);
2953 for (children = last_child; children;
2954 children = gtk_notebook_search_page (notebook, children,
2957 page = children->data;
2958 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2959 gtk_widget_unmap (page->tab_label);
2962 else /* !showarrow */
2964 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2967 if (GTK_WIDGET_REALIZED (notebook))
2968 gdk_window_hide (notebook->panel);
2977 children = notebook->children;
2978 switch (notebook->tab_pos)
2981 case GTK_POS_BOTTOM:
2984 page = children->data;
2985 children = children->next;
2987 if (GTK_WIDGET_VISIBLE (page->child))
2990 tab_space += page->requisition.width;
2995 tab_space -= allocation->width;
3001 page = children->data;
3002 children = children->next;
3004 if (GTK_WIDGET_VISIBLE (page->child))
3007 tab_space += page->requisition.height;
3012 tab_space -= allocation->height;
3014 tab_space += 2 * container->border_width + TAB_OVERLAP;
3016 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3018 if (notebook->homogeneous && n)
3022 children = notebook->first_tab;
3026 if (children == last_child)
3028 /* FIXME double check */
3032 page = children->data;
3033 if (!showarrow && page->pack != GTK_PACK_START)
3035 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3038 if (n && (showarrow || page->expand || notebook->homogeneous))
3040 new_fill = (tab_space * i++) / n;
3041 delta = new_fill - old_fill;
3042 old_fill = new_fill;
3045 switch (notebook->tab_pos)
3048 case GTK_POS_BOTTOM:
3049 child_allocation.width = (page->requisition.width +
3050 TAB_OVERLAP + delta);
3054 child_allocation.height = (page->requisition.height +
3055 TAB_OVERLAP + delta);
3059 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3061 switch (notebook->tab_pos)
3064 case GTK_POS_BOTTOM:
3065 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3069 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3073 if (GTK_WIDGET_REALIZED (notebook) &&
3074 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
3076 if (GTK_WIDGET_VISIBLE (page->tab_label))
3077 gtk_widget_map (page->tab_label);
3079 gtk_widget_show (page->tab_label);
3085 children = notebook->children;
3086 switch (notebook->tab_pos)
3089 case GTK_POS_BOTTOM:
3090 child_allocation.x = (allocation->x + allocation->width -
3091 container->border_width);
3095 child_allocation.y = (allocation->y + allocation->height -
3096 container->border_width);
3100 while (children != last_child)
3102 page = children->data;
3103 children = children->next;
3105 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3109 if (n && (page->expand || notebook->homogeneous))
3111 new_fill = (tab_space * i++) / n;
3112 delta = new_fill - old_fill;
3113 old_fill = new_fill;
3116 switch (notebook->tab_pos)
3119 case GTK_POS_BOTTOM:
3120 child_allocation.width = (page->requisition.width +
3121 TAB_OVERLAP + delta);
3122 child_allocation.x -= child_allocation.width;
3126 child_allocation.height = (page->requisition.height +
3127 TAB_OVERLAP + delta);
3128 child_allocation.y -= child_allocation.height;
3132 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3134 switch (notebook->tab_pos)
3137 case GTK_POS_BOTTOM:
3138 child_allocation.x += TAB_OVERLAP;
3142 child_allocation.y += TAB_OVERLAP;
3146 if (GTK_WIDGET_REALIZED (notebook) && page->tab_label &&
3147 !GTK_WIDGET_MAPPED (page->tab_label))
3149 if (GTK_WIDGET_VISIBLE (page->tab_label))
3150 gtk_widget_map (page->tab_label);
3152 gtk_widget_show (page->tab_label);
3158 gtk_notebook_set_shape (notebook);
3159 gtk_notebook_redraw_tabs (notebook);
3163 gtk_notebook_page_allocate (GtkNotebook *notebook,
3164 GtkNotebookPage *page,
3165 GtkAllocation *allocation)
3168 GtkAllocation child_allocation;
3169 GtkRequisition tab_requisition;
3174 g_return_if_fail (notebook != NULL);
3175 g_return_if_fail (page != NULL);
3176 g_return_if_fail (allocation != NULL);
3178 widget = GTK_WIDGET (notebook);
3180 xthickness = widget->style->xthickness;
3181 ythickness = widget->style->ythickness;
3183 /* If the size of the notebook tabs change, we need to queue
3184 * a redraw on the tab area
3186 if ((allocation->width != page->allocation.width) ||
3187 (allocation->height != page->allocation.height))
3189 gint x, y, width, height, border_width;
3191 border_width = GTK_CONTAINER (notebook)->border_width;
3193 switch (notebook->tab_pos)
3196 width = widget->allocation.width;
3197 height = MAX (page->allocation.height, allocation->height) + ythickness;
3202 case GTK_POS_BOTTOM:
3203 width = widget->allocation.width + xthickness;
3204 height = MAX (page->allocation.height, allocation->height) + ythickness;
3206 y = widget->allocation.height - height - border_width;
3210 width = MAX (page->allocation.width, allocation->width) + xthickness;
3211 height = widget->allocation.height;
3217 default: /* quiet gcc */
3218 width = MAX (page->allocation.width, allocation->width) + xthickness;
3219 height = widget->allocation.height;
3220 x = widget->allocation.width - width - border_width;
3225 gtk_widget_queue_clear_area (widget, x, y, width, height);
3228 page->allocation = *allocation;
3229 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3231 if (notebook->cur_page != page)
3233 switch (notebook->tab_pos)
3236 page->allocation.y += ythickness;
3237 case GTK_POS_BOTTOM:
3238 if (page->allocation.height > ythickness)
3239 page->allocation.height -= ythickness;
3242 page->allocation.x += xthickness;
3244 if (page->allocation.width > xthickness)
3245 page->allocation.width -= xthickness;
3250 switch (notebook->tab_pos)
3253 case GTK_POS_BOTTOM:
3254 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_hborder;
3257 child_allocation.x = (xthickness + FOCUS_WIDTH +
3258 notebook->tab_hborder);
3259 child_allocation.width = MAX (1, (((gint) page->allocation.width) -
3260 2 * child_allocation.x));
3261 child_allocation.x += page->allocation.x;
3265 child_allocation.x = (page->allocation.x +
3266 (page->allocation.width -
3267 tab_requisition.width) / 2);
3268 child_allocation.width = tab_requisition.width;
3270 child_allocation.y = (notebook->tab_vborder + FOCUS_WIDTH +
3271 page->allocation.y);
3272 if (notebook->tab_pos == GTK_POS_TOP)
3273 child_allocation.y += ythickness;
3274 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3275 2 * (notebook->tab_vborder + FOCUS_WIDTH)));
3279 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_vborder;
3282 child_allocation.y = ythickness + padding;
3283 child_allocation.height = MAX (1, (((gint) page->allocation.height) -
3284 2 * child_allocation.y));
3285 child_allocation.y += page->allocation.y;
3289 child_allocation.y = (page->allocation.y + (page->allocation.height -
3290 tab_requisition.height) / 2);
3291 child_allocation.height = tab_requisition.height;
3293 child_allocation.x = page->allocation.x + notebook->tab_hborder + FOCUS_WIDTH;
3294 if (notebook->tab_pos == GTK_POS_LEFT)
3295 child_allocation.x += xthickness;
3296 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3297 2 * (notebook->tab_hborder + FOCUS_WIDTH)));
3301 if (page->tab_label)
3302 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3306 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3312 GtkNotebookPage *page = NULL;
3314 GList *last_list = NULL;
3321 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3322 if (pack == GTK_PACK_END)
3323 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3327 switch (notebook->tab_pos)
3330 case GTK_POS_BOTTOM:
3333 page = children->data;
3334 if (GTK_WIDGET_VISIBLE (page->child))
3336 if (page->pack == pack)
3338 *tab_space -= page->requisition.width;
3339 if (*tab_space < 0 || children == *end)
3343 *tab_space = - (*tab_space +
3344 page->requisition.width);
3350 last_list = children;
3352 if (direction == STEP_NEXT)
3353 children = children->next;
3355 children = children->prev;
3362 page = children->data;
3363 if (GTK_WIDGET_VISIBLE (page->child))
3365 if (page->pack == pack)
3367 *tab_space -= page->requisition.height;
3368 if (*tab_space < 0 || children == *end)
3372 *tab_space = - (*tab_space +
3373 page->requisition.height);
3379 last_list = children;
3381 if (direction == STEP_NEXT)
3382 children = children->next;
3384 children = children->prev;
3388 if (direction == STEP_PREV)
3390 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3391 direction = STEP_PREV;
3392 children = last_list;
3396 /* Private GtkNotebook Page Switch Methods:
3398 * gtk_notebook_real_switch_page
3401 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3402 GtkNotebookPage *page,
3405 g_return_if_fail (notebook != NULL);
3406 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3407 g_return_if_fail (page != NULL);
3409 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3412 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
3413 gtk_widget_unmap (notebook->cur_page->child);
3415 notebook->cur_page = page;
3417 if (!notebook->focus_tab ||
3418 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3419 notebook->focus_tab =
3420 g_list_find (notebook->children, notebook->cur_page);
3422 if (GTK_WIDGET_MAPPED (notebook))
3423 gtk_widget_map (notebook->cur_page->child);
3425 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3426 g_object_notify (G_OBJECT (notebook), "page");
3429 /* Private GtkNotebook Page Switch Functions:
3431 * gtk_notebook_switch_page
3432 * gtk_notebook_page_select
3433 * gtk_notebook_switch_focus_tab
3434 * gtk_notebook_menu_switch_page
3437 gtk_notebook_switch_page (GtkNotebook *notebook,
3438 GtkNotebookPage *page,
3441 g_return_if_fail (notebook != NULL);
3442 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3443 g_return_if_fail (page != NULL);
3445 if (notebook->cur_page == page)
3449 page_num = g_list_index (notebook->children, page);
3451 gtk_signal_emit (GTK_OBJECT (notebook),
3452 notebook_signals[SWITCH_PAGE],
3458 gtk_notebook_page_select (GtkNotebook *notebook,
3459 gboolean move_focus)
3461 GtkNotebookPage *page;
3462 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3464 g_return_val_if_fail (notebook != NULL, FALSE);
3465 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3467 if (!notebook->focus_tab)
3470 page = notebook->focus_tab->data;
3471 gtk_notebook_switch_page (notebook, page, -1);
3475 switch (notebook->tab_pos)
3480 case GTK_POS_BOTTOM:
3484 dir = GTK_DIR_RIGHT;
3491 if (gtk_widget_child_focus (page->child, dir))
3498 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3502 GtkNotebookPage *old_page = NULL;
3503 GtkNotebookPage *page;
3505 g_return_if_fail (notebook != NULL);
3506 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3508 if (notebook->focus_tab == new_child)
3511 old_child = notebook->focus_tab;
3512 notebook->focus_tab = new_child;
3514 if (notebook->scrollable && GTK_WIDGET_DRAWABLE (notebook))
3515 gtk_notebook_redraw_arrows (notebook);
3517 if (!notebook->show_tabs || !notebook->focus_tab)
3521 old_page = old_child->data;
3523 page = notebook->focus_tab->data;
3524 if (GTK_WIDGET_MAPPED (page->tab_label))
3525 gtk_notebook_focus_changed (notebook, old_page);
3527 gtk_notebook_pages_allocate (notebook);
3529 gtk_notebook_set_shape (notebook);
3533 gtk_notebook_menu_switch_page (GtkWidget *widget,
3534 GtkNotebookPage *page)
3536 GtkNotebook *notebook;
3540 g_return_if_fail (widget != NULL);
3541 g_return_if_fail (page != NULL);
3543 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3544 (GTK_MENU (widget->parent)));
3546 if (notebook->cur_page == page)
3550 children = notebook->children;
3551 while (children && children->data != page)
3553 children = children->next;
3557 gtk_signal_emit (GTK_OBJECT (notebook),
3558 notebook_signals[SWITCH_PAGE],
3563 /* Private GtkNotebook Menu Functions:
3565 * gtk_notebook_menu_item_create
3566 * gtk_notebook_menu_label_unparent
3567 * gtk_notebook_menu_detacher
3570 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3573 GtkNotebookPage *page;
3574 GtkWidget *menu_item;
3577 if (page->default_menu)
3579 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3580 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3582 page->menu_label = gtk_label_new ("");
3583 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3586 gtk_widget_show (page->menu_label);
3587 menu_item = gtk_menu_item_new ();
3588 gtk_widget_lock_accelerators (menu_item);
3589 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3590 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3591 gtk_notebook_real_page_position (notebook, list));
3592 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3593 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3594 if (GTK_WIDGET_VISIBLE (page->child))
3595 gtk_widget_show (menu_item);
3599 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3602 gtk_widget_unparent (GTK_BIN(widget)->child);
3603 GTK_BIN(widget)->child = NULL;
3607 gtk_notebook_menu_detacher (GtkWidget *widget,
3610 GtkNotebook *notebook;
3612 g_return_if_fail (widget != NULL);
3613 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3615 notebook = GTK_NOTEBOOK (widget);
3616 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3618 notebook->menu = NULL;
3621 /* Public GtkNotebook Page Insert/Remove Methods :
3623 * gtk_notebook_append_page
3624 * gtk_notebook_append_page_menu
3625 * gtk_notebook_prepend_page
3626 * gtk_notebook_prepend_page_menu
3627 * gtk_notebook_insert_page
3628 * gtk_notebook_insert_page_menu
3629 * gtk_notebook_remove_page
3632 * gtk_notebook_append_page:
3633 * @notebook: a #GtkNotebook
3634 * @child: the #GtkWidget to use as the contents of the page.
3635 * @tab_label: the #GtkWidget to be used as the label for the page,
3636 * or %NULL to use the default label, 'page N'.
3638 * Appends a page to @notebook.
3641 gtk_notebook_append_page (GtkNotebook *notebook,
3643 GtkWidget *tab_label)
3645 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3646 g_return_if_fail (GTK_IS_WIDGET (child));
3647 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3649 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3653 * gtk_notebook_append_page_menu:
3654 * @notebook: a #GtkNotebook
3655 * @child: the #GtkWidget to use as the contents of the page.
3656 * @tab_label: the #GtkWidget to be used as the label for the page,
3657 * or %NULL to use the default label, 'page N'.
3658 * @menu_label: the widget to use as a label for the page-switch
3659 * menu, if that is enabled. If %NULL, and @tab_label
3660 * is a #GtkLabel or %NULL, then the menu label will be
3661 * a newly created label with the same text as @tab_label;
3662 * If @tab_label is not a #GtkLabel, @menu_label must be
3663 * specified if the page-switch menu is to be used.
3665 * Appends a page to @notebook, specifying the widget to use as the
3666 * label in the popup menu.
3669 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3671 GtkWidget *tab_label,
3672 GtkWidget *menu_label)
3674 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3675 g_return_if_fail (GTK_IS_WIDGET (child));
3676 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3677 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3679 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3683 * gtk_notebook_prepend_page:
3684 * @notebook: a #GtkNotebook
3685 * @child: the #GtkWidget to use as the contents of the page.
3686 * @tab_label: the #GtkWidget to be used as the label for the page,
3687 * or %NULL to use the default label, 'page N'.
3689 * Prepends a page to @noteobook.
3692 gtk_notebook_prepend_page (GtkNotebook *notebook,
3694 GtkWidget *tab_label)
3696 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3697 g_return_if_fail (GTK_IS_WIDGET (child));
3698 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3700 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3704 * gtk_notebook_prepend_page_menu:
3705 * @notebook: a #GtkNotebook
3706 * @child: the #GtkWidget to use as the contents of the page.
3707 * @tab_label: the #GtkWidget to be used as the label for the page,
3708 * or %NULL to use the default label, 'page N'.
3709 * @menu_label: the widget to use as a label for the page-switch
3710 * menu, if that is enabled. If %NULL, and @tab_label
3711 * is a #GtkLabel or %NULL, then the menu label will be
3712 * a newly created label with the same text as @tab_label;
3713 * If @tab_label is not a #GtkLabel, @menu_label must be
3714 * specified if the page-switch menu is to be used.
3716 * Prepends a page to @notebook, specifying the widget to use as the
3717 * label in the popup menu.
3720 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3722 GtkWidget *tab_label,
3723 GtkWidget *menu_label)
3725 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3726 g_return_if_fail (GTK_IS_WIDGET (child));
3727 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3728 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3730 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3734 * gtk_notebook_insert_page:
3735 * @notebook: a #GtkNotebook
3736 * @child: the #GtkWidget to use as the contents of the page.
3737 * @tab_label: the #GtkWidget to be used as the label for the page,
3738 * or %NULL to use the default label, 'page N'.
3739 * @position: the index (starting at 0) at which to insert the page,
3740 * or -1 to append the page after all other pages.
3742 * Insert a page into @notebook at the given position
3745 gtk_notebook_insert_page (GtkNotebook *notebook,
3747 GtkWidget *tab_label,
3750 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3751 g_return_if_fail (GTK_IS_WIDGET (child));
3752 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3754 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3759 gtk_notebook_page_compare_tab (gconstpointer a,
3762 return (((GtkNotebookPage *) a)->tab_label != b);
3766 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3770 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3773 list = g_list_find_custom (notebook->children, child,
3774 gtk_notebook_page_compare_tab);
3777 GtkNotebookPage *page = list->data;
3779 gtk_notebook_switch_page (notebook, page, -1);
3786 * gtk_notebook_insert_page_menu:
3787 * @notebook: a #GtkNotebook
3788 * @child: the #GtkWidget to use as the contents of the page.
3789 * @tab_label: the #GtkWidget to be used as the label for the page,
3790 * or %NULL to use the default label, 'page N'.
3791 * @menu_label: the widget to use as a label for the page-switch
3792 * menu, if that is enabled. If %NULL, and @tab_label
3793 * is a #GtkLabel or %NULL, then the menu label will be
3794 * a newly created label with the same text as @tab_label;
3795 * If @tab_label is not a #GtkLabel, @menu_label must be
3796 * specified if the page-switch menu is to be used.
3797 * @position: the index (starting at 0) at which to insert the page,
3798 * or -1 to append the page after all other pages.
3800 * Insert a page into @notebook at the given position, specifying
3801 * the widget to use as the label in the popup menu.
3804 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3806 GtkWidget *tab_label,
3807 GtkWidget *menu_label,
3810 GtkNotebookPage *page;
3813 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3814 g_return_if_fail (GTK_IS_WIDGET (child));
3815 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3816 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3818 gtk_widget_freeze_child_notify (child);
3820 page = g_new (GtkNotebookPage, 1);
3821 page->child = child;
3822 page->requisition.width = 0;
3823 page->requisition.height = 0;
3824 page->allocation.x = 0;
3825 page->allocation.y = 0;
3826 page->allocation.width = 0;
3827 page->allocation.height = 0;
3828 page->default_menu = FALSE;
3829 page->default_tab = FALSE;
3830 page->mnemonic_activate_signal = 0;
3832 nchildren = g_list_length (notebook->children);
3833 if ((position < 0) || (position > nchildren))
3834 position = nchildren;
3836 notebook->children = g_list_insert (notebook->children, page, position);
3840 page->default_tab = TRUE;
3841 if (notebook->show_tabs)
3842 tab_label = gtk_label_new ("");
3844 page->tab_label = tab_label;
3845 page->menu_label = menu_label;
3846 page->expand = FALSE;
3848 page->pack = GTK_PACK_START;
3851 page->default_menu = TRUE;
3854 gtk_widget_ref (page->menu_label);
3855 gtk_object_sink (GTK_OBJECT (page->menu_label));
3859 gtk_notebook_menu_item_create (notebook,
3860 g_list_find (notebook->children, page));
3862 gtk_notebook_update_labels (notebook);
3864 if (!notebook->first_tab)
3865 notebook->first_tab = notebook->children;
3867 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3869 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3871 if (!notebook->cur_page)
3873 gtk_notebook_switch_page (notebook, page, 0);
3874 gtk_notebook_switch_focus_tab (notebook, NULL);
3877 if (GTK_WIDGET_REALIZED (child->parent))
3878 gtk_widget_realize (child);
3880 if (GTK_WIDGET_VISIBLE (notebook))
3882 if (GTK_WIDGET_VISIBLE (child))
3884 if (GTK_WIDGET_MAPPED (notebook) &&
3885 !GTK_WIDGET_MAPPED (child) &&
3886 notebook->cur_page == page)
3887 gtk_widget_map (child);
3889 gtk_widget_queue_resize (child);
3894 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3896 if (!GTK_WIDGET_VISIBLE (tab_label))
3897 gtk_widget_show (tab_label);
3899 if (GTK_WIDGET_REALIZED (notebook) &&
3900 !GTK_WIDGET_REALIZED (tab_label))
3901 gtk_widget_realize (tab_label);
3903 if (GTK_WIDGET_MAPPED (notebook) &&
3904 !GTK_WIDGET_MAPPED (tab_label))
3905 gtk_widget_map (tab_label);
3907 else if (GTK_WIDGET_VISIBLE (tab_label))
3908 gtk_widget_hide (tab_label);
3913 page->mnemonic_activate_signal =
3914 gtk_signal_connect (GTK_OBJECT (tab_label),
3915 "mnemonic_activate",
3916 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
3919 gtk_widget_child_notify (child, "tab_expand");
3920 gtk_widget_child_notify (child, "tab_fill");
3921 gtk_widget_child_notify (child, "tab_pack");
3922 gtk_widget_child_notify (child, "tab_label");
3923 gtk_widget_child_notify (child, "menu_label");
3924 gtk_widget_child_notify (child, "position");
3925 gtk_widget_thaw_child_notify (child);
3929 * gtk_notebook_remove_page:
3930 * @notebook: a #GtkNotebook.
3931 * @page_num: the index of a notebook page, starting
3932 * from 0. If -1, the last page will
3935 * Removes a page from the notebook given its index
3939 gtk_notebook_remove_page (GtkNotebook *notebook,
3944 g_return_if_fail (notebook != NULL);
3945 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3949 list = g_list_nth (notebook->children, page_num);
3951 gtk_notebook_real_remove (notebook, list);
3955 list = g_list_last (notebook->children);
3957 gtk_notebook_real_remove (notebook, list);
3961 /* Public GtkNotebook Page Switch Methods :
3962 * gtk_notebook_get_current_page
3963 * gtk_notebook_page_num
3964 * gtk_notebook_set_current_page
3965 * gtk_notebook_next_page
3966 * gtk_notebook_prev_page
3969 * gtk_notebook_get_current_page:
3970 * @notebook: a #GtkNotebook
3972 * Returns the page number of the current page.
3974 * Return value: the index (starting from 0) of the current
3975 * page in the notebook. If the notebook has no pages, then
3976 * -1 will be returned.
3979 gtk_notebook_get_current_page (GtkNotebook *notebook)
3981 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3983 if (!notebook->cur_page)
3986 return g_list_index (notebook->children, notebook->cur_page);
3990 * gtk_notebook_get_nth_page:
3991 * @notebook: a #GtkNotebook
3992 * @page_num: the index of a page in the noteobok
3994 * Returns the child widget contained in page number @page_num.
3996 * Return value: the child widget, or %NULL if @page_num is
4000 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4003 GtkNotebookPage *page;
4005 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4007 page = g_list_nth_data (notebook->children, page_num);
4016 * gtk_notebook_page_num:
4017 * @notebook: a #GtkNotebook
4018 * @child: a #GtkWidget
4020 * Finds the index of the page which contains the given child
4023 * Return value: the index of the page containing @child, or
4024 * -1 if @child is not in the notebook.
4027 gtk_notebook_page_num (GtkNotebook *notebook,
4033 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4036 children = notebook->children;
4039 GtkNotebookPage *page = children->data;
4041 if (page->child == child)
4044 children = children->next;
4052 * gtk_notebook_set_current_page:
4053 * @notebook: a #GtkNotebook
4054 * @page_num: index of the page to switch to, starting from 0.
4055 * If negative, or greater than the number of pages
4056 * in the notebook the last page will be used.
4058 * Switches to the page number @page_num.
4061 gtk_notebook_set_current_page (GtkNotebook *notebook,
4066 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4069 list = g_list_nth (notebook->children, page_num);
4071 list = g_list_last (notebook->children);
4073 page_num = g_list_index (notebook->children, list);
4076 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4080 * gtk_notebook_next_page:
4081 * @notebook: a #GtkNotebook
4083 * Switches to the next page. Nothing happens if the current page is
4087 gtk_notebook_next_page (GtkNotebook *notebook)
4091 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4093 list = g_list_find (notebook->children, notebook->cur_page);
4097 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4101 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4105 * gtk_notebook_prev_page:
4106 * @notebook: a #GtkNotebook
4108 * Switches to the previous page. Nothing happens if the current page
4109 * is the first page.
4112 gtk_notebook_prev_page (GtkNotebook *notebook)
4116 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4118 list = g_list_find (notebook->children, notebook->cur_page);
4122 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4126 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4129 /* Public GtkNotebook/Tab Style Functions
4131 * gtk_notebook_set_show_border
4132 * gtk_notebook_set_show_tabs
4133 * gtk_notebook_set_tab_pos
4134 * gtk_notebook_set_homogeneous_tabs
4135 * gtk_notebook_set_tab_border
4136 * gtk_notebook_set_tab_hborder
4137 * gtk_notebook_set_tab_vborder
4138 * gtk_notebook_set_scrollable
4141 * gtk_notebook_set_show_border:
4142 * @notebook: a #GtkNotebook
4143 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4145 * Sets whether a bevel will be drawn around the notebook pages.
4146 * this is only has an effect when the tabs are not shown.
4147 * See gtk_notebook_set_show_tabs().
4150 gtk_notebook_set_show_border (GtkNotebook *notebook,
4151 gboolean show_border)
4153 g_return_if_fail (notebook != NULL);
4154 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4156 if (notebook->show_border != show_border)
4158 notebook->show_border = show_border;
4160 if (GTK_WIDGET_VISIBLE (notebook))
4161 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4163 g_object_notify (G_OBJECT (notebook), "show_border");
4168 * gtk_notebook_get_show_border:
4169 * @notebook: a #GtkNotebook
4171 * Returns whether a bevel will be drawn around the notebook pages. See
4172 * gtk_notebook_set_show_border().
4174 * Return value: %TRUE if the bevel is drawn
4177 gtk_notebook_get_show_border (GtkNotebook *notebook)
4179 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4181 return notebook->show_border;
4185 * gtk_notebook_set_show_tabs:
4186 * @notebook: a #GtkNotebook
4187 * @show_tabs: %TRUE if the tabs should be shown.
4189 * Sets whether to show the tabs for the notebook or not.
4192 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4195 GtkNotebookPage *page;
4198 g_return_if_fail (notebook != NULL);
4199 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4201 show_tabs = show_tabs != FALSE;
4203 if (notebook->show_tabs == show_tabs)
4206 notebook->show_tabs = show_tabs;
4207 children = notebook->children;
4211 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4215 page = children->data;
4216 children = children->next;
4217 if (page->default_tab)
4219 gtk_widget_destroy (page->tab_label);
4220 page->tab_label = NULL;
4223 gtk_widget_hide (page->tab_label);
4226 if (notebook->panel)
4227 gdk_window_hide (notebook->panel);
4231 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4232 gtk_notebook_update_labels (notebook);
4234 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4236 g_object_notify (G_OBJECT (notebook), "show_tabs");
4240 * gtk_notebook_get_show_tabs:
4241 * @notebook: a #GtkNotebook
4243 * Returns whether the tabs of the notebook are shown. See
4244 * gtk_notebook_set_show_tabs().
4246 * Return value: %TRUE if the tabs are shown
4249 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4251 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4253 return notebook->show_tabs;
4257 * gtk_notebook_set_tab_pos:
4261 * Sets the edge at which the tabs for switching pages in the
4262 * notebook are drawn.
4265 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4266 GtkPositionType pos)
4268 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4270 if (notebook->tab_pos != pos)
4272 notebook->tab_pos = pos;
4273 if (GTK_WIDGET_VISIBLE (notebook))
4274 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4277 g_object_notify (G_OBJECT (notebook), "tab_pos");
4281 * gtk_notebook_get_tab_pos:
4282 * @notebook: a #GtkNotebook
4284 * Gets the edge at which the tabs for switching pages in the
4285 * notebook are drawn.
4287 * Return value: the edge at which the tabs are drawn
4290 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4292 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4294 return notebook->tab_pos;
4298 * gtk_notebook_set_homogeneous_tabs:
4299 * @notebook: a #GtkNotebook
4300 * @homogeneous: %TRUE if all tabs should be the same size.
4302 * Sets whether the tabs must have all the same size or not.
4305 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4306 gboolean homogeneous)
4308 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4310 if (homogeneous == notebook->homogeneous)
4313 notebook->homogeneous = homogeneous;
4314 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4316 g_object_notify (G_OBJECT (notebook), "homogeneous");
4320 * gtk_notebook_set_tab_border:
4321 * @notebook: a #GtkNotebook
4322 * @border_width: width of the border around the tab labels.
4324 * Sets the width the border around the tab labels
4325 * in a notebook. This is equivalent to calling
4326 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4327 * by gtk_noteobok_set_tab_vborder (@notebook, @border_width).
4330 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4333 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4335 notebook->tab_hborder = border_width;
4336 notebook->tab_vborder = border_width;
4338 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4339 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4341 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4345 * gtk_notebook_set_tab_hborder:
4346 * @notebook: a #GtkNotebook
4347 * @tab_hborder: width of the horizontal border of tab labels.
4349 * Sets the width of the horizontal border of tab labels.
4352 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4355 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4357 if (notebook->tab_hborder == tab_hborder)
4360 notebook->tab_hborder = tab_hborder;
4362 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4363 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4365 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4369 * gtk_notebook_set_tab_vborder:
4370 * @notebook: a #GtkNotebook
4371 * @tab_vborder: width of the vertical border of tab labels.
4373 * Sets the width of the vertical border of tab labels.
4376 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4379 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4381 if (notebook->tab_vborder == tab_vborder)
4384 notebook->tab_vborder = tab_vborder;
4386 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4387 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4391 * gtk_notebook_set_scrollable:
4392 * @notebook: a #GtkNotebook
4393 * @scrollable: %TRUE if scroll arrows should be added
4395 * Sets whether the tab label area will have arrows for scrolling if
4396 * there are too many tabs to fit in the area.
4400 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4401 gboolean scrollable)
4403 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4405 scrollable = (scrollable != FALSE);
4407 if (scrollable != notebook->scrollable)
4409 notebook->scrollable = scrollable;
4411 if (GTK_WIDGET_REALIZED (notebook))
4415 gtk_notebook_panel_realize (notebook);
4417 else if (notebook->panel)
4419 gdk_window_set_user_data (notebook->panel, NULL);
4420 gdk_window_destroy (notebook->panel);
4421 notebook->panel = NULL;
4425 if (GTK_WIDGET_VISIBLE (notebook))
4426 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4428 g_object_notify (G_OBJECT (notebook), "scrollable");
4433 * gtk_notebook_get_scrollable:
4434 * @notebook: a #GtkNotebook
4436 * Returns whether the tab label area has arrows for scrolling. See
4437 * gtk_notebook_set_scrollable().
4439 * Return value: %TRUE if arrows for scrolling are present
4442 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4444 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4446 return notebook->scrollable;
4449 /* Public GtkNotebook Popup Menu Methods:
4451 * gtk_notebook_popup_enable
4452 * gtk_notebook_popup_disable
4457 * gtk_notebook_popup_enable:
4458 * @notebook: a #GtkNotebook
4460 * Enables the popup menu: if the user clicks with the right mouse button on
4461 * the bookmarks, a menu with all the pages will be popped up.
4464 gtk_notebook_popup_enable (GtkNotebook *notebook)
4468 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4473 notebook->menu = gtk_menu_new ();
4474 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4476 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4477 gtk_notebook_menu_item_create (notebook, list);
4479 gtk_notebook_update_labels (notebook);
4480 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4481 GTK_WIDGET (notebook),
4482 gtk_notebook_menu_detacher);
4484 g_object_notify (G_OBJECT (notebook), "enable_popup");
4488 * gtk_notebook_popup_disable:
4489 * @notebook: a #GtkNotebook
4491 * Disables the popup menu.
4494 gtk_notebook_popup_disable (GtkNotebook *notebook)
4496 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4498 if (!notebook->menu)
4501 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4502 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4503 gtk_widget_destroy (notebook->menu);
4505 g_object_notify (G_OBJECT (notebook), "enable_popup");
4508 /* Public GtkNotebook Page Properties Functions:
4510 * gtk_notebook_get_tab_label
4511 * gtk_notebook_set_tab_label
4512 * gtk_notebook_set_tab_label_text
4513 * gtk_notebook_get_menu_label
4514 * gtk_notebook_set_menu_label
4515 * gtk_notebook_set_menu_label_text
4516 * gtk_notebook_set_tab_label_packing
4517 * gtk_notebook_query_tab_label_packing
4521 * gtk_notebook_get_tab_label:
4522 * @notebook: a #GtkNotebook
4525 * Returns the tab label widget for the page @child. %NULL is returned
4526 * if @child is not in @notebook or if no tab label has specifically
4527 * been set for @child.
4529 * Return value: the tab label
4532 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4537 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4538 g_return_val_if_fail (child != NULL, NULL);
4540 list = CHECK_FIND_CHILD (notebook, child);
4544 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4547 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4551 * gtk_notebook_set_tab_label:
4552 * @notebook: a #GtkNotebook
4554 * @tab_label: the tab label widget to use, or %NULL for default tab
4557 * Changes the tab label for @child. If %NULL is specified
4558 * for @tab_label, then the page will have the label 'page N'.
4561 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4563 GtkWidget *tab_label)
4565 GtkNotebookPage *page;
4568 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4569 g_return_if_fail (child != NULL);
4571 list = CHECK_FIND_CHILD (notebook, child);
4575 /* a NULL pointer indicates a default_tab setting, otherwise
4576 * we need to set the associated label
4579 if (page->tab_label)
4580 gtk_widget_unparent (page->tab_label);
4584 page->default_tab = FALSE;
4585 page->tab_label = tab_label;
4586 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4590 page->default_tab = TRUE;
4591 page->tab_label = NULL;
4593 if (notebook->show_tabs)
4597 g_snprintf (string, sizeof(string), _("Page %u"),
4598 gtk_notebook_real_page_position (notebook, list));
4599 page->tab_label = gtk_label_new (string);
4600 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4604 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4606 gtk_widget_show (page->tab_label);
4607 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4609 gtk_widget_child_notify (child, "tab_label");
4613 * gtk_notebook_set_tab_label_text:
4614 * @notebook: a #GtkNotebook
4616 * @tab_text: the label text
4618 * Creates a new label and sets it as the tab label for the page
4619 * containing @child.
4622 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4624 const gchar *tab_text)
4626 GtkWidget *tab_label = NULL;
4628 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4631 tab_label = gtk_label_new (tab_text);
4632 gtk_notebook_set_tab_label (notebook, child, tab_label);
4633 gtk_widget_child_notify (child, "tab_label");
4637 * gtk_notebook_get_tab_label_text:
4638 * @notebook: a #GtkNotebook
4639 * @child: a widget contained in a page of @notebook
4641 * Retrieves the text of the tab label for the page containing
4644 * Returns value: the text of the tab label, or %NULL if the
4645 * tab label widget is not a #GtkLabel. The
4646 * string is owned by the widget and must not
4649 G_CONST_RETURN gchar *
4650 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4653 GtkWidget *tab_label;
4655 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4656 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4658 tab_label = gtk_notebook_get_tab_label (notebook, child);
4660 if (tab_label && GTK_IS_LABEL (tab_label))
4661 return gtk_label_get_text (GTK_LABEL (tab_label));
4667 * gtk_notebook_get_menu_label:
4668 * @notebook: a #GtkNotebook
4669 * @child: a widget contained in a page of @notebook
4671 * Retrieves the menu label widget of the page containing @child.
4673 * Return value: the menu label, or %NULL if the
4674 * notebook page does not have a menu label other
4675 * than the default (the tab label).
4678 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4683 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4684 g_return_val_if_fail (child != NULL, NULL);
4686 list = CHECK_FIND_CHILD (notebook, child);
4690 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4693 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4697 * gtk_notebook_set_menu_label:
4698 * @notebook: a #GtkNotebook
4699 * @child: the child widget
4700 * @menu_label: the menu label, or NULL for default
4702 * Changes the menu label for the page containing @child.
4705 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4707 GtkWidget *menu_label)
4709 GtkNotebookPage *page;
4712 g_return_if_fail (notebook != NULL);
4713 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4714 g_return_if_fail (child != NULL);
4716 list = CHECK_FIND_CHILD (notebook, child);
4721 if (page->menu_label)
4724 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4725 page->menu_label->parent);
4727 if (!page->default_menu)
4728 gtk_widget_unref (page->menu_label);
4733 page->menu_label = menu_label;
4734 gtk_widget_ref (page->menu_label);
4735 gtk_object_sink (GTK_OBJECT(page->menu_label));
4736 page->default_menu = FALSE;
4739 page->default_menu = TRUE;
4742 gtk_notebook_menu_item_create (notebook, list);
4743 gtk_widget_child_notify (child, "menu_label");
4747 * gtk_notebook_set_menu_label_text:
4748 * @notebook: a #GtkNotebook
4749 * @child: the child widget
4750 * @menu_text: the label text
4752 * Creates a new label and sets it as the menu label of @child.
4755 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4757 const gchar *menu_text)
4759 GtkWidget *menu_label = NULL;
4761 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4764 menu_label = gtk_label_new (menu_text);
4765 gtk_notebook_set_menu_label (notebook, child, menu_label);
4766 gtk_widget_child_notify (child, "menu_label");
4770 * gtk_notebook_get_menu_label_text:
4771 * @notebook: a #GtkNotebook
4772 * @child: the child widget of a page of the notebook.
4774 * Retrieves the text of the menu label for the page containing
4777 * Returns value: the text of the tab label, or %NULL if the
4778 * widget does not have a menu label other than
4779 * the default menu label, or the menu label widget
4780 * is not a #GtkLabel. The string is owned by
4781 * the widget and must not be freed.
4783 G_CONST_RETURN gchar *
4784 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4787 GtkWidget *menu_label;
4789 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4790 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4792 menu_label = gtk_notebook_get_menu_label (notebook, child);
4794 if (menu_label && GTK_IS_LABEL (menu_label))
4795 return gtk_label_get_text (GTK_LABEL (menu_label));
4800 /* Helper function called when pages are reordered
4803 gtk_notebook_child_reordered (GtkNotebook *notebook,
4804 GtkNotebookPage *page)
4808 GtkWidget *menu_item;
4810 menu_item = page->menu_label->parent;
4811 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4812 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4813 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4816 gtk_notebook_update_labels (notebook);
4820 * gtk_notebook_set_tab_label_packing:
4821 * @notebook: a #GtkNotebook
4822 * @child: the child widget
4823 * @expand: whether to expand the bookmark or not
4824 * @fill: whether the bookmark should fill the allocated area or not
4825 * @pack_type: the position of the bookmark
4827 * Sets the packing parameters for the tab label of the page
4828 * containing @child. See gtk_box_pack_start() for the exact meaning
4829 * of the parameters.
4832 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4836 GtkPackType pack_type)
4838 GtkNotebookPage *page;
4841 g_return_if_fail (notebook != NULL);
4842 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4843 g_return_if_fail (child != NULL);
4845 list = CHECK_FIND_CHILD (notebook, child);
4850 expand = expand != FALSE;
4851 fill = fill != FALSE;
4852 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4855 gtk_widget_freeze_child_notify (child);
4856 page->expand = expand;
4857 gtk_widget_child_notify (child, "tab_expand");
4859 gtk_widget_child_notify (child, "tab_fill");
4860 if (page->pack != pack_type)
4862 page->pack = pack_type;
4863 gtk_notebook_child_reordered (notebook, page);
4865 gtk_widget_child_notify (child, "tab_pack");
4866 gtk_widget_child_notify (child, "position");
4867 if (notebook->show_tabs)
4868 gtk_notebook_pages_allocate (notebook);
4869 gtk_widget_thaw_child_notify (child);
4873 * gtk_notebook_query_tab_label_packing:
4874 * @notebook: a #GtkNotebook
4876 * @expand: location to store the expand value (or NULL)
4877 * @fill: location to store the fill value (or NULL)
4878 * @pack_type: location to store the pack_type (or NULL)
4880 * Query the packing attributes for the tab label of the page
4881 * containing @child.
4884 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4888 GtkPackType *pack_type)
4892 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4893 g_return_if_fail (child != NULL);
4895 list = CHECK_FIND_CHILD (notebook, child);
4900 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
4902 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
4904 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
4908 * gtk_notebook_reorder_child:
4909 * @notebook: a #GtkNotebook
4910 * @child: the child to move
4911 * @position: the new position
4913 * Reorders the page containing @child, so that it appears in position
4914 * @position. Out of bounds @position will be clamped.
4917 gtk_notebook_reorder_child (GtkNotebook *notebook,
4921 GList *list, *new_list;
4922 GtkNotebookPage *page;
4925 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4926 g_return_if_fail (GTK_IS_WIDGET (child));
4928 list = CHECK_FIND_CHILD (notebook, child);
4932 old_pos = g_list_position (notebook->children, list);
4934 if (old_pos == position)
4938 notebook->children = g_list_delete_link (notebook->children, list);
4940 position = CLAMP (position, 0, g_list_length (notebook->children));
4942 notebook->children = g_list_insert (notebook->children, page, position);
4943 new_list = g_list_nth (notebook->children, position);
4945 /* Fix up GList references in GtkNotebook structure */
4946 if (notebook->first_tab == list)
4947 notebook->first_tab = new_list;
4948 if (notebook->focus_tab == list)
4949 notebook->focus_tab = new_list;
4951 gtk_widget_freeze_child_notify (child);
4953 /* Move around the menu items if necesary */
4954 gtk_notebook_child_reordered (notebook, page);
4955 gtk_widget_child_notify (child, "tab_pack");
4956 gtk_widget_child_notify (child, "position");
4958 if (notebook->show_tabs)
4959 gtk_notebook_pages_allocate (notebook);
4961 gtk_widget_thaw_child_notify (child);