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 gboolean destroying);
194 static void gtk_notebook_update_labels (GtkNotebook *notebook);
195 static gint gtk_notebook_timer (GtkNotebook *notebook);
196 static gint gtk_notebook_page_compare (gconstpointer a,
198 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
200 const gchar *function);
201 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
203 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
206 gboolean find_visible);
208 /*** GtkNotebook Drawing Functions ***/
209 static void gtk_notebook_paint (GtkWidget *widget,
211 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
212 GtkNotebookPage *page,
214 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
217 /*** GtkNotebook Size Allocate Functions ***/
218 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
219 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
220 GtkNotebookPage *page,
221 GtkAllocation *allocation);
222 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
228 /*** GtkNotebook Page Switch Methods ***/
229 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
230 GtkNotebookPage *page,
233 /*** GtkNotebook Page Switch Functions ***/
234 static void gtk_notebook_switch_page (GtkNotebook *notebook,
235 GtkNotebookPage *page,
237 static gint gtk_notebook_page_select (GtkNotebook *notebook,
238 gboolean move_focus);
239 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
241 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
242 GtkNotebookPage *page);
244 /*** GtkNotebook Menu Functions ***/
245 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
247 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
249 static void gtk_notebook_menu_detacher (GtkWidget *widget,
252 /*** GtkNotebook Private Setters ***/
253 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
254 gboolean homogeneous);
255 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
257 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
259 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
262 static gboolean focus_tabs_in (GtkNotebook *notebook);
263 static gboolean focus_child_in (GtkNotebook *notebook,
264 GtkDirectionType direction);
266 static GtkContainerClass *parent_class = NULL;
267 static guint notebook_signals[LAST_SIGNAL] = { 0 };
270 gtk_notebook_get_type (void)
272 static GType notebook_type = 0;
276 static const GTypeInfo notebook_info =
278 sizeof (GtkNotebookClass),
279 NULL, /* base_init */
280 NULL, /* base_finalize */
281 (GClassInitFunc) gtk_notebook_class_init,
282 NULL, /* class_finalize */
283 NULL, /* class_data */
284 sizeof (GtkNotebook),
286 (GInstanceInitFunc) gtk_notebook_init,
289 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
293 return notebook_type;
297 add_tab_bindings (GtkBindingSet *binding_set,
298 GdkModifierType modifiers,
299 GtkDirectionType direction)
301 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
303 GTK_TYPE_DIRECTION_TYPE, direction);
304 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
306 GTK_TYPE_DIRECTION_TYPE, direction);
310 add_arrow_bindings (GtkBindingSet *binding_set,
312 GtkDirectionType direction)
314 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
316 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
318 GTK_TYPE_DIRECTION_TYPE, direction);
319 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
321 GTK_TYPE_DIRECTION_TYPE, direction);
325 gtk_notebook_class_init (GtkNotebookClass *class)
327 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
328 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
329 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
330 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
331 GtkBindingSet *binding_set;
333 parent_class = g_type_class_peek_parent (class);
335 gobject_class->set_property = gtk_notebook_set_property;
336 gobject_class->get_property = gtk_notebook_get_property;
337 object_class->destroy = gtk_notebook_destroy;
339 widget_class->map = gtk_notebook_map;
340 widget_class->unmap = gtk_notebook_unmap;
341 widget_class->realize = gtk_notebook_realize;
342 widget_class->unrealize = gtk_notebook_unrealize;
343 widget_class->size_request = gtk_notebook_size_request;
344 widget_class->size_allocate = gtk_notebook_size_allocate;
345 widget_class->expose_event = gtk_notebook_expose;
346 widget_class->button_press_event = gtk_notebook_button_press;
347 widget_class->button_release_event = gtk_notebook_button_release;
348 widget_class->enter_notify_event = gtk_notebook_enter_notify;
349 widget_class->leave_notify_event = gtk_notebook_leave_notify;
350 widget_class->motion_notify_event = gtk_notebook_motion_notify;
351 widget_class->focus_in_event = gtk_notebook_focus_in;
352 widget_class->focus = gtk_notebook_focus;
354 container_class->add = gtk_notebook_add;
355 container_class->remove = gtk_notebook_remove;
356 container_class->forall = gtk_notebook_forall;
357 container_class->set_focus_child = gtk_notebook_set_focus_child;
358 container_class->get_child_property = gtk_notebook_get_child_property;
359 container_class->set_child_property = gtk_notebook_set_child_property;
360 container_class->child_type = gtk_notebook_child_type;
362 class->switch_page = gtk_notebook_real_switch_page;
364 class->focus_tab = gtk_notebook_focus_tab;
365 class->select_page = gtk_notebook_select_page;
366 class->change_current_page = gtk_notebook_change_current_page;
367 class->move_focus_out = gtk_notebook_move_focus_out;
369 g_object_class_install_property (gobject_class,
371 g_param_spec_int ("page",
373 _("The index of the current page"),
378 g_object_class_install_property (gobject_class,
380 g_param_spec_enum ("tab_pos",
382 _("Which side of the notebook holds the tabs"),
383 GTK_TYPE_POSITION_TYPE,
386 g_object_class_install_property (gobject_class,
388 g_param_spec_uint ("tab_border",
390 _("Width of the border around the tab labels"),
395 g_object_class_install_property (gobject_class,
397 g_param_spec_uint ("tab_hborder",
398 _("Horizontal Tab Border"),
399 _("Width of the horizontal border of tab labels"),
404 g_object_class_install_property (gobject_class,
406 g_param_spec_uint ("tab_vborder",
407 _("Vertical Tab Border"),
408 _("Width of the vertical border of tab labels"),
413 g_object_class_install_property (gobject_class,
415 g_param_spec_boolean ("show_tabs",
417 _("Whether tabs should be shown or not"),
420 g_object_class_install_property (gobject_class,
422 g_param_spec_boolean ("show_border",
424 _("Whether the border should be shown or not"),
427 g_object_class_install_property (gobject_class,
429 g_param_spec_boolean ("scrollable",
431 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
434 g_object_class_install_property (gobject_class,
436 g_param_spec_boolean ("enable_popup",
438 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
441 g_object_class_install_property (gobject_class,
443 g_param_spec_boolean ("homogeneous",
445 _("Whether tabs should have homogeneous sizes"),
449 gtk_container_class_install_child_property (container_class,
450 CHILD_PROP_TAB_LABEL,
451 g_param_spec_string ("tab_label",
453 _("The string displayed on the childs tab label"),
456 gtk_container_class_install_child_property (container_class,
457 CHILD_PROP_MENU_LABEL,
458 g_param_spec_string ("menu_label",
460 _("The string displayed in the childs menu entry"),
463 gtk_container_class_install_child_property (container_class,
465 g_param_spec_int ("position",
467 _("The index of the child in the parent"),
470 gtk_container_class_install_child_property (container_class,
471 CHILD_PROP_TAB_EXPAND,
472 g_param_spec_boolean ("tab_expand",
474 _("Whether to expand the childs tab or not"),
477 gtk_container_class_install_child_property (container_class,
479 g_param_spec_boolean ("tab_fill",
481 _("Wheather the childs tab should fill the allocated area or not"),
484 gtk_container_class_install_child_property (container_class,
486 g_param_spec_enum ("tab_pack",
488 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
489 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
492 notebook_signals[SWITCH_PAGE] =
493 g_signal_new ("switch_page",
494 G_TYPE_FROM_CLASS (gobject_class),
496 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
498 _gtk_marshal_VOID__POINTER_UINT,
502 notebook_signals[FOCUS_TAB] =
503 g_signal_new ("focus_tab",
504 G_TYPE_FROM_CLASS (gobject_class),
505 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
506 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
508 _gtk_marshal_BOOLEAN__ENUM,
510 GTK_TYPE_NOTEBOOK_TAB);
511 notebook_signals[SELECT_PAGE] =
512 g_signal_new ("select_page",
513 G_TYPE_FROM_CLASS (gobject_class),
514 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
515 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
517 _gtk_marshal_BOOLEAN__BOOLEAN,
520 notebook_signals[CHANGE_CURRENT_PAGE] =
521 g_signal_new ("change_current_page",
522 G_TYPE_FROM_CLASS (gobject_class),
523 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
524 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
526 _gtk_marshal_VOID__INT,
529 notebook_signals[MOVE_FOCUS_OUT] =
530 g_signal_new ("move_focus_out",
531 G_TYPE_FROM_CLASS (gobject_class),
532 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
533 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
535 _gtk_marshal_VOID__ENUM,
537 GTK_TYPE_DIRECTION_TYPE);
540 binding_set = gtk_binding_set_by_class (class);
541 gtk_binding_entry_add_signal (binding_set,
544 G_TYPE_BOOLEAN, FALSE);
545 gtk_binding_entry_add_signal (binding_set,
548 G_TYPE_BOOLEAN, FALSE);
550 gtk_binding_entry_add_signal (binding_set,
553 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
554 gtk_binding_entry_add_signal (binding_set,
557 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
558 gtk_binding_entry_add_signal (binding_set,
561 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
562 gtk_binding_entry_add_signal (binding_set,
565 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
567 gtk_binding_entry_add_signal (binding_set,
568 GDK_Page_Up, GDK_CONTROL_MASK,
569 "change_current_page", 1,
571 gtk_binding_entry_add_signal (binding_set,
572 GDK_Page_Down, GDK_CONTROL_MASK,
573 "change_current_page", 1,
576 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
577 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
578 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
579 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
581 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
582 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
586 gtk_notebook_init (GtkNotebook *notebook)
588 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
589 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
591 notebook->cur_page = NULL;
592 notebook->children = NULL;
593 notebook->first_tab = NULL;
594 notebook->focus_tab = NULL;
595 notebook->event_window = NULL;
596 notebook->menu = NULL;
598 notebook->tab_hborder = 2;
599 notebook->tab_vborder = 2;
601 notebook->show_tabs = TRUE;
602 notebook->show_border = TRUE;
603 notebook->tab_pos = GTK_POS_TOP;
604 notebook->scrollable = FALSE;
605 notebook->in_child = 0;
606 notebook->click_child = 0;
607 notebook->button = 0;
608 notebook->need_timer = 0;
609 notebook->child_has_focus = FALSE;
610 notebook->have_visible_child = FALSE;
611 notebook->focus_out = FALSE;
615 gtk_notebook_select_page (GtkNotebook *notebook,
618 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
620 gtk_notebook_page_select (notebook, move_focus);
628 gtk_notebook_focus_tab (GtkNotebook *notebook,
633 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
637 case GTK_NOTEBOOK_TAB_FIRST:
638 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
640 gtk_notebook_switch_focus_tab (notebook, list);
642 case GTK_NOTEBOOK_TAB_LAST:
643 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
645 gtk_notebook_switch_focus_tab (notebook, list);
656 gtk_notebook_change_current_page (GtkNotebook *notebook,
659 GList *current = NULL;
661 if (notebook->cur_page)
662 current = g_list_find (notebook->children, notebook->cur_page);
666 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
667 offset += offset < 0 ? 1 : -1;
671 gtk_notebook_switch_page (notebook, current->data, -1);
673 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
676 static GtkDirectionType
677 get_effective_direction (GtkNotebook *notebook,
678 GtkDirectionType direction)
680 /* Remap the directions into the effective direction it would be for a
681 * GTK_POS_TOP notebook
683 #define D(rest) GTK_DIR_##rest
685 static const GtkDirectionType translate_direction[4][6] = {
686 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
687 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
688 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
689 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
694 return translate_direction[notebook->tab_pos][direction];
698 gtk_notebook_move_focus_out (GtkNotebook *notebook,
699 GtkDirectionType direction_type)
701 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
704 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
705 if (focus_tabs_in (notebook))
708 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
709 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
712 /* At this point, we know we should be focusing out of the notebook entirely. We
713 * do this by setting a flag, then propagating the focus motion to the notebook.
715 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
716 if (!GTK_WIDGET_TOPLEVEL (toplevel))
719 g_object_ref (notebook);
721 notebook->focus_out = TRUE;
722 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
723 notebook->focus_out = FALSE;
725 g_object_unref (notebook);
732 * Creates a new #GtkNotebook widget with no pages.
734 * Return value: the newly created #GtkNotebook
737 gtk_notebook_new (void)
739 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
742 /* Private GtkObject Methods :
744 * gtk_notebook_destroy
745 * gtk_notebook_set_arg
746 * gtk_notebook_get_arg
749 gtk_notebook_destroy (GtkObject *object)
752 GtkNotebook *notebook = GTK_NOTEBOOK (object);
755 gtk_notebook_popup_disable (notebook);
757 children = notebook->children;
760 GList *child = children;
761 children = child->next;
763 gtk_notebook_real_remove (notebook, child, TRUE);
766 GTK_OBJECT_CLASS (parent_class)->destroy (object);
770 gtk_notebook_set_property (GObject *object,
775 GtkNotebook *notebook;
777 notebook = GTK_NOTEBOOK (object);
782 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
784 case PROP_SHOW_BORDER:
785 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
787 case PROP_SCROLLABLE:
788 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
790 case PROP_ENABLE_POPUP:
791 if (g_value_get_boolean (value))
792 gtk_notebook_popup_enable (notebook);
794 gtk_notebook_popup_disable (notebook);
796 case PROP_HOMOGENEOUS:
797 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
800 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
803 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
805 case PROP_TAB_BORDER:
806 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
808 case PROP_TAB_HBORDER:
809 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
811 case PROP_TAB_VBORDER:
812 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
820 gtk_notebook_get_property (GObject *object,
825 GtkNotebook *notebook;
827 notebook = GTK_NOTEBOOK (object);
832 g_value_set_boolean (value, notebook->show_tabs);
834 case PROP_SHOW_BORDER:
835 g_value_set_boolean (value, notebook->show_border);
837 case PROP_SCROLLABLE:
838 g_value_set_boolean (value, notebook->scrollable);
840 case PROP_ENABLE_POPUP:
841 g_value_set_boolean (value, notebook->menu != NULL);
843 case PROP_HOMOGENEOUS:
844 g_value_set_boolean (value, notebook->homogeneous);
847 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
850 g_value_set_enum (value, notebook->tab_pos);
852 case PROP_TAB_HBORDER:
853 g_value_set_uint (value, notebook->tab_hborder);
855 case PROP_TAB_VBORDER:
856 g_value_set_uint (value, notebook->tab_vborder);
859 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
864 /* Private GtkWidget Methods :
868 * gtk_notebook_realize
869 * gtk_notebook_size_request
870 * gtk_notebook_size_allocate
871 * gtk_notebook_expose
872 * gtk_notebook_button_press
873 * gtk_notebook_button_release
874 * gtk_notebook_enter_notify
875 * gtk_notebook_leave_notify
876 * gtk_notebook_motion_notify
877 * gtk_notebook_focus_in
878 * gtk_notebook_focus_out
879 * gtk_notebook_draw_focus
880 * gtk_notebook_style_set
883 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
884 GdkRectangle *rectangle)
886 GtkWidget *widget = GTK_WIDGET (notebook);
887 gint border_width = GTK_CONTAINER (notebook)->border_width;
888 GtkNotebookPage *visible_page = NULL;
891 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
893 GtkNotebookPage *page = tmp_list->data;
894 if (GTK_WIDGET_VISIBLE (page->child))
901 if (notebook->show_tabs && visible_page)
905 rectangle->x = widget->allocation.x + border_width;
906 rectangle->y = widget->allocation.y + border_width;
908 switch (notebook->tab_pos)
912 rectangle->width = widget->allocation.width - 2 * border_width;
913 rectangle->height = visible_page->requisition.height;
914 if (notebook->tab_pos == GTK_POS_BOTTOM)
915 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
919 rectangle->width = visible_page->requisition.width;
920 rectangle->height = widget->allocation.height - 2 * border_width;
921 if (notebook->tab_pos == GTK_POS_RIGHT)
922 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
933 rectangle->x = rectangle->y = 0;
934 rectangle->width = rectangle->height = 10;
942 gtk_notebook_map (GtkWidget *widget)
944 GtkNotebook *notebook;
945 GtkNotebookPage *page;
948 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
950 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
952 notebook = GTK_NOTEBOOK (widget);
954 if (notebook->cur_page &&
955 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
956 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
957 gtk_widget_map (notebook->cur_page->child);
959 if (notebook->scrollable)
960 gtk_notebook_pages_allocate (notebook);
963 children = notebook->children;
967 page = children->data;
968 children = children->next;
970 if (page->tab_label &&
971 GTK_WIDGET_VISIBLE (page->tab_label) &&
972 !GTK_WIDGET_MAPPED (page->tab_label))
973 gtk_widget_map (page->tab_label);
977 if (gtk_notebook_get_event_window_position (notebook, NULL))
978 gdk_window_show_unraised (notebook->event_window);
982 gtk_notebook_unmap (GtkWidget *widget)
984 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
986 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
988 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
990 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
994 gtk_notebook_realize (GtkWidget *widget)
996 GtkNotebook *notebook;
997 GdkWindowAttr attributes;
998 gint attributes_mask;
999 GdkRectangle event_window_pos;
1001 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1003 notebook = GTK_NOTEBOOK (widget);
1004 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1006 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1008 widget->window = gtk_widget_get_parent_window (widget);
1009 g_object_ref (widget->window);
1011 attributes.window_type = GDK_WINDOW_CHILD;
1012 attributes.x = event_window_pos.x;
1013 attributes.y = event_window_pos.y;
1014 attributes.width = event_window_pos.width;
1015 attributes.height = event_window_pos.height;
1016 attributes.wclass = GDK_INPUT_ONLY;
1017 attributes.event_mask = gtk_widget_get_events (widget);
1018 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
1019 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1021 attributes_mask = GDK_WA_X | GDK_WA_Y;
1023 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1024 &attributes, attributes_mask);
1025 gdk_window_set_user_data (notebook->event_window, notebook);
1027 widget->style = gtk_style_attach (widget->style, widget->window);
1031 gtk_notebook_unrealize (GtkWidget *widget)
1033 GtkNotebook *notebook;
1035 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1037 notebook = GTK_NOTEBOOK (widget);
1039 gdk_window_set_user_data (notebook->event_window, NULL);
1040 gdk_window_destroy (notebook->event_window);
1041 notebook->event_window = NULL;
1043 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1044 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1048 gtk_notebook_size_request (GtkWidget *widget,
1049 GtkRequisition *requisition)
1051 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1052 GtkNotebookPage *page;
1054 GtkRequisition child_requisition;
1055 gboolean switch_page = FALSE;
1059 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1061 widget->requisition.width = 0;
1062 widget->requisition.height = 0;
1064 for (children = notebook->children, vis_pages = 0; children;
1065 children = children->next)
1067 page = children->data;
1069 if (GTK_WIDGET_VISIBLE (page->child))
1072 gtk_widget_size_request (page->child, &child_requisition);
1074 widget->requisition.width = MAX (widget->requisition.width,
1075 child_requisition.width);
1076 widget->requisition.height = MAX (widget->requisition.height,
1077 child_requisition.height);
1079 if (notebook->menu && page->menu_label->parent &&
1080 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1081 gtk_widget_show (page->menu_label->parent);
1085 if (page == notebook->cur_page)
1087 if (notebook->menu && page->menu_label->parent &&
1088 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1089 gtk_widget_hide (page->menu_label->parent);
1093 if (notebook->show_border || notebook->show_tabs)
1095 widget->requisition.width += widget->style->xthickness * 2;
1096 widget->requisition.height += widget->style->ythickness * 2;
1098 if (notebook->show_tabs)
1101 gint tab_height = 0;
1105 for (children = notebook->children; children;
1106 children = children->next)
1108 page = children->data;
1110 if (GTK_WIDGET_VISIBLE (page->child))
1112 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1113 gtk_widget_show (page->tab_label);
1115 gtk_widget_size_request (page->tab_label,
1116 &child_requisition);
1118 page->requisition.width =
1119 child_requisition.width +
1120 2 * widget->style->xthickness;
1121 page->requisition.height =
1122 child_requisition.height +
1123 2 * widget->style->ythickness;
1125 switch (notebook->tab_pos)
1128 case GTK_POS_BOTTOM:
1129 page->requisition.height += 2 * (notebook->tab_vborder +
1131 tab_height = MAX (tab_height, page->requisition.height);
1132 tab_max = MAX (tab_max, page->requisition.width);
1136 page->requisition.width += 2 * (notebook->tab_hborder +
1138 tab_width = MAX (tab_width, page->requisition.width);
1139 tab_max = MAX (tab_max, page->requisition.height);
1143 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1144 gtk_widget_hide (page->tab_label);
1147 children = notebook->children;
1151 switch (notebook->tab_pos)
1154 case GTK_POS_BOTTOM:
1155 if (tab_height == 0)
1158 if (notebook->scrollable && vis_pages > 1 &&
1159 widget->requisition.width < tab_width)
1160 tab_height = MAX (tab_height, ARROW_SIZE);
1162 padding = 2 * (TAB_CURVATURE + focus_width +
1163 notebook->tab_hborder) - TAB_OVERLAP;
1167 page = children->data;
1168 children = children->next;
1170 if (!GTK_WIDGET_VISIBLE (page->child))
1173 if (notebook->homogeneous)
1174 page->requisition.width = tab_max;
1176 page->requisition.width += padding;
1178 tab_width += page->requisition.width;
1179 page->requisition.height = tab_height;
1182 if (notebook->scrollable && vis_pages > 1 &&
1183 widget->requisition.width < tab_width)
1184 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1186 if (notebook->homogeneous && !notebook->scrollable)
1187 widget->requisition.width = MAX (widget->requisition.width,
1188 vis_pages * tab_max +
1191 widget->requisition.width = MAX (widget->requisition.width,
1192 tab_width + TAB_OVERLAP);
1194 widget->requisition.height += tab_height;
1201 if (notebook->scrollable && vis_pages > 1 &&
1202 widget->requisition.height < tab_height)
1203 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1205 padding = 2 * (TAB_CURVATURE + focus_width +
1206 notebook->tab_vborder) - TAB_OVERLAP;
1211 page = children->data;
1212 children = children->next;
1214 if (!GTK_WIDGET_VISIBLE (page->child))
1217 page->requisition.width = tab_width;
1219 if (notebook->homogeneous)
1220 page->requisition.height = tab_max;
1222 page->requisition.height += padding;
1224 tab_height += page->requisition.height;
1227 if (notebook->scrollable && vis_pages > 1 &&
1228 widget->requisition.height < tab_height)
1229 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1231 widget->requisition.width += tab_width;
1233 if (notebook->homogeneous && !notebook->scrollable)
1234 widget->requisition.height =
1235 MAX (widget->requisition.height,
1236 vis_pages * tab_max + TAB_OVERLAP);
1238 widget->requisition.height =
1239 MAX (widget->requisition.height,
1240 tab_height + TAB_OVERLAP);
1242 if (!notebook->homogeneous || notebook->scrollable)
1244 widget->requisition.height = MAX (widget->requisition.height,
1245 vis_pages * tab_max +
1253 for (children = notebook->children; children;
1254 children = children->next)
1256 page = children->data;
1258 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1259 gtk_widget_hide (page->tab_label);
1264 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1265 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1271 for (children = notebook->children; children;
1272 children = children->next)
1274 page = children->data;
1275 if (GTK_WIDGET_VISIBLE (page->child))
1277 gtk_notebook_switch_page (notebook, page, -1);
1282 else if (GTK_WIDGET_VISIBLE (widget))
1284 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1285 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1288 if (vis_pages && !notebook->cur_page)
1290 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1293 notebook->first_tab = children;
1294 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1300 gtk_notebook_size_allocate (GtkWidget *widget,
1301 GtkAllocation *allocation)
1303 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1306 widget->allocation = *allocation;
1307 if (GTK_WIDGET_REALIZED (widget))
1309 GdkRectangle position;
1311 if (gtk_notebook_get_event_window_position (notebook, &position))
1312 gdk_window_move_resize (notebook->event_window,
1313 position.x, position.y,
1314 position.width, position.height);
1317 if (notebook->children)
1319 gint border_width = GTK_CONTAINER (widget)->border_width;
1320 GtkNotebookPage *page;
1321 GtkAllocation child_allocation;
1324 child_allocation.x = widget->allocation.x + border_width;
1325 child_allocation.y = widget->allocation.y + border_width;
1326 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1327 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1329 if (notebook->show_tabs || notebook->show_border)
1331 child_allocation.x += widget->style->xthickness;
1332 child_allocation.y += widget->style->ythickness;
1333 child_allocation.width = MAX (1, child_allocation.width -
1334 widget->style->xthickness * 2);
1335 child_allocation.height = MAX (1, child_allocation.height -
1336 widget->style->ythickness * 2);
1338 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1340 switch (notebook->tab_pos)
1343 child_allocation.y += notebook->cur_page->requisition.height;
1344 case GTK_POS_BOTTOM:
1345 child_allocation.height =
1346 MAX (1, child_allocation.height -
1347 notebook->cur_page->requisition.height);
1350 child_allocation.x += notebook->cur_page->requisition.width;
1352 child_allocation.width =
1353 MAX (1, child_allocation.width -
1354 notebook->cur_page->requisition.width);
1360 children = notebook->children;
1363 page = children->data;
1364 children = children->next;
1366 if (GTK_WIDGET_VISIBLE (page->child))
1368 gtk_widget_size_allocate (page->child, &child_allocation);
1373 gtk_notebook_pages_allocate (notebook);
1376 if ((vis_pages != 0) != notebook->have_visible_child)
1378 notebook->have_visible_child = (vis_pages != 0);
1379 if (notebook->show_tabs)
1380 gtk_widget_queue_draw (widget);
1385 gtk_notebook_expose (GtkWidget *widget,
1386 GdkEventExpose *event)
1388 GtkNotebook *notebook;
1389 GdkRectangle child_area;
1391 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1392 g_return_val_if_fail (event != NULL, FALSE);
1394 if (GTK_WIDGET_DRAWABLE (widget))
1396 notebook = GTK_NOTEBOOK (widget);
1398 gtk_notebook_paint (widget, &event->area);
1399 if (notebook->show_tabs)
1401 if (notebook->cur_page &&
1402 gtk_widget_intersect (notebook->cur_page->tab_label,
1403 &event->area, &child_area))
1404 gtk_notebook_draw_focus (widget);
1408 if (notebook->cur_page)
1409 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1410 notebook->cur_page->child,
1418 gtk_notebook_show_arrows (GtkNotebook *notebook)
1420 gboolean show_arrow = FALSE;
1423 if (!notebook->scrollable)
1426 children = notebook->children;
1429 GtkNotebookPage *page = children->data;
1431 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1434 children = children->next;
1441 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1442 GdkRectangle *rectangle)
1444 GdkRectangle event_window_pos;
1446 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1448 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1449 rectangle->height = ARROW_SIZE;
1451 switch (notebook->tab_pos)
1455 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1456 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1459 case GTK_POS_BOTTOM:
1460 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1461 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1468 gtk_notebook_get_arrow (GtkNotebook *notebook,
1472 GdkRectangle arrow_rect;
1473 GdkRectangle event_window_pos;
1475 if (gtk_notebook_show_arrows (notebook))
1477 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1478 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1483 if (y >= 0 && y < arrow_rect.height)
1485 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1486 return GTK_ARROW_LEFT;
1487 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1488 return GTK_ARROW_RIGHT;
1496 gtk_notebook_do_arrow (GtkNotebook *notebook,
1499 GtkWidget *widget = GTK_WIDGET (notebook);
1500 GtkDirectionType dir;
1502 if (!notebook->focus_tab ||
1503 gtk_notebook_search_page (notebook, notebook->focus_tab,
1504 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1507 if (notebook->tab_pos == GTK_POS_LEFT ||
1508 notebook->tab_pos == GTK_POS_RIGHT)
1509 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1511 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1512 gtk_widget_child_focus (widget, dir);
1517 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1519 GdkEventButton *event)
1521 GtkWidget *widget = GTK_WIDGET (notebook);
1523 if (!GTK_WIDGET_HAS_FOCUS (widget))
1524 gtk_widget_grab_focus (widget);
1526 notebook->button = event->button;
1527 notebook->click_child = arrow;
1529 if (event->button == 1)
1531 gtk_notebook_do_arrow (notebook, arrow);
1533 if (!notebook->timer)
1535 notebook->timer = gtk_timeout_add
1536 (NOTEBOOK_INIT_SCROLL_DELAY,
1537 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1538 notebook->need_timer = TRUE;
1541 else if (event->button == 2)
1542 gtk_notebook_page_select (notebook, TRUE);
1543 else if (event->button == 3)
1544 gtk_notebook_switch_focus_tab (notebook,
1545 gtk_notebook_search_page (notebook,
1547 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1549 gtk_notebook_redraw_arrows (notebook);
1555 get_widget_coordinates (GtkWidget *widget,
1560 GdkWindow *window = ((GdkEventAny *)event)->window;
1563 if (!gdk_event_get_coords (event, &tx, &ty))
1566 while (window && window != widget->window)
1568 gint window_x, window_y;
1570 gdk_window_get_position (window, &window_x, &window_y);
1574 window = gdk_window_get_parent (window);
1589 gtk_notebook_button_press (GtkWidget *widget,
1590 GdkEventButton *event)
1592 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1593 GtkNotebookPage *page;
1599 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1603 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1606 arrow = gtk_notebook_get_arrow (notebook, x, y);
1608 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1610 if (event->button == 3 && notebook->menu)
1612 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1613 NULL, NULL, 3, event->time);
1617 if (event->button != 1)
1621 children = notebook->children;
1624 page = children->data;
1626 if (GTK_WIDGET_VISIBLE (page->child) &&
1627 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1628 (x >= page->allocation.x) &&
1629 (y >= page->allocation.y) &&
1630 (x <= (page->allocation.x + page->allocation.width)) &&
1631 (y <= (page->allocation.y + page->allocation.height)))
1633 gboolean page_changed = page != notebook->cur_page;
1634 gboolean was_focus = gtk_widget_is_focus (widget);
1636 gtk_notebook_switch_focus_tab (notebook, children);
1637 gtk_widget_grab_focus (widget);
1639 if (page_changed && !was_focus)
1640 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1644 children = children->next;
1647 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1648 gtk_widget_grab_focus (widget);
1654 gtk_notebook_button_release (GtkWidget *widget,
1655 GdkEventButton *event)
1657 GtkNotebook *notebook;
1659 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1660 g_return_val_if_fail (event != NULL, FALSE);
1662 if (event->type != GDK_BUTTON_RELEASE)
1665 notebook = GTK_NOTEBOOK (widget);
1667 if (event->button == notebook->button)
1671 if (notebook->timer)
1673 gtk_timeout_remove (notebook->timer);
1674 notebook->timer = 0;
1675 notebook->need_timer = FALSE;
1677 click_child = notebook->click_child;
1678 notebook->click_child = 0;
1679 notebook->button = 0;
1680 gtk_notebook_redraw_arrows (notebook);
1689 gtk_notebook_enter_notify (GtkWidget *widget,
1690 GdkEventCrossing *event)
1692 GtkNotebook *notebook;
1696 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1697 g_return_val_if_fail (event != NULL, FALSE);
1699 notebook = GTK_NOTEBOOK (widget);
1701 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1704 arrow = gtk_notebook_get_arrow (notebook, x, y);
1706 if (arrow != notebook->in_child)
1708 notebook->in_child = arrow;
1709 gtk_notebook_redraw_arrows (notebook);
1718 gtk_notebook_leave_notify (GtkWidget *widget,
1719 GdkEventCrossing *event)
1721 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1725 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1728 arrow = gtk_notebook_get_arrow (notebook, x, y);
1730 if (notebook->in_child)
1732 notebook->in_child = 0;
1733 gtk_notebook_redraw_arrows (notebook);
1740 gtk_notebook_motion_notify (GtkWidget *widget,
1741 GdkEventMotion *event)
1743 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1747 if (notebook->button)
1750 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1753 arrow = gtk_notebook_get_arrow (notebook, x, y);
1755 if (arrow != notebook->in_child)
1757 notebook->in_child = arrow;
1758 gtk_notebook_redraw_arrows (notebook);
1765 gtk_notebook_focus_in (GtkWidget *widget,
1766 GdkEventFocus *event)
1768 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1770 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1774 gtk_notebook_draw_focus (GtkWidget *widget)
1776 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1778 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1779 notebook->focus_tab)
1781 GtkNotebookPage *page;
1785 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1787 page = notebook->focus_tab->data;
1789 area.x = page->tab_label->allocation.x - focus_width;
1790 area.y = page->tab_label->allocation.y - focus_width;
1791 area.width = page->tab_label->allocation.width + 2 * focus_width;
1792 area.height = page->tab_label->allocation.height + 2 * focus_width;
1794 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1798 /* Private GtkContainer Methods :
1800 * gtk_notebook_set_child_arg
1801 * gtk_notebook_get_child_arg
1803 * gtk_notebook_remove
1804 * gtk_notebook_focus
1805 * gtk_notebook_set_focus_child
1806 * gtk_notebook_child_type
1807 * gtk_notebook_forall
1810 gtk_notebook_set_child_property (GtkContainer *container,
1813 const GValue *value,
1818 GtkPackType pack_type;
1820 /* not finding child's page is valid for menus or labels */
1821 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1824 switch (property_id)
1826 case CHILD_PROP_TAB_LABEL:
1827 /* a NULL pointer indicates a default_tab setting, otherwise
1828 * we need to set the associated label
1830 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1831 g_value_get_string (value));
1833 case CHILD_PROP_MENU_LABEL:
1834 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1835 g_value_get_string (value));
1837 case CHILD_PROP_POSITION:
1838 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1839 g_value_get_int (value));
1841 case CHILD_PROP_TAB_EXPAND:
1842 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1843 &expand, &fill, &pack_type);
1844 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1845 g_value_get_boolean (value),
1848 case CHILD_PROP_TAB_FILL:
1849 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1850 &expand, &fill, &pack_type);
1851 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1853 g_value_get_boolean (value),
1856 case CHILD_PROP_TAB_PACK:
1857 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1858 &expand, &fill, &pack_type);
1859 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1861 g_value_get_enum (value));
1864 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1870 gtk_notebook_get_child_property (GtkContainer *container,
1877 GtkNotebook *notebook;
1881 GtkPackType pack_type;
1883 notebook = GTK_NOTEBOOK (container);
1885 /* not finding child's page is valid for menus or labels */
1886 list = gtk_notebook_find_child (notebook, child, NULL);
1889 /* nothing to set on labels or menus */
1890 g_param_value_set_default (pspec, value);
1894 switch (property_id)
1896 case CHILD_PROP_TAB_LABEL:
1897 label = gtk_notebook_get_tab_label (notebook, child);
1899 if (label && GTK_IS_LABEL (label))
1900 g_value_set_string (value, GTK_LABEL (label)->label);
1902 g_value_set_string (value, NULL);
1904 case CHILD_PROP_MENU_LABEL:
1905 label = gtk_notebook_get_menu_label (notebook, child);
1907 if (label && GTK_IS_LABEL (label))
1908 g_value_set_string (value, GTK_LABEL (label)->label);
1910 g_value_set_string (value, NULL);
1912 case CHILD_PROP_POSITION:
1913 g_value_set_int (value, g_list_position (notebook->children, list));
1915 case CHILD_PROP_TAB_EXPAND:
1916 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1917 &expand, NULL, NULL);
1918 g_value_set_boolean (value, expand);
1920 case CHILD_PROP_TAB_FILL:
1921 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1923 g_value_set_boolean (value, fill);
1925 case CHILD_PROP_TAB_PACK:
1926 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1927 NULL, NULL, &pack_type);
1928 g_value_set_enum (value, pack_type);
1931 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1937 gtk_notebook_add (GtkContainer *container,
1940 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1942 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1947 gtk_notebook_remove (GtkContainer *container,
1950 GtkNotebook *notebook;
1951 GtkNotebookPage *page;
1955 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1956 g_return_if_fail (widget != NULL);
1958 notebook = GTK_NOTEBOOK (container);
1960 children = notebook->children;
1964 page = children->data;
1965 if (page->child == widget)
1967 gtk_notebook_real_remove (notebook, children, FALSE);
1971 children = children->next;
1976 focus_tabs_in (GtkNotebook *notebook)
1978 if (notebook->show_tabs && notebook->cur_page)
1980 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1982 gtk_notebook_switch_focus_tab (notebook,
1983 g_list_find (notebook->children,
1984 notebook->cur_page));
1993 focus_tabs_move (GtkNotebook *notebook,
1994 GtkDirectionType direction,
1995 gint search_direction)
1999 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2000 search_direction, TRUE);
2002 gtk_notebook_switch_focus_tab (notebook, new_page);
2004 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2010 focus_child_in (GtkNotebook *notebook,
2011 GtkDirectionType direction)
2013 if (notebook->cur_page)
2014 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2019 /* Focus in the notebook can either be on the pages, or on
2023 gtk_notebook_focus (GtkWidget *widget,
2024 GtkDirectionType direction)
2026 GtkWidget *old_focus_child;
2027 GtkNotebook *notebook;
2028 GtkDirectionType effective_direction;
2030 gboolean widget_is_focus;
2031 GtkContainer *container;
2033 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2035 container = GTK_CONTAINER (widget);
2036 notebook = GTK_NOTEBOOK (container);
2038 if (notebook->focus_out)
2040 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2044 widget_is_focus = gtk_widget_is_focus (widget);
2045 old_focus_child = container->focus_child;
2047 effective_direction = get_effective_direction (notebook, direction);
2049 if (old_focus_child) /* Focus on page child */
2051 if (gtk_widget_child_focus (old_focus_child, direction))
2054 switch (effective_direction)
2056 case GTK_DIR_TAB_BACKWARD:
2058 /* Focus onto the tabs */
2059 return focus_tabs_in (notebook);
2061 case GTK_DIR_TAB_FORWARD:
2067 else if (widget_is_focus) /* Focus was on tabs */
2069 switch (effective_direction)
2071 case GTK_DIR_TAB_BACKWARD:
2074 case GTK_DIR_TAB_FORWARD:
2076 /* We use TAB_FORWARD rather than direction so that we focus a more
2077 * predictable widget for the user; users may be using arrow focusing
2078 * in this situation even if they don't usually use arrow focusing.
2080 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2082 return focus_tabs_move (notebook, direction, STEP_PREV);
2084 return focus_tabs_move (notebook, direction, STEP_NEXT);
2087 else /* Focus was not on widget */
2089 switch (effective_direction)
2091 case GTK_DIR_TAB_FORWARD:
2093 if (focus_tabs_in (notebook))
2095 if (focus_child_in (notebook, direction))
2098 case GTK_DIR_TAB_BACKWARD:
2100 if (focus_child_in (notebook, direction))
2102 if (focus_tabs_in (notebook))
2107 return focus_child_in (notebook, direction);
2111 g_assert_not_reached ();
2116 gtk_notebook_set_focus_child (GtkContainer *container,
2119 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2120 GtkWidget *page_child;
2121 GtkWidget *toplevel;
2123 /* If the old focus widget was within a page of the notebook,
2124 * (child may either be NULL or not in this case), record it
2125 * for future use if we switch to the page with a mnemonic.
2128 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2129 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2131 page_child = GTK_WINDOW (toplevel)->focus_widget;
2134 if (page_child->parent == GTK_WIDGET (container))
2136 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2139 GtkNotebookPage *page = list->data;
2141 if (page->last_focus_child)
2142 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2144 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2145 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2151 page_child = page_child->parent;
2157 g_return_if_fail (GTK_IS_WIDGET (child));
2159 notebook->child_has_focus = TRUE;
2160 if (!notebook->focus_tab)
2163 GtkNotebookPage *page;
2165 children = notebook->children;
2168 page = children->data;
2169 if (page->child == child || page->tab_label == child)
2170 gtk_notebook_switch_focus_tab (notebook, children);
2171 children = children->next;
2176 parent_class->set_focus_child (container, child);
2180 gtk_notebook_forall (GtkContainer *container,
2181 gboolean include_internals,
2182 GtkCallback callback,
2183 gpointer callback_data)
2185 GtkNotebook *notebook;
2188 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2189 g_return_if_fail (callback != NULL);
2191 notebook = GTK_NOTEBOOK (container);
2193 children = notebook->children;
2196 GtkNotebookPage *page;
2198 page = children->data;
2199 children = children->next;
2200 (* callback) (page->child, callback_data);
2201 if (include_internals)
2203 if (page->tab_label)
2204 (* callback) (page->tab_label, callback_data);
2205 if (page->menu_label)
2206 (* callback) (page->menu_label, callback_data);
2212 gtk_notebook_child_type (GtkContainer *container)
2214 return GTK_TYPE_WIDGET;
2217 /* Private GtkNotebook Functions:
2219 * gtk_notebook_redraw_tabs
2220 * gtk_notebook_real_remove
2221 * gtk_notebook_update_labels
2222 * gtk_notebook_timer
2223 * gtk_notebook_page_compare
2224 * gtk_notebook_real_page_position
2225 * gtk_notebook_search_page
2228 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2231 GtkNotebookPage *page;
2232 GdkRectangle redraw_rect;
2235 widget = GTK_WIDGET (notebook);
2236 border = GTK_CONTAINER (notebook)->border_width;
2238 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2241 page = notebook->first_tab->data;
2243 redraw_rect.x = border;
2244 redraw_rect.y = border;
2246 switch (notebook->tab_pos)
2248 case GTK_POS_BOTTOM:
2249 redraw_rect.y = (widget->allocation.height - border -
2250 page->allocation.height -
2251 widget->style->ythickness);
2252 if (page != notebook->cur_page)
2253 redraw_rect.y -= widget->style->ythickness;
2256 redraw_rect.width = widget->allocation.width - 2 * border;
2257 redraw_rect.height = (page->allocation.height +
2258 widget->style->ythickness);
2259 if (page != notebook->cur_page)
2260 redraw_rect.height += widget->style->ythickness;
2263 redraw_rect.x = (widget->allocation.width - border -
2264 page->allocation.width -
2265 widget->style->xthickness);
2266 if (page != notebook->cur_page)
2267 redraw_rect.x -= widget->style->xthickness;
2270 redraw_rect.width = (page->allocation.width +
2271 widget->style->xthickness);
2272 redraw_rect.height = widget->allocation.height - 2 * border;
2273 if (page != notebook->cur_page)
2274 redraw_rect.width += widget->style->xthickness;
2278 redraw_rect.x += widget->allocation.x;
2279 redraw_rect.y += widget->allocation.y;
2281 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2285 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2287 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2291 gtk_notebook_get_arrow_rect (notebook, &rect);
2292 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2297 gtk_notebook_timer (GtkNotebook *notebook)
2299 gboolean retval = FALSE;
2301 GDK_THREADS_ENTER ();
2303 if (notebook->timer)
2305 gtk_notebook_do_arrow (notebook, notebook->click_child);
2307 if (notebook->need_timer)
2309 notebook->need_timer = FALSE;
2310 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2311 (GtkFunction) gtk_notebook_timer,
2312 (gpointer) notebook);
2318 GDK_THREADS_LEAVE ();
2324 gtk_notebook_page_compare (gconstpointer a,
2327 return (((GtkNotebookPage *) a)->child != b);
2331 gtk_notebook_find_child (GtkNotebook *notebook,
2333 const gchar *function)
2335 GList *list = g_list_find_custom (notebook->children, child,
2336 gtk_notebook_page_compare);
2338 #ifndef G_DISABLE_CHECKS
2339 if (!list && function)
2340 g_warning ("%s: unable to find child %p in notebook %p",
2341 function, child, notebook);
2348 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2349 GtkNotebookPage *page)
2351 if (page->tab_label)
2353 if (page->mnemonic_activate_signal)
2354 g_signal_handler_disconnect (page->tab_label,
2355 page->mnemonic_activate_signal);
2356 page->mnemonic_activate_signal = 0;
2358 gtk_widget_unparent (page->tab_label);
2363 gtk_notebook_real_remove (GtkNotebook *notebook,
2365 gboolean destroying)
2367 GtkNotebookPage *page;
2369 gint need_resize = FALSE;
2371 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2373 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2375 if (notebook->cur_page == list->data)
2377 notebook->cur_page = NULL;
2378 if (next_list && !destroying)
2379 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2382 if (list == notebook->first_tab)
2383 notebook->first_tab = next_list;
2384 if (list == notebook->focus_tab && !destroying)
2385 gtk_notebook_switch_focus_tab (notebook, next_list);
2389 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2392 gtk_widget_unparent (page->child);
2394 gtk_notebook_remove_tab_label (notebook, page);
2398 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2399 page->menu_label->parent);
2400 gtk_widget_queue_resize (notebook->menu);
2402 if (!page->default_menu)
2403 g_object_unref (page->menu_label);
2405 notebook->children = g_list_remove_link (notebook->children, list);
2408 if (page->last_focus_child)
2410 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2411 page->last_focus_child = NULL;
2416 if (!notebook->children && notebook->show_tabs &&
2417 GTK_WIDGET_MAPPED (notebook))
2418 gdk_window_hide (notebook->event_window);
2420 gtk_notebook_update_labels (notebook);
2422 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2426 gtk_notebook_update_labels (GtkNotebook *notebook)
2428 GtkNotebookPage *page;
2433 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2435 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2438 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2439 if (notebook->show_tabs)
2441 if (page->default_tab)
2443 if (!page->tab_label)
2445 page->tab_label = gtk_label_new (string);
2446 gtk_widget_set_parent (page->tab_label,
2447 GTK_WIDGET (notebook));
2450 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2453 if (GTK_WIDGET_VISIBLE (page->child) &&
2454 !GTK_WIDGET_VISIBLE (page->tab_label))
2455 gtk_widget_show (page->tab_label);
2456 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2457 GTK_WIDGET_VISIBLE (page->tab_label))
2458 gtk_widget_hide (page->tab_label);
2460 if (notebook->menu && page->default_menu)
2462 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2463 gtk_label_set_text (GTK_LABEL (page->menu_label),
2464 GTK_LABEL (page->tab_label)->label);
2466 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2472 gtk_notebook_real_page_position (GtkNotebook *notebook,
2478 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2479 g_return_val_if_fail (list != NULL, -1);
2481 for (work = notebook->children, count_start = 0;
2482 work && work != list; work = work->next)
2483 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2489 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2492 return (count_start + g_list_length (list) - 1);
2496 gtk_notebook_search_page (GtkNotebook *notebook,
2499 gboolean find_visible)
2501 GtkNotebookPage *page = NULL;
2502 GList *old_list = NULL;
2505 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2510 flag = GTK_PACK_END;
2514 flag = GTK_PACK_START;
2521 if (!page || page->pack == flag)
2529 list = notebook->children;
2534 if (page->pack == flag &&
2535 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2550 if (page->pack != flag &&
2551 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2559 /* Private GtkNotebook Drawing Functions:
2561 * gtk_notebook_paint
2562 * gtk_notebook_draw_tab
2563 * gtk_notebook_draw_arrow
2566 gtk_notebook_paint (GtkWidget *widget,
2569 GtkNotebook *notebook;
2570 GtkNotebookPage *page;
2575 gint border_width = GTK_CONTAINER (widget)->border_width;
2576 gint gap_x = 0, gap_width = 0;
2578 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2579 g_return_if_fail (area != NULL);
2581 if (!GTK_WIDGET_DRAWABLE (widget))
2584 notebook = GTK_NOTEBOOK (widget);
2586 if ((!notebook->show_tabs && !notebook->show_border) ||
2587 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2590 x = widget->allocation.x + border_width;
2591 y = widget->allocation.y + border_width;
2592 width = widget->allocation.width - border_width * 2;
2593 height = widget->allocation.height - border_width * 2;
2595 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2597 gtk_paint_box (widget->style, widget->window,
2598 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2599 area, widget, "notebook",
2600 x, y, width, height);
2605 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2607 page = notebook->first_tab->data;
2609 switch (notebook->tab_pos)
2612 y += page->allocation.height + widget->style->ythickness;
2613 case GTK_POS_BOTTOM:
2614 height -= page->allocation.height + widget->style->ythickness;
2617 x += page->allocation.width + widget->style->xthickness;
2619 width -= page->allocation.width + widget->style->xthickness;
2622 gtk_paint_box (widget->style, widget->window,
2623 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2624 area, widget, "notebook",
2625 x, y, width, height);
2629 switch (notebook->tab_pos)
2632 y += notebook->cur_page->allocation.height;
2633 case GTK_POS_BOTTOM:
2634 height -= notebook->cur_page->allocation.height;
2637 x += notebook->cur_page->allocation.width;
2639 width -= notebook->cur_page->allocation.width;
2643 switch (notebook->tab_pos)
2646 case GTK_POS_BOTTOM:
2647 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2648 gap_width = notebook->cur_page->allocation.width;
2652 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2653 gap_width = notebook->cur_page->allocation.height;
2656 gtk_paint_box_gap(widget->style, widget->window,
2657 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2658 area, widget, "notebook",
2659 x, y, width, height,
2660 notebook->tab_pos, gap_x, gap_width);
2664 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2667 page = children->data;
2668 children = gtk_notebook_search_page (notebook, children,
2670 if (!GTK_WIDGET_VISIBLE (page->child))
2672 if (!GTK_WIDGET_MAPPED (page->tab_label))
2674 else if (page != notebook->cur_page)
2675 gtk_notebook_draw_tab (notebook, page, area);
2678 if (showarrow && notebook->scrollable)
2680 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2681 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2683 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2687 gtk_notebook_draw_tab (GtkNotebook *notebook,
2688 GtkNotebookPage *page,
2691 GdkRectangle child_area;
2692 GdkRectangle page_area;
2693 GtkStateType state_type;
2694 GtkPositionType gap_side;
2696 g_return_if_fail (notebook != NULL);
2697 g_return_if_fail (page != NULL);
2698 g_return_if_fail (area != NULL);
2700 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2701 (page->allocation.width == 0) || (page->allocation.height == 0))
2704 page_area.x = page->allocation.x;
2705 page_area.y = page->allocation.y;
2706 page_area.width = page->allocation.width;
2707 page_area.height = page->allocation.height;
2709 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2713 widget = GTK_WIDGET (notebook);
2715 switch (notebook->tab_pos)
2718 gap_side = GTK_POS_BOTTOM;
2720 case GTK_POS_BOTTOM:
2721 gap_side = GTK_POS_TOP;
2724 gap_side = GTK_POS_RIGHT;
2727 gap_side = GTK_POS_LEFT;
2731 if (notebook->cur_page == page)
2732 state_type = GTK_STATE_NORMAL;
2734 state_type = GTK_STATE_ACTIVE;
2735 gtk_paint_extension(widget->style, widget->window,
2736 state_type, GTK_SHADOW_OUT,
2737 area, widget, "tab",
2738 page_area.x, page_area.y,
2739 page_area.width, page_area.height,
2741 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2742 notebook->focus_tab && (notebook->focus_tab->data == page))
2746 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2748 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2749 area, widget, "tab",
2750 page->tab_label->allocation.x - focus_width,
2751 page->tab_label->allocation.y - focus_width,
2752 page->tab_label->allocation.width + 2 * focus_width,
2753 page->tab_label->allocation.height + 2 * focus_width);
2755 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2756 GTK_WIDGET_DRAWABLE (page->tab_label))
2758 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2760 /* This is a lame hack since all this code needs rewriting anyhow */
2762 expose_event->expose.window = g_object_ref (page->tab_label->window);
2763 expose_event->expose.area = child_area;
2764 expose_event->expose.region = gdk_region_rectangle (&child_area);
2765 expose_event->expose.send_event = TRUE;
2766 expose_event->expose.count = 0;
2768 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2770 gdk_event_free (expose_event);
2776 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2779 GtkStateType state_type;
2780 GtkShadowType shadow_type;
2782 GdkRectangle arrow_rect;
2784 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2786 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2788 widget = GTK_WIDGET(notebook);
2790 if (GTK_WIDGET_DRAWABLE (notebook))
2792 if (notebook->in_child == arrow)
2794 if (notebook->click_child == arrow)
2795 state_type = GTK_STATE_ACTIVE;
2797 state_type = GTK_STATE_PRELIGHT;
2800 state_type = GTK_STATE_NORMAL;
2802 if (notebook->click_child == arrow)
2803 shadow_type = GTK_SHADOW_IN;
2805 shadow_type = GTK_SHADOW_OUT;
2807 if (arrow == GTK_ARROW_LEFT)
2809 if (notebook->focus_tab &&
2810 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2813 shadow_type = GTK_SHADOW_ETCHED_IN;
2814 state_type = GTK_STATE_INSENSITIVE;
2817 if (notebook->tab_pos == GTK_POS_LEFT ||
2818 notebook->tab_pos == GTK_POS_RIGHT)
2819 arrow = GTK_ARROW_UP;
2821 gtk_paint_arrow (widget->style, widget->window, state_type,
2822 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2824 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2828 if (notebook->focus_tab &&
2829 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2832 shadow_type = GTK_SHADOW_ETCHED_IN;
2833 state_type = GTK_STATE_INSENSITIVE;
2836 if (notebook->tab_pos == GTK_POS_LEFT ||
2837 notebook->tab_pos == GTK_POS_RIGHT)
2838 arrow = GTK_ARROW_DOWN;
2840 gtk_paint_arrow (widget->style, widget->window, state_type,
2841 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2842 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2843 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2848 /* Private GtkNotebook Size Allocate Functions:
2850 * gtk_notebook_pages_allocate
2851 * gtk_notebook_page_allocate
2852 * gtk_notebook_calc_tabs
2855 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2857 GtkWidget *widget = GTK_WIDGET (notebook);
2858 GtkContainer *container = GTK_CONTAINER (notebook);
2859 GtkNotebookPage *page = NULL;
2860 GtkAllocation *allocation = &widget->allocation;
2861 GtkAllocation child_allocation;
2862 GList *children = NULL;
2863 GList *last_child = NULL;
2864 gboolean showarrow = FALSE;
2874 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2877 child_allocation.x = widget->allocation.x + container->border_width;
2878 child_allocation.y = widget->allocation.y + container->border_width;
2880 switch (notebook->tab_pos)
2882 case GTK_POS_BOTTOM:
2883 child_allocation.y = (widget->allocation.y +
2884 allocation->height -
2885 notebook->cur_page->requisition.height -
2886 container->border_width);
2889 child_allocation.height = notebook->cur_page->requisition.height;
2893 child_allocation.x = (widget->allocation.x +
2895 notebook->cur_page->requisition.width -
2896 container->border_width);
2899 child_allocation.width = notebook->cur_page->requisition.width;
2903 if (notebook->scrollable)
2907 children = notebook->children;
2909 if (notebook->focus_tab)
2910 focus_tab = notebook->focus_tab;
2911 else if (notebook->first_tab)
2912 focus_tab = notebook->first_tab;
2914 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2916 switch (notebook->tab_pos)
2919 case GTK_POS_BOTTOM:
2922 page = children->data;
2923 children = children->next;
2925 if (GTK_WIDGET_VISIBLE (page->child))
2926 tab_space += page->requisition.width;
2929 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2932 page = focus_tab->data;
2934 tab_space = (allocation->width - TAB_OVERLAP -
2935 page->requisition.width -
2936 2 * (container->border_width + ARROW_SPACING +
2938 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2939 container->border_width);
2941 page = notebook->children->data;
2942 if (notebook->tab_pos == GTK_POS_TOP)
2943 y = (container->border_width +
2944 (page->requisition.height - ARROW_SIZE) / 2);
2946 y = (allocation->height - container->border_width -
2947 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2954 page = children->data;
2955 children = children->next;
2957 if (GTK_WIDGET_VISIBLE (page->child))
2958 tab_space += page->requisition.height;
2961 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2964 page = focus_tab->data;
2965 tab_space = (allocation->height -
2966 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2967 2 * container->border_width -
2968 page->requisition.height);
2969 y = allocation->height - container->border_width - ARROW_SIZE;
2971 page = notebook->children->data;
2972 if (notebook->tab_pos == GTK_POS_LEFT)
2973 x = (container->border_width +
2974 (page->requisition.width -
2975 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2977 x = (allocation->width - container->border_width -
2978 (2 * ARROW_SIZE - ARROW_SPACING) -
2979 (page->requisition.width -
2980 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2984 if (showarrow) /* first_tab <- focus_tab */
2988 notebook->first_tab = focus_tab;
2989 last_child = gtk_notebook_search_page (notebook, focus_tab,
2995 if (notebook->first_tab && notebook->first_tab != focus_tab)
2997 /* Is first_tab really predecessor of focus_tab ? */
2998 page = notebook->first_tab->data;
2999 if (GTK_WIDGET_VISIBLE (page->child))
3000 for (children = focus_tab;
3001 children && children != notebook->first_tab;
3002 children = gtk_notebook_search_page (notebook,
3008 notebook->first_tab = focus_tab;
3010 gtk_notebook_calc_tabs (notebook,
3011 gtk_notebook_search_page (notebook,
3015 &(notebook->first_tab), &tab_space,
3020 notebook->first_tab =
3021 gtk_notebook_search_page (notebook, notebook->first_tab,
3023 if (!notebook->first_tab)
3024 notebook->first_tab = focus_tab;
3025 last_child = gtk_notebook_search_page (notebook, focus_tab,
3028 else /* focus_tab -> end */
3030 if (!notebook->first_tab)
3031 notebook->first_tab = gtk_notebook_search_page (notebook,
3036 gtk_notebook_calc_tabs (notebook,
3037 gtk_notebook_search_page (notebook,
3041 &children, &tab_space, STEP_NEXT);
3044 last_child = children;
3045 else /* start <- first_tab */
3049 gtk_notebook_calc_tabs
3051 gtk_notebook_search_page (notebook,
3052 notebook->first_tab,
3055 &children, &tab_space, STEP_PREV);
3056 notebook->first_tab = gtk_notebook_search_page(notebook,
3066 tab_space = -tab_space;
3068 for (children = notebook->first_tab;
3069 children && children != last_child;
3070 children = gtk_notebook_search_page (notebook, children,
3077 /*unmap all non-visible tabs*/
3078 for (children = gtk_notebook_search_page (notebook, NULL,
3080 children && children != notebook->first_tab;
3081 children = gtk_notebook_search_page (notebook, children,
3084 page = children->data;
3085 if (page->tab_label)
3086 gtk_widget_set_child_visible (page->tab_label, FALSE);
3088 for (children = last_child; children;
3089 children = gtk_notebook_search_page (notebook, children,
3092 page = children->data;
3093 if (page->tab_label)
3094 gtk_widget_set_child_visible (page->tab_label, FALSE);
3097 else /* !showarrow */
3099 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3110 children = notebook->children;
3111 switch (notebook->tab_pos)
3114 case GTK_POS_BOTTOM:
3117 page = children->data;
3118 children = children->next;
3120 if (GTK_WIDGET_VISIBLE (page->child))
3123 tab_space += page->requisition.width;
3128 tab_space -= allocation->width;
3134 page = children->data;
3135 children = children->next;
3137 if (GTK_WIDGET_VISIBLE (page->child))
3140 tab_space += page->requisition.height;
3145 tab_space -= allocation->height;
3147 tab_space += 2 * container->border_width + TAB_OVERLAP;
3149 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3151 if (notebook->homogeneous && n)
3155 children = notebook->first_tab;
3159 if (children == last_child)
3161 /* FIXME double check */
3165 page = children->data;
3166 if (!showarrow && page->pack != GTK_PACK_START)
3168 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3171 if (n && (showarrow || page->expand || notebook->homogeneous))
3173 new_fill = (tab_space * i++) / n;
3174 delta = new_fill - old_fill;
3175 old_fill = new_fill;
3178 switch (notebook->tab_pos)
3181 case GTK_POS_BOTTOM:
3182 child_allocation.width = (page->requisition.width +
3183 TAB_OVERLAP + delta);
3187 child_allocation.height = (page->requisition.height +
3188 TAB_OVERLAP + delta);
3192 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3194 switch (notebook->tab_pos)
3197 case GTK_POS_BOTTOM:
3198 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3202 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3206 if (page->tab_label)
3207 gtk_widget_set_child_visible (page->tab_label, TRUE);
3212 children = notebook->children;
3213 switch (notebook->tab_pos)
3216 case GTK_POS_BOTTOM:
3217 child_allocation.x = (allocation->x + allocation->width -
3218 container->border_width);
3222 child_allocation.y = (allocation->y + allocation->height -
3223 container->border_width);
3227 while (children != last_child)
3229 page = children->data;
3230 children = children->next;
3232 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3236 if (n && (page->expand || notebook->homogeneous))
3238 new_fill = (tab_space * i++) / n;
3239 delta = new_fill - old_fill;
3240 old_fill = new_fill;
3243 switch (notebook->tab_pos)
3246 case GTK_POS_BOTTOM:
3247 child_allocation.width = (page->requisition.width +
3248 TAB_OVERLAP + delta);
3249 child_allocation.x -= child_allocation.width;
3253 child_allocation.height = (page->requisition.height +
3254 TAB_OVERLAP + delta);
3255 child_allocation.y -= child_allocation.height;
3259 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3261 switch (notebook->tab_pos)
3264 case GTK_POS_BOTTOM:
3265 child_allocation.x += TAB_OVERLAP;
3269 child_allocation.y += TAB_OVERLAP;
3273 if (page->tab_label)
3274 gtk_widget_set_child_visible (page->tab_label, TRUE);
3279 gtk_notebook_redraw_tabs (notebook);
3283 gtk_notebook_page_allocate (GtkNotebook *notebook,
3284 GtkNotebookPage *page,
3285 GtkAllocation *allocation)
3287 GtkWidget *widget = GTK_WIDGET (notebook);
3288 GtkAllocation child_allocation;
3289 GtkRequisition tab_requisition;
3295 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3297 xthickness = widget->style->xthickness;
3298 ythickness = widget->style->ythickness;
3300 /* If the size of the notebook tabs change, we need to queue
3301 * a redraw on the tab area
3303 if ((allocation->width != page->allocation.width) ||
3304 (allocation->height != page->allocation.height))
3306 gint x, y, width, height, border_width;
3308 border_width = GTK_CONTAINER (notebook)->border_width;
3310 switch (notebook->tab_pos)
3313 width = widget->allocation.width;
3314 height = MAX (page->allocation.height, allocation->height) + ythickness;
3319 case GTK_POS_BOTTOM:
3320 width = widget->allocation.width + xthickness;
3321 height = MAX (page->allocation.height, allocation->height) + ythickness;
3323 y = widget->allocation.height - height - border_width;
3327 width = MAX (page->allocation.width, allocation->width) + xthickness;
3328 height = widget->allocation.height;
3334 default: /* quiet gcc */
3335 width = MAX (page->allocation.width, allocation->width) + xthickness;
3336 height = widget->allocation.height;
3337 x = widget->allocation.width - width - border_width;
3342 gtk_widget_queue_draw_area (widget, x, y, width, height);
3345 page->allocation = *allocation;
3346 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3348 if (notebook->cur_page != page)
3350 switch (notebook->tab_pos)
3353 page->allocation.y += ythickness;
3354 case GTK_POS_BOTTOM:
3355 if (page->allocation.height > ythickness)
3356 page->allocation.height -= ythickness;
3359 page->allocation.x += xthickness;
3361 if (page->allocation.width > xthickness)
3362 page->allocation.width -= xthickness;
3367 switch (notebook->tab_pos)
3370 case GTK_POS_BOTTOM:
3371 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3374 child_allocation.x = (xthickness + focus_width +
3375 notebook->tab_hborder);
3376 child_allocation.width = MAX (1, (page->allocation.width -
3377 2 * child_allocation.x));
3378 child_allocation.x += page->allocation.x;
3382 child_allocation.x = (page->allocation.x +
3383 (page->allocation.width -
3384 tab_requisition.width) / 2);
3385 child_allocation.width = tab_requisition.width;
3387 child_allocation.y = (notebook->tab_vborder + focus_width +
3388 page->allocation.y);
3389 if (notebook->tab_pos == GTK_POS_TOP)
3390 child_allocation.y += ythickness;
3391 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3392 2 * (notebook->tab_vborder + focus_width)));
3396 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3399 child_allocation.y = ythickness + padding;
3400 child_allocation.height = MAX (1, (page->allocation.height -
3401 2 * child_allocation.y));
3402 child_allocation.y += page->allocation.y;
3406 child_allocation.y = (page->allocation.y + (page->allocation.height -
3407 tab_requisition.height) / 2);
3408 child_allocation.height = tab_requisition.height;
3410 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3411 if (notebook->tab_pos == GTK_POS_LEFT)
3412 child_allocation.x += xthickness;
3413 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3414 2 * (notebook->tab_hborder + focus_width)));
3418 if (page->tab_label)
3419 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3423 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3429 GtkNotebookPage *page = NULL;
3431 GList *last_list = NULL;
3438 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3439 if (pack == GTK_PACK_END)
3440 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3444 switch (notebook->tab_pos)
3447 case GTK_POS_BOTTOM:
3450 page = children->data;
3451 if (GTK_WIDGET_VISIBLE (page->child))
3453 if (page->pack == pack)
3455 *tab_space -= page->requisition.width;
3456 if (*tab_space < 0 || children == *end)
3460 *tab_space = - (*tab_space +
3461 page->requisition.width);
3467 last_list = children;
3469 if (direction == STEP_NEXT)
3470 children = children->next;
3472 children = children->prev;
3479 page = children->data;
3480 if (GTK_WIDGET_VISIBLE (page->child))
3482 if (page->pack == pack)
3484 *tab_space -= page->requisition.height;
3485 if (*tab_space < 0 || children == *end)
3489 *tab_space = - (*tab_space +
3490 page->requisition.height);
3496 last_list = children;
3498 if (direction == STEP_NEXT)
3499 children = children->next;
3501 children = children->prev;
3505 if (direction == STEP_PREV)
3507 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3508 direction = STEP_PREV;
3509 children = last_list;
3513 /* Private GtkNotebook Page Switch Methods:
3515 * gtk_notebook_real_switch_page
3518 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3519 GtkNotebookPage *page,
3522 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3523 g_return_if_fail (page != NULL);
3525 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3528 if (notebook->cur_page)
3529 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3531 notebook->cur_page = page;
3533 if (!notebook->focus_tab ||
3534 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3535 notebook->focus_tab =
3536 g_list_find (notebook->children, notebook->cur_page);
3538 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3540 /* If the focus was on the previous page, move it to the first
3541 * element on the new page, if possible, or if not, to the
3544 if (notebook->child_has_focus)
3546 if (notebook->cur_page->last_focus_child &&
3547 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3548 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3550 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3551 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3554 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3555 g_object_notify (G_OBJECT (notebook), "page");
3558 /* Private GtkNotebook Page Switch Functions:
3560 * gtk_notebook_switch_page
3561 * gtk_notebook_page_select
3562 * gtk_notebook_switch_focus_tab
3563 * gtk_notebook_menu_switch_page
3566 gtk_notebook_switch_page (GtkNotebook *notebook,
3567 GtkNotebookPage *page,
3570 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3571 g_return_if_fail (page != NULL);
3573 if (notebook->cur_page == page)
3577 page_num = g_list_index (notebook->children, page);
3579 g_signal_emit (notebook,
3580 notebook_signals[SWITCH_PAGE],
3587 gtk_notebook_page_select (GtkNotebook *notebook,
3588 gboolean move_focus)
3590 GtkNotebookPage *page;
3591 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3593 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3595 if (!notebook->focus_tab)
3598 page = notebook->focus_tab->data;
3599 gtk_notebook_switch_page (notebook, page, -1);
3603 switch (notebook->tab_pos)
3608 case GTK_POS_BOTTOM:
3612 dir = GTK_DIR_RIGHT;
3619 if (gtk_widget_child_focus (page->child, dir))
3626 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3630 GtkNotebookPage *old_page = NULL;
3631 GtkNotebookPage *page;
3633 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3635 if (notebook->focus_tab == new_child)
3638 old_child = notebook->focus_tab;
3639 notebook->focus_tab = new_child;
3641 if (notebook->scrollable)
3642 gtk_notebook_redraw_arrows (notebook);
3644 if (!notebook->show_tabs || !notebook->focus_tab)
3648 old_page = old_child->data;
3650 page = notebook->focus_tab->data;
3651 if (GTK_WIDGET_MAPPED (page->tab_label))
3652 gtk_notebook_redraw_tabs (notebook);
3654 gtk_notebook_pages_allocate (notebook);
3656 gtk_notebook_switch_page (notebook, page,
3657 g_list_index (notebook->children, page));
3661 gtk_notebook_menu_switch_page (GtkWidget *widget,
3662 GtkNotebookPage *page)
3664 GtkNotebook *notebook;
3668 g_return_if_fail (widget != NULL);
3669 g_return_if_fail (page != NULL);
3671 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3672 (GTK_MENU (widget->parent)));
3674 if (notebook->cur_page == page)
3678 children = notebook->children;
3679 while (children && children->data != page)
3681 children = children->next;
3685 g_signal_emit (notebook,
3686 notebook_signals[SWITCH_PAGE],
3692 /* Private GtkNotebook Menu Functions:
3694 * gtk_notebook_menu_item_create
3695 * gtk_notebook_menu_label_unparent
3696 * gtk_notebook_menu_detacher
3699 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3702 GtkNotebookPage *page;
3703 GtkWidget *menu_item;
3706 if (page->default_menu)
3708 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3709 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3711 page->menu_label = gtk_label_new ("");
3712 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3715 gtk_widget_show (page->menu_label);
3716 menu_item = gtk_menu_item_new ();
3717 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3718 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3719 gtk_notebook_real_page_position (notebook, list));
3720 g_signal_connect (menu_item, "activate",
3721 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3722 if (GTK_WIDGET_VISIBLE (page->child))
3723 gtk_widget_show (menu_item);
3727 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3730 gtk_widget_unparent (GTK_BIN(widget)->child);
3731 GTK_BIN(widget)->child = NULL;
3735 gtk_notebook_menu_detacher (GtkWidget *widget,
3738 GtkNotebook *notebook;
3740 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3742 notebook = GTK_NOTEBOOK (widget);
3743 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3745 notebook->menu = NULL;
3748 /* Private GtkNotebook Setter Functions:
3750 * gtk_notebook_set_homogeneous_tabs_internal
3751 * gtk_notebook_set_tab_border_internal
3752 * gtk_notebook_set_tab_hborder_internal
3753 * gtk_notebook_set_tab_vborder_internal
3756 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
3757 gboolean homogeneous)
3759 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3761 if (homogeneous == notebook->homogeneous)
3764 notebook->homogeneous = homogeneous;
3765 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3767 g_object_notify (G_OBJECT (notebook), "homogeneous");
3771 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
3774 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3776 notebook->tab_hborder = border_width;
3777 notebook->tab_vborder = border_width;
3779 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3780 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3782 g_object_freeze_notify (G_OBJECT (notebook));
3783 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3784 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3785 g_object_thaw_notify (G_OBJECT (notebook));
3789 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
3792 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3794 if (notebook->tab_hborder == tab_hborder)
3797 notebook->tab_hborder = tab_hborder;
3799 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3800 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3802 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3806 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
3809 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3811 if (notebook->tab_vborder == tab_vborder)
3814 notebook->tab_vborder = tab_vborder;
3816 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3817 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3819 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3822 /* Public GtkNotebook Page Insert/Remove Methods :
3824 * gtk_notebook_append_page
3825 * gtk_notebook_append_page_menu
3826 * gtk_notebook_prepend_page
3827 * gtk_notebook_prepend_page_menu
3828 * gtk_notebook_insert_page
3829 * gtk_notebook_insert_page_menu
3830 * gtk_notebook_remove_page
3833 * gtk_notebook_append_page:
3834 * @notebook: a #GtkNotebook
3835 * @child: the #GtkWidget to use as the contents of the page.
3836 * @tab_label: the #GtkWidget to be used as the label for the page,
3837 * or %NULL to use the default label, 'page N'.
3839 * Appends a page to @notebook.
3842 gtk_notebook_append_page (GtkNotebook *notebook,
3844 GtkWidget *tab_label)
3846 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3847 g_return_if_fail (GTK_IS_WIDGET (child));
3848 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3850 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3854 * gtk_notebook_append_page_menu:
3855 * @notebook: a #GtkNotebook
3856 * @child: the #GtkWidget to use as the contents of the page.
3857 * @tab_label: the #GtkWidget to be used as the label for the page,
3858 * or %NULL to use the default label, 'page N'.
3859 * @menu_label: the widget to use as a label for the page-switch
3860 * menu, if that is enabled. If %NULL, and @tab_label
3861 * is a #GtkLabel or %NULL, then the menu label will be
3862 * a newly created label with the same text as @tab_label;
3863 * If @tab_label is not a #GtkLabel, @menu_label must be
3864 * specified if the page-switch menu is to be used.
3866 * Appends a page to @notebook, specifying the widget to use as the
3867 * label in the popup menu.
3870 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3872 GtkWidget *tab_label,
3873 GtkWidget *menu_label)
3875 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3876 g_return_if_fail (GTK_IS_WIDGET (child));
3877 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3878 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3880 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3884 * gtk_notebook_prepend_page:
3885 * @notebook: a #GtkNotebook
3886 * @child: the #GtkWidget to use as the contents of the page.
3887 * @tab_label: the #GtkWidget to be used as the label for the page,
3888 * or %NULL to use the default label, 'page N'.
3890 * Prepends a page to @notebook.
3893 gtk_notebook_prepend_page (GtkNotebook *notebook,
3895 GtkWidget *tab_label)
3897 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3898 g_return_if_fail (GTK_IS_WIDGET (child));
3899 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3901 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3905 * gtk_notebook_prepend_page_menu:
3906 * @notebook: a #GtkNotebook
3907 * @child: the #GtkWidget to use as the contents of the page.
3908 * @tab_label: the #GtkWidget to be used as the label for the page,
3909 * or %NULL to use the default label, 'page N'.
3910 * @menu_label: the widget to use as a label for the page-switch
3911 * menu, if that is enabled. If %NULL, and @tab_label
3912 * is a #GtkLabel or %NULL, then the menu label will be
3913 * a newly created label with the same text as @tab_label;
3914 * If @tab_label is not a #GtkLabel, @menu_label must be
3915 * specified if the page-switch menu is to be used.
3917 * Prepends a page to @notebook, specifying the widget to use as the
3918 * label in the popup menu.
3921 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3923 GtkWidget *tab_label,
3924 GtkWidget *menu_label)
3926 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3927 g_return_if_fail (GTK_IS_WIDGET (child));
3928 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3929 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3931 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3935 * gtk_notebook_insert_page:
3936 * @notebook: a #GtkNotebook
3937 * @child: the #GtkWidget to use as the contents of the page.
3938 * @tab_label: the #GtkWidget to be used as the label for the page,
3939 * or %NULL to use the default label, 'page N'.
3940 * @position: the index (starting at 0) at which to insert the page,
3941 * or -1 to append the page after all other pages.
3943 * Insert a page into @notebook at the given position
3946 gtk_notebook_insert_page (GtkNotebook *notebook,
3948 GtkWidget *tab_label,
3951 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3952 g_return_if_fail (GTK_IS_WIDGET (child));
3953 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3955 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3960 gtk_notebook_page_compare_tab (gconstpointer a,
3963 return (((GtkNotebookPage *) a)->tab_label != b);
3967 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3971 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3974 list = g_list_find_custom (notebook->children, child,
3975 gtk_notebook_page_compare_tab);
3978 GtkNotebookPage *page = list->data;
3980 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3981 gtk_notebook_switch_page (notebook, page, -1);
3982 focus_tabs_in (notebook);
3989 * gtk_notebook_insert_page_menu:
3990 * @notebook: a #GtkNotebook
3991 * @child: the #GtkWidget to use as the contents of the page.
3992 * @tab_label: the #GtkWidget to be used as the label for the page,
3993 * or %NULL to use the default label, 'page N'.
3994 * @menu_label: the widget to use as a label for the page-switch
3995 * menu, if that is enabled. If %NULL, and @tab_label
3996 * is a #GtkLabel or %NULL, then the menu label will be
3997 * a newly created label with the same text as @tab_label;
3998 * If @tab_label is not a #GtkLabel, @menu_label must be
3999 * specified if the page-switch menu is to be used.
4000 * @position: the index (starting at 0) at which to insert the page,
4001 * or -1 to append the page after all other pages.
4003 * Insert a page into @notebook at the given position, specifying
4004 * the widget to use as the label in the popup menu.
4007 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4009 GtkWidget *tab_label,
4010 GtkWidget *menu_label,
4013 GtkNotebookPage *page;
4016 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4017 g_return_if_fail (GTK_IS_WIDGET (child));
4018 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4019 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4021 gtk_widget_freeze_child_notify (child);
4023 page = g_new (GtkNotebookPage, 1);
4024 page->child = child;
4025 page->last_focus_child = NULL;
4026 page->requisition.width = 0;
4027 page->requisition.height = 0;
4028 page->allocation.x = 0;
4029 page->allocation.y = 0;
4030 page->allocation.width = 0;
4031 page->allocation.height = 0;
4032 page->default_menu = FALSE;
4033 page->default_tab = FALSE;
4034 page->mnemonic_activate_signal = 0;
4036 nchildren = g_list_length (notebook->children);
4037 if ((position < 0) || (position > nchildren))
4038 position = nchildren;
4040 notebook->children = g_list_insert (notebook->children, page, position);
4044 page->default_tab = TRUE;
4045 if (notebook->show_tabs)
4046 tab_label = gtk_label_new ("");
4048 page->tab_label = tab_label;
4049 page->menu_label = menu_label;
4050 page->expand = FALSE;
4052 page->pack = GTK_PACK_START;
4055 page->default_menu = TRUE;
4058 g_object_ref (page->menu_label);
4059 gtk_object_sink (GTK_OBJECT (page->menu_label));
4063 gtk_notebook_menu_item_create (notebook,
4064 g_list_find (notebook->children, page));
4066 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4068 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4070 gtk_notebook_update_labels (notebook);
4072 if (!notebook->first_tab)
4073 notebook->first_tab = notebook->children;
4075 if (!notebook->cur_page)
4076 gtk_widget_set_child_visible (child, TRUE);
4078 gtk_widget_set_child_visible (child, FALSE);
4082 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4083 gtk_widget_show (tab_label);
4085 gtk_widget_hide (tab_label);
4088 if (!notebook->cur_page)
4090 gtk_notebook_switch_page (notebook, page, 0);
4091 gtk_notebook_switch_focus_tab (notebook, NULL);
4095 page->mnemonic_activate_signal =
4096 g_signal_connect (tab_label,
4097 "mnemonic_activate",
4098 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4101 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4102 gdk_window_show_unraised (notebook->event_window);
4104 gtk_widget_child_notify (child, "tab_expand");
4105 gtk_widget_child_notify (child, "tab_fill");
4106 gtk_widget_child_notify (child, "tab_pack");
4107 gtk_widget_child_notify (child, "tab_label");
4108 gtk_widget_child_notify (child, "menu_label");
4109 gtk_widget_child_notify (child, "position");
4110 gtk_widget_thaw_child_notify (child);
4114 * gtk_notebook_remove_page:
4115 * @notebook: a #GtkNotebook.
4116 * @page_num: the index of a notebook page, starting
4117 * from 0. If -1, the last page will
4120 * Removes a page from the notebook given its index
4124 gtk_notebook_remove_page (GtkNotebook *notebook,
4129 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4133 list = g_list_nth (notebook->children, page_num);
4135 gtk_notebook_real_remove (notebook, list, FALSE);
4139 list = g_list_last (notebook->children);
4141 gtk_notebook_real_remove (notebook, list, FALSE);
4145 /* Public GtkNotebook Page Switch Methods :
4146 * gtk_notebook_get_current_page
4147 * gtk_notebook_page_num
4148 * gtk_notebook_set_current_page
4149 * gtk_notebook_next_page
4150 * gtk_notebook_prev_page
4153 * gtk_notebook_get_current_page:
4154 * @notebook: a #GtkNotebook
4156 * Returns the page number of the current page.
4158 * Return value: the index (starting from 0) of the current
4159 * page in the notebook. If the notebook has no pages, then
4160 * -1 will be returned.
4163 gtk_notebook_get_current_page (GtkNotebook *notebook)
4165 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4167 if (!notebook->cur_page)
4170 return g_list_index (notebook->children, notebook->cur_page);
4174 * gtk_notebook_get_nth_page:
4175 * @notebook: a #GtkNotebook
4176 * @page_num: the index of a page in the noteobok, or -1
4177 * to get the last page.
4179 * Returns the child widget contained in page number @page_num.
4181 * Return value: the child widget, or %NULL if @page_num is
4185 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4188 GtkNotebookPage *page;
4191 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4194 list = g_list_nth (notebook->children, page_num);
4196 list = g_list_last (notebook->children);
4208 * gtk_notebook_get_n_pages:
4209 * @notebook: a #GtkNotebook
4211 * Gets the number of pages in a notebook.
4213 * Return value: the number of pages in the notebook.
4218 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4220 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4222 return g_list_length (notebook->children);
4226 * gtk_notebook_page_num:
4227 * @notebook: a #GtkNotebook
4228 * @child: a #GtkWidget
4230 * Finds the index of the page which contains the given child
4233 * Return value: the index of the page containing @child, or
4234 * -1 if @child is not in the notebook.
4237 gtk_notebook_page_num (GtkNotebook *notebook,
4243 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4246 children = notebook->children;
4249 GtkNotebookPage *page = children->data;
4251 if (page->child == child)
4254 children = children->next;
4262 * gtk_notebook_set_current_page:
4263 * @notebook: a #GtkNotebook
4264 * @page_num: index of the page to switch to, starting from 0.
4265 * If negative, the last page will be used. If greater
4266 * than the number of pages in the notebook, nothing
4269 * Switches to the page number @page_num.
4272 gtk_notebook_set_current_page (GtkNotebook *notebook,
4277 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4280 list = g_list_nth (notebook->children, page_num);
4282 list = g_list_last (notebook->children);
4284 page_num = g_list_index (notebook->children, list);
4287 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4291 * gtk_notebook_next_page:
4292 * @notebook: a #GtkNotebook
4294 * Switches to the next page. Nothing happens if the current page is
4298 gtk_notebook_next_page (GtkNotebook *notebook)
4302 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4304 list = g_list_find (notebook->children, notebook->cur_page);
4308 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4312 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4316 * gtk_notebook_prev_page:
4317 * @notebook: a #GtkNotebook
4319 * Switches to the previous page. Nothing happens if the current page
4320 * is the first page.
4323 gtk_notebook_prev_page (GtkNotebook *notebook)
4327 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4329 list = g_list_find (notebook->children, notebook->cur_page);
4333 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4337 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4340 /* Public GtkNotebook/Tab Style Functions
4342 * gtk_notebook_set_show_border
4343 * gtk_notebook_set_show_tabs
4344 * gtk_notebook_set_tab_pos
4345 * gtk_notebook_set_homogeneous_tabs
4346 * gtk_notebook_set_tab_border
4347 * gtk_notebook_set_tab_hborder
4348 * gtk_notebook_set_tab_vborder
4349 * gtk_notebook_set_scrollable
4352 * gtk_notebook_set_show_border:
4353 * @notebook: a #GtkNotebook
4354 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4356 * Sets whether a bevel will be drawn around the notebook pages.
4357 * This only has a visual effect when the tabs are not shown.
4358 * See gtk_notebook_set_show_tabs().
4361 gtk_notebook_set_show_border (GtkNotebook *notebook,
4362 gboolean show_border)
4364 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4366 if (notebook->show_border != show_border)
4368 notebook->show_border = show_border;
4370 if (GTK_WIDGET_VISIBLE (notebook))
4371 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4373 g_object_notify (G_OBJECT (notebook), "show_border");
4378 * gtk_notebook_get_show_border:
4379 * @notebook: a #GtkNotebook
4381 * Returns whether a bevel will be drawn around the notebook pages. See
4382 * gtk_notebook_set_show_border().
4384 * Return value: %TRUE if the bevel is drawn
4387 gtk_notebook_get_show_border (GtkNotebook *notebook)
4389 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4391 return notebook->show_border;
4395 * gtk_notebook_set_show_tabs:
4396 * @notebook: a #GtkNotebook
4397 * @show_tabs: %TRUE if the tabs should be shown.
4399 * Sets whether to show the tabs for the notebook or not.
4402 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4405 GtkNotebookPage *page;
4408 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4410 show_tabs = show_tabs != FALSE;
4412 if (notebook->show_tabs == show_tabs)
4415 notebook->show_tabs = show_tabs;
4416 children = notebook->children;
4420 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4424 page = children->data;
4425 children = children->next;
4426 if (page->default_tab)
4428 gtk_widget_destroy (page->tab_label);
4429 page->tab_label = NULL;
4432 gtk_widget_hide (page->tab_label);
4437 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4438 gtk_notebook_update_labels (notebook);
4440 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4442 g_object_notify (G_OBJECT (notebook), "show_tabs");
4446 * gtk_notebook_get_show_tabs:
4447 * @notebook: a #GtkNotebook
4449 * Returns whether the tabs of the notebook are shown. See
4450 * gtk_notebook_set_show_tabs().
4452 * Return value: %TRUE if the tabs are shown
4455 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4457 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4459 return notebook->show_tabs;
4463 * gtk_notebook_set_tab_pos:
4464 * @notebook: a #GtkNotebook.
4465 * @pos: the edge to draw the tabs at.
4467 * Sets the edge at which the tabs for switching pages in the
4468 * notebook are drawn.
4471 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4472 GtkPositionType pos)
4474 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4476 if (notebook->tab_pos != pos)
4478 notebook->tab_pos = pos;
4479 if (GTK_WIDGET_VISIBLE (notebook))
4480 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4483 g_object_notify (G_OBJECT (notebook), "tab_pos");
4487 * gtk_notebook_get_tab_pos:
4488 * @notebook: a #GtkNotebook
4490 * Gets the edge at which the tabs for switching pages in the
4491 * notebook are drawn.
4493 * Return value: the edge at which the tabs are drawn
4496 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4498 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4500 return notebook->tab_pos;
4504 * gtk_notebook_set_homogeneous_tabs:
4505 * @notebook: a #GtkNotebook
4506 * @homogeneous: %TRUE if all tabs should be the same size.
4508 * Sets whether the tabs must have all the same size or not.
4511 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4512 gboolean homogeneous)
4514 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4516 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4520 * gtk_notebook_set_tab_border:
4521 * @notebook: a #GtkNotebook
4522 * @border_width: width of the border around the tab labels.
4524 * Sets the width the border around the tab labels
4525 * in a notebook. This is equivalent to calling
4526 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4527 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4530 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4533 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4535 gtk_notebook_set_tab_border_internal (notebook, border_width);
4539 * gtk_notebook_set_tab_hborder:
4540 * @notebook: a #GtkNotebook
4541 * @tab_hborder: width of the horizontal border of tab labels.
4543 * Sets the width of the horizontal border of tab labels.
4546 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4549 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4551 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4555 * gtk_notebook_set_tab_vborder:
4556 * @notebook: a #GtkNotebook
4557 * @tab_vborder: width of the vertical border of tab labels.
4559 * Sets the width of the vertical border of tab labels.
4562 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4565 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4567 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4571 * gtk_notebook_set_scrollable:
4572 * @notebook: a #GtkNotebook
4573 * @scrollable: %TRUE if scroll arrows should be added
4575 * Sets whether the tab label area will have arrows for scrolling if
4576 * there are too many tabs to fit in the area.
4579 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4580 gboolean scrollable)
4582 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4584 scrollable = (scrollable != FALSE);
4586 if (scrollable != notebook->scrollable)
4588 notebook->scrollable = scrollable;
4590 if (GTK_WIDGET_VISIBLE (notebook))
4591 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4593 g_object_notify (G_OBJECT (notebook), "scrollable");
4598 * gtk_notebook_get_scrollable:
4599 * @notebook: a #GtkNotebook
4601 * Returns whether the tab label area has arrows for scrolling. See
4602 * gtk_notebook_set_scrollable().
4604 * Return value: %TRUE if arrows for scrolling are present
4607 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4609 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4611 return notebook->scrollable;
4614 /* Public GtkNotebook Popup Menu Methods:
4616 * gtk_notebook_popup_enable
4617 * gtk_notebook_popup_disable
4622 * gtk_notebook_popup_enable:
4623 * @notebook: a #GtkNotebook
4625 * Enables the popup menu: if the user clicks with the right mouse button on
4626 * the bookmarks, a menu with all the pages will be popped up.
4629 gtk_notebook_popup_enable (GtkNotebook *notebook)
4633 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4638 notebook->menu = gtk_menu_new ();
4639 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4641 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4642 gtk_notebook_menu_item_create (notebook, list);
4644 gtk_notebook_update_labels (notebook);
4645 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4646 GTK_WIDGET (notebook),
4647 gtk_notebook_menu_detacher);
4649 g_object_notify (G_OBJECT (notebook), "enable_popup");
4653 * gtk_notebook_popup_disable:
4654 * @notebook: a #GtkNotebook
4656 * Disables the popup menu.
4659 gtk_notebook_popup_disable (GtkNotebook *notebook)
4661 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4663 if (!notebook->menu)
4666 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4667 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4668 gtk_widget_destroy (notebook->menu);
4670 g_object_notify (G_OBJECT (notebook), "enable_popup");
4673 /* Public GtkNotebook Page Properties Functions:
4675 * gtk_notebook_get_tab_label
4676 * gtk_notebook_set_tab_label
4677 * gtk_notebook_set_tab_label_text
4678 * gtk_notebook_get_menu_label
4679 * gtk_notebook_set_menu_label
4680 * gtk_notebook_set_menu_label_text
4681 * gtk_notebook_set_tab_label_packing
4682 * gtk_notebook_query_tab_label_packing
4686 * gtk_notebook_get_tab_label:
4687 * @notebook: a #GtkNotebook
4690 * Returns the tab label widget for the page @child. %NULL is returned
4691 * if @child is not in @notebook or if no tab label has specifically
4692 * been set for @child.
4694 * Return value: the tab label
4697 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4702 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4703 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4705 list = CHECK_FIND_CHILD (notebook, child);
4709 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4712 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4716 * gtk_notebook_set_tab_label:
4717 * @notebook: a #GtkNotebook
4719 * @tab_label: the tab label widget to use, or %NULL for default tab
4722 * Changes the tab label for @child. If %NULL is specified
4723 * for @tab_label, then the page will have the label 'page N'.
4726 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4728 GtkWidget *tab_label)
4730 GtkNotebookPage *page;
4733 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4734 g_return_if_fail (GTK_IS_WIDGET (child));
4736 list = CHECK_FIND_CHILD (notebook, child);
4740 /* a NULL pointer indicates a default_tab setting, otherwise
4741 * we need to set the associated label
4745 if (page->tab_label == tab_label)
4749 gtk_notebook_remove_tab_label (notebook, page);
4753 page->default_tab = FALSE;
4754 page->tab_label = tab_label;
4755 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4759 page->default_tab = TRUE;
4760 page->tab_label = NULL;
4762 if (notebook->show_tabs)
4766 g_snprintf (string, sizeof(string), _("Page %u"),
4767 gtk_notebook_real_page_position (notebook, list));
4768 page->tab_label = gtk_label_new (string);
4769 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4773 if (page->tab_label)
4774 page->mnemonic_activate_signal =
4775 g_signal_connect (page->tab_label,
4776 "mnemonic_activate",
4777 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4780 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4782 gtk_widget_show (page->tab_label);
4783 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4785 gtk_widget_child_notify (child, "tab_label");
4789 * gtk_notebook_set_tab_label_text:
4790 * @notebook: a #GtkNotebook
4792 * @tab_text: the label text
4794 * Creates a new label and sets it as the tab label for the page
4795 * containing @child.
4798 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4800 const gchar *tab_text)
4802 GtkWidget *tab_label = NULL;
4804 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4807 tab_label = gtk_label_new (tab_text);
4808 gtk_notebook_set_tab_label (notebook, child, tab_label);
4809 gtk_widget_child_notify (child, "tab_label");
4813 * gtk_notebook_get_tab_label_text:
4814 * @notebook: a #GtkNotebook
4815 * @child: a widget contained in a page of @notebook
4817 * Retrieves the text of the tab label for the page containing
4820 * Returns value: the text of the tab label, or %NULL if the
4821 * tab label widget is not a #GtkLabel. The
4822 * string is owned by the widget and must not
4825 G_CONST_RETURN gchar *
4826 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4829 GtkWidget *tab_label;
4831 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4832 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4834 tab_label = gtk_notebook_get_tab_label (notebook, child);
4836 if (tab_label && GTK_IS_LABEL (tab_label))
4837 return gtk_label_get_text (GTK_LABEL (tab_label));
4843 * gtk_notebook_get_menu_label:
4844 * @notebook: a #GtkNotebook
4845 * @child: a widget contained in a page of @notebook
4847 * Retrieves the menu label widget of the page containing @child.
4849 * Return value: the menu label, or %NULL if the
4850 * notebook page does not have a menu label other
4851 * than the default (the tab label).
4854 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4859 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4860 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4862 list = CHECK_FIND_CHILD (notebook, child);
4866 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4869 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4873 * gtk_notebook_set_menu_label:
4874 * @notebook: a #GtkNotebook
4875 * @child: the child widget
4876 * @menu_label: the menu label, or NULL for default
4878 * Changes the menu label for the page containing @child.
4881 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4883 GtkWidget *menu_label)
4885 GtkNotebookPage *page;
4888 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4889 g_return_if_fail (GTK_IS_WIDGET (child));
4891 list = CHECK_FIND_CHILD (notebook, child);
4896 if (page->menu_label)
4899 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4900 page->menu_label->parent);
4902 if (!page->default_menu)
4903 g_object_unref (page->menu_label);
4908 page->menu_label = menu_label;
4909 g_object_ref (page->menu_label);
4910 gtk_object_sink (GTK_OBJECT(page->menu_label));
4911 page->default_menu = FALSE;
4914 page->default_menu = TRUE;
4917 gtk_notebook_menu_item_create (notebook, list);
4918 gtk_widget_child_notify (child, "menu_label");
4922 * gtk_notebook_set_menu_label_text:
4923 * @notebook: a #GtkNotebook
4924 * @child: the child widget
4925 * @menu_text: the label text
4927 * Creates a new label and sets it as the menu label of @child.
4930 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4932 const gchar *menu_text)
4934 GtkWidget *menu_label = NULL;
4936 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4939 menu_label = gtk_label_new (menu_text);
4940 gtk_notebook_set_menu_label (notebook, child, menu_label);
4941 gtk_widget_child_notify (child, "menu_label");
4945 * gtk_notebook_get_menu_label_text:
4946 * @notebook: a #GtkNotebook
4947 * @child: the child widget of a page of the notebook.
4949 * Retrieves the text of the menu label for the page containing
4952 * Returns value: the text of the tab label, or %NULL if the
4953 * widget does not have a menu label other than
4954 * the default menu label, or the menu label widget
4955 * is not a #GtkLabel. The string is owned by
4956 * the widget and must not be freed.
4958 G_CONST_RETURN gchar *
4959 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4962 GtkWidget *menu_label;
4964 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4965 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4967 menu_label = gtk_notebook_get_menu_label (notebook, child);
4969 if (menu_label && GTK_IS_LABEL (menu_label))
4970 return gtk_label_get_text (GTK_LABEL (menu_label));
4975 /* Helper function called when pages are reordered
4978 gtk_notebook_child_reordered (GtkNotebook *notebook,
4979 GtkNotebookPage *page)
4983 GtkWidget *menu_item;
4985 menu_item = page->menu_label->parent;
4986 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4987 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4988 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4991 gtk_notebook_update_labels (notebook);
4995 * gtk_notebook_set_tab_label_packing:
4996 * @notebook: a #GtkNotebook
4997 * @child: the child widget
4998 * @expand: whether to expand the bookmark or not
4999 * @fill: whether the bookmark should fill the allocated area or not
5000 * @pack_type: the position of the bookmark
5002 * Sets the packing parameters for the tab label of the page
5003 * containing @child. See gtk_box_pack_start() for the exact meaning
5004 * of the parameters.
5007 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5011 GtkPackType pack_type)
5013 GtkNotebookPage *page;
5016 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5017 g_return_if_fail (GTK_IS_WIDGET (child));
5019 list = CHECK_FIND_CHILD (notebook, child);
5024 expand = expand != FALSE;
5025 fill = fill != FALSE;
5026 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5029 gtk_widget_freeze_child_notify (child);
5030 page->expand = expand;
5031 gtk_widget_child_notify (child, "tab_expand");
5033 gtk_widget_child_notify (child, "tab_fill");
5034 if (page->pack != pack_type)
5036 page->pack = pack_type;
5037 gtk_notebook_child_reordered (notebook, page);
5039 gtk_widget_child_notify (child, "tab_pack");
5040 gtk_widget_child_notify (child, "position");
5041 if (notebook->show_tabs)
5042 gtk_notebook_pages_allocate (notebook);
5043 gtk_widget_thaw_child_notify (child);
5047 * gtk_notebook_query_tab_label_packing:
5048 * @notebook: a #GtkNotebook
5050 * @expand: location to store the expand value (or NULL)
5051 * @fill: location to store the fill value (or NULL)
5052 * @pack_type: location to store the pack_type (or NULL)
5054 * Query the packing attributes for the tab label of the page
5055 * containing @child.
5058 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5062 GtkPackType *pack_type)
5066 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5067 g_return_if_fail (GTK_IS_WIDGET (child));
5069 list = CHECK_FIND_CHILD (notebook, child);
5074 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5076 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5078 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5082 * gtk_notebook_reorder_child:
5083 * @notebook: a #GtkNotebook
5084 * @child: the child to move
5085 * @position: the new position, or -1 to move to the end
5087 * Reorders the page containing @child, so that it appears in position
5088 * @position. If @position is greater than or equal to the number of
5089 * children in the list or negative, @child will be moved to the end
5093 gtk_notebook_reorder_child (GtkNotebook *notebook,
5097 GList *list, *new_list;
5098 GtkNotebookPage *page;
5102 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5103 g_return_if_fail (GTK_IS_WIDGET (child));
5105 list = CHECK_FIND_CHILD (notebook, child);
5109 max_pos = g_list_length (notebook->children) - 1;
5110 if (position < 0 || position > max_pos)
5113 old_pos = g_list_position (notebook->children, list);
5115 if (old_pos == position)
5119 notebook->children = g_list_delete_link (notebook->children, list);
5121 notebook->children = g_list_insert (notebook->children, page, position);
5122 new_list = g_list_nth (notebook->children, position);
5124 /* Fix up GList references in GtkNotebook structure */
5125 if (notebook->first_tab == list)
5126 notebook->first_tab = new_list;
5127 if (notebook->focus_tab == list)
5128 notebook->focus_tab = new_list;
5130 gtk_widget_freeze_child_notify (child);
5132 /* Move around the menu items if necesary */
5133 gtk_notebook_child_reordered (notebook, page);
5134 gtk_widget_child_notify (child, "tab_pack");
5135 gtk_widget_child_notify (child, "position");
5137 if (notebook->show_tabs)
5138 gtk_notebook_pages_allocate (notebook);
5140 gtk_widget_thaw_child_notify (child);