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 /*** GtkNotebook Private Setters ***/
252 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
253 gboolean homogeneous);
254 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
256 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
258 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
261 static gboolean focus_tabs_in (GtkNotebook *notebook);
262 static gboolean focus_child_in (GtkNotebook *notebook,
263 GtkDirectionType direction);
265 static GtkContainerClass *parent_class = NULL;
266 static guint notebook_signals[LAST_SIGNAL] = { 0 };
269 gtk_notebook_get_type (void)
271 static GType notebook_type = 0;
275 static const GTypeInfo notebook_info =
277 sizeof (GtkNotebookClass),
278 NULL, /* base_init */
279 NULL, /* base_finalize */
280 (GClassInitFunc) gtk_notebook_class_init,
281 NULL, /* class_finalize */
282 NULL, /* class_data */
283 sizeof (GtkNotebook),
285 (GInstanceInitFunc) gtk_notebook_init,
288 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
292 return notebook_type;
296 add_tab_bindings (GtkBindingSet *binding_set,
297 GdkModifierType modifiers,
298 GtkDirectionType direction)
300 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
302 GTK_TYPE_DIRECTION_TYPE, direction);
303 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
305 GTK_TYPE_DIRECTION_TYPE, direction);
309 add_arrow_bindings (GtkBindingSet *binding_set,
311 GtkDirectionType direction)
313 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
315 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
317 GTK_TYPE_DIRECTION_TYPE, direction);
318 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
320 GTK_TYPE_DIRECTION_TYPE, direction);
324 gtk_notebook_class_init (GtkNotebookClass *class)
326 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
327 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
328 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
329 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
330 GtkBindingSet *binding_set;
332 parent_class = g_type_class_peek_parent (class);
334 gobject_class->set_property = gtk_notebook_set_property;
335 gobject_class->get_property = gtk_notebook_get_property;
336 object_class->destroy = gtk_notebook_destroy;
338 widget_class->map = gtk_notebook_map;
339 widget_class->unmap = gtk_notebook_unmap;
340 widget_class->realize = gtk_notebook_realize;
341 widget_class->unrealize = gtk_notebook_unrealize;
342 widget_class->size_request = gtk_notebook_size_request;
343 widget_class->size_allocate = gtk_notebook_size_allocate;
344 widget_class->expose_event = gtk_notebook_expose;
345 widget_class->button_press_event = gtk_notebook_button_press;
346 widget_class->button_release_event = gtk_notebook_button_release;
347 widget_class->enter_notify_event = gtk_notebook_enter_notify;
348 widget_class->leave_notify_event = gtk_notebook_leave_notify;
349 widget_class->motion_notify_event = gtk_notebook_motion_notify;
350 widget_class->focus_in_event = gtk_notebook_focus_in;
351 widget_class->focus = gtk_notebook_focus;
353 container_class->add = gtk_notebook_add;
354 container_class->remove = gtk_notebook_remove;
355 container_class->forall = gtk_notebook_forall;
356 container_class->set_focus_child = gtk_notebook_set_focus_child;
357 container_class->get_child_property = gtk_notebook_get_child_property;
358 container_class->set_child_property = gtk_notebook_set_child_property;
359 container_class->child_type = gtk_notebook_child_type;
361 class->switch_page = gtk_notebook_real_switch_page;
363 class->focus_tab = gtk_notebook_focus_tab;
364 class->select_page = gtk_notebook_select_page;
365 class->change_current_page = gtk_notebook_change_current_page;
366 class->move_focus_out = gtk_notebook_move_focus_out;
368 g_object_class_install_property (gobject_class,
370 g_param_spec_int ("page",
372 _("The index of the current page"),
377 g_object_class_install_property (gobject_class,
379 g_param_spec_enum ("tab_pos",
381 _("Which side of the notebook holds the tabs"),
382 GTK_TYPE_POSITION_TYPE,
385 g_object_class_install_property (gobject_class,
387 g_param_spec_uint ("tab_border",
389 _("Width of the border around the tab labels"),
394 g_object_class_install_property (gobject_class,
396 g_param_spec_uint ("tab_hborder",
397 _("Horizontal Tab Border"),
398 _("Width of the horizontal border of tab labels"),
403 g_object_class_install_property (gobject_class,
405 g_param_spec_uint ("tab_vborder",
406 _("Vertical Tab Border"),
407 _("Width of the vertical border of tab labels"),
412 g_object_class_install_property (gobject_class,
414 g_param_spec_boolean ("show_tabs",
416 _("Whether tabs should be shown or not"),
419 g_object_class_install_property (gobject_class,
421 g_param_spec_boolean ("show_border",
423 _("Whether the border should be shown or not"),
426 g_object_class_install_property (gobject_class,
428 g_param_spec_boolean ("scrollable",
430 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
433 g_object_class_install_property (gobject_class,
435 g_param_spec_boolean ("enable_popup",
437 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
440 g_object_class_install_property (gobject_class,
442 g_param_spec_boolean ("homogeneous",
444 _("Whether tabs should have homogeneous sizes"),
448 gtk_container_class_install_child_property (container_class,
449 CHILD_PROP_TAB_LABEL,
450 g_param_spec_string ("tab_label",
452 _("The string displayed on the childs tab label"),
455 gtk_container_class_install_child_property (container_class,
456 CHILD_PROP_MENU_LABEL,
457 g_param_spec_string ("menu_label",
459 _("The string displayed in the childs menu entry"),
462 gtk_container_class_install_child_property (container_class,
464 g_param_spec_int ("position",
466 _("The index of the child in the parent"),
469 gtk_container_class_install_child_property (container_class,
470 CHILD_PROP_TAB_EXPAND,
471 g_param_spec_boolean ("tab_expand",
473 _("Whether to expand the childs tab or not"),
476 gtk_container_class_install_child_property (container_class,
478 g_param_spec_boolean ("tab_fill",
480 _("Wheather the childs tab should fill the allocated area or not"),
483 gtk_container_class_install_child_property (container_class,
485 g_param_spec_enum ("tab_pack",
487 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
488 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
491 notebook_signals[SWITCH_PAGE] =
492 g_signal_new ("switch_page",
493 G_TYPE_FROM_CLASS (gobject_class),
495 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
497 _gtk_marshal_VOID__POINTER_UINT,
501 notebook_signals[FOCUS_TAB] =
502 g_signal_new ("focus_tab",
503 G_TYPE_FROM_CLASS (gobject_class),
504 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
505 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
507 _gtk_marshal_BOOLEAN__ENUM,
509 GTK_TYPE_NOTEBOOK_TAB);
510 notebook_signals[SELECT_PAGE] =
511 g_signal_new ("select_page",
512 G_TYPE_FROM_CLASS (gobject_class),
513 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
514 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
516 _gtk_marshal_BOOLEAN__BOOLEAN,
519 notebook_signals[CHANGE_CURRENT_PAGE] =
520 g_signal_new ("change_current_page",
521 G_TYPE_FROM_CLASS (gobject_class),
522 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
523 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
525 _gtk_marshal_VOID__INT,
528 notebook_signals[MOVE_FOCUS_OUT] =
529 g_signal_new ("move_focus_out",
530 G_TYPE_FROM_CLASS (gobject_class),
531 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
532 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
534 _gtk_marshal_VOID__ENUM,
536 GTK_TYPE_DIRECTION_TYPE);
539 binding_set = gtk_binding_set_by_class (class);
540 gtk_binding_entry_add_signal (binding_set,
543 G_TYPE_BOOLEAN, FALSE);
544 gtk_binding_entry_add_signal (binding_set,
547 G_TYPE_BOOLEAN, FALSE);
549 gtk_binding_entry_add_signal (binding_set,
552 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
553 gtk_binding_entry_add_signal (binding_set,
556 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
557 gtk_binding_entry_add_signal (binding_set,
560 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
561 gtk_binding_entry_add_signal (binding_set,
564 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
566 gtk_binding_entry_add_signal (binding_set,
567 GDK_Page_Up, GDK_CONTROL_MASK,
568 "change_current_page", 1,
570 gtk_binding_entry_add_signal (binding_set,
571 GDK_Page_Down, GDK_CONTROL_MASK,
572 "change_current_page", 1,
575 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
576 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
577 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
578 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
580 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
581 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
585 gtk_notebook_init (GtkNotebook *notebook)
587 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
588 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
590 notebook->cur_page = NULL;
591 notebook->children = NULL;
592 notebook->first_tab = NULL;
593 notebook->focus_tab = NULL;
594 notebook->event_window = NULL;
595 notebook->menu = NULL;
597 notebook->tab_hborder = 2;
598 notebook->tab_vborder = 2;
600 notebook->show_tabs = TRUE;
601 notebook->show_border = TRUE;
602 notebook->tab_pos = GTK_POS_TOP;
603 notebook->scrollable = FALSE;
604 notebook->in_child = 0;
605 notebook->click_child = 0;
606 notebook->button = 0;
607 notebook->need_timer = 0;
608 notebook->child_has_focus = FALSE;
609 notebook->have_visible_child = FALSE;
610 notebook->focus_out = FALSE;
614 gtk_notebook_select_page (GtkNotebook *notebook,
617 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
619 gtk_notebook_page_select (notebook, move_focus);
627 gtk_notebook_focus_tab (GtkNotebook *notebook,
632 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
636 case GTK_NOTEBOOK_TAB_FIRST:
637 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
639 gtk_notebook_switch_focus_tab (notebook, list);
641 case GTK_NOTEBOOK_TAB_LAST:
642 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
644 gtk_notebook_switch_focus_tab (notebook, list);
655 gtk_notebook_change_current_page (GtkNotebook *notebook,
658 GList *current = NULL;
660 if (notebook->cur_page)
661 current = g_list_find (notebook->children, notebook->cur_page);
665 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
666 offset += offset < 0 ? 1 : -1;
670 gtk_notebook_switch_page (notebook, current->data, -1);
672 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
675 static GtkDirectionType
676 get_effective_direction (GtkNotebook *notebook,
677 GtkDirectionType direction)
679 /* Remap the directions into the effective direction it would be for a
680 * GTK_POS_TOP notebook
682 #define D(rest) GTK_DIR_##rest
684 static const GtkDirectionType translate_direction[4][6] = {
685 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
686 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
687 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
688 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
693 return translate_direction[notebook->tab_pos][direction];
697 gtk_notebook_move_focus_out (GtkNotebook *notebook,
698 GtkDirectionType direction_type)
700 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
703 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
704 if (focus_tabs_in (notebook))
707 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
708 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
711 /* At this point, we know we should be focusing out of the notebook entirely. We
712 * do this by setting a flag, then propagating the focus motion to the notebook.
714 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
715 if (!GTK_WIDGET_TOPLEVEL (toplevel))
718 g_object_ref (notebook);
720 notebook->focus_out = TRUE;
721 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
722 notebook->focus_out = FALSE;
724 g_object_unref (notebook);
731 * Creates a new #GtkNotebook widget with no pages.
733 * Return value: the newly created #GtkNotebook
736 gtk_notebook_new (void)
738 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
741 /* Private GtkObject Methods :
743 * gtk_notebook_destroy
744 * gtk_notebook_set_arg
745 * gtk_notebook_get_arg
748 gtk_notebook_destroy (GtkObject *object)
750 GtkNotebook *notebook = GTK_NOTEBOOK (object);
753 gtk_notebook_popup_disable (notebook);
755 GTK_OBJECT_CLASS (parent_class)->destroy (object);
759 gtk_notebook_set_property (GObject *object,
764 GtkNotebook *notebook;
766 notebook = GTK_NOTEBOOK (object);
771 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
773 case PROP_SHOW_BORDER:
774 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
776 case PROP_SCROLLABLE:
777 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
779 case PROP_ENABLE_POPUP:
780 if (g_value_get_boolean (value))
781 gtk_notebook_popup_enable (notebook);
783 gtk_notebook_popup_disable (notebook);
785 case PROP_HOMOGENEOUS:
786 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
789 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
792 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
794 case PROP_TAB_BORDER:
795 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
797 case PROP_TAB_HBORDER:
798 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
800 case PROP_TAB_VBORDER:
801 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
809 gtk_notebook_get_property (GObject *object,
814 GtkNotebook *notebook;
816 notebook = GTK_NOTEBOOK (object);
821 g_value_set_boolean (value, notebook->show_tabs);
823 case PROP_SHOW_BORDER:
824 g_value_set_boolean (value, notebook->show_border);
826 case PROP_SCROLLABLE:
827 g_value_set_boolean (value, notebook->scrollable);
829 case PROP_ENABLE_POPUP:
830 g_value_set_boolean (value, notebook->menu != NULL);
832 case PROP_HOMOGENEOUS:
833 g_value_set_boolean (value, notebook->homogeneous);
836 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
839 g_value_set_enum (value, notebook->tab_pos);
841 case PROP_TAB_HBORDER:
842 g_value_set_uint (value, notebook->tab_hborder);
844 case PROP_TAB_VBORDER:
845 g_value_set_uint (value, notebook->tab_vborder);
848 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
853 /* Private GtkWidget Methods :
857 * gtk_notebook_realize
858 * gtk_notebook_size_request
859 * gtk_notebook_size_allocate
860 * gtk_notebook_expose
861 * gtk_notebook_button_press
862 * gtk_notebook_button_release
863 * gtk_notebook_enter_notify
864 * gtk_notebook_leave_notify
865 * gtk_notebook_motion_notify
866 * gtk_notebook_focus_in
867 * gtk_notebook_focus_out
868 * gtk_notebook_draw_focus
869 * gtk_notebook_style_set
872 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
873 GdkRectangle *rectangle)
875 GtkWidget *widget = GTK_WIDGET (notebook);
876 gint border_width = GTK_CONTAINER (notebook)->border_width;
877 GtkNotebookPage *visible_page = NULL;
880 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
882 GtkNotebookPage *page = tmp_list->data;
883 if (GTK_WIDGET_VISIBLE (page->child))
890 if (notebook->show_tabs && visible_page)
894 rectangle->x = widget->allocation.x + border_width;
895 rectangle->y = widget->allocation.y + border_width;
897 switch (notebook->tab_pos)
901 rectangle->width = widget->allocation.width - 2 * border_width;
902 rectangle->height = visible_page->requisition.height;
903 if (notebook->tab_pos == GTK_POS_BOTTOM)
904 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
908 rectangle->width = visible_page->requisition.width;
909 rectangle->height = widget->allocation.height - 2 * border_width;
910 if (notebook->tab_pos == GTK_POS_RIGHT)
911 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
922 rectangle->x = rectangle->y = 0;
923 rectangle->width = rectangle->height = 10;
931 gtk_notebook_map (GtkWidget *widget)
933 GtkNotebook *notebook;
934 GtkNotebookPage *page;
937 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
939 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
941 notebook = GTK_NOTEBOOK (widget);
943 if (notebook->cur_page &&
944 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
945 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
946 gtk_widget_map (notebook->cur_page->child);
948 if (notebook->scrollable)
949 gtk_notebook_pages_allocate (notebook);
952 children = notebook->children;
956 page = children->data;
957 children = children->next;
959 if (page->tab_label &&
960 GTK_WIDGET_VISIBLE (page->tab_label) &&
961 !GTK_WIDGET_MAPPED (page->tab_label))
962 gtk_widget_map (page->tab_label);
966 if (gtk_notebook_get_event_window_position (notebook, NULL))
967 gdk_window_show_unraised (notebook->event_window);
971 gtk_notebook_unmap (GtkWidget *widget)
973 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
975 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
977 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
979 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
983 gtk_notebook_realize (GtkWidget *widget)
985 GtkNotebook *notebook;
986 GdkWindowAttr attributes;
987 gint attributes_mask;
988 GdkRectangle event_window_pos;
990 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
992 notebook = GTK_NOTEBOOK (widget);
993 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
995 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
997 widget->window = gtk_widget_get_parent_window (widget);
998 g_object_ref (widget->window);
1000 attributes.window_type = GDK_WINDOW_CHILD;
1001 attributes.x = event_window_pos.x;
1002 attributes.y = event_window_pos.y;
1003 attributes.width = event_window_pos.width;
1004 attributes.height = event_window_pos.height;
1005 attributes.wclass = GDK_INPUT_ONLY;
1006 attributes.event_mask = gtk_widget_get_events (widget);
1007 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
1008 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1010 attributes_mask = GDK_WA_X | GDK_WA_Y;
1012 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1013 &attributes, attributes_mask);
1014 gdk_window_set_user_data (notebook->event_window, notebook);
1016 widget->style = gtk_style_attach (widget->style, widget->window);
1020 gtk_notebook_unrealize (GtkWidget *widget)
1022 GtkNotebook *notebook;
1024 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1026 notebook = GTK_NOTEBOOK (widget);
1028 gdk_window_set_user_data (notebook->event_window, NULL);
1029 gdk_window_destroy (notebook->event_window);
1030 notebook->event_window = NULL;
1032 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1033 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1037 gtk_notebook_size_request (GtkWidget *widget,
1038 GtkRequisition *requisition)
1040 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1041 GtkNotebookPage *page;
1043 GtkRequisition child_requisition;
1044 gboolean switch_page = FALSE;
1048 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1050 widget->requisition.width = 0;
1051 widget->requisition.height = 0;
1053 for (children = notebook->children, vis_pages = 0; children;
1054 children = children->next)
1056 page = children->data;
1058 if (GTK_WIDGET_VISIBLE (page->child))
1061 gtk_widget_size_request (page->child, &child_requisition);
1063 widget->requisition.width = MAX (widget->requisition.width,
1064 child_requisition.width);
1065 widget->requisition.height = MAX (widget->requisition.height,
1066 child_requisition.height);
1068 if (notebook->menu && page->menu_label->parent &&
1069 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1070 gtk_widget_show (page->menu_label->parent);
1074 if (page == notebook->cur_page)
1076 if (notebook->menu && page->menu_label->parent &&
1077 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1078 gtk_widget_hide (page->menu_label->parent);
1082 if (notebook->show_border || notebook->show_tabs)
1084 widget->requisition.width += widget->style->xthickness * 2;
1085 widget->requisition.height += widget->style->ythickness * 2;
1087 if (notebook->show_tabs)
1090 gint tab_height = 0;
1094 for (children = notebook->children; children;
1095 children = children->next)
1097 page = children->data;
1099 if (GTK_WIDGET_VISIBLE (page->child))
1101 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1102 gtk_widget_show (page->tab_label);
1104 gtk_widget_size_request (page->tab_label,
1105 &child_requisition);
1107 page->requisition.width =
1108 child_requisition.width +
1109 2 * widget->style->xthickness;
1110 page->requisition.height =
1111 child_requisition.height +
1112 2 * widget->style->ythickness;
1114 switch (notebook->tab_pos)
1117 case GTK_POS_BOTTOM:
1118 page->requisition.height += 2 * (notebook->tab_vborder +
1120 tab_height = MAX (tab_height, page->requisition.height);
1121 tab_max = MAX (tab_max, page->requisition.width);
1125 page->requisition.width += 2 * (notebook->tab_hborder +
1127 tab_width = MAX (tab_width, page->requisition.width);
1128 tab_max = MAX (tab_max, page->requisition.height);
1132 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1133 gtk_widget_hide (page->tab_label);
1136 children = notebook->children;
1140 switch (notebook->tab_pos)
1143 case GTK_POS_BOTTOM:
1144 if (tab_height == 0)
1147 if (notebook->scrollable && vis_pages > 1 &&
1148 widget->requisition.width < tab_width)
1149 tab_height = MAX (tab_height, ARROW_SIZE);
1151 padding = 2 * (TAB_CURVATURE + focus_width +
1152 notebook->tab_hborder) - TAB_OVERLAP;
1156 page = children->data;
1157 children = children->next;
1159 if (!GTK_WIDGET_VISIBLE (page->child))
1162 if (notebook->homogeneous)
1163 page->requisition.width = tab_max;
1165 page->requisition.width += padding;
1167 tab_width += page->requisition.width;
1168 page->requisition.height = tab_height;
1171 if (notebook->scrollable && vis_pages > 1 &&
1172 widget->requisition.width < tab_width)
1173 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1175 if (notebook->homogeneous && !notebook->scrollable)
1176 widget->requisition.width = MAX (widget->requisition.width,
1177 vis_pages * tab_max +
1180 widget->requisition.width = MAX (widget->requisition.width,
1181 tab_width + TAB_OVERLAP);
1183 widget->requisition.height += tab_height;
1190 if (notebook->scrollable && vis_pages > 1 &&
1191 widget->requisition.height < tab_height)
1192 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1194 padding = 2 * (TAB_CURVATURE + focus_width +
1195 notebook->tab_vborder) - TAB_OVERLAP;
1200 page = children->data;
1201 children = children->next;
1203 if (!GTK_WIDGET_VISIBLE (page->child))
1206 page->requisition.width = tab_width;
1208 if (notebook->homogeneous)
1209 page->requisition.height = tab_max;
1211 page->requisition.height += padding;
1213 tab_height += page->requisition.height;
1216 if (notebook->scrollable && vis_pages > 1 &&
1217 widget->requisition.height < tab_height)
1218 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1220 widget->requisition.width += tab_width;
1222 if (notebook->homogeneous && !notebook->scrollable)
1223 widget->requisition.height =
1224 MAX (widget->requisition.height,
1225 vis_pages * tab_max + TAB_OVERLAP);
1227 widget->requisition.height =
1228 MAX (widget->requisition.height,
1229 tab_height + TAB_OVERLAP);
1231 if (!notebook->homogeneous || notebook->scrollable)
1233 widget->requisition.height = MAX (widget->requisition.height,
1234 vis_pages * tab_max +
1242 for (children = notebook->children; children;
1243 children = children->next)
1245 page = children->data;
1247 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1248 gtk_widget_hide (page->tab_label);
1253 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1254 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1260 for (children = notebook->children; children;
1261 children = children->next)
1263 page = children->data;
1264 if (GTK_WIDGET_VISIBLE (page->child))
1266 gtk_notebook_switch_page (notebook, page, -1);
1271 else if (GTK_WIDGET_VISIBLE (widget))
1273 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1274 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1277 if (vis_pages && !notebook->cur_page)
1279 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1282 notebook->first_tab = children;
1283 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1289 gtk_notebook_size_allocate (GtkWidget *widget,
1290 GtkAllocation *allocation)
1292 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1295 widget->allocation = *allocation;
1296 if (GTK_WIDGET_REALIZED (widget))
1298 GdkRectangle position;
1300 if (gtk_notebook_get_event_window_position (notebook, &position))
1301 gdk_window_move_resize (notebook->event_window,
1302 position.x, position.y,
1303 position.width, position.height);
1306 if (notebook->children)
1308 gint border_width = GTK_CONTAINER (widget)->border_width;
1309 GtkNotebookPage *page;
1310 GtkAllocation child_allocation;
1313 child_allocation.x = widget->allocation.x + border_width;
1314 child_allocation.y = widget->allocation.y + border_width;
1315 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1316 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1318 if (notebook->show_tabs || notebook->show_border)
1320 child_allocation.x += widget->style->xthickness;
1321 child_allocation.y += widget->style->ythickness;
1322 child_allocation.width = MAX (1, child_allocation.width -
1323 widget->style->xthickness * 2);
1324 child_allocation.height = MAX (1, child_allocation.height -
1325 widget->style->ythickness * 2);
1327 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1329 switch (notebook->tab_pos)
1332 child_allocation.y += notebook->cur_page->requisition.height;
1333 case GTK_POS_BOTTOM:
1334 child_allocation.height =
1335 MAX (1, child_allocation.height -
1336 notebook->cur_page->requisition.height);
1339 child_allocation.x += notebook->cur_page->requisition.width;
1341 child_allocation.width =
1342 MAX (1, child_allocation.width -
1343 notebook->cur_page->requisition.width);
1349 children = notebook->children;
1352 page = children->data;
1353 children = children->next;
1355 if (GTK_WIDGET_VISIBLE (page->child))
1357 gtk_widget_size_allocate (page->child, &child_allocation);
1362 gtk_notebook_pages_allocate (notebook);
1365 if ((vis_pages != 0) != notebook->have_visible_child)
1367 notebook->have_visible_child = (vis_pages != 0);
1368 if (notebook->show_tabs)
1369 gtk_widget_queue_draw (widget);
1374 gtk_notebook_expose (GtkWidget *widget,
1375 GdkEventExpose *event)
1377 GtkNotebook *notebook;
1378 GdkRectangle child_area;
1380 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1381 g_return_val_if_fail (event != NULL, FALSE);
1383 if (GTK_WIDGET_DRAWABLE (widget))
1385 notebook = GTK_NOTEBOOK (widget);
1387 gtk_notebook_paint (widget, &event->area);
1388 if (notebook->show_tabs)
1390 if (notebook->cur_page &&
1391 gtk_widget_intersect (notebook->cur_page->tab_label,
1392 &event->area, &child_area))
1393 gtk_notebook_draw_focus (widget);
1397 if (notebook->cur_page)
1398 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1399 notebook->cur_page->child,
1407 gtk_notebook_show_arrows (GtkNotebook *notebook)
1409 gboolean show_arrow = FALSE;
1412 if (!notebook->scrollable)
1415 children = notebook->children;
1418 GtkNotebookPage *page = children->data;
1420 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1423 children = children->next;
1430 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1431 GdkRectangle *rectangle)
1433 GdkRectangle event_window_pos;
1435 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1437 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1438 rectangle->height = ARROW_SIZE;
1440 switch (notebook->tab_pos)
1444 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1445 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1448 case GTK_POS_BOTTOM:
1449 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1450 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1457 gtk_notebook_get_arrow (GtkNotebook *notebook,
1461 GdkRectangle arrow_rect;
1462 GdkRectangle event_window_pos;
1464 if (gtk_notebook_show_arrows (notebook))
1466 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1467 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1472 if (y >= 0 && y < arrow_rect.height)
1474 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1475 return GTK_ARROW_LEFT;
1476 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1477 return GTK_ARROW_RIGHT;
1485 gtk_notebook_do_arrow (GtkNotebook *notebook,
1488 GtkWidget *widget = GTK_WIDGET (notebook);
1489 GtkDirectionType dir;
1491 if (!notebook->focus_tab ||
1492 gtk_notebook_search_page (notebook, notebook->focus_tab,
1493 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1496 if (notebook->tab_pos == GTK_POS_LEFT ||
1497 notebook->tab_pos == GTK_POS_RIGHT)
1498 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1500 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1501 gtk_widget_child_focus (widget, dir);
1506 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1508 GdkEventButton *event)
1510 GtkWidget *widget = GTK_WIDGET (notebook);
1512 if (!GTK_WIDGET_HAS_FOCUS (widget))
1513 gtk_widget_grab_focus (widget);
1515 notebook->button = event->button;
1516 notebook->click_child = arrow;
1518 if (event->button == 1)
1520 gtk_notebook_do_arrow (notebook, arrow);
1522 if (!notebook->timer)
1524 notebook->timer = gtk_timeout_add
1525 (NOTEBOOK_INIT_SCROLL_DELAY,
1526 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1527 notebook->need_timer = TRUE;
1530 else if (event->button == 2)
1531 gtk_notebook_page_select (notebook, TRUE);
1532 else if (event->button == 3)
1533 gtk_notebook_switch_focus_tab (notebook,
1534 gtk_notebook_search_page (notebook,
1536 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1538 gtk_notebook_redraw_arrows (notebook);
1544 get_widget_coordinates (GtkWidget *widget,
1549 GdkWindow *window = ((GdkEventAny *)event)->window;
1552 if (!gdk_event_get_coords (event, &tx, &ty))
1555 while (window && window != widget->window)
1557 gint window_x, window_y;
1559 gdk_window_get_position (window, &window_x, &window_y);
1563 window = gdk_window_get_parent (window);
1578 gtk_notebook_button_press (GtkWidget *widget,
1579 GdkEventButton *event)
1581 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1582 GtkNotebookPage *page;
1588 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1592 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1595 arrow = gtk_notebook_get_arrow (notebook, x, y);
1597 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1599 if (event->button == 3 && notebook->menu)
1601 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1602 NULL, NULL, 3, event->time);
1606 if (event->button != 1)
1610 children = notebook->children;
1613 page = children->data;
1615 if (GTK_WIDGET_VISIBLE (page->child) &&
1616 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1617 (x >= page->allocation.x) &&
1618 (y >= page->allocation.y) &&
1619 (x <= (page->allocation.x + page->allocation.width)) &&
1620 (y <= (page->allocation.y + page->allocation.height)))
1622 gboolean page_changed = page != notebook->cur_page;
1623 gboolean was_focus = gtk_widget_is_focus (widget);
1625 gtk_notebook_switch_focus_tab (notebook, children);
1626 gtk_widget_grab_focus (widget);
1628 if (page_changed && !was_focus)
1629 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1633 children = children->next;
1636 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1637 gtk_widget_grab_focus (widget);
1643 gtk_notebook_button_release (GtkWidget *widget,
1644 GdkEventButton *event)
1646 GtkNotebook *notebook;
1648 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1649 g_return_val_if_fail (event != NULL, FALSE);
1651 if (event->type != GDK_BUTTON_RELEASE)
1654 notebook = GTK_NOTEBOOK (widget);
1656 if (event->button == notebook->button)
1660 if (notebook->timer)
1662 gtk_timeout_remove (notebook->timer);
1663 notebook->timer = 0;
1664 notebook->need_timer = FALSE;
1666 click_child = notebook->click_child;
1667 notebook->click_child = 0;
1668 notebook->button = 0;
1669 gtk_notebook_redraw_arrows (notebook);
1678 gtk_notebook_enter_notify (GtkWidget *widget,
1679 GdkEventCrossing *event)
1681 GtkNotebook *notebook;
1685 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1686 g_return_val_if_fail (event != NULL, FALSE);
1688 notebook = GTK_NOTEBOOK (widget);
1690 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1693 arrow = gtk_notebook_get_arrow (notebook, x, y);
1695 if (arrow != notebook->in_child)
1697 notebook->in_child = arrow;
1698 gtk_notebook_redraw_arrows (notebook);
1707 gtk_notebook_leave_notify (GtkWidget *widget,
1708 GdkEventCrossing *event)
1710 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1714 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1717 arrow = gtk_notebook_get_arrow (notebook, x, y);
1719 if (notebook->in_child)
1721 notebook->in_child = 0;
1722 gtk_notebook_redraw_arrows (notebook);
1729 gtk_notebook_motion_notify (GtkWidget *widget,
1730 GdkEventMotion *event)
1732 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1736 if (notebook->button)
1739 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1742 arrow = gtk_notebook_get_arrow (notebook, x, y);
1744 if (arrow != notebook->in_child)
1746 notebook->in_child = arrow;
1747 gtk_notebook_redraw_arrows (notebook);
1754 gtk_notebook_focus_in (GtkWidget *widget,
1755 GdkEventFocus *event)
1757 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1759 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1763 gtk_notebook_draw_focus (GtkWidget *widget)
1765 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1767 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1768 notebook->focus_tab)
1770 GtkNotebookPage *page;
1774 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1776 page = notebook->focus_tab->data;
1778 area.x = page->tab_label->allocation.x - focus_width;
1779 area.y = page->tab_label->allocation.y - focus_width;
1780 area.width = page->tab_label->allocation.width + 2 * focus_width;
1781 area.height = page->tab_label->allocation.height + 2 * focus_width;
1783 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1787 /* Private GtkContainer Methods :
1789 * gtk_notebook_set_child_arg
1790 * gtk_notebook_get_child_arg
1792 * gtk_notebook_remove
1793 * gtk_notebook_focus
1794 * gtk_notebook_set_focus_child
1795 * gtk_notebook_child_type
1796 * gtk_notebook_forall
1799 gtk_notebook_set_child_property (GtkContainer *container,
1802 const GValue *value,
1807 GtkPackType pack_type;
1809 /* not finding child's page is valid for menus or labels */
1810 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1813 switch (property_id)
1815 case CHILD_PROP_TAB_LABEL:
1816 /* a NULL pointer indicates a default_tab setting, otherwise
1817 * we need to set the associated label
1819 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1820 g_value_get_string (value));
1822 case CHILD_PROP_MENU_LABEL:
1823 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1824 g_value_get_string (value));
1826 case CHILD_PROP_POSITION:
1827 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1828 g_value_get_int (value));
1830 case CHILD_PROP_TAB_EXPAND:
1831 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1832 &expand, &fill, &pack_type);
1833 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1834 g_value_get_boolean (value),
1837 case CHILD_PROP_TAB_FILL:
1838 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1839 &expand, &fill, &pack_type);
1840 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1842 g_value_get_boolean (value),
1845 case CHILD_PROP_TAB_PACK:
1846 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1847 &expand, &fill, &pack_type);
1848 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1850 g_value_get_enum (value));
1853 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1859 gtk_notebook_get_child_property (GtkContainer *container,
1866 GtkNotebook *notebook;
1870 GtkPackType pack_type;
1872 notebook = GTK_NOTEBOOK (container);
1874 /* not finding child's page is valid for menus or labels */
1875 list = gtk_notebook_find_child (notebook, child, NULL);
1878 /* nothing to set on labels or menus */
1879 g_param_value_set_default (pspec, value);
1883 switch (property_id)
1885 case CHILD_PROP_TAB_LABEL:
1886 label = gtk_notebook_get_tab_label (notebook, child);
1888 if (label && GTK_IS_LABEL (label))
1889 g_value_set_string (value, GTK_LABEL (label)->label);
1891 g_value_set_string (value, NULL);
1893 case CHILD_PROP_MENU_LABEL:
1894 label = gtk_notebook_get_menu_label (notebook, child);
1896 if (label && GTK_IS_LABEL (label))
1897 g_value_set_string (value, GTK_LABEL (label)->label);
1899 g_value_set_string (value, NULL);
1901 case CHILD_PROP_POSITION:
1902 g_value_set_int (value, g_list_position (notebook->children, list));
1904 case CHILD_PROP_TAB_EXPAND:
1905 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1906 &expand, NULL, NULL);
1907 g_value_set_boolean (value, expand);
1909 case CHILD_PROP_TAB_FILL:
1910 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1912 g_value_set_boolean (value, fill);
1914 case CHILD_PROP_TAB_PACK:
1915 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1916 NULL, NULL, &pack_type);
1917 g_value_set_enum (value, pack_type);
1920 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1926 gtk_notebook_add (GtkContainer *container,
1929 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1931 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1936 gtk_notebook_remove (GtkContainer *container,
1939 GtkNotebook *notebook;
1940 GtkNotebookPage *page;
1944 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1945 g_return_if_fail (widget != NULL);
1947 notebook = GTK_NOTEBOOK (container);
1949 children = notebook->children;
1953 page = children->data;
1954 if (page->child == widget)
1956 gtk_notebook_real_remove (notebook, children);
1960 children = children->next;
1965 focus_tabs_in (GtkNotebook *notebook)
1967 if (notebook->show_tabs && notebook->cur_page)
1969 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1971 gtk_notebook_switch_focus_tab (notebook,
1972 g_list_find (notebook->children,
1973 notebook->cur_page));
1982 focus_tabs_move (GtkNotebook *notebook,
1983 GtkDirectionType direction,
1984 gint search_direction)
1988 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1989 search_direction, TRUE);
1991 gtk_notebook_switch_focus_tab (notebook, new_page);
1993 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1999 focus_child_in (GtkNotebook *notebook,
2000 GtkDirectionType direction)
2002 if (notebook->cur_page)
2003 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2008 /* Focus in the notebook can either be on the pages, or on
2012 gtk_notebook_focus (GtkWidget *widget,
2013 GtkDirectionType direction)
2015 GtkWidget *old_focus_child;
2016 GtkNotebook *notebook;
2017 GtkDirectionType effective_direction;
2019 gboolean widget_is_focus;
2020 GtkContainer *container;
2022 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2024 container = GTK_CONTAINER (widget);
2025 notebook = GTK_NOTEBOOK (container);
2027 if (notebook->focus_out)
2029 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2033 widget_is_focus = gtk_widget_is_focus (widget);
2034 old_focus_child = container->focus_child;
2036 effective_direction = get_effective_direction (notebook, direction);
2038 if (old_focus_child) /* Focus on page child */
2040 if (gtk_widget_child_focus (old_focus_child, direction))
2043 switch (effective_direction)
2045 case GTK_DIR_TAB_BACKWARD:
2047 /* Focus onto the tabs */
2048 return focus_tabs_in (notebook);
2050 case GTK_DIR_TAB_FORWARD:
2056 else if (widget_is_focus) /* Focus was on tabs */
2058 switch (effective_direction)
2060 case GTK_DIR_TAB_BACKWARD:
2063 case GTK_DIR_TAB_FORWARD:
2065 /* We use TAB_FORWARD rather than direction so that we focus a more
2066 * predictable widget for the user; users may be using arrow focusing
2067 * in this situation even if they don't usually use arrow focusing.
2069 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2071 return focus_tabs_move (notebook, direction, STEP_PREV);
2073 return focus_tabs_move (notebook, direction, STEP_NEXT);
2076 else /* Focus was not on widget */
2078 switch (effective_direction)
2080 case GTK_DIR_TAB_FORWARD:
2082 if (focus_tabs_in (notebook))
2084 if (focus_child_in (notebook, direction))
2087 case GTK_DIR_TAB_BACKWARD:
2089 if (focus_child_in (notebook, direction))
2091 if (focus_tabs_in (notebook))
2096 return focus_child_in (notebook, direction);
2100 g_assert_not_reached ();
2105 gtk_notebook_set_focus_child (GtkContainer *container,
2108 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2109 GtkWidget *page_child;
2110 GtkWidget *toplevel;
2112 /* If the old focus widget was within a page of the notebook,
2113 * (child may either be NULL or not in this case), record it
2114 * for future use if we switch to the page with a mnemonic.
2117 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2118 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2120 page_child = GTK_WINDOW (toplevel)->focus_widget;
2123 if (page_child->parent == GTK_WIDGET (container))
2125 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2128 GtkNotebookPage *page = list->data;
2130 if (page->last_focus_child)
2131 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2133 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2134 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2140 page_child = page_child->parent;
2146 g_return_if_fail (GTK_IS_WIDGET (child));
2148 notebook->child_has_focus = TRUE;
2149 if (!notebook->focus_tab)
2152 GtkNotebookPage *page;
2154 children = notebook->children;
2157 page = children->data;
2158 if (page->child == child || page->tab_label == child)
2159 gtk_notebook_switch_focus_tab (notebook, children);
2160 children = children->next;
2165 parent_class->set_focus_child (container, child);
2169 gtk_notebook_forall (GtkContainer *container,
2170 gboolean include_internals,
2171 GtkCallback callback,
2172 gpointer callback_data)
2174 GtkNotebook *notebook;
2177 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2178 g_return_if_fail (callback != NULL);
2180 notebook = GTK_NOTEBOOK (container);
2182 children = notebook->children;
2185 GtkNotebookPage *page;
2187 page = children->data;
2188 children = children->next;
2189 (* callback) (page->child, callback_data);
2190 if (include_internals)
2192 if (page->tab_label)
2193 (* callback) (page->tab_label, callback_data);
2194 if (page->menu_label)
2195 (* callback) (page->menu_label, callback_data);
2201 gtk_notebook_child_type (GtkContainer *container)
2203 return GTK_TYPE_WIDGET;
2206 /* Private GtkNotebook Functions:
2208 * gtk_notebook_redraw_tabs
2209 * gtk_notebook_real_remove
2210 * gtk_notebook_update_labels
2211 * gtk_notebook_timer
2212 * gtk_notebook_page_compare
2213 * gtk_notebook_real_page_position
2214 * gtk_notebook_search_page
2217 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2220 GtkNotebookPage *page;
2221 GdkRectangle redraw_rect;
2224 widget = GTK_WIDGET (notebook);
2225 border = GTK_CONTAINER (notebook)->border_width;
2227 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2230 page = notebook->first_tab->data;
2232 redraw_rect.x = border;
2233 redraw_rect.y = border;
2235 switch (notebook->tab_pos)
2237 case GTK_POS_BOTTOM:
2238 redraw_rect.y = (widget->allocation.height - border -
2239 page->allocation.height -
2240 widget->style->ythickness);
2241 if (page != notebook->cur_page)
2242 redraw_rect.y -= widget->style->ythickness;
2245 redraw_rect.width = widget->allocation.width - 2 * border;
2246 redraw_rect.height = (page->allocation.height +
2247 widget->style->ythickness);
2248 if (page != notebook->cur_page)
2249 redraw_rect.height += widget->style->ythickness;
2252 redraw_rect.x = (widget->allocation.width - border -
2253 page->allocation.width -
2254 widget->style->xthickness);
2255 if (page != notebook->cur_page)
2256 redraw_rect.x -= widget->style->xthickness;
2259 redraw_rect.width = (page->allocation.width +
2260 widget->style->xthickness);
2261 redraw_rect.height = widget->allocation.height - 2 * border;
2262 if (page != notebook->cur_page)
2263 redraw_rect.width += widget->style->xthickness;
2267 redraw_rect.x += widget->allocation.x;
2268 redraw_rect.y += widget->allocation.y;
2270 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2274 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2276 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2280 gtk_notebook_get_arrow_rect (notebook, &rect);
2281 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2286 gtk_notebook_timer (GtkNotebook *notebook)
2288 gboolean retval = FALSE;
2290 GDK_THREADS_ENTER ();
2292 if (notebook->timer)
2294 gtk_notebook_do_arrow (notebook, notebook->click_child);
2296 if (notebook->need_timer)
2298 notebook->need_timer = FALSE;
2299 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2300 (GtkFunction) gtk_notebook_timer,
2301 (gpointer) notebook);
2307 GDK_THREADS_LEAVE ();
2313 gtk_notebook_page_compare (gconstpointer a,
2316 return (((GtkNotebookPage *) a)->child != b);
2320 gtk_notebook_find_child (GtkNotebook *notebook,
2322 const gchar *function)
2324 GList *list = g_list_find_custom (notebook->children, child,
2325 gtk_notebook_page_compare);
2327 #ifndef G_DISABLE_CHECKS
2328 if (!list && function)
2329 g_warning ("%s: unable to find child %p in notebook %p",
2330 function, child, notebook);
2337 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2338 GtkNotebookPage *page)
2340 if (page->tab_label)
2342 if (page->mnemonic_activate_signal)
2343 g_signal_handler_disconnect (page->tab_label,
2344 page->mnemonic_activate_signal);
2345 page->mnemonic_activate_signal = 0;
2347 gtk_widget_unparent (page->tab_label);
2352 gtk_notebook_real_remove (GtkNotebook *notebook,
2355 GtkNotebookPage *page;
2357 gint need_resize = FALSE;
2359 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2361 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2363 if (notebook->cur_page == list->data)
2365 notebook->cur_page = NULL;
2367 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2370 if (list == notebook->first_tab)
2371 notebook->first_tab = next_list;
2372 if (list == notebook->focus_tab)
2373 gtk_notebook_switch_focus_tab (notebook, next_list);
2377 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2380 gtk_widget_unparent (page->child);
2382 gtk_notebook_remove_tab_label (notebook, page);
2386 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2387 page->menu_label->parent);
2388 gtk_widget_queue_resize (notebook->menu);
2390 if (!page->default_menu)
2391 g_object_unref (page->menu_label);
2393 notebook->children = g_list_remove_link (notebook->children, list);
2396 if (page->last_focus_child)
2398 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2399 page->last_focus_child = NULL;
2404 if (!notebook->children && notebook->show_tabs &&
2405 GTK_WIDGET_MAPPED (notebook))
2406 gdk_window_hide (notebook->event_window);
2408 gtk_notebook_update_labels (notebook);
2410 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2414 gtk_notebook_update_labels (GtkNotebook *notebook)
2416 GtkNotebookPage *page;
2421 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2423 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2426 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2427 if (notebook->show_tabs)
2429 if (page->default_tab)
2431 if (!page->tab_label)
2433 page->tab_label = gtk_label_new (string);
2434 gtk_widget_set_parent (page->tab_label,
2435 GTK_WIDGET (notebook));
2438 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2441 if (GTK_WIDGET_VISIBLE (page->child) &&
2442 !GTK_WIDGET_VISIBLE (page->tab_label))
2443 gtk_widget_show (page->tab_label);
2444 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2445 GTK_WIDGET_VISIBLE (page->tab_label))
2446 gtk_widget_hide (page->tab_label);
2448 if (notebook->menu && page->default_menu)
2450 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2451 gtk_label_set_text (GTK_LABEL (page->menu_label),
2452 GTK_LABEL (page->tab_label)->label);
2454 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2460 gtk_notebook_real_page_position (GtkNotebook *notebook,
2466 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2467 g_return_val_if_fail (list != NULL, -1);
2469 for (work = notebook->children, count_start = 0;
2470 work && work != list; work = work->next)
2471 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2477 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2480 return (count_start + g_list_length (list) - 1);
2484 gtk_notebook_search_page (GtkNotebook *notebook,
2487 gboolean find_visible)
2489 GtkNotebookPage *page = NULL;
2490 GList *old_list = NULL;
2493 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2498 flag = GTK_PACK_END;
2502 flag = GTK_PACK_START;
2509 if (!page || page->pack == flag)
2517 list = notebook->children;
2522 if (page->pack == flag &&
2523 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2538 if (page->pack != flag &&
2539 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2547 /* Private GtkNotebook Drawing Functions:
2549 * gtk_notebook_paint
2550 * gtk_notebook_draw_tab
2551 * gtk_notebook_draw_arrow
2554 gtk_notebook_paint (GtkWidget *widget,
2557 GtkNotebook *notebook;
2558 GtkNotebookPage *page;
2563 gint border_width = GTK_CONTAINER (widget)->border_width;
2564 gint gap_x = 0, gap_width = 0;
2566 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2567 g_return_if_fail (area != NULL);
2569 if (!GTK_WIDGET_DRAWABLE (widget))
2572 notebook = GTK_NOTEBOOK (widget);
2574 if ((!notebook->show_tabs && !notebook->show_border) ||
2575 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2578 x = widget->allocation.x + border_width;
2579 y = widget->allocation.y + border_width;
2580 width = widget->allocation.width - border_width * 2;
2581 height = widget->allocation.height - border_width * 2;
2583 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2585 gtk_paint_box (widget->style, widget->window,
2586 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2587 area, widget, "notebook",
2588 x, y, width, height);
2593 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2595 page = notebook->first_tab->data;
2597 switch (notebook->tab_pos)
2600 y += page->allocation.height + widget->style->ythickness;
2601 case GTK_POS_BOTTOM:
2602 height -= page->allocation.height + widget->style->ythickness;
2605 x += page->allocation.width + widget->style->xthickness;
2607 width -= page->allocation.width + widget->style->xthickness;
2610 gtk_paint_box (widget->style, widget->window,
2611 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2612 area, widget, "notebook",
2613 x, y, width, height);
2617 switch (notebook->tab_pos)
2620 y += notebook->cur_page->allocation.height;
2621 case GTK_POS_BOTTOM:
2622 height -= notebook->cur_page->allocation.height;
2625 x += notebook->cur_page->allocation.width;
2627 width -= notebook->cur_page->allocation.width;
2631 switch (notebook->tab_pos)
2634 case GTK_POS_BOTTOM:
2635 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2636 gap_width = notebook->cur_page->allocation.width;
2640 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2641 gap_width = notebook->cur_page->allocation.height;
2644 gtk_paint_box_gap(widget->style, widget->window,
2645 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2646 area, widget, "notebook",
2647 x, y, width, height,
2648 notebook->tab_pos, gap_x, gap_width);
2652 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2655 page = children->data;
2656 children = gtk_notebook_search_page (notebook, children,
2658 if (!GTK_WIDGET_VISIBLE (page->child))
2660 if (!GTK_WIDGET_MAPPED (page->tab_label))
2662 else if (page != notebook->cur_page)
2663 gtk_notebook_draw_tab (notebook, page, area);
2666 if (showarrow && notebook->scrollable)
2668 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2669 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2671 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2675 gtk_notebook_draw_tab (GtkNotebook *notebook,
2676 GtkNotebookPage *page,
2679 GdkRectangle child_area;
2680 GdkRectangle page_area;
2681 GtkStateType state_type;
2682 GtkPositionType gap_side;
2684 g_return_if_fail (notebook != NULL);
2685 g_return_if_fail (page != NULL);
2686 g_return_if_fail (area != NULL);
2688 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2689 (page->allocation.width == 0) || (page->allocation.height == 0))
2692 page_area.x = page->allocation.x;
2693 page_area.y = page->allocation.y;
2694 page_area.width = page->allocation.width;
2695 page_area.height = page->allocation.height;
2697 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2701 widget = GTK_WIDGET (notebook);
2703 switch (notebook->tab_pos)
2706 gap_side = GTK_POS_BOTTOM;
2708 case GTK_POS_BOTTOM:
2709 gap_side = GTK_POS_TOP;
2712 gap_side = GTK_POS_RIGHT;
2715 gap_side = GTK_POS_LEFT;
2719 if (notebook->cur_page == page)
2720 state_type = GTK_STATE_NORMAL;
2722 state_type = GTK_STATE_ACTIVE;
2723 gtk_paint_extension(widget->style, widget->window,
2724 state_type, GTK_SHADOW_OUT,
2725 area, widget, "tab",
2726 page_area.x, page_area.y,
2727 page_area.width, page_area.height,
2729 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2730 notebook->focus_tab && (notebook->focus_tab->data == page))
2734 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2736 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2737 area, widget, "tab",
2738 page->tab_label->allocation.x - focus_width,
2739 page->tab_label->allocation.y - focus_width,
2740 page->tab_label->allocation.width + 2 * focus_width,
2741 page->tab_label->allocation.height + 2 * focus_width);
2743 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2744 GTK_WIDGET_DRAWABLE (page->tab_label))
2746 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2748 /* This is a lame hack since all this code needs rewriting anyhow */
2750 expose_event->expose.window = g_object_ref (page->tab_label->window);
2751 expose_event->expose.area = child_area;
2752 expose_event->expose.region = gdk_region_rectangle (&child_area);
2753 expose_event->expose.send_event = TRUE;
2754 expose_event->expose.count = 0;
2756 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2758 gdk_event_free (expose_event);
2764 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2767 GtkStateType state_type;
2768 GtkShadowType shadow_type;
2770 GdkRectangle arrow_rect;
2772 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2774 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2776 widget = GTK_WIDGET(notebook);
2778 if (GTK_WIDGET_DRAWABLE (notebook))
2780 if (notebook->in_child == arrow)
2782 if (notebook->click_child == arrow)
2783 state_type = GTK_STATE_ACTIVE;
2785 state_type = GTK_STATE_PRELIGHT;
2788 state_type = GTK_STATE_NORMAL;
2790 if (notebook->click_child == arrow)
2791 shadow_type = GTK_SHADOW_IN;
2793 shadow_type = GTK_SHADOW_OUT;
2795 if (arrow == GTK_ARROW_LEFT)
2797 if (notebook->focus_tab &&
2798 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2801 shadow_type = GTK_SHADOW_ETCHED_IN;
2802 state_type = GTK_STATE_INSENSITIVE;
2805 if (notebook->tab_pos == GTK_POS_LEFT ||
2806 notebook->tab_pos == GTK_POS_RIGHT)
2807 arrow = GTK_ARROW_UP;
2809 gtk_paint_arrow (widget->style, widget->window, state_type,
2810 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2812 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2816 if (notebook->focus_tab &&
2817 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2820 shadow_type = GTK_SHADOW_ETCHED_IN;
2821 state_type = GTK_STATE_INSENSITIVE;
2824 if (notebook->tab_pos == GTK_POS_LEFT ||
2825 notebook->tab_pos == GTK_POS_RIGHT)
2826 arrow = GTK_ARROW_DOWN;
2828 gtk_paint_arrow (widget->style, widget->window, state_type,
2829 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2830 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2831 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2836 /* Private GtkNotebook Size Allocate Functions:
2838 * gtk_notebook_pages_allocate
2839 * gtk_notebook_page_allocate
2840 * gtk_notebook_calc_tabs
2843 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2845 GtkWidget *widget = GTK_WIDGET (notebook);
2846 GtkContainer *container = GTK_CONTAINER (notebook);
2847 GtkNotebookPage *page = NULL;
2848 GtkAllocation *allocation = &widget->allocation;
2849 GtkAllocation child_allocation;
2850 GList *children = NULL;
2851 GList *last_child = NULL;
2852 gboolean showarrow = FALSE;
2862 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2865 child_allocation.x = widget->allocation.x + container->border_width;
2866 child_allocation.y = widget->allocation.y + container->border_width;
2868 switch (notebook->tab_pos)
2870 case GTK_POS_BOTTOM:
2871 child_allocation.y = (widget->allocation.y +
2872 allocation->height -
2873 notebook->cur_page->requisition.height -
2874 container->border_width);
2877 child_allocation.height = notebook->cur_page->requisition.height;
2881 child_allocation.x = (widget->allocation.x +
2883 notebook->cur_page->requisition.width -
2884 container->border_width);
2887 child_allocation.width = notebook->cur_page->requisition.width;
2891 if (notebook->scrollable)
2895 children = notebook->children;
2897 if (notebook->focus_tab)
2898 focus_tab = notebook->focus_tab;
2899 else if (notebook->first_tab)
2900 focus_tab = notebook->first_tab;
2902 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2904 switch (notebook->tab_pos)
2907 case GTK_POS_BOTTOM:
2910 page = children->data;
2911 children = children->next;
2913 if (GTK_WIDGET_VISIBLE (page->child))
2914 tab_space += page->requisition.width;
2917 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2920 page = focus_tab->data;
2922 tab_space = (allocation->width - TAB_OVERLAP -
2923 page->requisition.width -
2924 2 * (container->border_width + ARROW_SPACING +
2926 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2927 container->border_width);
2929 page = notebook->children->data;
2930 if (notebook->tab_pos == GTK_POS_TOP)
2931 y = (container->border_width +
2932 (page->requisition.height - ARROW_SIZE) / 2);
2934 y = (allocation->height - container->border_width -
2935 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2942 page = children->data;
2943 children = children->next;
2945 if (GTK_WIDGET_VISIBLE (page->child))
2946 tab_space += page->requisition.height;
2949 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2952 page = focus_tab->data;
2953 tab_space = (allocation->height -
2954 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2955 2 * container->border_width -
2956 page->requisition.height);
2957 y = allocation->height - container->border_width - ARROW_SIZE;
2959 page = notebook->children->data;
2960 if (notebook->tab_pos == GTK_POS_LEFT)
2961 x = (container->border_width +
2962 (page->requisition.width -
2963 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2965 x = (allocation->width - container->border_width -
2966 (2 * ARROW_SIZE - ARROW_SPACING) -
2967 (page->requisition.width -
2968 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2972 if (showarrow) /* first_tab <- focus_tab */
2976 notebook->first_tab = focus_tab;
2977 last_child = gtk_notebook_search_page (notebook, focus_tab,
2983 if (notebook->first_tab && notebook->first_tab != focus_tab)
2985 /* Is first_tab really predecessor of focus_tab ? */
2986 page = notebook->first_tab->data;
2987 if (GTK_WIDGET_VISIBLE (page->child))
2988 for (children = focus_tab;
2989 children && children != notebook->first_tab;
2990 children = gtk_notebook_search_page (notebook,
2996 notebook->first_tab = focus_tab;
2998 gtk_notebook_calc_tabs (notebook,
2999 gtk_notebook_search_page (notebook,
3003 &(notebook->first_tab), &tab_space,
3008 notebook->first_tab =
3009 gtk_notebook_search_page (notebook, notebook->first_tab,
3011 if (!notebook->first_tab)
3012 notebook->first_tab = focus_tab;
3013 last_child = gtk_notebook_search_page (notebook, focus_tab,
3016 else /* focus_tab -> end */
3018 if (!notebook->first_tab)
3019 notebook->first_tab = gtk_notebook_search_page (notebook,
3024 gtk_notebook_calc_tabs (notebook,
3025 gtk_notebook_search_page (notebook,
3029 &children, &tab_space, STEP_NEXT);
3032 last_child = children;
3033 else /* start <- first_tab */
3037 gtk_notebook_calc_tabs
3039 gtk_notebook_search_page (notebook,
3040 notebook->first_tab,
3043 &children, &tab_space, STEP_PREV);
3044 notebook->first_tab = gtk_notebook_search_page(notebook,
3054 tab_space = -tab_space;
3056 for (children = notebook->first_tab;
3057 children && children != last_child;
3058 children = gtk_notebook_search_page (notebook, children,
3065 /*unmap all non-visible tabs*/
3066 for (children = gtk_notebook_search_page (notebook, NULL,
3068 children && children != notebook->first_tab;
3069 children = gtk_notebook_search_page (notebook, children,
3072 page = children->data;
3073 if (page->tab_label)
3074 gtk_widget_set_child_visible (page->tab_label, FALSE);
3076 for (children = last_child; children;
3077 children = gtk_notebook_search_page (notebook, children,
3080 page = children->data;
3081 if (page->tab_label)
3082 gtk_widget_set_child_visible (page->tab_label, FALSE);
3085 else /* !showarrow */
3087 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3098 children = notebook->children;
3099 switch (notebook->tab_pos)
3102 case GTK_POS_BOTTOM:
3105 page = children->data;
3106 children = children->next;
3108 if (GTK_WIDGET_VISIBLE (page->child))
3111 tab_space += page->requisition.width;
3116 tab_space -= allocation->width;
3122 page = children->data;
3123 children = children->next;
3125 if (GTK_WIDGET_VISIBLE (page->child))
3128 tab_space += page->requisition.height;
3133 tab_space -= allocation->height;
3135 tab_space += 2 * container->border_width + TAB_OVERLAP;
3137 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3139 if (notebook->homogeneous && n)
3143 children = notebook->first_tab;
3147 if (children == last_child)
3149 /* FIXME double check */
3153 page = children->data;
3154 if (!showarrow && page->pack != GTK_PACK_START)
3156 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3159 if (n && (showarrow || page->expand || notebook->homogeneous))
3161 new_fill = (tab_space * i++) / n;
3162 delta = new_fill - old_fill;
3163 old_fill = new_fill;
3166 switch (notebook->tab_pos)
3169 case GTK_POS_BOTTOM:
3170 child_allocation.width = (page->requisition.width +
3171 TAB_OVERLAP + delta);
3175 child_allocation.height = (page->requisition.height +
3176 TAB_OVERLAP + delta);
3180 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3182 switch (notebook->tab_pos)
3185 case GTK_POS_BOTTOM:
3186 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3190 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3194 if (page->tab_label)
3195 gtk_widget_set_child_visible (page->tab_label, TRUE);
3200 children = notebook->children;
3201 switch (notebook->tab_pos)
3204 case GTK_POS_BOTTOM:
3205 child_allocation.x = (allocation->x + allocation->width -
3206 container->border_width);
3210 child_allocation.y = (allocation->y + allocation->height -
3211 container->border_width);
3215 while (children != last_child)
3217 page = children->data;
3218 children = children->next;
3220 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3224 if (n && (page->expand || notebook->homogeneous))
3226 new_fill = (tab_space * i++) / n;
3227 delta = new_fill - old_fill;
3228 old_fill = new_fill;
3231 switch (notebook->tab_pos)
3234 case GTK_POS_BOTTOM:
3235 child_allocation.width = (page->requisition.width +
3236 TAB_OVERLAP + delta);
3237 child_allocation.x -= child_allocation.width;
3241 child_allocation.height = (page->requisition.height +
3242 TAB_OVERLAP + delta);
3243 child_allocation.y -= child_allocation.height;
3247 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3249 switch (notebook->tab_pos)
3252 case GTK_POS_BOTTOM:
3253 child_allocation.x += TAB_OVERLAP;
3257 child_allocation.y += TAB_OVERLAP;
3261 if (page->tab_label)
3262 gtk_widget_set_child_visible (page->tab_label, TRUE);
3267 gtk_notebook_redraw_tabs (notebook);
3271 gtk_notebook_page_allocate (GtkNotebook *notebook,
3272 GtkNotebookPage *page,
3273 GtkAllocation *allocation)
3275 GtkWidget *widget = GTK_WIDGET (notebook);
3276 GtkAllocation child_allocation;
3277 GtkRequisition tab_requisition;
3283 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3285 xthickness = widget->style->xthickness;
3286 ythickness = widget->style->ythickness;
3288 /* If the size of the notebook tabs change, we need to queue
3289 * a redraw on the tab area
3291 if ((allocation->width != page->allocation.width) ||
3292 (allocation->height != page->allocation.height))
3294 gint x, y, width, height, border_width;
3296 border_width = GTK_CONTAINER (notebook)->border_width;
3298 switch (notebook->tab_pos)
3301 width = widget->allocation.width;
3302 height = MAX (page->allocation.height, allocation->height) + ythickness;
3307 case GTK_POS_BOTTOM:
3308 width = widget->allocation.width + xthickness;
3309 height = MAX (page->allocation.height, allocation->height) + ythickness;
3311 y = widget->allocation.height - height - border_width;
3315 width = MAX (page->allocation.width, allocation->width) + xthickness;
3316 height = widget->allocation.height;
3322 default: /* quiet gcc */
3323 width = MAX (page->allocation.width, allocation->width) + xthickness;
3324 height = widget->allocation.height;
3325 x = widget->allocation.width - width - border_width;
3330 gtk_widget_queue_draw_area (widget, x, y, width, height);
3333 page->allocation = *allocation;
3334 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3336 if (notebook->cur_page != page)
3338 switch (notebook->tab_pos)
3341 page->allocation.y += ythickness;
3342 case GTK_POS_BOTTOM:
3343 if (page->allocation.height > ythickness)
3344 page->allocation.height -= ythickness;
3347 page->allocation.x += xthickness;
3349 if (page->allocation.width > xthickness)
3350 page->allocation.width -= xthickness;
3355 switch (notebook->tab_pos)
3358 case GTK_POS_BOTTOM:
3359 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3362 child_allocation.x = (xthickness + focus_width +
3363 notebook->tab_hborder);
3364 child_allocation.width = MAX (1, (page->allocation.width -
3365 2 * child_allocation.x));
3366 child_allocation.x += page->allocation.x;
3370 child_allocation.x = (page->allocation.x +
3371 (page->allocation.width -
3372 tab_requisition.width) / 2);
3373 child_allocation.width = tab_requisition.width;
3375 child_allocation.y = (notebook->tab_vborder + focus_width +
3376 page->allocation.y);
3377 if (notebook->tab_pos == GTK_POS_TOP)
3378 child_allocation.y += ythickness;
3379 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3380 2 * (notebook->tab_vborder + focus_width)));
3384 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3387 child_allocation.y = ythickness + padding;
3388 child_allocation.height = MAX (1, (page->allocation.height -
3389 2 * child_allocation.y));
3390 child_allocation.y += page->allocation.y;
3394 child_allocation.y = (page->allocation.y + (page->allocation.height -
3395 tab_requisition.height) / 2);
3396 child_allocation.height = tab_requisition.height;
3398 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3399 if (notebook->tab_pos == GTK_POS_LEFT)
3400 child_allocation.x += xthickness;
3401 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3402 2 * (notebook->tab_hborder + focus_width)));
3406 if (page->tab_label)
3407 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3411 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3417 GtkNotebookPage *page = NULL;
3419 GList *last_list = NULL;
3426 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3427 if (pack == GTK_PACK_END)
3428 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3432 switch (notebook->tab_pos)
3435 case GTK_POS_BOTTOM:
3438 page = children->data;
3439 if (GTK_WIDGET_VISIBLE (page->child))
3441 if (page->pack == pack)
3443 *tab_space -= page->requisition.width;
3444 if (*tab_space < 0 || children == *end)
3448 *tab_space = - (*tab_space +
3449 page->requisition.width);
3455 last_list = children;
3457 if (direction == STEP_NEXT)
3458 children = children->next;
3460 children = children->prev;
3467 page = children->data;
3468 if (GTK_WIDGET_VISIBLE (page->child))
3470 if (page->pack == pack)
3472 *tab_space -= page->requisition.height;
3473 if (*tab_space < 0 || children == *end)
3477 *tab_space = - (*tab_space +
3478 page->requisition.height);
3484 last_list = children;
3486 if (direction == STEP_NEXT)
3487 children = children->next;
3489 children = children->prev;
3493 if (direction == STEP_PREV)
3495 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3496 direction = STEP_PREV;
3497 children = last_list;
3501 /* Private GtkNotebook Page Switch Methods:
3503 * gtk_notebook_real_switch_page
3506 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3507 GtkNotebookPage *page,
3510 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3511 g_return_if_fail (page != NULL);
3513 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3516 if (notebook->cur_page)
3517 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3519 notebook->cur_page = page;
3521 if (!notebook->focus_tab ||
3522 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3523 notebook->focus_tab =
3524 g_list_find (notebook->children, notebook->cur_page);
3526 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3528 /* If the focus was on the previous page, move it to the first
3529 * element on the new page, if possible, or if not, to the
3532 if (notebook->child_has_focus)
3534 if (notebook->cur_page->last_focus_child &&
3535 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3536 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3538 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3539 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3542 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3543 g_object_notify (G_OBJECT (notebook), "page");
3546 /* Private GtkNotebook Page Switch Functions:
3548 * gtk_notebook_switch_page
3549 * gtk_notebook_page_select
3550 * gtk_notebook_switch_focus_tab
3551 * gtk_notebook_menu_switch_page
3554 gtk_notebook_switch_page (GtkNotebook *notebook,
3555 GtkNotebookPage *page,
3558 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3559 g_return_if_fail (page != NULL);
3561 if (notebook->cur_page == page)
3565 page_num = g_list_index (notebook->children, page);
3567 g_signal_emit (notebook,
3568 notebook_signals[SWITCH_PAGE],
3575 gtk_notebook_page_select (GtkNotebook *notebook,
3576 gboolean move_focus)
3578 GtkNotebookPage *page;
3579 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3581 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3583 if (!notebook->focus_tab)
3586 page = notebook->focus_tab->data;
3587 gtk_notebook_switch_page (notebook, page, -1);
3591 switch (notebook->tab_pos)
3596 case GTK_POS_BOTTOM:
3600 dir = GTK_DIR_RIGHT;
3607 if (gtk_widget_child_focus (page->child, dir))
3614 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3618 GtkNotebookPage *old_page = NULL;
3619 GtkNotebookPage *page;
3621 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3623 if (notebook->focus_tab == new_child)
3626 old_child = notebook->focus_tab;
3627 notebook->focus_tab = new_child;
3629 if (notebook->scrollable)
3630 gtk_notebook_redraw_arrows (notebook);
3632 if (!notebook->show_tabs || !notebook->focus_tab)
3636 old_page = old_child->data;
3638 page = notebook->focus_tab->data;
3639 if (GTK_WIDGET_MAPPED (page->tab_label))
3640 gtk_notebook_redraw_tabs (notebook);
3642 gtk_notebook_pages_allocate (notebook);
3644 gtk_notebook_switch_page (notebook, page,
3645 g_list_index (notebook->children, page));
3649 gtk_notebook_menu_switch_page (GtkWidget *widget,
3650 GtkNotebookPage *page)
3652 GtkNotebook *notebook;
3656 g_return_if_fail (widget != NULL);
3657 g_return_if_fail (page != NULL);
3659 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3660 (GTK_MENU (widget->parent)));
3662 if (notebook->cur_page == page)
3666 children = notebook->children;
3667 while (children && children->data != page)
3669 children = children->next;
3673 g_signal_emit (notebook,
3674 notebook_signals[SWITCH_PAGE],
3680 /* Private GtkNotebook Menu Functions:
3682 * gtk_notebook_menu_item_create
3683 * gtk_notebook_menu_label_unparent
3684 * gtk_notebook_menu_detacher
3687 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3690 GtkNotebookPage *page;
3691 GtkWidget *menu_item;
3694 if (page->default_menu)
3696 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3697 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3699 page->menu_label = gtk_label_new ("");
3700 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3703 gtk_widget_show (page->menu_label);
3704 menu_item = gtk_menu_item_new ();
3705 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3706 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3707 gtk_notebook_real_page_position (notebook, list));
3708 g_signal_connect (menu_item, "activate",
3709 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3710 if (GTK_WIDGET_VISIBLE (page->child))
3711 gtk_widget_show (menu_item);
3715 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3718 gtk_widget_unparent (GTK_BIN(widget)->child);
3719 GTK_BIN(widget)->child = NULL;
3723 gtk_notebook_menu_detacher (GtkWidget *widget,
3726 GtkNotebook *notebook;
3728 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3730 notebook = GTK_NOTEBOOK (widget);
3731 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3733 notebook->menu = NULL;
3736 /* Private GtkNotebook Setter Functions:
3738 * gtk_notebook_set_homogeneous_tabs_internal
3739 * gtk_notebook_set_tab_border_internal
3740 * gtk_notebook_set_tab_hborder_internal
3741 * gtk_notebook_set_tab_vborder_internal
3744 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
3745 gboolean homogeneous)
3747 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3749 if (homogeneous == notebook->homogeneous)
3752 notebook->homogeneous = homogeneous;
3753 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3755 g_object_notify (G_OBJECT (notebook), "homogeneous");
3759 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
3762 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3764 notebook->tab_hborder = border_width;
3765 notebook->tab_vborder = border_width;
3767 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3768 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3770 g_object_freeze_notify (G_OBJECT (notebook));
3771 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3772 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3773 g_object_thaw_notify (G_OBJECT (notebook));
3777 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
3780 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3782 if (notebook->tab_hborder == tab_hborder)
3785 notebook->tab_hborder = tab_hborder;
3787 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3788 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3790 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3794 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
3797 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3799 if (notebook->tab_vborder == tab_vborder)
3802 notebook->tab_vborder = tab_vborder;
3804 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3805 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3807 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3810 /* Public GtkNotebook Page Insert/Remove Methods :
3812 * gtk_notebook_append_page
3813 * gtk_notebook_append_page_menu
3814 * gtk_notebook_prepend_page
3815 * gtk_notebook_prepend_page_menu
3816 * gtk_notebook_insert_page
3817 * gtk_notebook_insert_page_menu
3818 * gtk_notebook_remove_page
3821 * gtk_notebook_append_page:
3822 * @notebook: a #GtkNotebook
3823 * @child: the #GtkWidget to use as the contents of the page.
3824 * @tab_label: the #GtkWidget to be used as the label for the page,
3825 * or %NULL to use the default label, 'page N'.
3827 * Appends a page to @notebook.
3830 gtk_notebook_append_page (GtkNotebook *notebook,
3832 GtkWidget *tab_label)
3834 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3835 g_return_if_fail (GTK_IS_WIDGET (child));
3836 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3838 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3842 * gtk_notebook_append_page_menu:
3843 * @notebook: a #GtkNotebook
3844 * @child: the #GtkWidget to use as the contents of the page.
3845 * @tab_label: the #GtkWidget to be used as the label for the page,
3846 * or %NULL to use the default label, 'page N'.
3847 * @menu_label: the widget to use as a label for the page-switch
3848 * menu, if that is enabled. If %NULL, and @tab_label
3849 * is a #GtkLabel or %NULL, then the menu label will be
3850 * a newly created label with the same text as @tab_label;
3851 * If @tab_label is not a #GtkLabel, @menu_label must be
3852 * specified if the page-switch menu is to be used.
3854 * Appends a page to @notebook, specifying the widget to use as the
3855 * label in the popup menu.
3858 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3860 GtkWidget *tab_label,
3861 GtkWidget *menu_label)
3863 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3864 g_return_if_fail (GTK_IS_WIDGET (child));
3865 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3866 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3868 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3872 * gtk_notebook_prepend_page:
3873 * @notebook: a #GtkNotebook
3874 * @child: the #GtkWidget to use as the contents of the page.
3875 * @tab_label: the #GtkWidget to be used as the label for the page,
3876 * or %NULL to use the default label, 'page N'.
3878 * Prepends a page to @notebook.
3881 gtk_notebook_prepend_page (GtkNotebook *notebook,
3883 GtkWidget *tab_label)
3885 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3886 g_return_if_fail (GTK_IS_WIDGET (child));
3887 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3889 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3893 * gtk_notebook_prepend_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.
3905 * Prepends a page to @notebook, specifying the widget to use as the
3906 * label in the popup menu.
3909 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3911 GtkWidget *tab_label,
3912 GtkWidget *menu_label)
3914 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3915 g_return_if_fail (GTK_IS_WIDGET (child));
3916 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3917 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3919 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3923 * gtk_notebook_insert_page:
3924 * @notebook: a #GtkNotebook
3925 * @child: the #GtkWidget to use as the contents of the page.
3926 * @tab_label: the #GtkWidget to be used as the label for the page,
3927 * or %NULL to use the default label, 'page N'.
3928 * @position: the index (starting at 0) at which to insert the page,
3929 * or -1 to append the page after all other pages.
3931 * Insert a page into @notebook at the given position
3934 gtk_notebook_insert_page (GtkNotebook *notebook,
3936 GtkWidget *tab_label,
3939 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3940 g_return_if_fail (GTK_IS_WIDGET (child));
3941 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3943 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3948 gtk_notebook_page_compare_tab (gconstpointer a,
3951 return (((GtkNotebookPage *) a)->tab_label != b);
3955 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3959 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3962 list = g_list_find_custom (notebook->children, child,
3963 gtk_notebook_page_compare_tab);
3966 GtkNotebookPage *page = list->data;
3968 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3969 gtk_notebook_switch_page (notebook, page, -1);
3970 focus_tabs_in (notebook);
3977 * gtk_notebook_insert_page_menu:
3978 * @notebook: a #GtkNotebook
3979 * @child: the #GtkWidget to use as the contents of the page.
3980 * @tab_label: the #GtkWidget to be used as the label for the page,
3981 * or %NULL to use the default label, 'page N'.
3982 * @menu_label: the widget to use as a label for the page-switch
3983 * menu, if that is enabled. If %NULL, and @tab_label
3984 * is a #GtkLabel or %NULL, then the menu label will be
3985 * a newly created label with the same text as @tab_label;
3986 * If @tab_label is not a #GtkLabel, @menu_label must be
3987 * specified if the page-switch menu is to be used.
3988 * @position: the index (starting at 0) at which to insert the page,
3989 * or -1 to append the page after all other pages.
3991 * Insert a page into @notebook at the given position, specifying
3992 * the widget to use as the label in the popup menu.
3995 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3997 GtkWidget *tab_label,
3998 GtkWidget *menu_label,
4001 GtkNotebookPage *page;
4004 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4005 g_return_if_fail (GTK_IS_WIDGET (child));
4006 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4007 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4009 gtk_widget_freeze_child_notify (child);
4011 page = g_new (GtkNotebookPage, 1);
4012 page->child = child;
4013 page->last_focus_child = NULL;
4014 page->requisition.width = 0;
4015 page->requisition.height = 0;
4016 page->allocation.x = 0;
4017 page->allocation.y = 0;
4018 page->allocation.width = 0;
4019 page->allocation.height = 0;
4020 page->default_menu = FALSE;
4021 page->default_tab = FALSE;
4022 page->mnemonic_activate_signal = 0;
4024 nchildren = g_list_length (notebook->children);
4025 if ((position < 0) || (position > nchildren))
4026 position = nchildren;
4028 notebook->children = g_list_insert (notebook->children, page, position);
4032 page->default_tab = TRUE;
4033 if (notebook->show_tabs)
4034 tab_label = gtk_label_new ("");
4036 page->tab_label = tab_label;
4037 page->menu_label = menu_label;
4038 page->expand = FALSE;
4040 page->pack = GTK_PACK_START;
4043 page->default_menu = TRUE;
4046 g_object_ref (page->menu_label);
4047 gtk_object_sink (GTK_OBJECT (page->menu_label));
4051 gtk_notebook_menu_item_create (notebook,
4052 g_list_find (notebook->children, page));
4054 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4056 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4058 gtk_notebook_update_labels (notebook);
4060 if (!notebook->first_tab)
4061 notebook->first_tab = notebook->children;
4063 if (!notebook->cur_page)
4064 gtk_widget_set_child_visible (child, TRUE);
4066 gtk_widget_set_child_visible (child, FALSE);
4070 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4071 gtk_widget_show (tab_label);
4073 gtk_widget_hide (tab_label);
4076 if (!notebook->cur_page)
4078 gtk_notebook_switch_page (notebook, page, 0);
4079 gtk_notebook_switch_focus_tab (notebook, NULL);
4083 page->mnemonic_activate_signal =
4084 g_signal_connect (tab_label,
4085 "mnemonic_activate",
4086 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4089 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4090 gdk_window_show_unraised (notebook->event_window);
4092 gtk_widget_child_notify (child, "tab_expand");
4093 gtk_widget_child_notify (child, "tab_fill");
4094 gtk_widget_child_notify (child, "tab_pack");
4095 gtk_widget_child_notify (child, "tab_label");
4096 gtk_widget_child_notify (child, "menu_label");
4097 gtk_widget_child_notify (child, "position");
4098 gtk_widget_thaw_child_notify (child);
4102 * gtk_notebook_remove_page:
4103 * @notebook: a #GtkNotebook.
4104 * @page_num: the index of a notebook page, starting
4105 * from 0. If -1, the last page will
4108 * Removes a page from the notebook given its index
4112 gtk_notebook_remove_page (GtkNotebook *notebook,
4117 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4121 list = g_list_nth (notebook->children, page_num);
4123 gtk_notebook_real_remove (notebook, list);
4127 list = g_list_last (notebook->children);
4129 gtk_notebook_real_remove (notebook, list);
4133 /* Public GtkNotebook Page Switch Methods :
4134 * gtk_notebook_get_current_page
4135 * gtk_notebook_page_num
4136 * gtk_notebook_set_current_page
4137 * gtk_notebook_next_page
4138 * gtk_notebook_prev_page
4141 * gtk_notebook_get_current_page:
4142 * @notebook: a #GtkNotebook
4144 * Returns the page number of the current page.
4146 * Return value: the index (starting from 0) of the current
4147 * page in the notebook. If the notebook has no pages, then
4148 * -1 will be returned.
4151 gtk_notebook_get_current_page (GtkNotebook *notebook)
4153 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4155 if (!notebook->cur_page)
4158 return g_list_index (notebook->children, notebook->cur_page);
4162 * gtk_notebook_get_nth_page:
4163 * @notebook: a #GtkNotebook
4164 * @page_num: the index of a page in the noteobok, or -1
4165 * to get the last page.
4167 * Returns the child widget contained in page number @page_num.
4169 * Return value: the child widget, or %NULL if @page_num is
4173 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4176 GtkNotebookPage *page;
4179 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4182 list = g_list_nth (notebook->children, page_num);
4184 list = g_list_last (notebook->children);
4196 * gtk_notebook_get_n_pages:
4197 * @notebook: a #GtkNotebook
4199 * Gets the number of pages in a notebook.
4201 * Return value: the number of pages in the notebook.
4206 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4208 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4210 return g_list_length (notebook->children);
4214 * gtk_notebook_page_num:
4215 * @notebook: a #GtkNotebook
4216 * @child: a #GtkWidget
4218 * Finds the index of the page which contains the given child
4221 * Return value: the index of the page containing @child, or
4222 * -1 if @child is not in the notebook.
4225 gtk_notebook_page_num (GtkNotebook *notebook,
4231 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4234 children = notebook->children;
4237 GtkNotebookPage *page = children->data;
4239 if (page->child == child)
4242 children = children->next;
4250 * gtk_notebook_set_current_page:
4251 * @notebook: a #GtkNotebook
4252 * @page_num: index of the page to switch to, starting from 0.
4253 * If negative, the last page will be used. If greater
4254 * than the number of pages in the notebook, nothing
4257 * Switches to the page number @page_num.
4260 gtk_notebook_set_current_page (GtkNotebook *notebook,
4265 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4268 list = g_list_nth (notebook->children, page_num);
4270 list = g_list_last (notebook->children);
4272 page_num = g_list_index (notebook->children, list);
4275 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4279 * gtk_notebook_next_page:
4280 * @notebook: a #GtkNotebook
4282 * Switches to the next page. Nothing happens if the current page is
4286 gtk_notebook_next_page (GtkNotebook *notebook)
4290 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4292 list = g_list_find (notebook->children, notebook->cur_page);
4296 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4300 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4304 * gtk_notebook_prev_page:
4305 * @notebook: a #GtkNotebook
4307 * Switches to the previous page. Nothing happens if the current page
4308 * is the first page.
4311 gtk_notebook_prev_page (GtkNotebook *notebook)
4315 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4317 list = g_list_find (notebook->children, notebook->cur_page);
4321 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4325 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4328 /* Public GtkNotebook/Tab Style Functions
4330 * gtk_notebook_set_show_border
4331 * gtk_notebook_set_show_tabs
4332 * gtk_notebook_set_tab_pos
4333 * gtk_notebook_set_homogeneous_tabs
4334 * gtk_notebook_set_tab_border
4335 * gtk_notebook_set_tab_hborder
4336 * gtk_notebook_set_tab_vborder
4337 * gtk_notebook_set_scrollable
4340 * gtk_notebook_set_show_border:
4341 * @notebook: a #GtkNotebook
4342 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4344 * Sets whether a bevel will be drawn around the notebook pages.
4345 * This only has a visual effect when the tabs are not shown.
4346 * See gtk_notebook_set_show_tabs().
4349 gtk_notebook_set_show_border (GtkNotebook *notebook,
4350 gboolean show_border)
4352 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4354 if (notebook->show_border != show_border)
4356 notebook->show_border = show_border;
4358 if (GTK_WIDGET_VISIBLE (notebook))
4359 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4361 g_object_notify (G_OBJECT (notebook), "show_border");
4366 * gtk_notebook_get_show_border:
4367 * @notebook: a #GtkNotebook
4369 * Returns whether a bevel will be drawn around the notebook pages. See
4370 * gtk_notebook_set_show_border().
4372 * Return value: %TRUE if the bevel is drawn
4375 gtk_notebook_get_show_border (GtkNotebook *notebook)
4377 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4379 return notebook->show_border;
4383 * gtk_notebook_set_show_tabs:
4384 * @notebook: a #GtkNotebook
4385 * @show_tabs: %TRUE if the tabs should be shown.
4387 * Sets whether to show the tabs for the notebook or not.
4390 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4393 GtkNotebookPage *page;
4396 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4398 show_tabs = show_tabs != FALSE;
4400 if (notebook->show_tabs == show_tabs)
4403 notebook->show_tabs = show_tabs;
4404 children = notebook->children;
4408 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4412 page = children->data;
4413 children = children->next;
4414 if (page->default_tab)
4416 gtk_widget_destroy (page->tab_label);
4417 page->tab_label = NULL;
4420 gtk_widget_hide (page->tab_label);
4425 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4426 gtk_notebook_update_labels (notebook);
4428 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4430 g_object_notify (G_OBJECT (notebook), "show_tabs");
4434 * gtk_notebook_get_show_tabs:
4435 * @notebook: a #GtkNotebook
4437 * Returns whether the tabs of the notebook are shown. See
4438 * gtk_notebook_set_show_tabs().
4440 * Return value: %TRUE if the tabs are shown
4443 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4445 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4447 return notebook->show_tabs;
4451 * gtk_notebook_set_tab_pos:
4452 * @notebook: a #GtkNotebook.
4453 * @pos: the edge to draw the tabs at.
4455 * Sets the edge at which the tabs for switching pages in the
4456 * notebook are drawn.
4459 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4460 GtkPositionType pos)
4462 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4464 if (notebook->tab_pos != pos)
4466 notebook->tab_pos = pos;
4467 if (GTK_WIDGET_VISIBLE (notebook))
4468 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4471 g_object_notify (G_OBJECT (notebook), "tab_pos");
4475 * gtk_notebook_get_tab_pos:
4476 * @notebook: a #GtkNotebook
4478 * Gets the edge at which the tabs for switching pages in the
4479 * notebook are drawn.
4481 * Return value: the edge at which the tabs are drawn
4484 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4486 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4488 return notebook->tab_pos;
4492 * gtk_notebook_set_homogeneous_tabs:
4493 * @notebook: a #GtkNotebook
4494 * @homogeneous: %TRUE if all tabs should be the same size.
4496 * Sets whether the tabs must have all the same size or not.
4499 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4500 gboolean homogeneous)
4502 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4504 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4508 * gtk_notebook_set_tab_border:
4509 * @notebook: a #GtkNotebook
4510 * @border_width: width of the border around the tab labels.
4512 * Sets the width the border around the tab labels
4513 * in a notebook. This is equivalent to calling
4514 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4515 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4518 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4521 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4523 gtk_notebook_set_tab_border_internal (notebook, border_width);
4527 * gtk_notebook_set_tab_hborder:
4528 * @notebook: a #GtkNotebook
4529 * @tab_hborder: width of the horizontal border of tab labels.
4531 * Sets the width of the horizontal border of tab labels.
4534 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4537 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4539 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4543 * gtk_notebook_set_tab_vborder:
4544 * @notebook: a #GtkNotebook
4545 * @tab_vborder: width of the vertical border of tab labels.
4547 * Sets the width of the vertical border of tab labels.
4550 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4553 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4555 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4559 * gtk_notebook_set_scrollable:
4560 * @notebook: a #GtkNotebook
4561 * @scrollable: %TRUE if scroll arrows should be added
4563 * Sets whether the tab label area will have arrows for scrolling if
4564 * there are too many tabs to fit in the area.
4567 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4568 gboolean scrollable)
4570 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4572 scrollable = (scrollable != FALSE);
4574 if (scrollable != notebook->scrollable)
4576 notebook->scrollable = scrollable;
4578 if (GTK_WIDGET_VISIBLE (notebook))
4579 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4581 g_object_notify (G_OBJECT (notebook), "scrollable");
4586 * gtk_notebook_get_scrollable:
4587 * @notebook: a #GtkNotebook
4589 * Returns whether the tab label area has arrows for scrolling. See
4590 * gtk_notebook_set_scrollable().
4592 * Return value: %TRUE if arrows for scrolling are present
4595 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4597 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4599 return notebook->scrollable;
4602 /* Public GtkNotebook Popup Menu Methods:
4604 * gtk_notebook_popup_enable
4605 * gtk_notebook_popup_disable
4610 * gtk_notebook_popup_enable:
4611 * @notebook: a #GtkNotebook
4613 * Enables the popup menu: if the user clicks with the right mouse button on
4614 * the bookmarks, a menu with all the pages will be popped up.
4617 gtk_notebook_popup_enable (GtkNotebook *notebook)
4621 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4626 notebook->menu = gtk_menu_new ();
4627 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4629 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4630 gtk_notebook_menu_item_create (notebook, list);
4632 gtk_notebook_update_labels (notebook);
4633 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4634 GTK_WIDGET (notebook),
4635 gtk_notebook_menu_detacher);
4637 g_object_notify (G_OBJECT (notebook), "enable_popup");
4641 * gtk_notebook_popup_disable:
4642 * @notebook: a #GtkNotebook
4644 * Disables the popup menu.
4647 gtk_notebook_popup_disable (GtkNotebook *notebook)
4649 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4651 if (!notebook->menu)
4654 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4655 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4656 gtk_widget_destroy (notebook->menu);
4658 g_object_notify (G_OBJECT (notebook), "enable_popup");
4661 /* Public GtkNotebook Page Properties Functions:
4663 * gtk_notebook_get_tab_label
4664 * gtk_notebook_set_tab_label
4665 * gtk_notebook_set_tab_label_text
4666 * gtk_notebook_get_menu_label
4667 * gtk_notebook_set_menu_label
4668 * gtk_notebook_set_menu_label_text
4669 * gtk_notebook_set_tab_label_packing
4670 * gtk_notebook_query_tab_label_packing
4674 * gtk_notebook_get_tab_label:
4675 * @notebook: a #GtkNotebook
4678 * Returns the tab label widget for the page @child. %NULL is returned
4679 * if @child is not in @notebook or if no tab label has specifically
4680 * been set for @child.
4682 * Return value: the tab label
4685 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4690 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4691 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4693 list = CHECK_FIND_CHILD (notebook, child);
4697 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4700 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4704 * gtk_notebook_set_tab_label:
4705 * @notebook: a #GtkNotebook
4707 * @tab_label: the tab label widget to use, or %NULL for default tab
4710 * Changes the tab label for @child. If %NULL is specified
4711 * for @tab_label, then the page will have the label 'page N'.
4714 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4716 GtkWidget *tab_label)
4718 GtkNotebookPage *page;
4721 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4722 g_return_if_fail (GTK_IS_WIDGET (child));
4724 list = CHECK_FIND_CHILD (notebook, child);
4728 /* a NULL pointer indicates a default_tab setting, otherwise
4729 * we need to set the associated label
4733 if (page->tab_label == tab_label)
4737 gtk_notebook_remove_tab_label (notebook, page);
4741 page->default_tab = FALSE;
4742 page->tab_label = tab_label;
4743 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4747 page->default_tab = TRUE;
4748 page->tab_label = NULL;
4750 if (notebook->show_tabs)
4754 g_snprintf (string, sizeof(string), _("Page %u"),
4755 gtk_notebook_real_page_position (notebook, list));
4756 page->tab_label = gtk_label_new (string);
4757 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4761 if (page->tab_label)
4762 page->mnemonic_activate_signal =
4763 g_signal_connect (page->tab_label,
4764 "mnemonic_activate",
4765 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4768 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4770 gtk_widget_show (page->tab_label);
4771 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4773 gtk_widget_child_notify (child, "tab_label");
4777 * gtk_notebook_set_tab_label_text:
4778 * @notebook: a #GtkNotebook
4780 * @tab_text: the label text
4782 * Creates a new label and sets it as the tab label for the page
4783 * containing @child.
4786 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4788 const gchar *tab_text)
4790 GtkWidget *tab_label = NULL;
4792 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4795 tab_label = gtk_label_new (tab_text);
4796 gtk_notebook_set_tab_label (notebook, child, tab_label);
4797 gtk_widget_child_notify (child, "tab_label");
4801 * gtk_notebook_get_tab_label_text:
4802 * @notebook: a #GtkNotebook
4803 * @child: a widget contained in a page of @notebook
4805 * Retrieves the text of the tab label for the page containing
4808 * Returns value: the text of the tab label, or %NULL if the
4809 * tab label widget is not a #GtkLabel. The
4810 * string is owned by the widget and must not
4813 G_CONST_RETURN gchar *
4814 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4817 GtkWidget *tab_label;
4819 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4820 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4822 tab_label = gtk_notebook_get_tab_label (notebook, child);
4824 if (tab_label && GTK_IS_LABEL (tab_label))
4825 return gtk_label_get_text (GTK_LABEL (tab_label));
4831 * gtk_notebook_get_menu_label:
4832 * @notebook: a #GtkNotebook
4833 * @child: a widget contained in a page of @notebook
4835 * Retrieves the menu label widget of the page containing @child.
4837 * Return value: the menu label, or %NULL if the
4838 * notebook page does not have a menu label other
4839 * than the default (the tab label).
4842 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4847 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4848 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4850 list = CHECK_FIND_CHILD (notebook, child);
4854 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4857 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4861 * gtk_notebook_set_menu_label:
4862 * @notebook: a #GtkNotebook
4863 * @child: the child widget
4864 * @menu_label: the menu label, or NULL for default
4866 * Changes the menu label for the page containing @child.
4869 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4871 GtkWidget *menu_label)
4873 GtkNotebookPage *page;
4876 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4877 g_return_if_fail (GTK_IS_WIDGET (child));
4879 list = CHECK_FIND_CHILD (notebook, child);
4884 if (page->menu_label)
4887 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4888 page->menu_label->parent);
4890 if (!page->default_menu)
4891 g_object_unref (page->menu_label);
4896 page->menu_label = menu_label;
4897 g_object_ref (page->menu_label);
4898 gtk_object_sink (GTK_OBJECT(page->menu_label));
4899 page->default_menu = FALSE;
4902 page->default_menu = TRUE;
4905 gtk_notebook_menu_item_create (notebook, list);
4906 gtk_widget_child_notify (child, "menu_label");
4910 * gtk_notebook_set_menu_label_text:
4911 * @notebook: a #GtkNotebook
4912 * @child: the child widget
4913 * @menu_text: the label text
4915 * Creates a new label and sets it as the menu label of @child.
4918 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4920 const gchar *menu_text)
4922 GtkWidget *menu_label = NULL;
4924 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4927 menu_label = gtk_label_new (menu_text);
4928 gtk_notebook_set_menu_label (notebook, child, menu_label);
4929 gtk_widget_child_notify (child, "menu_label");
4933 * gtk_notebook_get_menu_label_text:
4934 * @notebook: a #GtkNotebook
4935 * @child: the child widget of a page of the notebook.
4937 * Retrieves the text of the menu label for the page containing
4940 * Returns value: the text of the tab label, or %NULL if the
4941 * widget does not have a menu label other than
4942 * the default menu label, or the menu label widget
4943 * is not a #GtkLabel. The string is owned by
4944 * the widget and must not be freed.
4946 G_CONST_RETURN gchar *
4947 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4950 GtkWidget *menu_label;
4952 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4953 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4955 menu_label = gtk_notebook_get_menu_label (notebook, child);
4957 if (menu_label && GTK_IS_LABEL (menu_label))
4958 return gtk_label_get_text (GTK_LABEL (menu_label));
4963 /* Helper function called when pages are reordered
4966 gtk_notebook_child_reordered (GtkNotebook *notebook,
4967 GtkNotebookPage *page)
4971 GtkWidget *menu_item;
4973 menu_item = page->menu_label->parent;
4974 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4975 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4976 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4979 gtk_notebook_update_labels (notebook);
4983 * gtk_notebook_set_tab_label_packing:
4984 * @notebook: a #GtkNotebook
4985 * @child: the child widget
4986 * @expand: whether to expand the bookmark or not
4987 * @fill: whether the bookmark should fill the allocated area or not
4988 * @pack_type: the position of the bookmark
4990 * Sets the packing parameters for the tab label of the page
4991 * containing @child. See gtk_box_pack_start() for the exact meaning
4992 * of the parameters.
4995 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4999 GtkPackType pack_type)
5001 GtkNotebookPage *page;
5004 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5005 g_return_if_fail (GTK_IS_WIDGET (child));
5007 list = CHECK_FIND_CHILD (notebook, child);
5012 expand = expand != FALSE;
5013 fill = fill != FALSE;
5014 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5017 gtk_widget_freeze_child_notify (child);
5018 page->expand = expand;
5019 gtk_widget_child_notify (child, "tab_expand");
5021 gtk_widget_child_notify (child, "tab_fill");
5022 if (page->pack != pack_type)
5024 page->pack = pack_type;
5025 gtk_notebook_child_reordered (notebook, page);
5027 gtk_widget_child_notify (child, "tab_pack");
5028 gtk_widget_child_notify (child, "position");
5029 if (notebook->show_tabs)
5030 gtk_notebook_pages_allocate (notebook);
5031 gtk_widget_thaw_child_notify (child);
5035 * gtk_notebook_query_tab_label_packing:
5036 * @notebook: a #GtkNotebook
5038 * @expand: location to store the expand value (or NULL)
5039 * @fill: location to store the fill value (or NULL)
5040 * @pack_type: location to store the pack_type (or NULL)
5042 * Query the packing attributes for the tab label of the page
5043 * containing @child.
5046 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5050 GtkPackType *pack_type)
5054 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5055 g_return_if_fail (GTK_IS_WIDGET (child));
5057 list = CHECK_FIND_CHILD (notebook, child);
5062 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5064 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5066 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5070 * gtk_notebook_reorder_child:
5071 * @notebook: a #GtkNotebook
5072 * @child: the child to move
5073 * @position: the new position, or -1 to move to the end
5075 * Reorders the page containing @child, so that it appears in position
5076 * @position. If @position is greater than or equal to the number of
5077 * children in the list or negative, @child will be moved to the end
5081 gtk_notebook_reorder_child (GtkNotebook *notebook,
5085 GList *list, *new_list;
5086 GtkNotebookPage *page;
5090 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5091 g_return_if_fail (GTK_IS_WIDGET (child));
5093 list = CHECK_FIND_CHILD (notebook, child);
5097 max_pos = g_list_length (notebook->children) - 1;
5098 if (position < 0 || position > max_pos)
5101 old_pos = g_list_position (notebook->children, list);
5103 if (old_pos == position)
5107 notebook->children = g_list_delete_link (notebook->children, list);
5109 notebook->children = g_list_insert (notebook->children, page, position);
5110 new_list = g_list_nth (notebook->children, position);
5112 /* Fix up GList references in GtkNotebook structure */
5113 if (notebook->first_tab == list)
5114 notebook->first_tab = new_list;
5115 if (notebook->focus_tab == list)
5116 notebook->focus_tab = new_list;
5118 gtk_widget_freeze_child_notify (child);
5120 /* Move around the menu items if necesary */
5121 gtk_notebook_child_reordered (notebook, page);
5122 gtk_widget_child_notify (child, "tab_pack");
5123 gtk_widget_child_notify (child, "position");
5125 if (notebook->show_tabs)
5126 gtk_notebook_pages_allocate (notebook);
5128 gtk_widget_thaw_child_notify (child);