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"
30 #include "gtkmenuitem.h"
32 #include <gdk/gdkkeysyms.h>
35 #include "gtkmarshalers.h"
36 #include "gtkbindings.h"
40 #define TAB_CURVATURE 1
42 #define ARROW_SPACING 0
43 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
44 #define NOTEBOOK_SCROLL_DELAY (100)
78 CHILD_PROP_MENU_LABEL,
80 CHILD_PROP_TAB_EXPAND,
85 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
87 struct _GtkNotebookPage
91 GtkWidget *menu_label;
92 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
94 guint default_menu : 1; /* If true, we create the menu label ourself */
95 guint default_tab : 1; /* If true, we create the tab label ourself */
100 GtkRequisition requisition;
101 GtkAllocation allocation;
103 guint mnemonic_activate_signal;
106 #ifdef G_DISABLE_CHECKS
107 #define CHECK_FIND_CHILD(notebook, child) \
108 gtk_notebook_find_child (notebook, child, G_STRLOC)
110 #define CHECK_FIND_CHILD(notebook, child) \
111 gtk_notebook_find_child (notebook, child, NULL)
114 /*** GtkNotebook Methods ***/
115 static void gtk_notebook_class_init (GtkNotebookClass *klass);
116 static void gtk_notebook_init (GtkNotebook *notebook);
118 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
119 gboolean move_focus);
120 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
121 GtkNotebookTab type);
122 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
124 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
125 GtkDirectionType direction_type);
127 /*** GtkObject Methods ***/
128 static void gtk_notebook_destroy (GtkObject *object);
129 static void gtk_notebook_set_property (GObject *object,
133 static void gtk_notebook_get_property (GObject *object,
138 /*** GtkWidget Methods ***/
139 static void gtk_notebook_map (GtkWidget *widget);
140 static void gtk_notebook_unmap (GtkWidget *widget);
141 static void gtk_notebook_realize (GtkWidget *widget);
142 static void gtk_notebook_unrealize (GtkWidget *widget);
143 static void gtk_notebook_size_request (GtkWidget *widget,
144 GtkRequisition *requisition);
145 static void gtk_notebook_size_allocate (GtkWidget *widget,
146 GtkAllocation *allocation);
147 static gint gtk_notebook_expose (GtkWidget *widget,
148 GdkEventExpose *event);
149 static gint gtk_notebook_button_press (GtkWidget *widget,
150 GdkEventButton *event);
151 static gint gtk_notebook_button_release (GtkWidget *widget,
152 GdkEventButton *event);
153 static gint gtk_notebook_enter_notify (GtkWidget *widget,
154 GdkEventCrossing *event);
155 static gint gtk_notebook_leave_notify (GtkWidget *widget,
156 GdkEventCrossing *event);
157 static gint gtk_notebook_motion_notify (GtkWidget *widget,
158 GdkEventMotion *event);
159 static gint gtk_notebook_focus_in (GtkWidget *widget,
160 GdkEventFocus *event);
161 static void gtk_notebook_draw_focus (GtkWidget *widget);
162 static gint gtk_notebook_focus (GtkWidget *widget,
163 GtkDirectionType direction);
165 /*** GtkContainer Methods ***/
166 static void gtk_notebook_set_child_property (GtkContainer *container,
171 static void gtk_notebook_get_child_property (GtkContainer *container,
176 static void gtk_notebook_add (GtkContainer *container,
178 static void gtk_notebook_remove (GtkContainer *container,
180 static void gtk_notebook_set_focus_child (GtkContainer *container,
182 static GType gtk_notebook_child_type (GtkContainer *container);
183 static void gtk_notebook_forall (GtkContainer *container,
184 gboolean include_internals,
185 GtkCallback callback,
186 gpointer callback_data);
188 /*** GtkNotebook Private Functions ***/
189 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
190 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
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,
216 /*** GtkNotebook Size Allocate Functions ***/
217 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
218 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
219 GtkNotebookPage *page,
220 GtkAllocation *allocation);
221 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
227 /*** GtkNotebook Page Switch Methods ***/
228 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
229 GtkNotebookPage *page,
232 /*** GtkNotebook Page Switch Functions ***/
233 static void gtk_notebook_switch_page (GtkNotebook *notebook,
234 GtkNotebookPage *page,
236 static gint gtk_notebook_page_select (GtkNotebook *notebook,
237 gboolean move_focus);
238 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
240 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
241 GtkNotebookPage *page);
243 /*** GtkNotebook Menu Functions ***/
244 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
246 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
248 static void gtk_notebook_menu_detacher (GtkWidget *widget,
251 static gboolean focus_tabs_in (GtkNotebook *notebook);
252 static gboolean focus_child_in (GtkNotebook *notebook,
253 GtkDirectionType direction);
255 static GtkContainerClass *parent_class = NULL;
256 static guint notebook_signals[LAST_SIGNAL] = { 0 };
259 gtk_notebook_get_type (void)
261 static GType notebook_type = 0;
265 static const GTypeInfo notebook_info =
267 sizeof (GtkNotebookClass),
268 NULL, /* base_init */
269 NULL, /* base_finalize */
270 (GClassInitFunc) gtk_notebook_class_init,
271 NULL, /* class_finalize */
272 NULL, /* class_data */
273 sizeof (GtkNotebook),
275 (GInstanceInitFunc) gtk_notebook_init,
278 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
282 return notebook_type;
286 add_tab_bindings (GtkBindingSet *binding_set,
287 GdkModifierType modifiers,
288 GtkDirectionType direction)
290 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
292 GTK_TYPE_DIRECTION_TYPE, direction);
293 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
295 GTK_TYPE_DIRECTION_TYPE, direction);
299 add_arrow_bindings (GtkBindingSet *binding_set,
301 GtkDirectionType direction)
303 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
305 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
307 GTK_TYPE_DIRECTION_TYPE, direction);
308 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
310 GTK_TYPE_DIRECTION_TYPE, direction);
314 gtk_notebook_class_init (GtkNotebookClass *class)
316 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
317 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
318 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
319 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
320 GtkBindingSet *binding_set;
322 parent_class = g_type_class_peek_parent (class);
324 gobject_class->set_property = gtk_notebook_set_property;
325 gobject_class->get_property = gtk_notebook_get_property;
326 object_class->destroy = gtk_notebook_destroy;
328 widget_class->map = gtk_notebook_map;
329 widget_class->unmap = gtk_notebook_unmap;
330 widget_class->realize = gtk_notebook_realize;
331 widget_class->unrealize = gtk_notebook_unrealize;
332 widget_class->size_request = gtk_notebook_size_request;
333 widget_class->size_allocate = gtk_notebook_size_allocate;
334 widget_class->expose_event = gtk_notebook_expose;
335 widget_class->button_press_event = gtk_notebook_button_press;
336 widget_class->button_release_event = gtk_notebook_button_release;
337 widget_class->enter_notify_event = gtk_notebook_enter_notify;
338 widget_class->leave_notify_event = gtk_notebook_leave_notify;
339 widget_class->motion_notify_event = gtk_notebook_motion_notify;
340 widget_class->focus_in_event = gtk_notebook_focus_in;
341 widget_class->focus = gtk_notebook_focus;
343 container_class->add = gtk_notebook_add;
344 container_class->remove = gtk_notebook_remove;
345 container_class->forall = gtk_notebook_forall;
346 container_class->set_focus_child = gtk_notebook_set_focus_child;
347 container_class->get_child_property = gtk_notebook_get_child_property;
348 container_class->set_child_property = gtk_notebook_set_child_property;
349 container_class->child_type = gtk_notebook_child_type;
351 class->switch_page = gtk_notebook_real_switch_page;
353 class->focus_tab = gtk_notebook_focus_tab;
354 class->select_page = gtk_notebook_select_page;
355 class->change_current_page = gtk_notebook_change_current_page;
356 class->move_focus_out = gtk_notebook_move_focus_out;
358 g_object_class_install_property (gobject_class,
360 g_param_spec_int ("page",
362 _("The index of the current page"),
367 g_object_class_install_property (gobject_class,
369 g_param_spec_enum ("tab_pos",
371 _("Which side of the notebook holds the tabs"),
372 GTK_TYPE_POSITION_TYPE,
375 g_object_class_install_property (gobject_class,
377 g_param_spec_uint ("tab_border",
379 _("Width of the border around the tab labels"),
384 g_object_class_install_property (gobject_class,
386 g_param_spec_uint ("tab_hborder",
387 _("Horizontal Tab Border"),
388 _("Width of the horizontal border of tab labels"),
393 g_object_class_install_property (gobject_class,
395 g_param_spec_uint ("tab_vborder",
396 _("Vertical Tab Border"),
397 _("Width of the vertical border of tab labels"),
402 g_object_class_install_property (gobject_class,
404 g_param_spec_boolean ("show_tabs",
406 _("Whether tabs should be shown or not"),
409 g_object_class_install_property (gobject_class,
411 g_param_spec_boolean ("show_border",
413 _("Whether the border should be shown or not"),
416 g_object_class_install_property (gobject_class,
418 g_param_spec_boolean ("scrollable",
420 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
423 g_object_class_install_property (gobject_class,
425 g_param_spec_boolean ("enable_popup",
427 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
430 g_object_class_install_property (gobject_class,
432 g_param_spec_boolean ("homogeneous",
434 _("Whether tabs should have homogeneous sizes"),
438 gtk_container_class_install_child_property (container_class,
439 CHILD_PROP_TAB_LABEL,
440 g_param_spec_string ("tab_label",
442 _("The string displayed on the childs tab label"),
445 gtk_container_class_install_child_property (container_class,
446 CHILD_PROP_MENU_LABEL,
447 g_param_spec_string ("menu_label",
449 _("The string displayed in the childs menu entry"),
452 gtk_container_class_install_child_property (container_class,
454 g_param_spec_int ("position",
456 _("The index of the child in the parent"),
459 gtk_container_class_install_child_property (container_class,
460 CHILD_PROP_TAB_EXPAND,
461 g_param_spec_boolean ("tab_expand",
463 _("Whether to expand the childs tab or not"),
466 gtk_container_class_install_child_property (container_class,
468 g_param_spec_boolean ("tab_fill",
470 _("Wheather the childs tab should fill the allocated area or not"),
473 gtk_container_class_install_child_property (container_class,
475 g_param_spec_enum ("tab_pack",
477 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
478 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
481 notebook_signals[SWITCH_PAGE] =
482 g_signal_new ("switch_page",
483 G_TYPE_FROM_CLASS (gobject_class),
485 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
487 _gtk_marshal_VOID__POINTER_UINT,
491 notebook_signals[FOCUS_TAB] =
492 g_signal_new ("focus_tab",
493 G_TYPE_FROM_CLASS (gobject_class),
494 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
495 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
497 _gtk_marshal_BOOLEAN__ENUM,
499 GTK_TYPE_NOTEBOOK_TAB);
500 notebook_signals[SELECT_PAGE] =
501 g_signal_new ("select_page",
502 G_TYPE_FROM_CLASS (gobject_class),
503 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
504 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
506 _gtk_marshal_BOOLEAN__BOOLEAN,
509 notebook_signals[CHANGE_CURRENT_PAGE] =
510 g_signal_new ("change_current_page",
511 G_TYPE_FROM_CLASS (gobject_class),
512 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
513 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
515 _gtk_marshal_VOID__INT,
518 notebook_signals[MOVE_FOCUS_OUT] =
519 g_signal_new ("move_focus_out",
520 G_TYPE_FROM_CLASS (gobject_class),
521 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
522 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
524 _gtk_marshal_VOID__ENUM,
526 GTK_TYPE_DIRECTION_TYPE);
529 binding_set = gtk_binding_set_by_class (class);
530 gtk_binding_entry_add_signal (binding_set,
533 G_TYPE_BOOLEAN, FALSE);
534 gtk_binding_entry_add_signal (binding_set,
537 G_TYPE_BOOLEAN, FALSE);
539 gtk_binding_entry_add_signal (binding_set,
542 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
543 gtk_binding_entry_add_signal (binding_set,
546 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
547 gtk_binding_entry_add_signal (binding_set,
550 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
551 gtk_binding_entry_add_signal (binding_set,
554 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
556 gtk_binding_entry_add_signal (binding_set,
557 GDK_Page_Up, GDK_CONTROL_MASK,
558 "change_current_page", 1,
560 gtk_binding_entry_add_signal (binding_set,
561 GDK_Page_Down, GDK_CONTROL_MASK,
562 "change_current_page", 1,
565 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
566 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
567 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
568 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
570 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
571 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
575 gtk_notebook_init (GtkNotebook *notebook)
577 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
578 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
580 notebook->cur_page = NULL;
581 notebook->children = NULL;
582 notebook->first_tab = NULL;
583 notebook->focus_tab = NULL;
584 notebook->event_window = NULL;
585 notebook->menu = NULL;
587 notebook->tab_hborder = 2;
588 notebook->tab_vborder = 2;
590 notebook->show_tabs = TRUE;
591 notebook->show_border = TRUE;
592 notebook->tab_pos = GTK_POS_TOP;
593 notebook->scrollable = FALSE;
594 notebook->in_child = 0;
595 notebook->click_child = 0;
596 notebook->button = 0;
597 notebook->need_timer = 0;
598 notebook->child_has_focus = FALSE;
599 notebook->have_visible_child = FALSE;
600 notebook->focus_out = FALSE;
604 gtk_notebook_select_page (GtkNotebook *notebook,
607 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
609 gtk_notebook_page_select (notebook, move_focus);
617 gtk_notebook_focus_tab (GtkNotebook *notebook,
622 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
626 case GTK_NOTEBOOK_TAB_FIRST:
627 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
629 gtk_notebook_switch_focus_tab (notebook, list);
631 case GTK_NOTEBOOK_TAB_LAST:
632 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
634 gtk_notebook_switch_focus_tab (notebook, list);
645 gtk_notebook_change_current_page (GtkNotebook *notebook,
648 GList *current = NULL;
650 if (notebook->cur_page)
651 current = g_list_find (notebook->children, notebook->cur_page);
655 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
656 offset += offset < 0 ? 1 : -1;
660 gtk_notebook_switch_page (notebook, current->data, -1);
662 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
665 static GtkDirectionType
666 get_effective_direction (GtkNotebook *notebook,
667 GtkDirectionType direction)
669 /* Remap the directions into the effective direction it would be for a
670 * GTK_POS_TOP notebook
672 #define D(rest) GTK_DIR_##rest
674 static const GtkDirectionType translate_direction[4][6] = {
675 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
676 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
677 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
678 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
683 return translate_direction[notebook->tab_pos][direction];
687 gtk_notebook_move_focus_out (GtkNotebook *notebook,
688 GtkDirectionType direction_type)
690 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
693 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
694 if (focus_tabs_in (notebook))
697 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
698 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
701 /* At this point, we know we should be focusing out of the notebook entirely. We
702 * do this by setting a flag, then propagating the focus motion to the notebook.
704 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
705 if (!GTK_WIDGET_TOPLEVEL (toplevel))
708 g_object_ref (notebook);
710 notebook->focus_out = TRUE;
711 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
712 notebook->focus_out = FALSE;
714 g_object_unref (notebook);
721 * Creates a new #GtkNotebook widget with no pages.
723 * Return value: the newly created #GtkNotebook
726 gtk_notebook_new (void)
728 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
731 /* Private GtkObject Methods :
733 * gtk_notebook_destroy
734 * gtk_notebook_set_arg
735 * gtk_notebook_get_arg
738 gtk_notebook_destroy (GtkObject *object)
740 GtkNotebook *notebook = GTK_NOTEBOOK (object);
743 gtk_notebook_popup_disable (notebook);
745 GTK_OBJECT_CLASS (parent_class)->destroy (object);
749 gtk_notebook_set_property (GObject *object,
754 GtkNotebook *notebook;
756 notebook = GTK_NOTEBOOK (object);
761 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
763 case PROP_SHOW_BORDER:
764 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
766 case PROP_SCROLLABLE:
767 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
769 case PROP_ENABLE_POPUP:
770 if (g_value_get_boolean (value))
771 gtk_notebook_popup_enable (notebook);
773 gtk_notebook_popup_disable (notebook);
775 case PROP_HOMOGENEOUS:
776 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
779 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
782 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
784 case PROP_TAB_BORDER:
785 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
787 case PROP_TAB_HBORDER:
788 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
790 case PROP_TAB_VBORDER:
791 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
799 gtk_notebook_get_property (GObject *object,
804 GtkNotebook *notebook;
806 notebook = GTK_NOTEBOOK (object);
811 g_value_set_boolean (value, notebook->show_tabs);
813 case PROP_SHOW_BORDER:
814 g_value_set_boolean (value, notebook->show_border);
816 case PROP_SCROLLABLE:
817 g_value_set_boolean (value, notebook->scrollable);
819 case PROP_ENABLE_POPUP:
820 g_value_set_boolean (value, notebook->menu != NULL);
822 case PROP_HOMOGENEOUS:
823 g_value_set_boolean (value, notebook->homogeneous);
826 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
829 g_value_set_enum (value, notebook->tab_pos);
831 case PROP_TAB_HBORDER:
832 g_value_set_uint (value, notebook->tab_hborder);
834 case PROP_TAB_VBORDER:
835 g_value_set_uint (value, notebook->tab_vborder);
838 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
843 /* Private GtkWidget Methods :
847 * gtk_notebook_realize
848 * gtk_notebook_size_request
849 * gtk_notebook_size_allocate
850 * gtk_notebook_expose
851 * gtk_notebook_button_press
852 * gtk_notebook_button_release
853 * gtk_notebook_enter_notify
854 * gtk_notebook_leave_notify
855 * gtk_notebook_motion_notify
856 * gtk_notebook_focus_in
857 * gtk_notebook_focus_out
858 * gtk_notebook_draw_focus
859 * gtk_notebook_style_set
862 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
863 GdkRectangle *rectangle)
865 GtkWidget *widget = GTK_WIDGET (notebook);
866 gint border_width = GTK_CONTAINER (notebook)->border_width;
867 GtkNotebookPage *visible_page = NULL;
870 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
872 GtkNotebookPage *page = tmp_list->data;
873 if (GTK_WIDGET_VISIBLE (page->child))
880 if (notebook->show_tabs && visible_page)
884 rectangle->x = widget->allocation.x + border_width;
885 rectangle->y = widget->allocation.y + border_width;
887 switch (notebook->tab_pos)
891 rectangle->width = widget->allocation.width - 2 * border_width;
892 rectangle->height = visible_page->requisition.height;
893 if (notebook->tab_pos == GTK_POS_BOTTOM)
894 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
898 rectangle->width = visible_page->requisition.width;
899 rectangle->height = widget->allocation.height - 2 * border_width;
900 if (notebook->tab_pos == GTK_POS_RIGHT)
901 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
912 rectangle->x = rectangle->y = 0;
913 rectangle->width = rectangle->height = 10;
921 gtk_notebook_map (GtkWidget *widget)
923 GtkNotebook *notebook;
924 GtkNotebookPage *page;
927 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
929 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
931 notebook = GTK_NOTEBOOK (widget);
933 if (notebook->cur_page &&
934 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
935 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
936 gtk_widget_map (notebook->cur_page->child);
938 if (notebook->scrollable)
939 gtk_notebook_pages_allocate (notebook);
942 children = notebook->children;
946 page = children->data;
947 children = children->next;
949 if (page->tab_label &&
950 GTK_WIDGET_VISIBLE (page->tab_label) &&
951 !GTK_WIDGET_MAPPED (page->tab_label))
952 gtk_widget_map (page->tab_label);
956 if (gtk_notebook_get_event_window_position (notebook, NULL))
957 gdk_window_show_unraised (notebook->event_window);
961 gtk_notebook_unmap (GtkWidget *widget)
963 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
965 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
967 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
969 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
973 gtk_notebook_realize (GtkWidget *widget)
975 GtkNotebook *notebook;
976 GdkWindowAttr attributes;
977 gint attributes_mask;
978 GdkRectangle event_window_pos;
980 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
982 notebook = GTK_NOTEBOOK (widget);
983 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
985 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
987 widget->window = gtk_widget_get_parent_window (widget);
988 g_object_ref (widget->window);
990 attributes.window_type = GDK_WINDOW_CHILD;
991 attributes.x = event_window_pos.x;
992 attributes.y = event_window_pos.y;
993 attributes.width = event_window_pos.width;
994 attributes.height = event_window_pos.height;
995 attributes.wclass = GDK_INPUT_ONLY;
996 attributes.event_mask = gtk_widget_get_events (widget);
997 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
998 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1000 attributes_mask = GDK_WA_X | GDK_WA_Y;
1002 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1003 &attributes, attributes_mask);
1004 gdk_window_set_user_data (notebook->event_window, notebook);
1006 widget->style = gtk_style_attach (widget->style, widget->window);
1010 gtk_notebook_unrealize (GtkWidget *widget)
1012 GtkNotebook *notebook;
1014 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1016 notebook = GTK_NOTEBOOK (widget);
1018 gdk_window_set_user_data (notebook->event_window, NULL);
1019 gdk_window_destroy (notebook->event_window);
1020 notebook->event_window = NULL;
1022 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1023 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1027 gtk_notebook_size_request (GtkWidget *widget,
1028 GtkRequisition *requisition)
1030 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1031 GtkNotebookPage *page;
1033 GtkRequisition child_requisition;
1034 gboolean switch_page = FALSE;
1038 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1040 widget->requisition.width = 0;
1041 widget->requisition.height = 0;
1043 for (children = notebook->children, vis_pages = 0; children;
1044 children = children->next)
1046 page = children->data;
1048 if (GTK_WIDGET_VISIBLE (page->child))
1051 gtk_widget_size_request (page->child, &child_requisition);
1053 widget->requisition.width = MAX (widget->requisition.width,
1054 child_requisition.width);
1055 widget->requisition.height = MAX (widget->requisition.height,
1056 child_requisition.height);
1058 if (notebook->menu && page->menu_label->parent &&
1059 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1060 gtk_widget_show (page->menu_label->parent);
1064 if (page == notebook->cur_page)
1066 if (notebook->menu && page->menu_label->parent &&
1067 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1068 gtk_widget_hide (page->menu_label->parent);
1072 if (notebook->show_border || notebook->show_tabs)
1074 widget->requisition.width += widget->style->xthickness * 2;
1075 widget->requisition.height += widget->style->ythickness * 2;
1077 if (notebook->show_tabs)
1080 gint tab_height = 0;
1084 for (children = notebook->children; children;
1085 children = children->next)
1087 page = children->data;
1089 if (GTK_WIDGET_VISIBLE (page->child))
1091 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1092 gtk_widget_show (page->tab_label);
1094 gtk_widget_size_request (page->tab_label,
1095 &child_requisition);
1097 page->requisition.width =
1098 child_requisition.width +
1099 2 * widget->style->xthickness;
1100 page->requisition.height =
1101 child_requisition.height +
1102 2 * widget->style->ythickness;
1104 switch (notebook->tab_pos)
1107 case GTK_POS_BOTTOM:
1108 page->requisition.height += 2 * (notebook->tab_vborder +
1110 tab_height = MAX (tab_height, page->requisition.height);
1111 tab_max = MAX (tab_max, page->requisition.width);
1115 page->requisition.width += 2 * (notebook->tab_hborder +
1117 tab_width = MAX (tab_width, page->requisition.width);
1118 tab_max = MAX (tab_max, page->requisition.height);
1122 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1123 gtk_widget_hide (page->tab_label);
1126 children = notebook->children;
1130 switch (notebook->tab_pos)
1133 case GTK_POS_BOTTOM:
1134 if (tab_height == 0)
1137 if (notebook->scrollable && vis_pages > 1 &&
1138 widget->requisition.width < tab_width)
1139 tab_height = MAX (tab_height, ARROW_SIZE);
1141 padding = 2 * (TAB_CURVATURE + focus_width +
1142 notebook->tab_hborder) - TAB_OVERLAP;
1146 page = children->data;
1147 children = children->next;
1149 if (!GTK_WIDGET_VISIBLE (page->child))
1152 if (notebook->homogeneous)
1153 page->requisition.width = tab_max;
1155 page->requisition.width += padding;
1157 tab_width += page->requisition.width;
1158 page->requisition.height = tab_height;
1161 if (notebook->scrollable && vis_pages > 1 &&
1162 widget->requisition.width < tab_width)
1163 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1165 if (notebook->homogeneous && !notebook->scrollable)
1166 widget->requisition.width = MAX (widget->requisition.width,
1167 vis_pages * tab_max +
1170 widget->requisition.width = MAX (widget->requisition.width,
1171 tab_width + TAB_OVERLAP);
1173 widget->requisition.height += tab_height;
1180 if (notebook->scrollable && vis_pages > 1 &&
1181 widget->requisition.height < tab_height)
1182 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1184 padding = 2 * (TAB_CURVATURE + focus_width +
1185 notebook->tab_vborder) - TAB_OVERLAP;
1190 page = children->data;
1191 children = children->next;
1193 if (!GTK_WIDGET_VISIBLE (page->child))
1196 page->requisition.width = tab_width;
1198 if (notebook->homogeneous)
1199 page->requisition.height = tab_max;
1201 page->requisition.height += padding;
1203 tab_height += page->requisition.height;
1206 if (notebook->scrollable && vis_pages > 1 &&
1207 widget->requisition.height < tab_height)
1208 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1210 widget->requisition.width += tab_width;
1212 if (notebook->homogeneous && !notebook->scrollable)
1213 widget->requisition.height =
1214 MAX (widget->requisition.height,
1215 vis_pages * tab_max + TAB_OVERLAP);
1217 widget->requisition.height =
1218 MAX (widget->requisition.height,
1219 tab_height + TAB_OVERLAP);
1221 if (!notebook->homogeneous || notebook->scrollable)
1223 widget->requisition.height = MAX (widget->requisition.height,
1224 vis_pages * tab_max +
1232 for (children = notebook->children; children;
1233 children = children->next)
1235 page = children->data;
1237 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1238 gtk_widget_hide (page->tab_label);
1243 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1244 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1250 for (children = notebook->children; children;
1251 children = children->next)
1253 page = children->data;
1254 if (GTK_WIDGET_VISIBLE (page->child))
1256 gtk_notebook_switch_page (notebook, page, -1);
1261 else if (GTK_WIDGET_VISIBLE (widget))
1263 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1264 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1267 if (vis_pages && !notebook->cur_page)
1269 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1272 notebook->first_tab = children;
1273 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1279 gtk_notebook_size_allocate (GtkWidget *widget,
1280 GtkAllocation *allocation)
1282 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1285 widget->allocation = *allocation;
1286 if (GTK_WIDGET_REALIZED (widget))
1288 GdkRectangle position;
1290 if (gtk_notebook_get_event_window_position (notebook, &position))
1291 gdk_window_move_resize (notebook->event_window,
1292 position.x, position.y,
1293 position.width, position.height);
1296 if (notebook->children)
1298 gint border_width = GTK_CONTAINER (widget)->border_width;
1299 GtkNotebookPage *page;
1300 GtkAllocation child_allocation;
1303 child_allocation.x = widget->allocation.x + border_width;
1304 child_allocation.y = widget->allocation.y + border_width;
1305 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1306 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1308 if (notebook->show_tabs || notebook->show_border)
1310 child_allocation.x += widget->style->xthickness;
1311 child_allocation.y += widget->style->ythickness;
1312 child_allocation.width = MAX (1, child_allocation.width -
1313 widget->style->xthickness * 2);
1314 child_allocation.height = MAX (1, child_allocation.height -
1315 widget->style->ythickness * 2);
1317 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1319 switch (notebook->tab_pos)
1322 child_allocation.y += notebook->cur_page->requisition.height;
1323 case GTK_POS_BOTTOM:
1324 child_allocation.height =
1325 MAX (1, child_allocation.height -
1326 notebook->cur_page->requisition.height);
1329 child_allocation.x += notebook->cur_page->requisition.width;
1331 child_allocation.width =
1332 MAX (1, child_allocation.width -
1333 notebook->cur_page->requisition.width);
1339 children = notebook->children;
1342 page = children->data;
1343 children = children->next;
1345 if (GTK_WIDGET_VISIBLE (page->child))
1347 gtk_widget_size_allocate (page->child, &child_allocation);
1352 gtk_notebook_pages_allocate (notebook);
1355 if ((vis_pages != 0) != notebook->have_visible_child)
1357 notebook->have_visible_child = (vis_pages != 0);
1358 if (notebook->show_tabs)
1359 gtk_widget_queue_draw (widget);
1364 gtk_notebook_expose (GtkWidget *widget,
1365 GdkEventExpose *event)
1367 GtkNotebook *notebook;
1368 GdkRectangle child_area;
1370 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1371 g_return_val_if_fail (event != NULL, FALSE);
1373 if (GTK_WIDGET_DRAWABLE (widget))
1375 notebook = GTK_NOTEBOOK (widget);
1377 gtk_notebook_paint (widget, &event->area);
1378 if (notebook->show_tabs)
1380 if (notebook->cur_page &&
1381 gtk_widget_intersect (notebook->cur_page->tab_label,
1382 &event->area, &child_area))
1383 gtk_notebook_draw_focus (widget);
1387 if (notebook->cur_page)
1388 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1389 notebook->cur_page->child,
1397 gtk_notebook_show_arrows (GtkNotebook *notebook)
1399 gboolean show_arrow = FALSE;
1402 if (!notebook->scrollable)
1405 children = notebook->children;
1408 GtkNotebookPage *page = children->data;
1410 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1413 children = children->next;
1420 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1421 GdkRectangle *rectangle)
1423 GdkRectangle event_window_pos;
1425 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1427 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1428 rectangle->height = ARROW_SIZE;
1430 switch (notebook->tab_pos)
1434 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1435 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1438 case GTK_POS_BOTTOM:
1439 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1440 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1447 gtk_notebook_get_arrow (GtkNotebook *notebook,
1451 GdkRectangle arrow_rect;
1452 GdkRectangle event_window_pos;
1454 if (gtk_notebook_show_arrows (notebook))
1456 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1457 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1462 if (y >= 0 && y < arrow_rect.height)
1464 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1465 return GTK_ARROW_LEFT;
1466 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1467 return GTK_ARROW_RIGHT;
1475 gtk_notebook_do_arrow (GtkNotebook *notebook,
1478 GtkWidget *widget = GTK_WIDGET (notebook);
1479 GtkDirectionType dir;
1481 if (!notebook->focus_tab ||
1482 gtk_notebook_search_page (notebook, notebook->focus_tab,
1483 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1486 if (notebook->tab_pos == GTK_POS_LEFT ||
1487 notebook->tab_pos == GTK_POS_RIGHT)
1488 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1490 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1491 gtk_widget_child_focus (widget, dir);
1496 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1498 GdkEventButton *event)
1500 GtkWidget *widget = GTK_WIDGET (notebook);
1502 if (!GTK_WIDGET_HAS_FOCUS (widget))
1503 gtk_widget_grab_focus (widget);
1505 notebook->button = event->button;
1506 notebook->click_child = arrow;
1508 if (event->button == 1)
1510 gtk_notebook_do_arrow (notebook, arrow);
1512 if (!notebook->timer)
1514 notebook->timer = gtk_timeout_add
1515 (NOTEBOOK_INIT_SCROLL_DELAY,
1516 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1517 notebook->need_timer = TRUE;
1520 else if (event->button == 2)
1521 gtk_notebook_page_select (notebook, TRUE);
1522 else if (event->button == 3)
1523 gtk_notebook_switch_focus_tab (notebook,
1524 gtk_notebook_search_page (notebook,
1526 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1528 gtk_notebook_redraw_arrows (notebook);
1534 get_widget_coordinates (GtkWidget *widget,
1539 GdkWindow *window = ((GdkEventAny *)event)->window;
1542 if (!gdk_event_get_coords (event, &tx, &ty))
1545 while (window && window != widget->window)
1547 gint window_x, window_y;
1549 gdk_window_get_position (window, &window_x, &window_y);
1553 window = gdk_window_get_parent (window);
1568 gtk_notebook_button_press (GtkWidget *widget,
1569 GdkEventButton *event)
1571 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1572 GtkNotebookPage *page;
1578 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1582 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1585 arrow = gtk_notebook_get_arrow (notebook, x, y);
1587 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1589 if (event->button == 3 && notebook->menu)
1591 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1592 NULL, NULL, 3, event->time);
1596 if (event->button != 1)
1600 children = notebook->children;
1603 page = children->data;
1605 if (GTK_WIDGET_VISIBLE (page->child) &&
1606 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1607 (x >= page->allocation.x) &&
1608 (y >= page->allocation.y) &&
1609 (x <= (page->allocation.x + page->allocation.width)) &&
1610 (y <= (page->allocation.y + page->allocation.height)))
1612 gboolean page_changed = page != notebook->cur_page;
1613 gboolean was_focus = gtk_widget_is_focus (notebook);
1615 gtk_notebook_switch_focus_tab (notebook, children);
1616 gtk_widget_grab_focus (widget);
1618 if (page_changed && !was_focus)
1619 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1623 children = children->next;
1626 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1627 gtk_widget_grab_focus (widget);
1633 gtk_notebook_button_release (GtkWidget *widget,
1634 GdkEventButton *event)
1636 GtkNotebook *notebook;
1638 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1639 g_return_val_if_fail (event != NULL, FALSE);
1641 if (event->type != GDK_BUTTON_RELEASE)
1644 notebook = GTK_NOTEBOOK (widget);
1646 if (event->button == notebook->button)
1650 if (notebook->timer)
1652 gtk_timeout_remove (notebook->timer);
1653 notebook->timer = 0;
1654 notebook->need_timer = FALSE;
1656 click_child = notebook->click_child;
1657 notebook->click_child = 0;
1658 notebook->button = 0;
1659 gtk_notebook_redraw_arrows (notebook);
1668 gtk_notebook_enter_notify (GtkWidget *widget,
1669 GdkEventCrossing *event)
1671 GtkNotebook *notebook;
1675 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1676 g_return_val_if_fail (event != NULL, FALSE);
1678 notebook = GTK_NOTEBOOK (widget);
1680 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1683 arrow = gtk_notebook_get_arrow (notebook, x, y);
1685 if (arrow != notebook->in_child)
1687 notebook->in_child = arrow;
1688 gtk_notebook_redraw_arrows (notebook);
1697 gtk_notebook_leave_notify (GtkWidget *widget,
1698 GdkEventCrossing *event)
1700 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1704 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1707 arrow = gtk_notebook_get_arrow (notebook, x, y);
1709 if (notebook->in_child)
1711 notebook->in_child = 0;
1712 gtk_notebook_redraw_arrows (notebook);
1719 gtk_notebook_motion_notify (GtkWidget *widget,
1720 GdkEventMotion *event)
1722 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1726 if (notebook->button)
1729 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1732 arrow = gtk_notebook_get_arrow (notebook, x, y);
1734 if (arrow != notebook->in_child)
1736 notebook->in_child = arrow;
1737 gtk_notebook_redraw_arrows (notebook);
1744 gtk_notebook_focus_in (GtkWidget *widget,
1745 GdkEventFocus *event)
1747 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1749 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1753 gtk_notebook_draw_focus (GtkWidget *widget)
1755 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1757 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1758 notebook->focus_tab)
1760 GtkNotebookPage *page;
1764 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1766 page = notebook->focus_tab->data;
1768 area.x = page->tab_label->allocation.x - focus_width;
1769 area.y = page->tab_label->allocation.y - focus_width;
1770 area.width = page->tab_label->allocation.width + 2 * focus_width;
1771 area.height = page->tab_label->allocation.height + 2 * focus_width;
1773 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1777 /* Private GtkContainer Methods :
1779 * gtk_notebook_set_child_arg
1780 * gtk_notebook_get_child_arg
1782 * gtk_notebook_remove
1783 * gtk_notebook_focus
1784 * gtk_notebook_set_focus_child
1785 * gtk_notebook_child_type
1786 * gtk_notebook_forall
1789 gtk_notebook_set_child_property (GtkContainer *container,
1792 const GValue *value,
1797 GtkPackType pack_type;
1799 /* not finding child's page is valid for menus or labels */
1800 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1803 switch (property_id)
1805 case CHILD_PROP_TAB_LABEL:
1806 /* a NULL pointer indicates a default_tab setting, otherwise
1807 * we need to set the associated label
1809 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1810 g_value_get_string (value));
1812 case CHILD_PROP_MENU_LABEL:
1813 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1814 g_value_get_string (value));
1816 case CHILD_PROP_POSITION:
1817 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1818 g_value_get_int (value));
1820 case CHILD_PROP_TAB_EXPAND:
1821 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1822 &expand, &fill, &pack_type);
1823 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1824 g_value_get_boolean (value),
1827 case CHILD_PROP_TAB_FILL:
1828 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1829 &expand, &fill, &pack_type);
1830 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1832 g_value_get_boolean (value),
1835 case CHILD_PROP_TAB_PACK:
1836 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1837 &expand, &fill, &pack_type);
1838 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1840 g_value_get_enum (value));
1843 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1849 gtk_notebook_get_child_property (GtkContainer *container,
1856 GtkNotebook *notebook;
1860 GtkPackType pack_type;
1862 notebook = GTK_NOTEBOOK (container);
1864 /* not finding child's page is valid for menus or labels */
1865 list = gtk_notebook_find_child (notebook, child, NULL);
1868 /* nothing to set on labels or menus */
1869 g_param_value_set_default (pspec, value);
1873 switch (property_id)
1875 case CHILD_PROP_TAB_LABEL:
1876 label = gtk_notebook_get_tab_label (notebook, child);
1878 if (label && GTK_IS_LABEL (label))
1879 g_value_set_string (value, GTK_LABEL (label)->label);
1881 g_value_set_string (value, NULL);
1883 case CHILD_PROP_MENU_LABEL:
1884 label = gtk_notebook_get_menu_label (notebook, child);
1886 if (label && GTK_IS_LABEL (label))
1887 g_value_set_string (value, GTK_LABEL (label)->label);
1889 g_value_set_string (value, NULL);
1891 case CHILD_PROP_POSITION:
1892 g_value_set_int (value, g_list_position (notebook->children, list));
1894 case CHILD_PROP_TAB_EXPAND:
1895 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1896 &expand, NULL, NULL);
1897 g_value_set_boolean (value, expand);
1899 case CHILD_PROP_TAB_FILL:
1900 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1902 g_value_set_boolean (value, fill);
1904 case CHILD_PROP_TAB_PACK:
1905 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1906 NULL, NULL, &pack_type);
1907 g_value_set_enum (value, pack_type);
1910 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1916 gtk_notebook_add (GtkContainer *container,
1919 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1921 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1926 gtk_notebook_remove (GtkContainer *container,
1929 GtkNotebook *notebook;
1930 GtkNotebookPage *page;
1934 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1935 g_return_if_fail (widget != NULL);
1937 notebook = GTK_NOTEBOOK (container);
1939 children = notebook->children;
1943 page = children->data;
1944 if (page->child == widget)
1946 gtk_notebook_real_remove (notebook, children);
1950 children = children->next;
1955 focus_tabs_in (GtkNotebook *notebook)
1957 if (notebook->show_tabs && notebook->cur_page)
1959 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1961 gtk_notebook_switch_focus_tab (notebook,
1962 g_list_find (notebook->children,
1963 notebook->cur_page));
1972 focus_tabs_move (GtkNotebook *notebook,
1973 GtkDirectionType direction,
1974 gint search_direction)
1978 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1979 search_direction, TRUE);
1981 gtk_notebook_switch_focus_tab (notebook, new_page);
1983 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1989 focus_child_in (GtkNotebook *notebook,
1990 GtkDirectionType direction)
1992 if (notebook->cur_page)
1993 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1998 /* Focus in the notebook can either be on the pages, or on
2002 gtk_notebook_focus (GtkWidget *widget,
2003 GtkDirectionType direction)
2005 GtkWidget *old_focus_child;
2006 GtkNotebook *notebook;
2007 GtkDirectionType effective_direction;
2009 gboolean widget_is_focus;
2010 GtkContainer *container;
2012 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2014 container = GTK_CONTAINER (widget);
2015 notebook = GTK_NOTEBOOK (container);
2017 if (notebook->focus_out)
2019 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2023 widget_is_focus = gtk_widget_is_focus (widget);
2024 old_focus_child = container->focus_child;
2026 effective_direction = get_effective_direction (notebook, direction);
2028 if (old_focus_child) /* Focus on page child */
2030 if (gtk_widget_child_focus (old_focus_child, direction))
2033 switch (effective_direction)
2035 case GTK_DIR_TAB_BACKWARD:
2037 /* Focus onto the tabs */
2038 return focus_tabs_in (notebook);
2040 case GTK_DIR_TAB_FORWARD:
2046 else if (widget_is_focus) /* Focus was on tabs */
2048 switch (effective_direction)
2050 case GTK_DIR_TAB_BACKWARD:
2053 case GTK_DIR_TAB_FORWARD:
2055 /* We use TAB_FORWARD rather than direction so that we focus a more
2056 * predictable widget for the user; users may be using arrow focusing
2057 * in this situation even if they don't usually use arrow focusing.
2059 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2061 return focus_tabs_move (notebook, direction, STEP_PREV);
2063 return focus_tabs_move (notebook, direction, STEP_NEXT);
2066 else /* Focus was not on widget */
2068 switch (effective_direction)
2070 case GTK_DIR_TAB_FORWARD:
2072 if (focus_tabs_in (notebook))
2074 if (focus_child_in (notebook, direction))
2077 case GTK_DIR_TAB_BACKWARD:
2079 if (focus_child_in (notebook, direction))
2081 if (focus_tabs_in (notebook))
2086 return focus_child_in (notebook, direction);
2090 g_assert_not_reached ();
2095 gtk_notebook_set_focus_child (GtkContainer *container,
2098 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2099 GtkWidget *page_child;
2100 GtkWidget *toplevel;
2102 /* If the old focus widget was within a page of the notebook,
2103 * (child may either be NULL or not in this case), record it
2104 * for future use if we switch to the page with a mnemonic.
2107 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2108 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2110 page_child = GTK_WINDOW (toplevel)->focus_widget;
2113 if (page_child->parent == GTK_WIDGET (container))
2115 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2118 GtkNotebookPage *page = list->data;
2120 if (page->last_focus_child)
2121 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2123 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2124 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2130 page_child = page_child->parent;
2136 g_return_if_fail (GTK_IS_WIDGET (child));
2138 notebook->child_has_focus = TRUE;
2139 if (!notebook->focus_tab)
2142 GtkNotebookPage *page;
2144 children = notebook->children;
2147 page = children->data;
2148 if (page->child == child || page->tab_label == child)
2149 gtk_notebook_switch_focus_tab (notebook, children);
2150 children = children->next;
2155 parent_class->set_focus_child (container, child);
2159 gtk_notebook_forall (GtkContainer *container,
2160 gboolean include_internals,
2161 GtkCallback callback,
2162 gpointer callback_data)
2164 GtkNotebook *notebook;
2167 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2168 g_return_if_fail (callback != NULL);
2170 notebook = GTK_NOTEBOOK (container);
2172 children = notebook->children;
2175 GtkNotebookPage *page;
2177 page = children->data;
2178 children = children->next;
2179 (* callback) (page->child, callback_data);
2180 if (include_internals)
2182 if (page->tab_label)
2183 (* callback) (page->tab_label, callback_data);
2184 if (page->menu_label)
2185 (* callback) (page->menu_label, callback_data);
2191 gtk_notebook_child_type (GtkContainer *container)
2193 return GTK_TYPE_WIDGET;
2196 /* Private GtkNotebook Functions:
2198 * gtk_notebook_redraw_tabs
2199 * gtk_notebook_real_remove
2200 * gtk_notebook_update_labels
2201 * gtk_notebook_timer
2202 * gtk_notebook_page_compare
2203 * gtk_notebook_real_page_position
2204 * gtk_notebook_search_page
2207 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2210 GtkNotebookPage *page;
2211 GdkRectangle redraw_rect;
2214 widget = GTK_WIDGET (notebook);
2215 border = GTK_CONTAINER (notebook)->border_width;
2217 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2220 page = notebook->first_tab->data;
2222 redraw_rect.x = border;
2223 redraw_rect.y = border;
2225 switch (notebook->tab_pos)
2227 case GTK_POS_BOTTOM:
2228 redraw_rect.y = (widget->allocation.height - border -
2229 page->allocation.height -
2230 widget->style->ythickness);
2231 if (page != notebook->cur_page)
2232 redraw_rect.y -= widget->style->ythickness;
2235 redraw_rect.width = widget->allocation.width - 2 * border;
2236 redraw_rect.height = (page->allocation.height +
2237 widget->style->ythickness);
2238 if (page != notebook->cur_page)
2239 redraw_rect.height += widget->style->ythickness;
2242 redraw_rect.x = (widget->allocation.width - border -
2243 page->allocation.width -
2244 widget->style->xthickness);
2245 if (page != notebook->cur_page)
2246 redraw_rect.x -= widget->style->xthickness;
2249 redraw_rect.width = (page->allocation.width +
2250 widget->style->xthickness);
2251 redraw_rect.height = widget->allocation.height - 2 * border;
2252 if (page != notebook->cur_page)
2253 redraw_rect.width += widget->style->xthickness;
2257 redraw_rect.x += widget->allocation.x;
2258 redraw_rect.y += widget->allocation.y;
2260 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2264 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2266 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2270 gtk_notebook_get_arrow_rect (notebook, &rect);
2271 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2276 gtk_notebook_timer (GtkNotebook *notebook)
2278 gboolean retval = FALSE;
2280 GDK_THREADS_ENTER ();
2282 if (notebook->timer)
2284 gtk_notebook_do_arrow (notebook, notebook->click_child);
2286 if (notebook->need_timer)
2288 notebook->need_timer = FALSE;
2289 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2290 (GtkFunction) gtk_notebook_timer,
2291 (gpointer) notebook);
2297 GDK_THREADS_LEAVE ();
2303 gtk_notebook_page_compare (gconstpointer a,
2306 return (((GtkNotebookPage *) a)->child != b);
2310 gtk_notebook_find_child (GtkNotebook *notebook,
2312 const gchar *function)
2314 GList *list = g_list_find_custom (notebook->children, child,
2315 gtk_notebook_page_compare);
2317 #ifndef G_DISABLE_CHECKS
2318 if (!list && function)
2319 g_warning ("%s: unable to find child %p in notebook %p",
2320 function, child, notebook);
2327 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2328 GtkNotebookPage *page)
2330 if (page->tab_label)
2332 if (page->mnemonic_activate_signal)
2333 g_signal_handler_disconnect (page->tab_label,
2334 page->mnemonic_activate_signal);
2335 page->mnemonic_activate_signal = 0;
2337 gtk_widget_unparent (page->tab_label);
2342 gtk_notebook_real_remove (GtkNotebook *notebook,
2345 GtkNotebookPage *page;
2347 gint need_resize = FALSE;
2349 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2351 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2353 if (notebook->cur_page == list->data)
2355 notebook->cur_page = NULL;
2357 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2360 if (list == notebook->first_tab)
2361 notebook->first_tab = next_list;
2362 if (list == notebook->focus_tab)
2363 gtk_notebook_switch_focus_tab (notebook, next_list);
2367 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2370 gtk_widget_unparent (page->child);
2372 gtk_notebook_remove_tab_label (notebook, page);
2376 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2377 page->menu_label->parent);
2378 gtk_widget_queue_resize (notebook->menu);
2380 if (!page->default_menu)
2381 g_object_unref (page->menu_label);
2383 notebook->children = g_list_remove_link (notebook->children, list);
2386 if (page->last_focus_child)
2388 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2389 page->last_focus_child = NULL;
2394 if (!notebook->children && notebook->show_tabs &&
2395 GTK_WIDGET_MAPPED (notebook))
2396 gdk_window_hide (notebook->event_window);
2398 gtk_notebook_update_labels (notebook);
2400 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2404 gtk_notebook_update_labels (GtkNotebook *notebook)
2406 GtkNotebookPage *page;
2411 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2413 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2416 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2417 if (notebook->show_tabs)
2419 if (page->default_tab)
2421 if (!page->tab_label)
2423 page->tab_label = gtk_label_new (string);
2424 gtk_widget_set_parent (page->tab_label,
2425 GTK_WIDGET (notebook));
2428 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2431 if (GTK_WIDGET_VISIBLE (page->child) &&
2432 !GTK_WIDGET_VISIBLE (page->tab_label))
2433 gtk_widget_show (page->tab_label);
2434 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2435 GTK_WIDGET_VISIBLE (page->tab_label))
2436 gtk_widget_hide (page->tab_label);
2438 if (notebook->menu && page->default_menu)
2440 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2441 gtk_label_set_text (GTK_LABEL (page->menu_label),
2442 GTK_LABEL (page->tab_label)->label);
2444 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2450 gtk_notebook_real_page_position (GtkNotebook *notebook,
2456 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2457 g_return_val_if_fail (list != NULL, -1);
2459 for (work = notebook->children, count_start = 0;
2460 work && work != list; work = work->next)
2461 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2467 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2470 return (count_start + g_list_length (list) - 1);
2474 gtk_notebook_search_page (GtkNotebook *notebook,
2477 gboolean find_visible)
2479 GtkNotebookPage *page = NULL;
2480 GList *old_list = NULL;
2483 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2488 flag = GTK_PACK_END;
2492 flag = GTK_PACK_START;
2499 if (!page || page->pack == flag)
2507 list = notebook->children;
2512 if (page->pack == flag &&
2513 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2528 if (page->pack != flag &&
2529 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2537 /* Private GtkNotebook Drawing Functions:
2539 * gtk_notebook_paint
2540 * gtk_notebook_draw_tab
2541 * gtk_notebook_draw_arrow
2544 gtk_notebook_paint (GtkWidget *widget,
2547 GtkNotebook *notebook;
2548 GtkNotebookPage *page;
2553 gint border_width = GTK_CONTAINER (widget)->border_width;
2554 gint gap_x = 0, gap_width = 0;
2556 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2557 g_return_if_fail (area != NULL);
2559 if (!GTK_WIDGET_DRAWABLE (widget))
2562 notebook = GTK_NOTEBOOK (widget);
2564 if ((!notebook->show_tabs && !notebook->show_border) ||
2565 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2568 x = widget->allocation.x + border_width;
2569 y = widget->allocation.y + border_width;
2570 width = widget->allocation.width - border_width * 2;
2571 height = widget->allocation.height - border_width * 2;
2573 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2575 gtk_paint_box (widget->style, widget->window,
2576 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2577 area, widget, "notebook",
2578 x, y, width, height);
2583 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2585 page = notebook->first_tab->data;
2587 switch (notebook->tab_pos)
2590 y += page->allocation.height + widget->style->ythickness;
2591 case GTK_POS_BOTTOM:
2592 height -= page->allocation.height + widget->style->ythickness;
2595 x += page->allocation.width + widget->style->xthickness;
2597 width -= page->allocation.width + widget->style->xthickness;
2600 gtk_paint_box (widget->style, widget->window,
2601 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2602 area, widget, "notebook",
2603 x, y, width, height);
2607 switch (notebook->tab_pos)
2610 y += notebook->cur_page->allocation.height;
2611 case GTK_POS_BOTTOM:
2612 height -= notebook->cur_page->allocation.height;
2615 x += notebook->cur_page->allocation.width;
2617 width -= notebook->cur_page->allocation.width;
2621 switch (notebook->tab_pos)
2624 case GTK_POS_BOTTOM:
2625 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2626 gap_width = notebook->cur_page->allocation.width;
2630 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2631 gap_width = notebook->cur_page->allocation.height;
2634 gtk_paint_box_gap(widget->style, widget->window,
2635 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2636 area, widget, "notebook",
2637 x, y, width, height,
2638 notebook->tab_pos, gap_x, gap_width);
2642 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2645 page = children->data;
2646 children = gtk_notebook_search_page (notebook, children,
2648 if (!GTK_WIDGET_VISIBLE (page->child))
2650 if (!GTK_WIDGET_MAPPED (page->tab_label))
2652 else if (page != notebook->cur_page)
2653 gtk_notebook_draw_tab (notebook, page, area);
2656 if (showarrow && notebook->scrollable)
2658 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2659 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2661 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2665 gtk_notebook_draw_tab (GtkNotebook *notebook,
2666 GtkNotebookPage *page,
2669 GdkRectangle child_area;
2670 GdkRectangle page_area;
2671 GtkStateType state_type;
2672 GtkPositionType gap_side;
2674 g_return_if_fail (notebook != NULL);
2675 g_return_if_fail (page != NULL);
2676 g_return_if_fail (area != NULL);
2678 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2679 (page->allocation.width == 0) || (page->allocation.height == 0))
2682 page_area.x = page->allocation.x;
2683 page_area.y = page->allocation.y;
2684 page_area.width = page->allocation.width;
2685 page_area.height = page->allocation.height;
2687 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2691 widget = GTK_WIDGET (notebook);
2693 switch (notebook->tab_pos)
2696 gap_side = GTK_POS_BOTTOM;
2698 case GTK_POS_BOTTOM:
2699 gap_side = GTK_POS_TOP;
2702 gap_side = GTK_POS_RIGHT;
2705 gap_side = GTK_POS_LEFT;
2709 if (notebook->cur_page == page)
2710 state_type = GTK_STATE_NORMAL;
2712 state_type = GTK_STATE_ACTIVE;
2713 gtk_paint_extension(widget->style, widget->window,
2714 state_type, GTK_SHADOW_OUT,
2715 area, widget, "tab",
2716 page_area.x, page_area.y,
2717 page_area.width, page_area.height,
2719 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2720 notebook->focus_tab && (notebook->focus_tab->data == page))
2724 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2726 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2727 area, widget, "tab",
2728 page->tab_label->allocation.x - focus_width,
2729 page->tab_label->allocation.y - focus_width,
2730 page->tab_label->allocation.width + 2 * focus_width,
2731 page->tab_label->allocation.height + 2 * focus_width);
2733 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2734 GTK_WIDGET_DRAWABLE (page->tab_label))
2736 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2738 /* This is a lame hack since all this code needs rewriting anyhow */
2740 expose_event->expose.window = g_object_ref (page->tab_label->window);
2741 expose_event->expose.area = child_area;
2742 expose_event->expose.region = gdk_region_rectangle (&child_area);
2743 expose_event->expose.send_event = TRUE;
2744 expose_event->expose.count = 0;
2746 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2748 gdk_event_free (expose_event);
2754 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2757 GtkStateType state_type;
2758 GtkShadowType shadow_type;
2760 GdkRectangle arrow_rect;
2762 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2764 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2766 widget = GTK_WIDGET(notebook);
2768 if (GTK_WIDGET_DRAWABLE (notebook))
2770 if (notebook->in_child == arrow)
2772 if (notebook->click_child == arrow)
2773 state_type = GTK_STATE_ACTIVE;
2775 state_type = GTK_STATE_PRELIGHT;
2778 state_type = GTK_STATE_NORMAL;
2780 if (notebook->click_child == arrow)
2781 shadow_type = GTK_SHADOW_IN;
2783 shadow_type = GTK_SHADOW_OUT;
2785 if (arrow == GTK_ARROW_LEFT)
2787 if (notebook->focus_tab &&
2788 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2791 shadow_type = GTK_SHADOW_ETCHED_IN;
2792 state_type = GTK_STATE_INSENSITIVE;
2795 if (notebook->tab_pos == GTK_POS_LEFT ||
2796 notebook->tab_pos == GTK_POS_RIGHT)
2797 arrow = GTK_ARROW_UP;
2799 gtk_paint_arrow (widget->style, widget->window, state_type,
2800 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2802 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2806 if (notebook->focus_tab &&
2807 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2810 shadow_type = GTK_SHADOW_ETCHED_IN;
2811 state_type = GTK_STATE_INSENSITIVE;
2814 if (notebook->tab_pos == GTK_POS_LEFT ||
2815 notebook->tab_pos == GTK_POS_RIGHT)
2816 arrow = GTK_ARROW_DOWN;
2818 gtk_paint_arrow (widget->style, widget->window, state_type,
2819 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2820 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2821 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2826 /* Private GtkNotebook Size Allocate Functions:
2828 * gtk_notebook_pages_allocate
2829 * gtk_notebook_page_allocate
2830 * gtk_notebook_calc_tabs
2833 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2835 GtkWidget *widget = GTK_WIDGET (notebook);
2836 GtkContainer *container = GTK_CONTAINER (notebook);
2837 GtkNotebookPage *page = NULL;
2838 GtkAllocation *allocation = &widget->allocation;
2839 GtkAllocation child_allocation;
2840 GList *children = NULL;
2841 GList *last_child = NULL;
2842 gboolean showarrow = FALSE;
2852 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2855 child_allocation.x = widget->allocation.x + container->border_width;
2856 child_allocation.y = widget->allocation.y + container->border_width;
2858 switch (notebook->tab_pos)
2860 case GTK_POS_BOTTOM:
2861 child_allocation.y = (widget->allocation.y +
2862 allocation->height -
2863 notebook->cur_page->requisition.height -
2864 container->border_width);
2867 child_allocation.height = notebook->cur_page->requisition.height;
2871 child_allocation.x = (widget->allocation.x +
2873 notebook->cur_page->requisition.width -
2874 container->border_width);
2877 child_allocation.width = notebook->cur_page->requisition.width;
2881 if (notebook->scrollable)
2885 children = notebook->children;
2887 if (notebook->focus_tab)
2888 focus_tab = notebook->focus_tab;
2889 else if (notebook->first_tab)
2890 focus_tab = notebook->first_tab;
2892 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2894 switch (notebook->tab_pos)
2897 case GTK_POS_BOTTOM:
2900 page = children->data;
2901 children = children->next;
2903 if (GTK_WIDGET_VISIBLE (page->child))
2904 tab_space += page->requisition.width;
2907 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2910 page = focus_tab->data;
2912 tab_space = (allocation->width - TAB_OVERLAP -
2913 page->requisition.width -
2914 2 * (container->border_width + ARROW_SPACING +
2916 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2917 container->border_width);
2919 page = notebook->children->data;
2920 if (notebook->tab_pos == GTK_POS_TOP)
2921 y = (container->border_width +
2922 (page->requisition.height - ARROW_SIZE) / 2);
2924 y = (allocation->height - container->border_width -
2925 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2932 page = children->data;
2933 children = children->next;
2935 if (GTK_WIDGET_VISIBLE (page->child))
2936 tab_space += page->requisition.height;
2939 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2942 page = focus_tab->data;
2943 tab_space = (allocation->height -
2944 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2945 2 * container->border_width -
2946 page->requisition.height);
2947 y = allocation->height - container->border_width - ARROW_SIZE;
2949 page = notebook->children->data;
2950 if (notebook->tab_pos == GTK_POS_LEFT)
2951 x = (container->border_width +
2952 (page->requisition.width -
2953 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2955 x = (allocation->width - container->border_width -
2956 (2 * ARROW_SIZE - ARROW_SPACING) -
2957 (page->requisition.width -
2958 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2962 if (showarrow) /* first_tab <- focus_tab */
2966 notebook->first_tab = focus_tab;
2967 last_child = gtk_notebook_search_page (notebook, focus_tab,
2973 if (notebook->first_tab && notebook->first_tab != focus_tab)
2975 /* Is first_tab really predecessor of focus_tab ? */
2976 page = notebook->first_tab->data;
2977 if (GTK_WIDGET_VISIBLE (page->child))
2978 for (children = focus_tab;
2979 children && children != notebook->first_tab;
2980 children = gtk_notebook_search_page (notebook,
2986 notebook->first_tab = focus_tab;
2988 gtk_notebook_calc_tabs (notebook,
2989 gtk_notebook_search_page (notebook,
2993 &(notebook->first_tab), &tab_space,
2998 notebook->first_tab =
2999 gtk_notebook_search_page (notebook, notebook->first_tab,
3001 if (!notebook->first_tab)
3002 notebook->first_tab = focus_tab;
3003 last_child = gtk_notebook_search_page (notebook, focus_tab,
3006 else /* focus_tab -> end */
3008 if (!notebook->first_tab)
3009 notebook->first_tab = gtk_notebook_search_page (notebook,
3014 gtk_notebook_calc_tabs (notebook,
3015 gtk_notebook_search_page (notebook,
3019 &children, &tab_space, STEP_NEXT);
3022 last_child = children;
3023 else /* start <- first_tab */
3027 gtk_notebook_calc_tabs
3029 gtk_notebook_search_page (notebook,
3030 notebook->first_tab,
3033 &children, &tab_space, STEP_PREV);
3034 notebook->first_tab = gtk_notebook_search_page(notebook,
3044 tab_space = -tab_space;
3046 for (children = notebook->first_tab;
3047 children && children != last_child;
3048 children = gtk_notebook_search_page (notebook, children,
3055 /*unmap all non-visible tabs*/
3056 for (children = gtk_notebook_search_page (notebook, NULL,
3058 children && children != notebook->first_tab;
3059 children = gtk_notebook_search_page (notebook, children,
3062 page = children->data;
3063 if (page->tab_label)
3064 gtk_widget_set_child_visible (page->tab_label, FALSE);
3066 for (children = last_child; children;
3067 children = gtk_notebook_search_page (notebook, children,
3070 page = children->data;
3071 if (page->tab_label)
3072 gtk_widget_set_child_visible (page->tab_label, FALSE);
3075 else /* !showarrow */
3077 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3088 children = notebook->children;
3089 switch (notebook->tab_pos)
3092 case GTK_POS_BOTTOM:
3095 page = children->data;
3096 children = children->next;
3098 if (GTK_WIDGET_VISIBLE (page->child))
3101 tab_space += page->requisition.width;
3106 tab_space -= allocation->width;
3112 page = children->data;
3113 children = children->next;
3115 if (GTK_WIDGET_VISIBLE (page->child))
3118 tab_space += page->requisition.height;
3123 tab_space -= allocation->height;
3125 tab_space += 2 * container->border_width + TAB_OVERLAP;
3127 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3129 if (notebook->homogeneous && n)
3133 children = notebook->first_tab;
3137 if (children == last_child)
3139 /* FIXME double check */
3143 page = children->data;
3144 if (!showarrow && page->pack != GTK_PACK_START)
3146 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3149 if (n && (showarrow || page->expand || notebook->homogeneous))
3151 new_fill = (tab_space * i++) / n;
3152 delta = new_fill - old_fill;
3153 old_fill = new_fill;
3156 switch (notebook->tab_pos)
3159 case GTK_POS_BOTTOM:
3160 child_allocation.width = (page->requisition.width +
3161 TAB_OVERLAP + delta);
3165 child_allocation.height = (page->requisition.height +
3166 TAB_OVERLAP + delta);
3170 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3172 switch (notebook->tab_pos)
3175 case GTK_POS_BOTTOM:
3176 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3180 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3184 if (page->tab_label)
3185 gtk_widget_set_child_visible (page->tab_label, TRUE);
3190 children = notebook->children;
3191 switch (notebook->tab_pos)
3194 case GTK_POS_BOTTOM:
3195 child_allocation.x = (allocation->x + allocation->width -
3196 container->border_width);
3200 child_allocation.y = (allocation->y + allocation->height -
3201 container->border_width);
3205 while (children != last_child)
3207 page = children->data;
3208 children = children->next;
3210 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3214 if (n && (page->expand || notebook->homogeneous))
3216 new_fill = (tab_space * i++) / n;
3217 delta = new_fill - old_fill;
3218 old_fill = new_fill;
3221 switch (notebook->tab_pos)
3224 case GTK_POS_BOTTOM:
3225 child_allocation.width = (page->requisition.width +
3226 TAB_OVERLAP + delta);
3227 child_allocation.x -= child_allocation.width;
3231 child_allocation.height = (page->requisition.height +
3232 TAB_OVERLAP + delta);
3233 child_allocation.y -= child_allocation.height;
3237 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3239 switch (notebook->tab_pos)
3242 case GTK_POS_BOTTOM:
3243 child_allocation.x += TAB_OVERLAP;
3247 child_allocation.y += TAB_OVERLAP;
3251 if (page->tab_label)
3252 gtk_widget_set_child_visible (page->tab_label, TRUE);
3257 gtk_notebook_redraw_tabs (notebook);
3261 gtk_notebook_page_allocate (GtkNotebook *notebook,
3262 GtkNotebookPage *page,
3263 GtkAllocation *allocation)
3265 GtkWidget *widget = GTK_WIDGET (notebook);
3266 GtkAllocation child_allocation;
3267 GtkRequisition tab_requisition;
3273 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3275 xthickness = widget->style->xthickness;
3276 ythickness = widget->style->ythickness;
3278 /* If the size of the notebook tabs change, we need to queue
3279 * a redraw on the tab area
3281 if ((allocation->width != page->allocation.width) ||
3282 (allocation->height != page->allocation.height))
3284 gint x, y, width, height, border_width;
3286 border_width = GTK_CONTAINER (notebook)->border_width;
3288 switch (notebook->tab_pos)
3291 width = widget->allocation.width;
3292 height = MAX (page->allocation.height, allocation->height) + ythickness;
3297 case GTK_POS_BOTTOM:
3298 width = widget->allocation.width + xthickness;
3299 height = MAX (page->allocation.height, allocation->height) + ythickness;
3301 y = widget->allocation.height - height - border_width;
3305 width = MAX (page->allocation.width, allocation->width) + xthickness;
3306 height = widget->allocation.height;
3312 default: /* quiet gcc */
3313 width = MAX (page->allocation.width, allocation->width) + xthickness;
3314 height = widget->allocation.height;
3315 x = widget->allocation.width - width - border_width;
3320 gtk_widget_queue_draw_area (widget, x, y, width, height);
3323 page->allocation = *allocation;
3324 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3326 if (notebook->cur_page != page)
3328 switch (notebook->tab_pos)
3331 page->allocation.y += ythickness;
3332 case GTK_POS_BOTTOM:
3333 if (page->allocation.height > ythickness)
3334 page->allocation.height -= ythickness;
3337 page->allocation.x += xthickness;
3339 if (page->allocation.width > xthickness)
3340 page->allocation.width -= xthickness;
3345 switch (notebook->tab_pos)
3348 case GTK_POS_BOTTOM:
3349 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3352 child_allocation.x = (xthickness + focus_width +
3353 notebook->tab_hborder);
3354 child_allocation.width = MAX (1, (page->allocation.width -
3355 2 * child_allocation.x));
3356 child_allocation.x += page->allocation.x;
3360 child_allocation.x = (page->allocation.x +
3361 (page->allocation.width -
3362 tab_requisition.width) / 2);
3363 child_allocation.width = tab_requisition.width;
3365 child_allocation.y = (notebook->tab_vborder + focus_width +
3366 page->allocation.y);
3367 if (notebook->tab_pos == GTK_POS_TOP)
3368 child_allocation.y += ythickness;
3369 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3370 2 * (notebook->tab_vborder + focus_width)));
3374 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3377 child_allocation.y = ythickness + padding;
3378 child_allocation.height = MAX (1, (page->allocation.height -
3379 2 * child_allocation.y));
3380 child_allocation.y += page->allocation.y;
3384 child_allocation.y = (page->allocation.y + (page->allocation.height -
3385 tab_requisition.height) / 2);
3386 child_allocation.height = tab_requisition.height;
3388 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3389 if (notebook->tab_pos == GTK_POS_LEFT)
3390 child_allocation.x += xthickness;
3391 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3392 2 * (notebook->tab_hborder + focus_width)));
3396 if (page->tab_label)
3397 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3401 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3407 GtkNotebookPage *page = NULL;
3409 GList *last_list = NULL;
3416 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3417 if (pack == GTK_PACK_END)
3418 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3422 switch (notebook->tab_pos)
3425 case GTK_POS_BOTTOM:
3428 page = children->data;
3429 if (GTK_WIDGET_VISIBLE (page->child))
3431 if (page->pack == pack)
3433 *tab_space -= page->requisition.width;
3434 if (*tab_space < 0 || children == *end)
3438 *tab_space = - (*tab_space +
3439 page->requisition.width);
3445 last_list = children;
3447 if (direction == STEP_NEXT)
3448 children = children->next;
3450 children = children->prev;
3457 page = children->data;
3458 if (GTK_WIDGET_VISIBLE (page->child))
3460 if (page->pack == pack)
3462 *tab_space -= page->requisition.height;
3463 if (*tab_space < 0 || children == *end)
3467 *tab_space = - (*tab_space +
3468 page->requisition.height);
3474 last_list = children;
3476 if (direction == STEP_NEXT)
3477 children = children->next;
3479 children = children->prev;
3483 if (direction == STEP_PREV)
3485 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3486 direction = STEP_PREV;
3487 children = last_list;
3491 /* Private GtkNotebook Page Switch Methods:
3493 * gtk_notebook_real_switch_page
3496 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3497 GtkNotebookPage *page,
3500 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3501 g_return_if_fail (page != NULL);
3503 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3506 if (notebook->cur_page)
3507 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3509 notebook->cur_page = page;
3511 if (!notebook->focus_tab ||
3512 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3513 notebook->focus_tab =
3514 g_list_find (notebook->children, notebook->cur_page);
3516 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3518 /* If the focus was on the previous page, move it to the first
3519 * element on the new page, if possible, or if not, to the
3522 if (notebook->child_has_focus)
3524 if (notebook->cur_page->last_focus_child &&
3525 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3526 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3528 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3529 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3532 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3533 g_object_notify (G_OBJECT (notebook), "page");
3536 /* Private GtkNotebook Page Switch Functions:
3538 * gtk_notebook_switch_page
3539 * gtk_notebook_page_select
3540 * gtk_notebook_switch_focus_tab
3541 * gtk_notebook_menu_switch_page
3544 gtk_notebook_switch_page (GtkNotebook *notebook,
3545 GtkNotebookPage *page,
3548 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3549 g_return_if_fail (page != NULL);
3551 if (notebook->cur_page == page)
3555 page_num = g_list_index (notebook->children, page);
3557 g_signal_emit (notebook,
3558 notebook_signals[SWITCH_PAGE],
3565 gtk_notebook_page_select (GtkNotebook *notebook,
3566 gboolean move_focus)
3568 GtkNotebookPage *page;
3569 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3571 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3573 if (!notebook->focus_tab)
3576 page = notebook->focus_tab->data;
3577 gtk_notebook_switch_page (notebook, page, -1);
3581 switch (notebook->tab_pos)
3586 case GTK_POS_BOTTOM:
3590 dir = GTK_DIR_RIGHT;
3597 if (gtk_widget_child_focus (page->child, dir))
3604 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3608 GtkNotebookPage *old_page = NULL;
3609 GtkNotebookPage *page;
3611 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3613 if (notebook->focus_tab == new_child)
3616 old_child = notebook->focus_tab;
3617 notebook->focus_tab = new_child;
3619 if (notebook->scrollable)
3620 gtk_notebook_redraw_arrows (notebook);
3622 if (!notebook->show_tabs || !notebook->focus_tab)
3626 old_page = old_child->data;
3628 page = notebook->focus_tab->data;
3629 if (GTK_WIDGET_MAPPED (page->tab_label))
3630 gtk_notebook_redraw_tabs (notebook);
3632 gtk_notebook_pages_allocate (notebook);
3634 gtk_notebook_switch_page (notebook, page,
3635 g_list_index (notebook->children, page));
3639 gtk_notebook_menu_switch_page (GtkWidget *widget,
3640 GtkNotebookPage *page)
3642 GtkNotebook *notebook;
3646 g_return_if_fail (widget != NULL);
3647 g_return_if_fail (page != NULL);
3649 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3650 (GTK_MENU (widget->parent)));
3652 if (notebook->cur_page == page)
3656 children = notebook->children;
3657 while (children && children->data != page)
3659 children = children->next;
3663 g_signal_emit (notebook,
3664 notebook_signals[SWITCH_PAGE],
3670 /* Private GtkNotebook Menu Functions:
3672 * gtk_notebook_menu_item_create
3673 * gtk_notebook_menu_label_unparent
3674 * gtk_notebook_menu_detacher
3677 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3680 GtkNotebookPage *page;
3681 GtkWidget *menu_item;
3684 if (page->default_menu)
3686 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3687 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3689 page->menu_label = gtk_label_new ("");
3690 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3693 gtk_widget_show (page->menu_label);
3694 menu_item = gtk_menu_item_new ();
3695 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3696 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3697 gtk_notebook_real_page_position (notebook, list));
3698 g_signal_connect (menu_item, "activate",
3699 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3700 if (GTK_WIDGET_VISIBLE (page->child))
3701 gtk_widget_show (menu_item);
3705 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3708 gtk_widget_unparent (GTK_BIN(widget)->child);
3709 GTK_BIN(widget)->child = NULL;
3713 gtk_notebook_menu_detacher (GtkWidget *widget,
3716 GtkNotebook *notebook;
3718 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3720 notebook = GTK_NOTEBOOK (widget);
3721 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3723 notebook->menu = NULL;
3726 /* Public GtkNotebook Page Insert/Remove Methods :
3728 * gtk_notebook_append_page
3729 * gtk_notebook_append_page_menu
3730 * gtk_notebook_prepend_page
3731 * gtk_notebook_prepend_page_menu
3732 * gtk_notebook_insert_page
3733 * gtk_notebook_insert_page_menu
3734 * gtk_notebook_remove_page
3737 * gtk_notebook_append_page:
3738 * @notebook: a #GtkNotebook
3739 * @child: the #GtkWidget to use as the contents of the page.
3740 * @tab_label: the #GtkWidget to be used as the label for the page,
3741 * or %NULL to use the default label, 'page N'.
3743 * Appends a page to @notebook.
3746 gtk_notebook_append_page (GtkNotebook *notebook,
3748 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, -1);
3758 * gtk_notebook_append_page_menu:
3759 * @notebook: a #GtkNotebook
3760 * @child: the #GtkWidget to use as the contents of the page.
3761 * @tab_label: the #GtkWidget to be used as the label for the page,
3762 * or %NULL to use the default label, 'page N'.
3763 * @menu_label: the widget to use as a label for the page-switch
3764 * menu, if that is enabled. If %NULL, and @tab_label
3765 * is a #GtkLabel or %NULL, then the menu label will be
3766 * a newly created label with the same text as @tab_label;
3767 * If @tab_label is not a #GtkLabel, @menu_label must be
3768 * specified if the page-switch menu is to be used.
3770 * Appends a page to @notebook, specifying the widget to use as the
3771 * label in the popup menu.
3774 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3776 GtkWidget *tab_label,
3777 GtkWidget *menu_label)
3779 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3780 g_return_if_fail (GTK_IS_WIDGET (child));
3781 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3782 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3784 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3788 * gtk_notebook_prepend_page:
3789 * @notebook: a #GtkNotebook
3790 * @child: the #GtkWidget to use as the contents of the page.
3791 * @tab_label: the #GtkWidget to be used as the label for the page,
3792 * or %NULL to use the default label, 'page N'.
3794 * Prepends a page to @notebook.
3797 gtk_notebook_prepend_page (GtkNotebook *notebook,
3799 GtkWidget *tab_label)
3801 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3802 g_return_if_fail (GTK_IS_WIDGET (child));
3803 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3805 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3809 * gtk_notebook_prepend_page_menu:
3810 * @notebook: a #GtkNotebook
3811 * @child: the #GtkWidget to use as the contents of the page.
3812 * @tab_label: the #GtkWidget to be used as the label for the page,
3813 * or %NULL to use the default label, 'page N'.
3814 * @menu_label: the widget to use as a label for the page-switch
3815 * menu, if that is enabled. If %NULL, and @tab_label
3816 * is a #GtkLabel or %NULL, then the menu label will be
3817 * a newly created label with the same text as @tab_label;
3818 * If @tab_label is not a #GtkLabel, @menu_label must be
3819 * specified if the page-switch menu is to be used.
3821 * Prepends a page to @notebook, specifying the widget to use as the
3822 * label in the popup menu.
3825 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3827 GtkWidget *tab_label,
3828 GtkWidget *menu_label)
3830 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3831 g_return_if_fail (GTK_IS_WIDGET (child));
3832 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3833 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3835 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3839 * gtk_notebook_insert_page:
3840 * @notebook: a #GtkNotebook
3841 * @child: the #GtkWidget to use as the contents of the page.
3842 * @tab_label: the #GtkWidget to be used as the label for the page,
3843 * or %NULL to use the default label, 'page N'.
3844 * @position: the index (starting at 0) at which to insert the page,
3845 * or -1 to append the page after all other pages.
3847 * Insert a page into @notebook at the given position
3850 gtk_notebook_insert_page (GtkNotebook *notebook,
3852 GtkWidget *tab_label,
3855 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3856 g_return_if_fail (GTK_IS_WIDGET (child));
3857 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3859 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3864 gtk_notebook_page_compare_tab (gconstpointer a,
3867 return (((GtkNotebookPage *) a)->tab_label != b);
3871 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3875 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3878 list = g_list_find_custom (notebook->children, child,
3879 gtk_notebook_page_compare_tab);
3882 GtkNotebookPage *page = list->data;
3884 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3885 gtk_notebook_switch_page (notebook, page, -1);
3886 focus_tabs_in (notebook);
3893 * gtk_notebook_insert_page_menu:
3894 * @notebook: a #GtkNotebook
3895 * @child: the #GtkWidget to use as the contents of the page.
3896 * @tab_label: the #GtkWidget to be used as the label for the page,
3897 * or %NULL to use the default label, 'page N'.
3898 * @menu_label: the widget to use as a label for the page-switch
3899 * menu, if that is enabled. If %NULL, and @tab_label
3900 * is a #GtkLabel or %NULL, then the menu label will be
3901 * a newly created label with the same text as @tab_label;
3902 * If @tab_label is not a #GtkLabel, @menu_label must be
3903 * specified if the page-switch menu is to be used.
3904 * @position: the index (starting at 0) at which to insert the page,
3905 * or -1 to append the page after all other pages.
3907 * Insert a page into @notebook at the given position, specifying
3908 * the widget to use as the label in the popup menu.
3911 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3913 GtkWidget *tab_label,
3914 GtkWidget *menu_label,
3917 GtkNotebookPage *page;
3920 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3921 g_return_if_fail (GTK_IS_WIDGET (child));
3922 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3923 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3925 gtk_widget_freeze_child_notify (child);
3927 page = g_new (GtkNotebookPage, 1);
3928 page->child = child;
3929 page->last_focus_child = NULL;
3930 page->requisition.width = 0;
3931 page->requisition.height = 0;
3932 page->allocation.x = 0;
3933 page->allocation.y = 0;
3934 page->allocation.width = 0;
3935 page->allocation.height = 0;
3936 page->default_menu = FALSE;
3937 page->default_tab = FALSE;
3938 page->mnemonic_activate_signal = 0;
3940 nchildren = g_list_length (notebook->children);
3941 if ((position < 0) || (position > nchildren))
3942 position = nchildren;
3944 notebook->children = g_list_insert (notebook->children, page, position);
3948 page->default_tab = TRUE;
3949 if (notebook->show_tabs)
3950 tab_label = gtk_label_new ("");
3952 page->tab_label = tab_label;
3953 page->menu_label = menu_label;
3954 page->expand = FALSE;
3956 page->pack = GTK_PACK_START;
3959 page->default_menu = TRUE;
3962 g_object_ref (page->menu_label);
3963 gtk_object_sink (GTK_OBJECT (page->menu_label));
3967 gtk_notebook_menu_item_create (notebook,
3968 g_list_find (notebook->children, page));
3970 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3972 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3974 gtk_notebook_update_labels (notebook);
3976 if (!notebook->first_tab)
3977 notebook->first_tab = notebook->children;
3979 if (!notebook->cur_page)
3980 gtk_widget_set_child_visible (child, TRUE);
3982 gtk_widget_set_child_visible (child, FALSE);
3986 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3987 gtk_widget_show (tab_label);
3989 gtk_widget_hide (tab_label);
3992 if (!notebook->cur_page)
3994 gtk_notebook_switch_page (notebook, page, 0);
3995 gtk_notebook_switch_focus_tab (notebook, NULL);
3999 page->mnemonic_activate_signal =
4000 g_signal_connect (tab_label,
4001 "mnemonic_activate",
4002 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4005 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4006 gdk_window_show_unraised (notebook->event_window);
4008 gtk_widget_child_notify (child, "tab_expand");
4009 gtk_widget_child_notify (child, "tab_fill");
4010 gtk_widget_child_notify (child, "tab_pack");
4011 gtk_widget_child_notify (child, "tab_label");
4012 gtk_widget_child_notify (child, "menu_label");
4013 gtk_widget_child_notify (child, "position");
4014 gtk_widget_thaw_child_notify (child);
4018 * gtk_notebook_remove_page:
4019 * @notebook: a #GtkNotebook.
4020 * @page_num: the index of a notebook page, starting
4021 * from 0. If -1, the last page will
4024 * Removes a page from the notebook given its index
4028 gtk_notebook_remove_page (GtkNotebook *notebook,
4033 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4037 list = g_list_nth (notebook->children, page_num);
4039 gtk_notebook_real_remove (notebook, list);
4043 list = g_list_last (notebook->children);
4045 gtk_notebook_real_remove (notebook, list);
4049 /* Public GtkNotebook Page Switch Methods :
4050 * gtk_notebook_get_current_page
4051 * gtk_notebook_page_num
4052 * gtk_notebook_set_current_page
4053 * gtk_notebook_next_page
4054 * gtk_notebook_prev_page
4057 * gtk_notebook_get_current_page:
4058 * @notebook: a #GtkNotebook
4060 * Returns the page number of the current page.
4062 * Return value: the index (starting from 0) of the current
4063 * page in the notebook. If the notebook has no pages, then
4064 * -1 will be returned.
4067 gtk_notebook_get_current_page (GtkNotebook *notebook)
4069 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4071 if (!notebook->cur_page)
4074 return g_list_index (notebook->children, notebook->cur_page);
4078 * gtk_notebook_get_nth_page:
4079 * @notebook: a #GtkNotebook
4080 * @page_num: the index of a page in the noteobok, or -1
4081 * to get the last page.
4083 * Returns the child widget contained in page number @page_num.
4085 * Return value: the child widget, or %NULL if @page_num is
4089 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4092 GtkNotebookPage *page;
4095 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4098 list = g_list_nth (notebook->children, page_num);
4100 list = g_list_last (notebook->children);
4112 * gtk_notebook_get_n_pages:
4113 * @notebook: a #GtkNotebook
4115 * Gets the number of pages in a notebook.
4117 * Return value: the number of pages in the notebook.
4120 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4122 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4124 return g_list_length (notebook->children);
4128 * gtk_notebook_page_num:
4129 * @notebook: a #GtkNotebook
4130 * @child: a #GtkWidget
4132 * Finds the index of the page which contains the given child
4135 * Return value: the index of the page containing @child, or
4136 * -1 if @child is not in the notebook.
4139 gtk_notebook_page_num (GtkNotebook *notebook,
4145 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4148 children = notebook->children;
4151 GtkNotebookPage *page = children->data;
4153 if (page->child == child)
4156 children = children->next;
4164 * gtk_notebook_set_current_page:
4165 * @notebook: a #GtkNotebook
4166 * @page_num: index of the page to switch to, starting from 0.
4167 * If negative, the last page will be used. If greater
4168 * than the number of pages in the notebook, nothing
4171 * Switches to the page number @page_num.
4174 gtk_notebook_set_current_page (GtkNotebook *notebook,
4179 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4182 list = g_list_nth (notebook->children, page_num);
4184 list = g_list_last (notebook->children);
4186 page_num = g_list_index (notebook->children, list);
4189 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4193 * gtk_notebook_next_page:
4194 * @notebook: a #GtkNotebook
4196 * Switches to the next page. Nothing happens if the current page is
4200 gtk_notebook_next_page (GtkNotebook *notebook)
4204 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4206 list = g_list_find (notebook->children, notebook->cur_page);
4210 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4214 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4218 * gtk_notebook_prev_page:
4219 * @notebook: a #GtkNotebook
4221 * Switches to the previous page. Nothing happens if the current page
4222 * is the first page.
4225 gtk_notebook_prev_page (GtkNotebook *notebook)
4229 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4231 list = g_list_find (notebook->children, notebook->cur_page);
4235 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4239 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4242 /* Public GtkNotebook/Tab Style Functions
4244 * gtk_notebook_set_show_border
4245 * gtk_notebook_set_show_tabs
4246 * gtk_notebook_set_tab_pos
4247 * gtk_notebook_set_homogeneous_tabs
4248 * gtk_notebook_set_tab_border
4249 * gtk_notebook_set_tab_hborder
4250 * gtk_notebook_set_tab_vborder
4251 * gtk_notebook_set_scrollable
4254 * gtk_notebook_set_show_border:
4255 * @notebook: a #GtkNotebook
4256 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4258 * Sets whether a bevel will be drawn around the notebook pages.
4259 * This only has a visual effect when the tabs are not shown.
4260 * See gtk_notebook_set_show_tabs().
4263 gtk_notebook_set_show_border (GtkNotebook *notebook,
4264 gboolean show_border)
4266 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4268 if (notebook->show_border != show_border)
4270 notebook->show_border = show_border;
4272 if (GTK_WIDGET_VISIBLE (notebook))
4273 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4275 g_object_notify (G_OBJECT (notebook), "show_border");
4280 * gtk_notebook_get_show_border:
4281 * @notebook: a #GtkNotebook
4283 * Returns whether a bevel will be drawn around the notebook pages. See
4284 * gtk_notebook_set_show_border().
4286 * Return value: %TRUE if the bevel is drawn
4289 gtk_notebook_get_show_border (GtkNotebook *notebook)
4291 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4293 return notebook->show_border;
4297 * gtk_notebook_set_show_tabs:
4298 * @notebook: a #GtkNotebook
4299 * @show_tabs: %TRUE if the tabs should be shown.
4301 * Sets whether to show the tabs for the notebook or not.
4304 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4307 GtkNotebookPage *page;
4310 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4312 show_tabs = show_tabs != FALSE;
4314 if (notebook->show_tabs == show_tabs)
4317 notebook->show_tabs = show_tabs;
4318 children = notebook->children;
4322 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4326 page = children->data;
4327 children = children->next;
4328 if (page->default_tab)
4330 gtk_widget_destroy (page->tab_label);
4331 page->tab_label = NULL;
4334 gtk_widget_hide (page->tab_label);
4339 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4340 gtk_notebook_update_labels (notebook);
4342 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4344 g_object_notify (G_OBJECT (notebook), "show_tabs");
4348 * gtk_notebook_get_show_tabs:
4349 * @notebook: a #GtkNotebook
4351 * Returns whether the tabs of the notebook are shown. See
4352 * gtk_notebook_set_show_tabs().
4354 * Return value: %TRUE if the tabs are shown
4357 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4359 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4361 return notebook->show_tabs;
4365 * gtk_notebook_set_tab_pos:
4366 * @notebook: a #GtkNotebook.
4367 * @pos: the edge to draw the tabs at.
4369 * Sets the edge at which the tabs for switching pages in the
4370 * notebook are drawn.
4373 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4374 GtkPositionType pos)
4376 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4378 if (notebook->tab_pos != pos)
4380 notebook->tab_pos = pos;
4381 if (GTK_WIDGET_VISIBLE (notebook))
4382 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4385 g_object_notify (G_OBJECT (notebook), "tab_pos");
4389 * gtk_notebook_get_tab_pos:
4390 * @notebook: a #GtkNotebook
4392 * Gets the edge at which the tabs for switching pages in the
4393 * notebook are drawn.
4395 * Return value: the edge at which the tabs are drawn
4398 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4400 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4402 return notebook->tab_pos;
4406 * gtk_notebook_set_homogeneous_tabs:
4407 * @notebook: a #GtkNotebook
4408 * @homogeneous: %TRUE if all tabs should be the same size.
4410 * Sets whether the tabs must have all the same size or not.
4413 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4414 gboolean homogeneous)
4416 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4418 if (homogeneous == notebook->homogeneous)
4421 notebook->homogeneous = homogeneous;
4422 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4424 g_object_notify (G_OBJECT (notebook), "homogeneous");
4428 * gtk_notebook_set_tab_border:
4429 * @notebook: a #GtkNotebook
4430 * @border_width: width of the border around the tab labels.
4432 * Sets the width the border around the tab labels
4433 * in a notebook. This is equivalent to calling
4434 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4435 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4438 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4441 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4443 notebook->tab_hborder = border_width;
4444 notebook->tab_vborder = border_width;
4446 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4447 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4449 g_object_freeze_notify (G_OBJECT (notebook));
4450 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4451 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4452 g_object_thaw_notify (G_OBJECT (notebook));
4457 * gtk_notebook_set_tab_hborder:
4458 * @notebook: a #GtkNotebook
4459 * @tab_hborder: width of the horizontal border of tab labels.
4461 * Sets the width of the horizontal border of tab labels.
4464 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4467 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4469 if (notebook->tab_hborder == tab_hborder)
4472 notebook->tab_hborder = tab_hborder;
4474 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4475 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4477 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4481 * gtk_notebook_set_tab_vborder:
4482 * @notebook: a #GtkNotebook
4483 * @tab_vborder: width of the vertical border of tab labels.
4485 * Sets the width of the vertical border of tab labels.
4488 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4491 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4493 if (notebook->tab_vborder == tab_vborder)
4496 notebook->tab_vborder = tab_vborder;
4498 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4499 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4501 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4505 * gtk_notebook_set_scrollable:
4506 * @notebook: a #GtkNotebook
4507 * @scrollable: %TRUE if scroll arrows should be added
4509 * Sets whether the tab label area will have arrows for scrolling if
4510 * there are too many tabs to fit in the area.
4513 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4514 gboolean scrollable)
4516 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4518 scrollable = (scrollable != FALSE);
4520 if (scrollable != notebook->scrollable)
4522 notebook->scrollable = scrollable;
4524 if (GTK_WIDGET_VISIBLE (notebook))
4525 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4527 g_object_notify (G_OBJECT (notebook), "scrollable");
4532 * gtk_notebook_get_scrollable:
4533 * @notebook: a #GtkNotebook
4535 * Returns whether the tab label area has arrows for scrolling. See
4536 * gtk_notebook_set_scrollable().
4538 * Return value: %TRUE if arrows for scrolling are present
4541 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4543 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4545 return notebook->scrollable;
4548 /* Public GtkNotebook Popup Menu Methods:
4550 * gtk_notebook_popup_enable
4551 * gtk_notebook_popup_disable
4556 * gtk_notebook_popup_enable:
4557 * @notebook: a #GtkNotebook
4559 * Enables the popup menu: if the user clicks with the right mouse button on
4560 * the bookmarks, a menu with all the pages will be popped up.
4563 gtk_notebook_popup_enable (GtkNotebook *notebook)
4567 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4572 notebook->menu = gtk_menu_new ();
4573 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4575 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4576 gtk_notebook_menu_item_create (notebook, list);
4578 gtk_notebook_update_labels (notebook);
4579 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4580 GTK_WIDGET (notebook),
4581 gtk_notebook_menu_detacher);
4583 g_object_notify (G_OBJECT (notebook), "enable_popup");
4587 * gtk_notebook_popup_disable:
4588 * @notebook: a #GtkNotebook
4590 * Disables the popup menu.
4593 gtk_notebook_popup_disable (GtkNotebook *notebook)
4595 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4597 if (!notebook->menu)
4600 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4601 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4602 gtk_widget_destroy (notebook->menu);
4604 g_object_notify (G_OBJECT (notebook), "enable_popup");
4607 /* Public GtkNotebook Page Properties Functions:
4609 * gtk_notebook_get_tab_label
4610 * gtk_notebook_set_tab_label
4611 * gtk_notebook_set_tab_label_text
4612 * gtk_notebook_get_menu_label
4613 * gtk_notebook_set_menu_label
4614 * gtk_notebook_set_menu_label_text
4615 * gtk_notebook_set_tab_label_packing
4616 * gtk_notebook_query_tab_label_packing
4620 * gtk_notebook_get_tab_label:
4621 * @notebook: a #GtkNotebook
4624 * Returns the tab label widget for the page @child. %NULL is returned
4625 * if @child is not in @notebook or if no tab label has specifically
4626 * been set for @child.
4628 * Return value: the tab label
4631 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4636 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4637 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4639 list = CHECK_FIND_CHILD (notebook, child);
4643 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4646 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4650 * gtk_notebook_set_tab_label:
4651 * @notebook: a #GtkNotebook
4653 * @tab_label: the tab label widget to use, or %NULL for default tab
4656 * Changes the tab label for @child. If %NULL is specified
4657 * for @tab_label, then the page will have the label 'page N'.
4660 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4662 GtkWidget *tab_label)
4664 GtkNotebookPage *page;
4667 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4668 g_return_if_fail (GTK_IS_WIDGET (child));
4670 list = CHECK_FIND_CHILD (notebook, child);
4674 /* a NULL pointer indicates a default_tab setting, otherwise
4675 * we need to set the associated label
4679 if (page->tab_label == tab_label)
4683 gtk_notebook_remove_tab_label (notebook, page);
4687 page->default_tab = FALSE;
4688 page->tab_label = tab_label;
4689 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4693 page->default_tab = TRUE;
4694 page->tab_label = NULL;
4696 if (notebook->show_tabs)
4700 g_snprintf (string, sizeof(string), _("Page %u"),
4701 gtk_notebook_real_page_position (notebook, list));
4702 page->tab_label = gtk_label_new (string);
4703 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4707 if (page->tab_label)
4708 page->mnemonic_activate_signal =
4709 g_signal_connect (page->tab_label,
4710 "mnemonic_activate",
4711 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4714 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4716 gtk_widget_show (page->tab_label);
4717 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4719 gtk_widget_child_notify (child, "tab_label");
4723 * gtk_notebook_set_tab_label_text:
4724 * @notebook: a #GtkNotebook
4726 * @tab_text: the label text
4728 * Creates a new label and sets it as the tab label for the page
4729 * containing @child.
4732 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4734 const gchar *tab_text)
4736 GtkWidget *tab_label = NULL;
4738 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4741 tab_label = gtk_label_new (tab_text);
4742 gtk_notebook_set_tab_label (notebook, child, tab_label);
4743 gtk_widget_child_notify (child, "tab_label");
4747 * gtk_notebook_get_tab_label_text:
4748 * @notebook: a #GtkNotebook
4749 * @child: a widget contained in a page of @notebook
4751 * Retrieves the text of the tab label for the page containing
4754 * Returns value: the text of the tab label, or %NULL if the
4755 * tab label widget is not a #GtkLabel. The
4756 * string is owned by the widget and must not
4759 G_CONST_RETURN gchar *
4760 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4763 GtkWidget *tab_label;
4765 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4766 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4768 tab_label = gtk_notebook_get_tab_label (notebook, child);
4770 if (tab_label && GTK_IS_LABEL (tab_label))
4771 return gtk_label_get_text (GTK_LABEL (tab_label));
4777 * gtk_notebook_get_menu_label:
4778 * @notebook: a #GtkNotebook
4779 * @child: a widget contained in a page of @notebook
4781 * Retrieves the menu label widget of the page containing @child.
4783 * Return value: the menu label, or %NULL if the
4784 * notebook page does not have a menu label other
4785 * than the default (the tab label).
4788 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4793 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4794 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4796 list = CHECK_FIND_CHILD (notebook, child);
4800 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4803 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4807 * gtk_notebook_set_menu_label:
4808 * @notebook: a #GtkNotebook
4809 * @child: the child widget
4810 * @menu_label: the menu label, or NULL for default
4812 * Changes the menu label for the page containing @child.
4815 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4817 GtkWidget *menu_label)
4819 GtkNotebookPage *page;
4822 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4823 g_return_if_fail (GTK_IS_WIDGET (child));
4825 list = CHECK_FIND_CHILD (notebook, child);
4830 if (page->menu_label)
4833 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4834 page->menu_label->parent);
4836 if (!page->default_menu)
4837 g_object_unref (page->menu_label);
4842 page->menu_label = menu_label;
4843 g_object_ref (page->menu_label);
4844 gtk_object_sink (GTK_OBJECT(page->menu_label));
4845 page->default_menu = FALSE;
4848 page->default_menu = TRUE;
4851 gtk_notebook_menu_item_create (notebook, list);
4852 gtk_widget_child_notify (child, "menu_label");
4856 * gtk_notebook_set_menu_label_text:
4857 * @notebook: a #GtkNotebook
4858 * @child: the child widget
4859 * @menu_text: the label text
4861 * Creates a new label and sets it as the menu label of @child.
4864 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4866 const gchar *menu_text)
4868 GtkWidget *menu_label = NULL;
4870 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4873 menu_label = gtk_label_new (menu_text);
4874 gtk_notebook_set_menu_label (notebook, child, menu_label);
4875 gtk_widget_child_notify (child, "menu_label");
4879 * gtk_notebook_get_menu_label_text:
4880 * @notebook: a #GtkNotebook
4881 * @child: the child widget of a page of the notebook.
4883 * Retrieves the text of the menu label for the page containing
4886 * Returns value: the text of the tab label, or %NULL if the
4887 * widget does not have a menu label other than
4888 * the default menu label, or the menu label widget
4889 * is not a #GtkLabel. The string is owned by
4890 * the widget and must not be freed.
4892 G_CONST_RETURN gchar *
4893 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4896 GtkWidget *menu_label;
4898 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4899 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4901 menu_label = gtk_notebook_get_menu_label (notebook, child);
4903 if (menu_label && GTK_IS_LABEL (menu_label))
4904 return gtk_label_get_text (GTK_LABEL (menu_label));
4909 /* Helper function called when pages are reordered
4912 gtk_notebook_child_reordered (GtkNotebook *notebook,
4913 GtkNotebookPage *page)
4917 GtkWidget *menu_item;
4919 menu_item = page->menu_label->parent;
4920 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4921 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4922 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4925 gtk_notebook_update_labels (notebook);
4929 * gtk_notebook_set_tab_label_packing:
4930 * @notebook: a #GtkNotebook
4931 * @child: the child widget
4932 * @expand: whether to expand the bookmark or not
4933 * @fill: whether the bookmark should fill the allocated area or not
4934 * @pack_type: the position of the bookmark
4936 * Sets the packing parameters for the tab label of the page
4937 * containing @child. See gtk_box_pack_start() for the exact meaning
4938 * of the parameters.
4941 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4945 GtkPackType pack_type)
4947 GtkNotebookPage *page;
4950 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4951 g_return_if_fail (GTK_IS_WIDGET (child));
4953 list = CHECK_FIND_CHILD (notebook, child);
4958 expand = expand != FALSE;
4959 fill = fill != FALSE;
4960 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4963 gtk_widget_freeze_child_notify (child);
4964 page->expand = expand;
4965 gtk_widget_child_notify (child, "tab_expand");
4967 gtk_widget_child_notify (child, "tab_fill");
4968 if (page->pack != pack_type)
4970 page->pack = pack_type;
4971 gtk_notebook_child_reordered (notebook, page);
4973 gtk_widget_child_notify (child, "tab_pack");
4974 gtk_widget_child_notify (child, "position");
4975 if (notebook->show_tabs)
4976 gtk_notebook_pages_allocate (notebook);
4977 gtk_widget_thaw_child_notify (child);
4981 * gtk_notebook_query_tab_label_packing:
4982 * @notebook: a #GtkNotebook
4984 * @expand: location to store the expand value (or NULL)
4985 * @fill: location to store the fill value (or NULL)
4986 * @pack_type: location to store the pack_type (or NULL)
4988 * Query the packing attributes for the tab label of the page
4989 * containing @child.
4992 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4996 GtkPackType *pack_type)
5000 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5001 g_return_if_fail (GTK_IS_WIDGET (child));
5003 list = CHECK_FIND_CHILD (notebook, child);
5008 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5010 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5012 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5016 * gtk_notebook_reorder_child:
5017 * @notebook: a #GtkNotebook
5018 * @child: the child to move
5019 * @position: the new position, or -1 to move to the end
5021 * Reorders the page containing @child, so that it appears in position
5022 * @position. If @position is greater than or equal to the number of
5023 * children in the list or negative, @child will be moved to the end
5027 gtk_notebook_reorder_child (GtkNotebook *notebook,
5031 GList *list, *new_list;
5032 GtkNotebookPage *page;
5036 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5037 g_return_if_fail (GTK_IS_WIDGET (child));
5039 list = CHECK_FIND_CHILD (notebook, child);
5043 max_pos = g_list_length (notebook->children) - 1;
5044 if (position < 0 || position > max_pos)
5047 old_pos = g_list_position (notebook->children, list);
5049 if (old_pos == position)
5053 notebook->children = g_list_delete_link (notebook->children, list);
5055 notebook->children = g_list_insert (notebook->children, page, position);
5056 new_list = g_list_nth (notebook->children, position);
5058 /* Fix up GList references in GtkNotebook structure */
5059 if (notebook->first_tab == list)
5060 notebook->first_tab = new_list;
5061 if (notebook->focus_tab == list)
5062 notebook->focus_tab = new_list;
5064 gtk_widget_freeze_child_notify (child);
5066 /* Move around the menu items if necesary */
5067 gtk_notebook_child_reordered (notebook, page);
5068 gtk_widget_child_notify (child, "tab_pack");
5069 gtk_widget_child_notify (child, "position");
5071 if (notebook->show_tabs)
5072 gtk_notebook_pages_allocate (notebook);
5074 gtk_widget_thaw_child_notify (child);