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))
1313 gdk_window_move_resize (notebook->event_window,
1314 position.x, position.y,
1315 position.width, position.height);
1316 gdk_window_show_unraised (notebook->event_window);
1319 gdk_window_hide (notebook->event_window);
1322 if (notebook->children)
1324 gint border_width = GTK_CONTAINER (widget)->border_width;
1325 GtkNotebookPage *page;
1326 GtkAllocation child_allocation;
1329 child_allocation.x = widget->allocation.x + border_width;
1330 child_allocation.y = widget->allocation.y + border_width;
1331 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1332 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1334 if (notebook->show_tabs || notebook->show_border)
1336 child_allocation.x += widget->style->xthickness;
1337 child_allocation.y += widget->style->ythickness;
1338 child_allocation.width = MAX (1, child_allocation.width -
1339 widget->style->xthickness * 2);
1340 child_allocation.height = MAX (1, child_allocation.height -
1341 widget->style->ythickness * 2);
1343 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1345 switch (notebook->tab_pos)
1348 child_allocation.y += notebook->cur_page->requisition.height;
1349 case GTK_POS_BOTTOM:
1350 child_allocation.height =
1351 MAX (1, child_allocation.height -
1352 notebook->cur_page->requisition.height);
1355 child_allocation.x += notebook->cur_page->requisition.width;
1357 child_allocation.width =
1358 MAX (1, child_allocation.width -
1359 notebook->cur_page->requisition.width);
1365 children = notebook->children;
1368 page = children->data;
1369 children = children->next;
1371 if (GTK_WIDGET_VISIBLE (page->child))
1373 gtk_widget_size_allocate (page->child, &child_allocation);
1378 gtk_notebook_pages_allocate (notebook);
1381 if ((vis_pages != 0) != notebook->have_visible_child)
1383 notebook->have_visible_child = (vis_pages != 0);
1384 if (notebook->show_tabs)
1385 gtk_widget_queue_draw (widget);
1390 gtk_notebook_expose (GtkWidget *widget,
1391 GdkEventExpose *event)
1393 GtkNotebook *notebook;
1394 GdkRectangle child_area;
1396 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1397 g_return_val_if_fail (event != NULL, FALSE);
1399 if (GTK_WIDGET_DRAWABLE (widget))
1401 notebook = GTK_NOTEBOOK (widget);
1403 gtk_notebook_paint (widget, &event->area);
1404 if (notebook->show_tabs)
1406 if (notebook->cur_page &&
1407 gtk_widget_intersect (notebook->cur_page->tab_label,
1408 &event->area, &child_area))
1409 gtk_notebook_draw_focus (widget);
1413 if (notebook->cur_page)
1414 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1415 notebook->cur_page->child,
1423 gtk_notebook_show_arrows (GtkNotebook *notebook)
1425 gboolean show_arrow = FALSE;
1428 if (!notebook->scrollable)
1431 children = notebook->children;
1434 GtkNotebookPage *page = children->data;
1436 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1439 children = children->next;
1446 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1447 GdkRectangle *rectangle)
1449 GdkRectangle event_window_pos;
1451 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1453 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1454 rectangle->height = ARROW_SIZE;
1456 switch (notebook->tab_pos)
1460 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1461 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1464 case GTK_POS_BOTTOM:
1465 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1466 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1473 gtk_notebook_get_arrow (GtkNotebook *notebook,
1477 GdkRectangle arrow_rect;
1478 GdkRectangle event_window_pos;
1480 if (gtk_notebook_show_arrows (notebook))
1482 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1483 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1488 if (y >= 0 && y < arrow_rect.height)
1490 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1491 return GTK_ARROW_LEFT;
1492 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1493 return GTK_ARROW_RIGHT;
1501 gtk_notebook_do_arrow (GtkNotebook *notebook,
1504 GtkWidget *widget = GTK_WIDGET (notebook);
1505 GtkDirectionType dir;
1507 if (!notebook->focus_tab ||
1508 gtk_notebook_search_page (notebook, notebook->focus_tab,
1509 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1512 if (notebook->tab_pos == GTK_POS_LEFT ||
1513 notebook->tab_pos == GTK_POS_RIGHT)
1514 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1516 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1517 gtk_widget_child_focus (widget, dir);
1522 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1524 GdkEventButton *event)
1526 GtkWidget *widget = GTK_WIDGET (notebook);
1528 if (!GTK_WIDGET_HAS_FOCUS (widget))
1529 gtk_widget_grab_focus (widget);
1531 notebook->button = event->button;
1532 notebook->click_child = arrow;
1534 if (event->button == 1)
1536 gtk_notebook_do_arrow (notebook, arrow);
1538 if (!notebook->timer)
1540 notebook->timer = gtk_timeout_add
1541 (NOTEBOOK_INIT_SCROLL_DELAY,
1542 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1543 notebook->need_timer = TRUE;
1546 else if (event->button == 2)
1547 gtk_notebook_page_select (notebook, TRUE);
1548 else if (event->button == 3)
1549 gtk_notebook_switch_focus_tab (notebook,
1550 gtk_notebook_search_page (notebook,
1552 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1554 gtk_notebook_redraw_arrows (notebook);
1560 get_widget_coordinates (GtkWidget *widget,
1565 GdkWindow *window = ((GdkEventAny *)event)->window;
1568 if (!gdk_event_get_coords (event, &tx, &ty))
1571 while (window && window != widget->window)
1573 gint window_x, window_y;
1575 gdk_window_get_position (window, &window_x, &window_y);
1579 window = gdk_window_get_parent (window);
1594 gtk_notebook_button_press (GtkWidget *widget,
1595 GdkEventButton *event)
1597 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1598 GtkNotebookPage *page;
1604 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1608 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1611 arrow = gtk_notebook_get_arrow (notebook, x, y);
1613 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1615 if (event->button == 3 && notebook->menu)
1617 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1618 NULL, NULL, 3, event->time);
1622 if (event->button != 1)
1626 children = notebook->children;
1629 page = children->data;
1631 if (GTK_WIDGET_VISIBLE (page->child) &&
1632 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1633 (x >= page->allocation.x) &&
1634 (y >= page->allocation.y) &&
1635 (x <= (page->allocation.x + page->allocation.width)) &&
1636 (y <= (page->allocation.y + page->allocation.height)))
1638 gboolean page_changed = page != notebook->cur_page;
1639 gboolean was_focus = gtk_widget_is_focus (widget);
1641 gtk_notebook_switch_focus_tab (notebook, children);
1642 gtk_widget_grab_focus (widget);
1644 if (page_changed && !was_focus)
1645 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1649 children = children->next;
1652 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1653 gtk_widget_grab_focus (widget);
1659 gtk_notebook_button_release (GtkWidget *widget,
1660 GdkEventButton *event)
1662 GtkNotebook *notebook;
1664 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1665 g_return_val_if_fail (event != NULL, FALSE);
1667 if (event->type != GDK_BUTTON_RELEASE)
1670 notebook = GTK_NOTEBOOK (widget);
1672 if (event->button == notebook->button)
1676 if (notebook->timer)
1678 gtk_timeout_remove (notebook->timer);
1679 notebook->timer = 0;
1680 notebook->need_timer = FALSE;
1682 click_child = notebook->click_child;
1683 notebook->click_child = 0;
1684 notebook->button = 0;
1685 gtk_notebook_redraw_arrows (notebook);
1694 gtk_notebook_enter_notify (GtkWidget *widget,
1695 GdkEventCrossing *event)
1697 GtkNotebook *notebook;
1701 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1702 g_return_val_if_fail (event != NULL, FALSE);
1704 notebook = GTK_NOTEBOOK (widget);
1706 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1709 arrow = gtk_notebook_get_arrow (notebook, x, y);
1711 if (arrow != notebook->in_child)
1713 notebook->in_child = arrow;
1714 gtk_notebook_redraw_arrows (notebook);
1723 gtk_notebook_leave_notify (GtkWidget *widget,
1724 GdkEventCrossing *event)
1726 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1730 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1733 arrow = gtk_notebook_get_arrow (notebook, x, y);
1735 if (notebook->in_child)
1737 notebook->in_child = 0;
1738 gtk_notebook_redraw_arrows (notebook);
1745 gtk_notebook_motion_notify (GtkWidget *widget,
1746 GdkEventMotion *event)
1748 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1752 if (notebook->button)
1755 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1758 arrow = gtk_notebook_get_arrow (notebook, x, y);
1760 if (arrow != notebook->in_child)
1762 notebook->in_child = arrow;
1763 gtk_notebook_redraw_arrows (notebook);
1770 gtk_notebook_focus_in (GtkWidget *widget,
1771 GdkEventFocus *event)
1773 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1775 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1779 gtk_notebook_draw_focus (GtkWidget *widget)
1781 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1783 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1784 notebook->focus_tab)
1786 GtkNotebookPage *page;
1790 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1792 page = notebook->focus_tab->data;
1794 area.x = page->tab_label->allocation.x - focus_width;
1795 area.y = page->tab_label->allocation.y - focus_width;
1796 area.width = page->tab_label->allocation.width + 2 * focus_width;
1797 area.height = page->tab_label->allocation.height + 2 * focus_width;
1799 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1803 /* Private GtkContainer Methods :
1805 * gtk_notebook_set_child_arg
1806 * gtk_notebook_get_child_arg
1808 * gtk_notebook_remove
1809 * gtk_notebook_focus
1810 * gtk_notebook_set_focus_child
1811 * gtk_notebook_child_type
1812 * gtk_notebook_forall
1815 gtk_notebook_set_child_property (GtkContainer *container,
1818 const GValue *value,
1823 GtkPackType pack_type;
1825 /* not finding child's page is valid for menus or labels */
1826 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1829 switch (property_id)
1831 case CHILD_PROP_TAB_LABEL:
1832 /* a NULL pointer indicates a default_tab setting, otherwise
1833 * we need to set the associated label
1835 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1836 g_value_get_string (value));
1838 case CHILD_PROP_MENU_LABEL:
1839 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1840 g_value_get_string (value));
1842 case CHILD_PROP_POSITION:
1843 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1844 g_value_get_int (value));
1846 case CHILD_PROP_TAB_EXPAND:
1847 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1848 &expand, &fill, &pack_type);
1849 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1850 g_value_get_boolean (value),
1853 case CHILD_PROP_TAB_FILL:
1854 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1855 &expand, &fill, &pack_type);
1856 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1858 g_value_get_boolean (value),
1861 case CHILD_PROP_TAB_PACK:
1862 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1863 &expand, &fill, &pack_type);
1864 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1866 g_value_get_enum (value));
1869 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1875 gtk_notebook_get_child_property (GtkContainer *container,
1882 GtkNotebook *notebook;
1886 GtkPackType pack_type;
1888 notebook = GTK_NOTEBOOK (container);
1890 /* not finding child's page is valid for menus or labels */
1891 list = gtk_notebook_find_child (notebook, child, NULL);
1894 /* nothing to set on labels or menus */
1895 g_param_value_set_default (pspec, value);
1899 switch (property_id)
1901 case CHILD_PROP_TAB_LABEL:
1902 label = gtk_notebook_get_tab_label (notebook, child);
1904 if (label && GTK_IS_LABEL (label))
1905 g_value_set_string (value, GTK_LABEL (label)->label);
1907 g_value_set_string (value, NULL);
1909 case CHILD_PROP_MENU_LABEL:
1910 label = gtk_notebook_get_menu_label (notebook, child);
1912 if (label && GTK_IS_LABEL (label))
1913 g_value_set_string (value, GTK_LABEL (label)->label);
1915 g_value_set_string (value, NULL);
1917 case CHILD_PROP_POSITION:
1918 g_value_set_int (value, g_list_position (notebook->children, list));
1920 case CHILD_PROP_TAB_EXPAND:
1921 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1922 &expand, NULL, NULL);
1923 g_value_set_boolean (value, expand);
1925 case CHILD_PROP_TAB_FILL:
1926 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1928 g_value_set_boolean (value, fill);
1930 case CHILD_PROP_TAB_PACK:
1931 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1932 NULL, NULL, &pack_type);
1933 g_value_set_enum (value, pack_type);
1936 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1942 gtk_notebook_add (GtkContainer *container,
1945 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1947 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1952 gtk_notebook_remove (GtkContainer *container,
1955 GtkNotebook *notebook;
1956 GtkNotebookPage *page;
1960 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1961 g_return_if_fail (widget != NULL);
1963 notebook = GTK_NOTEBOOK (container);
1965 children = notebook->children;
1969 page = children->data;
1970 if (page->child == widget)
1972 gtk_notebook_real_remove (notebook, children, FALSE);
1976 children = children->next;
1981 focus_tabs_in (GtkNotebook *notebook)
1983 if (notebook->show_tabs && notebook->cur_page)
1985 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1987 gtk_notebook_switch_focus_tab (notebook,
1988 g_list_find (notebook->children,
1989 notebook->cur_page));
1998 focus_tabs_move (GtkNotebook *notebook,
1999 GtkDirectionType direction,
2000 gint search_direction)
2004 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2005 search_direction, TRUE);
2007 gtk_notebook_switch_focus_tab (notebook, new_page);
2009 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2015 focus_child_in (GtkNotebook *notebook,
2016 GtkDirectionType direction)
2018 if (notebook->cur_page)
2019 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2024 /* Focus in the notebook can either be on the pages, or on
2028 gtk_notebook_focus (GtkWidget *widget,
2029 GtkDirectionType direction)
2031 GtkWidget *old_focus_child;
2032 GtkNotebook *notebook;
2033 GtkDirectionType effective_direction;
2035 gboolean widget_is_focus;
2036 GtkContainer *container;
2038 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2040 container = GTK_CONTAINER (widget);
2041 notebook = GTK_NOTEBOOK (container);
2043 if (notebook->focus_out)
2045 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2049 widget_is_focus = gtk_widget_is_focus (widget);
2050 old_focus_child = container->focus_child;
2052 effective_direction = get_effective_direction (notebook, direction);
2054 if (old_focus_child) /* Focus on page child */
2056 if (gtk_widget_child_focus (old_focus_child, direction))
2059 switch (effective_direction)
2061 case GTK_DIR_TAB_BACKWARD:
2063 /* Focus onto the tabs */
2064 return focus_tabs_in (notebook);
2066 case GTK_DIR_TAB_FORWARD:
2072 else if (widget_is_focus) /* Focus was on tabs */
2074 switch (effective_direction)
2076 case GTK_DIR_TAB_BACKWARD:
2079 case GTK_DIR_TAB_FORWARD:
2081 /* We use TAB_FORWARD rather than direction so that we focus a more
2082 * predictable widget for the user; users may be using arrow focusing
2083 * in this situation even if they don't usually use arrow focusing.
2085 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2087 return focus_tabs_move (notebook, direction, STEP_PREV);
2089 return focus_tabs_move (notebook, direction, STEP_NEXT);
2092 else /* Focus was not on widget */
2094 switch (effective_direction)
2096 case GTK_DIR_TAB_FORWARD:
2098 if (focus_tabs_in (notebook))
2100 if (focus_child_in (notebook, direction))
2103 case GTK_DIR_TAB_BACKWARD:
2105 if (focus_child_in (notebook, direction))
2107 if (focus_tabs_in (notebook))
2112 return focus_child_in (notebook, direction);
2116 g_assert_not_reached ();
2121 gtk_notebook_set_focus_child (GtkContainer *container,
2124 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2125 GtkWidget *page_child;
2126 GtkWidget *toplevel;
2128 /* If the old focus widget was within a page of the notebook,
2129 * (child may either be NULL or not in this case), record it
2130 * for future use if we switch to the page with a mnemonic.
2133 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2134 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2136 page_child = GTK_WINDOW (toplevel)->focus_widget;
2139 if (page_child->parent == GTK_WIDGET (container))
2141 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2144 GtkNotebookPage *page = list->data;
2146 if (page->last_focus_child)
2147 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2149 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2150 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2156 page_child = page_child->parent;
2162 g_return_if_fail (GTK_IS_WIDGET (child));
2164 notebook->child_has_focus = TRUE;
2165 if (!notebook->focus_tab)
2168 GtkNotebookPage *page;
2170 children = notebook->children;
2173 page = children->data;
2174 if (page->child == child || page->tab_label == child)
2175 gtk_notebook_switch_focus_tab (notebook, children);
2176 children = children->next;
2181 parent_class->set_focus_child (container, child);
2185 gtk_notebook_forall (GtkContainer *container,
2186 gboolean include_internals,
2187 GtkCallback callback,
2188 gpointer callback_data)
2190 GtkNotebook *notebook;
2193 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2194 g_return_if_fail (callback != NULL);
2196 notebook = GTK_NOTEBOOK (container);
2198 children = notebook->children;
2201 GtkNotebookPage *page;
2203 page = children->data;
2204 children = children->next;
2205 (* callback) (page->child, callback_data);
2206 if (include_internals)
2208 if (page->tab_label)
2209 (* callback) (page->tab_label, callback_data);
2210 if (page->menu_label)
2211 (* callback) (page->menu_label, callback_data);
2217 gtk_notebook_child_type (GtkContainer *container)
2219 return GTK_TYPE_WIDGET;
2222 /* Private GtkNotebook Functions:
2224 * gtk_notebook_redraw_tabs
2225 * gtk_notebook_real_remove
2226 * gtk_notebook_update_labels
2227 * gtk_notebook_timer
2228 * gtk_notebook_page_compare
2229 * gtk_notebook_real_page_position
2230 * gtk_notebook_search_page
2233 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2236 GtkNotebookPage *page;
2237 GdkRectangle redraw_rect;
2240 widget = GTK_WIDGET (notebook);
2241 border = GTK_CONTAINER (notebook)->border_width;
2243 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2246 page = notebook->first_tab->data;
2248 redraw_rect.x = border;
2249 redraw_rect.y = border;
2251 switch (notebook->tab_pos)
2253 case GTK_POS_BOTTOM:
2254 redraw_rect.y = (widget->allocation.height - border -
2255 page->allocation.height -
2256 widget->style->ythickness);
2257 if (page != notebook->cur_page)
2258 redraw_rect.y -= widget->style->ythickness;
2261 redraw_rect.width = widget->allocation.width - 2 * border;
2262 redraw_rect.height = (page->allocation.height +
2263 widget->style->ythickness);
2264 if (page != notebook->cur_page)
2265 redraw_rect.height += widget->style->ythickness;
2268 redraw_rect.x = (widget->allocation.width - border -
2269 page->allocation.width -
2270 widget->style->xthickness);
2271 if (page != notebook->cur_page)
2272 redraw_rect.x -= widget->style->xthickness;
2275 redraw_rect.width = (page->allocation.width +
2276 widget->style->xthickness);
2277 redraw_rect.height = widget->allocation.height - 2 * border;
2278 if (page != notebook->cur_page)
2279 redraw_rect.width += widget->style->xthickness;
2283 redraw_rect.x += widget->allocation.x;
2284 redraw_rect.y += widget->allocation.y;
2286 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2290 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2292 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2296 gtk_notebook_get_arrow_rect (notebook, &rect);
2297 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2302 gtk_notebook_timer (GtkNotebook *notebook)
2304 gboolean retval = FALSE;
2306 GDK_THREADS_ENTER ();
2308 if (notebook->timer)
2310 gtk_notebook_do_arrow (notebook, notebook->click_child);
2312 if (notebook->need_timer)
2314 notebook->need_timer = FALSE;
2315 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2316 (GtkFunction) gtk_notebook_timer,
2317 (gpointer) notebook);
2323 GDK_THREADS_LEAVE ();
2329 gtk_notebook_page_compare (gconstpointer a,
2332 return (((GtkNotebookPage *) a)->child != b);
2336 gtk_notebook_find_child (GtkNotebook *notebook,
2338 const gchar *function)
2340 GList *list = g_list_find_custom (notebook->children, child,
2341 gtk_notebook_page_compare);
2343 #ifndef G_DISABLE_CHECKS
2344 if (!list && function)
2345 g_warning ("%s: unable to find child %p in notebook %p",
2346 function, child, notebook);
2353 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2354 GtkNotebookPage *page)
2356 if (page->tab_label)
2358 if (page->mnemonic_activate_signal)
2359 g_signal_handler_disconnect (page->tab_label,
2360 page->mnemonic_activate_signal);
2361 page->mnemonic_activate_signal = 0;
2363 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2364 gtk_widget_unparent (page->tab_label);
2369 gtk_notebook_real_remove (GtkNotebook *notebook,
2371 gboolean destroying)
2373 GtkNotebookPage *page;
2375 gint need_resize = FALSE;
2377 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2379 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2381 if (notebook->cur_page == list->data)
2383 notebook->cur_page = NULL;
2384 if (next_list && !destroying)
2385 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2388 if (list == notebook->first_tab)
2389 notebook->first_tab = next_list;
2390 if (list == notebook->focus_tab && !destroying)
2391 gtk_notebook_switch_focus_tab (notebook, next_list);
2395 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2398 gtk_widget_unparent (page->child);
2400 gtk_notebook_remove_tab_label (notebook, page);
2404 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2405 page->menu_label->parent);
2406 gtk_widget_queue_resize (notebook->menu);
2408 if (!page->default_menu)
2409 g_object_unref (page->menu_label);
2411 notebook->children = g_list_remove_link (notebook->children, list);
2414 if (page->last_focus_child)
2416 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2417 page->last_focus_child = NULL;
2422 gtk_notebook_update_labels (notebook);
2424 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2428 gtk_notebook_update_labels (GtkNotebook *notebook)
2430 GtkNotebookPage *page;
2435 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2437 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2440 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2441 if (notebook->show_tabs)
2443 if (page->default_tab)
2445 if (!page->tab_label)
2447 page->tab_label = gtk_label_new (string);
2448 gtk_widget_set_parent (page->tab_label,
2449 GTK_WIDGET (notebook));
2452 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2455 if (GTK_WIDGET_VISIBLE (page->child) &&
2456 !GTK_WIDGET_VISIBLE (page->tab_label))
2457 gtk_widget_show (page->tab_label);
2458 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2459 GTK_WIDGET_VISIBLE (page->tab_label))
2460 gtk_widget_hide (page->tab_label);
2462 if (notebook->menu && page->default_menu)
2464 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2465 gtk_label_set_text (GTK_LABEL (page->menu_label),
2466 GTK_LABEL (page->tab_label)->label);
2468 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2474 gtk_notebook_real_page_position (GtkNotebook *notebook,
2480 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2481 g_return_val_if_fail (list != NULL, -1);
2483 for (work = notebook->children, count_start = 0;
2484 work && work != list; work = work->next)
2485 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2491 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2494 return (count_start + g_list_length (list) - 1);
2498 gtk_notebook_search_page (GtkNotebook *notebook,
2501 gboolean find_visible)
2503 GtkNotebookPage *page = NULL;
2504 GList *old_list = NULL;
2507 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2512 flag = GTK_PACK_END;
2516 flag = GTK_PACK_START;
2523 if (!page || page->pack == flag)
2531 list = notebook->children;
2536 if (page->pack == flag &&
2537 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2552 if (page->pack != flag &&
2553 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2561 /* Private GtkNotebook Drawing Functions:
2563 * gtk_notebook_paint
2564 * gtk_notebook_draw_tab
2565 * gtk_notebook_draw_arrow
2568 gtk_notebook_paint (GtkWidget *widget,
2571 GtkNotebook *notebook;
2572 GtkNotebookPage *page;
2577 gint border_width = GTK_CONTAINER (widget)->border_width;
2578 gint gap_x = 0, gap_width = 0;
2580 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2581 g_return_if_fail (area != NULL);
2583 if (!GTK_WIDGET_DRAWABLE (widget))
2586 notebook = GTK_NOTEBOOK (widget);
2588 if ((!notebook->show_tabs && !notebook->show_border) ||
2589 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2592 x = widget->allocation.x + border_width;
2593 y = widget->allocation.y + border_width;
2594 width = widget->allocation.width - border_width * 2;
2595 height = widget->allocation.height - border_width * 2;
2597 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2599 gtk_paint_box (widget->style, widget->window,
2600 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2601 area, widget, "notebook",
2602 x, y, width, height);
2607 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2609 page = notebook->first_tab->data;
2611 switch (notebook->tab_pos)
2614 y += page->allocation.height + widget->style->ythickness;
2615 case GTK_POS_BOTTOM:
2616 height -= page->allocation.height + widget->style->ythickness;
2619 x += page->allocation.width + widget->style->xthickness;
2621 width -= page->allocation.width + widget->style->xthickness;
2624 gtk_paint_box (widget->style, widget->window,
2625 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2626 area, widget, "notebook",
2627 x, y, width, height);
2631 switch (notebook->tab_pos)
2634 y += notebook->cur_page->allocation.height;
2635 case GTK_POS_BOTTOM:
2636 height -= notebook->cur_page->allocation.height;
2639 x += notebook->cur_page->allocation.width;
2641 width -= notebook->cur_page->allocation.width;
2645 switch (notebook->tab_pos)
2648 case GTK_POS_BOTTOM:
2649 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2650 gap_width = notebook->cur_page->allocation.width;
2654 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2655 gap_width = notebook->cur_page->allocation.height;
2658 gtk_paint_box_gap(widget->style, widget->window,
2659 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2660 area, widget, "notebook",
2661 x, y, width, height,
2662 notebook->tab_pos, gap_x, gap_width);
2666 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2669 page = children->data;
2670 children = gtk_notebook_search_page (notebook, children,
2672 if (!GTK_WIDGET_VISIBLE (page->child))
2674 if (!GTK_WIDGET_MAPPED (page->tab_label))
2676 else if (page != notebook->cur_page)
2677 gtk_notebook_draw_tab (notebook, page, area);
2680 if (showarrow && notebook->scrollable)
2682 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2683 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2685 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2689 gtk_notebook_draw_tab (GtkNotebook *notebook,
2690 GtkNotebookPage *page,
2693 GdkRectangle child_area;
2694 GdkRectangle page_area;
2695 GtkStateType state_type;
2696 GtkPositionType gap_side;
2698 g_return_if_fail (notebook != NULL);
2699 g_return_if_fail (page != NULL);
2700 g_return_if_fail (area != NULL);
2702 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2703 (page->allocation.width == 0) || (page->allocation.height == 0))
2706 page_area.x = page->allocation.x;
2707 page_area.y = page->allocation.y;
2708 page_area.width = page->allocation.width;
2709 page_area.height = page->allocation.height;
2711 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2715 widget = GTK_WIDGET (notebook);
2717 switch (notebook->tab_pos)
2720 gap_side = GTK_POS_BOTTOM;
2722 case GTK_POS_BOTTOM:
2723 gap_side = GTK_POS_TOP;
2726 gap_side = GTK_POS_RIGHT;
2729 gap_side = GTK_POS_LEFT;
2733 if (notebook->cur_page == page)
2734 state_type = GTK_STATE_NORMAL;
2736 state_type = GTK_STATE_ACTIVE;
2737 gtk_paint_extension(widget->style, widget->window,
2738 state_type, GTK_SHADOW_OUT,
2739 area, widget, "tab",
2740 page_area.x, page_area.y,
2741 page_area.width, page_area.height,
2743 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2744 notebook->focus_tab && (notebook->focus_tab->data == page))
2748 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2750 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2751 area, widget, "tab",
2752 page->tab_label->allocation.x - focus_width,
2753 page->tab_label->allocation.y - focus_width,
2754 page->tab_label->allocation.width + 2 * focus_width,
2755 page->tab_label->allocation.height + 2 * focus_width);
2757 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2758 GTK_WIDGET_DRAWABLE (page->tab_label))
2760 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2762 /* This is a lame hack since all this code needs rewriting anyhow */
2764 expose_event->expose.window = g_object_ref (page->tab_label->window);
2765 expose_event->expose.area = child_area;
2766 expose_event->expose.region = gdk_region_rectangle (&child_area);
2767 expose_event->expose.send_event = TRUE;
2768 expose_event->expose.count = 0;
2770 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2772 gdk_event_free (expose_event);
2778 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2781 GtkStateType state_type;
2782 GtkShadowType shadow_type;
2784 GdkRectangle arrow_rect;
2786 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2788 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2790 widget = GTK_WIDGET(notebook);
2792 if (GTK_WIDGET_DRAWABLE (notebook))
2794 if (notebook->in_child == arrow)
2796 if (notebook->click_child == arrow)
2797 state_type = GTK_STATE_ACTIVE;
2799 state_type = GTK_STATE_PRELIGHT;
2802 state_type = GTK_STATE_NORMAL;
2804 if (notebook->click_child == arrow)
2805 shadow_type = GTK_SHADOW_IN;
2807 shadow_type = GTK_SHADOW_OUT;
2809 if (arrow == GTK_ARROW_LEFT)
2811 if (notebook->focus_tab &&
2812 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2815 shadow_type = GTK_SHADOW_ETCHED_IN;
2816 state_type = GTK_STATE_INSENSITIVE;
2819 if (notebook->tab_pos == GTK_POS_LEFT ||
2820 notebook->tab_pos == GTK_POS_RIGHT)
2821 arrow = GTK_ARROW_UP;
2823 gtk_paint_arrow (widget->style, widget->window, state_type,
2824 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2826 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2830 if (notebook->focus_tab &&
2831 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2834 shadow_type = GTK_SHADOW_ETCHED_IN;
2835 state_type = GTK_STATE_INSENSITIVE;
2838 if (notebook->tab_pos == GTK_POS_LEFT ||
2839 notebook->tab_pos == GTK_POS_RIGHT)
2840 arrow = GTK_ARROW_DOWN;
2842 gtk_paint_arrow (widget->style, widget->window, state_type,
2843 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2844 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2845 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2850 /* Private GtkNotebook Size Allocate Functions:
2852 * gtk_notebook_pages_allocate
2853 * gtk_notebook_page_allocate
2854 * gtk_notebook_calc_tabs
2857 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2859 GtkWidget *widget = GTK_WIDGET (notebook);
2860 GtkContainer *container = GTK_CONTAINER (notebook);
2861 GtkNotebookPage *page = NULL;
2862 GtkAllocation *allocation = &widget->allocation;
2863 GtkAllocation child_allocation;
2864 GList *children = NULL;
2865 GList *last_child = NULL;
2866 gboolean showarrow = FALSE;
2876 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2879 child_allocation.x = widget->allocation.x + container->border_width;
2880 child_allocation.y = widget->allocation.y + container->border_width;
2882 switch (notebook->tab_pos)
2884 case GTK_POS_BOTTOM:
2885 child_allocation.y = (widget->allocation.y +
2886 allocation->height -
2887 notebook->cur_page->requisition.height -
2888 container->border_width);
2891 child_allocation.height = notebook->cur_page->requisition.height;
2895 child_allocation.x = (widget->allocation.x +
2897 notebook->cur_page->requisition.width -
2898 container->border_width);
2901 child_allocation.width = notebook->cur_page->requisition.width;
2905 if (notebook->scrollable)
2909 children = notebook->children;
2911 if (notebook->focus_tab)
2912 focus_tab = notebook->focus_tab;
2913 else if (notebook->first_tab)
2914 focus_tab = notebook->first_tab;
2916 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2918 switch (notebook->tab_pos)
2921 case GTK_POS_BOTTOM:
2924 page = children->data;
2925 children = children->next;
2927 if (GTK_WIDGET_VISIBLE (page->child))
2928 tab_space += page->requisition.width;
2931 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2934 page = focus_tab->data;
2936 tab_space = (allocation->width - TAB_OVERLAP -
2937 page->requisition.width -
2938 2 * (container->border_width + ARROW_SPACING +
2940 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2941 container->border_width);
2943 page = notebook->children->data;
2944 if (notebook->tab_pos == GTK_POS_TOP)
2945 y = (container->border_width +
2946 (page->requisition.height - ARROW_SIZE) / 2);
2948 y = (allocation->height - container->border_width -
2949 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2956 page = children->data;
2957 children = children->next;
2959 if (GTK_WIDGET_VISIBLE (page->child))
2960 tab_space += page->requisition.height;
2963 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2966 page = focus_tab->data;
2967 tab_space = (allocation->height -
2968 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2969 2 * container->border_width -
2970 page->requisition.height);
2971 y = allocation->height - container->border_width - ARROW_SIZE;
2973 page = notebook->children->data;
2974 if (notebook->tab_pos == GTK_POS_LEFT)
2975 x = (container->border_width +
2976 (page->requisition.width -
2977 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2979 x = (allocation->width - container->border_width -
2980 (2 * ARROW_SIZE - ARROW_SPACING) -
2981 (page->requisition.width -
2982 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2986 if (showarrow) /* first_tab <- focus_tab */
2990 notebook->first_tab = focus_tab;
2991 last_child = gtk_notebook_search_page (notebook, focus_tab,
2997 if (notebook->first_tab && notebook->first_tab != focus_tab)
2999 /* Is first_tab really predecessor of focus_tab ? */
3000 page = notebook->first_tab->data;
3001 if (GTK_WIDGET_VISIBLE (page->child))
3002 for (children = focus_tab;
3003 children && children != notebook->first_tab;
3004 children = gtk_notebook_search_page (notebook,
3010 notebook->first_tab = focus_tab;
3012 gtk_notebook_calc_tabs (notebook,
3013 gtk_notebook_search_page (notebook,
3017 &(notebook->first_tab), &tab_space,
3022 notebook->first_tab =
3023 gtk_notebook_search_page (notebook, notebook->first_tab,
3025 if (!notebook->first_tab)
3026 notebook->first_tab = focus_tab;
3027 last_child = gtk_notebook_search_page (notebook, focus_tab,
3030 else /* focus_tab -> end */
3032 if (!notebook->first_tab)
3033 notebook->first_tab = gtk_notebook_search_page (notebook,
3038 gtk_notebook_calc_tabs (notebook,
3039 gtk_notebook_search_page (notebook,
3043 &children, &tab_space, STEP_NEXT);
3046 last_child = children;
3047 else /* start <- first_tab */
3051 gtk_notebook_calc_tabs
3053 gtk_notebook_search_page (notebook,
3054 notebook->first_tab,
3057 &children, &tab_space, STEP_PREV);
3058 notebook->first_tab = gtk_notebook_search_page(notebook,
3068 tab_space = -tab_space;
3070 for (children = notebook->first_tab;
3071 children && children != last_child;
3072 children = gtk_notebook_search_page (notebook, children,
3079 /*unmap all non-visible tabs*/
3080 for (children = gtk_notebook_search_page (notebook, NULL,
3082 children && children != notebook->first_tab;
3083 children = gtk_notebook_search_page (notebook, children,
3086 page = children->data;
3087 if (page->tab_label)
3088 gtk_widget_set_child_visible (page->tab_label, FALSE);
3090 for (children = last_child; children;
3091 children = gtk_notebook_search_page (notebook, children,
3094 page = children->data;
3095 if (page->tab_label)
3096 gtk_widget_set_child_visible (page->tab_label, FALSE);
3099 else /* !showarrow */
3101 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3112 children = notebook->children;
3113 switch (notebook->tab_pos)
3116 case GTK_POS_BOTTOM:
3119 page = children->data;
3120 children = children->next;
3122 if (GTK_WIDGET_VISIBLE (page->child))
3125 tab_space += page->requisition.width;
3130 tab_space -= allocation->width;
3136 page = children->data;
3137 children = children->next;
3139 if (GTK_WIDGET_VISIBLE (page->child))
3142 tab_space += page->requisition.height;
3147 tab_space -= allocation->height;
3149 tab_space += 2 * container->border_width + TAB_OVERLAP;
3151 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3153 if (notebook->homogeneous && n)
3157 children = notebook->first_tab;
3161 if (children == last_child)
3163 /* FIXME double check */
3167 page = children->data;
3168 if (!showarrow && page->pack != GTK_PACK_START)
3170 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3173 if (n && (showarrow || page->expand || notebook->homogeneous))
3175 new_fill = (tab_space * i++) / n;
3176 delta = new_fill - old_fill;
3177 old_fill = new_fill;
3180 switch (notebook->tab_pos)
3183 case GTK_POS_BOTTOM:
3184 child_allocation.width = (page->requisition.width +
3185 TAB_OVERLAP + delta);
3189 child_allocation.height = (page->requisition.height +
3190 TAB_OVERLAP + delta);
3194 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3196 switch (notebook->tab_pos)
3199 case GTK_POS_BOTTOM:
3200 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3204 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3208 if (page->tab_label)
3209 gtk_widget_set_child_visible (page->tab_label, TRUE);
3214 children = notebook->children;
3215 switch (notebook->tab_pos)
3218 case GTK_POS_BOTTOM:
3219 child_allocation.x = (allocation->x + allocation->width -
3220 container->border_width);
3224 child_allocation.y = (allocation->y + allocation->height -
3225 container->border_width);
3229 while (children != last_child)
3231 page = children->data;
3232 children = children->next;
3234 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3238 if (n && (page->expand || notebook->homogeneous))
3240 new_fill = (tab_space * i++) / n;
3241 delta = new_fill - old_fill;
3242 old_fill = new_fill;
3245 switch (notebook->tab_pos)
3248 case GTK_POS_BOTTOM:
3249 child_allocation.width = (page->requisition.width +
3250 TAB_OVERLAP + delta);
3251 child_allocation.x -= child_allocation.width;
3255 child_allocation.height = (page->requisition.height +
3256 TAB_OVERLAP + delta);
3257 child_allocation.y -= child_allocation.height;
3261 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3263 switch (notebook->tab_pos)
3266 case GTK_POS_BOTTOM:
3267 child_allocation.x += TAB_OVERLAP;
3271 child_allocation.y += TAB_OVERLAP;
3275 if (page->tab_label)
3276 gtk_widget_set_child_visible (page->tab_label, TRUE);
3281 gtk_notebook_redraw_tabs (notebook);
3285 gtk_notebook_page_allocate (GtkNotebook *notebook,
3286 GtkNotebookPage *page,
3287 GtkAllocation *allocation)
3289 GtkWidget *widget = GTK_WIDGET (notebook);
3290 GtkAllocation child_allocation;
3291 GtkRequisition tab_requisition;
3297 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3299 xthickness = widget->style->xthickness;
3300 ythickness = widget->style->ythickness;
3302 /* If the size of the notebook tabs change, we need to queue
3303 * a redraw on the tab area
3305 if ((allocation->width != page->allocation.width) ||
3306 (allocation->height != page->allocation.height))
3308 gint x, y, width, height, border_width;
3310 border_width = GTK_CONTAINER (notebook)->border_width;
3312 switch (notebook->tab_pos)
3315 width = widget->allocation.width;
3316 height = MAX (page->allocation.height, allocation->height) + ythickness;
3321 case GTK_POS_BOTTOM:
3322 width = widget->allocation.width + xthickness;
3323 height = MAX (page->allocation.height, allocation->height) + ythickness;
3325 y = widget->allocation.height - height - border_width;
3329 width = MAX (page->allocation.width, allocation->width) + xthickness;
3330 height = widget->allocation.height;
3336 default: /* quiet gcc */
3337 width = MAX (page->allocation.width, allocation->width) + xthickness;
3338 height = widget->allocation.height;
3339 x = widget->allocation.width - width - border_width;
3344 gtk_widget_queue_draw_area (widget, x, y, width, height);
3347 page->allocation = *allocation;
3348 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3350 if (notebook->cur_page != page)
3352 switch (notebook->tab_pos)
3355 page->allocation.y += ythickness;
3356 case GTK_POS_BOTTOM:
3357 if (page->allocation.height > ythickness)
3358 page->allocation.height -= ythickness;
3361 page->allocation.x += xthickness;
3363 if (page->allocation.width > xthickness)
3364 page->allocation.width -= xthickness;
3369 switch (notebook->tab_pos)
3372 case GTK_POS_BOTTOM:
3373 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3376 child_allocation.x = (xthickness + focus_width +
3377 notebook->tab_hborder);
3378 child_allocation.width = MAX (1, (page->allocation.width -
3379 2 * child_allocation.x));
3380 child_allocation.x += page->allocation.x;
3384 child_allocation.x = (page->allocation.x +
3385 (page->allocation.width -
3386 tab_requisition.width) / 2);
3387 child_allocation.width = tab_requisition.width;
3389 child_allocation.y = (notebook->tab_vborder + focus_width +
3390 page->allocation.y);
3391 if (notebook->tab_pos == GTK_POS_TOP)
3392 child_allocation.y += ythickness;
3393 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3394 2 * (notebook->tab_vborder + focus_width)));
3398 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3401 child_allocation.y = ythickness + padding;
3402 child_allocation.height = MAX (1, (page->allocation.height -
3403 2 * child_allocation.y));
3404 child_allocation.y += page->allocation.y;
3408 child_allocation.y = (page->allocation.y + (page->allocation.height -
3409 tab_requisition.height) / 2);
3410 child_allocation.height = tab_requisition.height;
3412 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3413 if (notebook->tab_pos == GTK_POS_LEFT)
3414 child_allocation.x += xthickness;
3415 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3416 2 * (notebook->tab_hborder + focus_width)));
3420 if (page->tab_label)
3421 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3425 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3431 GtkNotebookPage *page = NULL;
3433 GList *last_list = NULL;
3440 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3441 if (pack == GTK_PACK_END)
3442 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3446 switch (notebook->tab_pos)
3449 case GTK_POS_BOTTOM:
3452 page = children->data;
3453 if (GTK_WIDGET_VISIBLE (page->child))
3455 if (page->pack == pack)
3457 *tab_space -= page->requisition.width;
3458 if (*tab_space < 0 || children == *end)
3462 *tab_space = - (*tab_space +
3463 page->requisition.width);
3469 last_list = children;
3471 if (direction == STEP_NEXT)
3472 children = children->next;
3474 children = children->prev;
3481 page = children->data;
3482 if (GTK_WIDGET_VISIBLE (page->child))
3484 if (page->pack == pack)
3486 *tab_space -= page->requisition.height;
3487 if (*tab_space < 0 || children == *end)
3491 *tab_space = - (*tab_space +
3492 page->requisition.height);
3498 last_list = children;
3500 if (direction == STEP_NEXT)
3501 children = children->next;
3503 children = children->prev;
3507 if (direction == STEP_PREV)
3509 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3510 direction = STEP_PREV;
3511 children = last_list;
3516 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3520 for (list = notebook->children; list != NULL; list = list->next)
3522 GtkNotebookPage *page = list->data;
3524 if (page->tab_label)
3526 if (page == notebook->cur_page)
3527 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3529 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3534 /* Private GtkNotebook Page Switch Methods:
3536 * gtk_notebook_real_switch_page
3539 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3540 GtkNotebookPage *page,
3543 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3544 g_return_if_fail (page != NULL);
3546 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3549 if (notebook->cur_page)
3550 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3552 notebook->cur_page = page;
3554 if (!notebook->focus_tab ||
3555 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3556 notebook->focus_tab =
3557 g_list_find (notebook->children, notebook->cur_page);
3559 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3561 /* If the focus was on the previous page, move it to the first
3562 * element on the new page, if possible, or if not, to the
3565 if (notebook->child_has_focus)
3567 if (notebook->cur_page->last_focus_child &&
3568 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3569 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3571 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3572 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3575 gtk_notebook_update_tab_states (notebook);
3576 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3577 g_object_notify (G_OBJECT (notebook), "page");
3580 /* Private GtkNotebook Page Switch Functions:
3582 * gtk_notebook_switch_page
3583 * gtk_notebook_page_select
3584 * gtk_notebook_switch_focus_tab
3585 * gtk_notebook_menu_switch_page
3588 gtk_notebook_switch_page (GtkNotebook *notebook,
3589 GtkNotebookPage *page,
3592 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3593 g_return_if_fail (page != NULL);
3595 if (notebook->cur_page == page)
3599 page_num = g_list_index (notebook->children, page);
3601 g_signal_emit (notebook,
3602 notebook_signals[SWITCH_PAGE],
3609 gtk_notebook_page_select (GtkNotebook *notebook,
3610 gboolean move_focus)
3612 GtkNotebookPage *page;
3613 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3615 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3617 if (!notebook->focus_tab)
3620 page = notebook->focus_tab->data;
3621 gtk_notebook_switch_page (notebook, page, -1);
3625 switch (notebook->tab_pos)
3630 case GTK_POS_BOTTOM:
3634 dir = GTK_DIR_RIGHT;
3641 if (gtk_widget_child_focus (page->child, dir))
3648 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3652 GtkNotebookPage *old_page = NULL;
3653 GtkNotebookPage *page;
3655 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3657 if (notebook->focus_tab == new_child)
3660 old_child = notebook->focus_tab;
3661 notebook->focus_tab = new_child;
3663 if (notebook->scrollable)
3664 gtk_notebook_redraw_arrows (notebook);
3666 if (!notebook->show_tabs || !notebook->focus_tab)
3670 old_page = old_child->data;
3672 page = notebook->focus_tab->data;
3673 if (GTK_WIDGET_MAPPED (page->tab_label))
3674 gtk_notebook_redraw_tabs (notebook);
3676 gtk_notebook_pages_allocate (notebook);
3678 gtk_notebook_switch_page (notebook, page,
3679 g_list_index (notebook->children, page));
3683 gtk_notebook_menu_switch_page (GtkWidget *widget,
3684 GtkNotebookPage *page)
3686 GtkNotebook *notebook;
3690 g_return_if_fail (widget != NULL);
3691 g_return_if_fail (page != NULL);
3693 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3694 (GTK_MENU (widget->parent)));
3696 if (notebook->cur_page == page)
3700 children = notebook->children;
3701 while (children && children->data != page)
3703 children = children->next;
3707 g_signal_emit (notebook,
3708 notebook_signals[SWITCH_PAGE],
3714 /* Private GtkNotebook Menu Functions:
3716 * gtk_notebook_menu_item_create
3717 * gtk_notebook_menu_label_unparent
3718 * gtk_notebook_menu_detacher
3721 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3724 GtkNotebookPage *page;
3725 GtkWidget *menu_item;
3728 if (page->default_menu)
3730 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3731 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3733 page->menu_label = gtk_label_new ("");
3734 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3737 gtk_widget_show (page->menu_label);
3738 menu_item = gtk_menu_item_new ();
3739 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3740 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3741 gtk_notebook_real_page_position (notebook, list));
3742 g_signal_connect (menu_item, "activate",
3743 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3744 if (GTK_WIDGET_VISIBLE (page->child))
3745 gtk_widget_show (menu_item);
3749 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3752 gtk_widget_unparent (GTK_BIN(widget)->child);
3753 GTK_BIN(widget)->child = NULL;
3757 gtk_notebook_menu_detacher (GtkWidget *widget,
3760 GtkNotebook *notebook;
3762 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3764 notebook = GTK_NOTEBOOK (widget);
3765 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3767 notebook->menu = NULL;
3770 /* Private GtkNotebook Setter Functions:
3772 * gtk_notebook_set_homogeneous_tabs_internal
3773 * gtk_notebook_set_tab_border_internal
3774 * gtk_notebook_set_tab_hborder_internal
3775 * gtk_notebook_set_tab_vborder_internal
3778 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
3779 gboolean homogeneous)
3781 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3783 if (homogeneous == notebook->homogeneous)
3786 notebook->homogeneous = homogeneous;
3787 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3789 g_object_notify (G_OBJECT (notebook), "homogeneous");
3793 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
3796 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3798 notebook->tab_hborder = border_width;
3799 notebook->tab_vborder = border_width;
3801 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3802 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3804 g_object_freeze_notify (G_OBJECT (notebook));
3805 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3806 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3807 g_object_thaw_notify (G_OBJECT (notebook));
3811 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
3814 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3816 if (notebook->tab_hborder == tab_hborder)
3819 notebook->tab_hborder = tab_hborder;
3821 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3822 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3824 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3828 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
3831 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3833 if (notebook->tab_vborder == tab_vborder)
3836 notebook->tab_vborder = tab_vborder;
3838 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3839 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3841 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3844 /* Public GtkNotebook Page Insert/Remove Methods :
3846 * gtk_notebook_append_page
3847 * gtk_notebook_append_page_menu
3848 * gtk_notebook_prepend_page
3849 * gtk_notebook_prepend_page_menu
3850 * gtk_notebook_insert_page
3851 * gtk_notebook_insert_page_menu
3852 * gtk_notebook_remove_page
3855 * gtk_notebook_append_page:
3856 * @notebook: a #GtkNotebook
3857 * @child: the #GtkWidget to use as the contents of the page.
3858 * @tab_label: the #GtkWidget to be used as the label for the page,
3859 * or %NULL to use the default label, 'page N'.
3861 * Appends a page to @notebook.
3864 gtk_notebook_append_page (GtkNotebook *notebook,
3866 GtkWidget *tab_label)
3868 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3869 g_return_if_fail (GTK_IS_WIDGET (child));
3870 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3872 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3876 * gtk_notebook_append_page_menu:
3877 * @notebook: a #GtkNotebook
3878 * @child: the #GtkWidget to use as the contents of the page.
3879 * @tab_label: the #GtkWidget to be used as the label for the page,
3880 * or %NULL to use the default label, 'page N'.
3881 * @menu_label: the widget to use as a label for the page-switch
3882 * menu, if that is enabled. If %NULL, and @tab_label
3883 * is a #GtkLabel or %NULL, then the menu label will be
3884 * a newly created label with the same text as @tab_label;
3885 * If @tab_label is not a #GtkLabel, @menu_label must be
3886 * specified if the page-switch menu is to be used.
3888 * Appends a page to @notebook, specifying the widget to use as the
3889 * label in the popup menu.
3892 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3894 GtkWidget *tab_label,
3895 GtkWidget *menu_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));
3900 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3902 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3906 * gtk_notebook_prepend_page:
3907 * @notebook: a #GtkNotebook
3908 * @child: the #GtkWidget to use as the contents of the page.
3909 * @tab_label: the #GtkWidget to be used as the label for the page,
3910 * or %NULL to use the default label, 'page N'.
3912 * Prepends a page to @notebook.
3915 gtk_notebook_prepend_page (GtkNotebook *notebook,
3917 GtkWidget *tab_label)
3919 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3920 g_return_if_fail (GTK_IS_WIDGET (child));
3921 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3923 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3927 * gtk_notebook_prepend_page_menu:
3928 * @notebook: a #GtkNotebook
3929 * @child: the #GtkWidget to use as the contents of the page.
3930 * @tab_label: the #GtkWidget to be used as the label for the page,
3931 * or %NULL to use the default label, 'page N'.
3932 * @menu_label: the widget to use as a label for the page-switch
3933 * menu, if that is enabled. If %NULL, and @tab_label
3934 * is a #GtkLabel or %NULL, then the menu label will be
3935 * a newly created label with the same text as @tab_label;
3936 * If @tab_label is not a #GtkLabel, @menu_label must be
3937 * specified if the page-switch menu is to be used.
3939 * Prepends a page to @notebook, specifying the widget to use as the
3940 * label in the popup menu.
3943 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3945 GtkWidget *tab_label,
3946 GtkWidget *menu_label)
3948 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3949 g_return_if_fail (GTK_IS_WIDGET (child));
3950 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3951 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3953 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3957 * gtk_notebook_insert_page:
3958 * @notebook: a #GtkNotebook
3959 * @child: the #GtkWidget to use as the contents of the page.
3960 * @tab_label: the #GtkWidget to be used as the label for the page,
3961 * or %NULL to use the default label, 'page N'.
3962 * @position: the index (starting at 0) at which to insert the page,
3963 * or -1 to append the page after all other pages.
3965 * Insert a page into @notebook at the given position
3968 gtk_notebook_insert_page (GtkNotebook *notebook,
3970 GtkWidget *tab_label,
3973 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3974 g_return_if_fail (GTK_IS_WIDGET (child));
3975 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3977 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3982 gtk_notebook_page_compare_tab (gconstpointer a,
3985 return (((GtkNotebookPage *) a)->tab_label != b);
3989 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3993 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3996 list = g_list_find_custom (notebook->children, child,
3997 gtk_notebook_page_compare_tab);
4000 GtkNotebookPage *page = list->data;
4002 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4003 gtk_notebook_switch_page (notebook, page, -1);
4004 focus_tabs_in (notebook);
4011 * gtk_notebook_insert_page_menu:
4012 * @notebook: a #GtkNotebook
4013 * @child: the #GtkWidget to use as the contents of the page.
4014 * @tab_label: the #GtkWidget to be used as the label for the page,
4015 * or %NULL to use the default label, 'page N'.
4016 * @menu_label: the widget to use as a label for the page-switch
4017 * menu, if that is enabled. If %NULL, and @tab_label
4018 * is a #GtkLabel or %NULL, then the menu label will be
4019 * a newly created label with the same text as @tab_label;
4020 * If @tab_label is not a #GtkLabel, @menu_label must be
4021 * specified if the page-switch menu is to be used.
4022 * @position: the index (starting at 0) at which to insert the page,
4023 * or -1 to append the page after all other pages.
4025 * Insert a page into @notebook at the given position, specifying
4026 * the widget to use as the label in the popup menu.
4029 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4031 GtkWidget *tab_label,
4032 GtkWidget *menu_label,
4035 GtkNotebookPage *page;
4038 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4039 g_return_if_fail (GTK_IS_WIDGET (child));
4040 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4041 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4043 gtk_widget_freeze_child_notify (child);
4045 page = g_new (GtkNotebookPage, 1);
4046 page->child = child;
4047 page->last_focus_child = NULL;
4048 page->requisition.width = 0;
4049 page->requisition.height = 0;
4050 page->allocation.x = 0;
4051 page->allocation.y = 0;
4052 page->allocation.width = 0;
4053 page->allocation.height = 0;
4054 page->default_menu = FALSE;
4055 page->default_tab = FALSE;
4056 page->mnemonic_activate_signal = 0;
4058 nchildren = g_list_length (notebook->children);
4059 if ((position < 0) || (position > nchildren))
4060 position = nchildren;
4062 notebook->children = g_list_insert (notebook->children, page, position);
4066 page->default_tab = TRUE;
4067 if (notebook->show_tabs)
4068 tab_label = gtk_label_new ("");
4070 page->tab_label = tab_label;
4071 page->menu_label = menu_label;
4072 page->expand = FALSE;
4074 page->pack = GTK_PACK_START;
4077 page->default_menu = TRUE;
4080 g_object_ref (page->menu_label);
4081 gtk_object_sink (GTK_OBJECT (page->menu_label));
4085 gtk_notebook_menu_item_create (notebook,
4086 g_list_find (notebook->children, page));
4088 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4090 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4092 gtk_notebook_update_labels (notebook);
4094 if (!notebook->first_tab)
4095 notebook->first_tab = notebook->children;
4097 if (!notebook->cur_page)
4098 gtk_widget_set_child_visible (child, TRUE);
4100 gtk_widget_set_child_visible (child, FALSE);
4104 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4105 gtk_widget_show (tab_label);
4107 gtk_widget_hide (tab_label);
4110 if (!notebook->cur_page)
4112 gtk_notebook_switch_page (notebook, page, 0);
4113 gtk_notebook_switch_focus_tab (notebook, NULL);
4116 gtk_notebook_update_tab_states (notebook);
4119 page->mnemonic_activate_signal =
4120 g_signal_connect (tab_label,
4121 "mnemonic_activate",
4122 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4125 gtk_widget_child_notify (child, "tab_expand");
4126 gtk_widget_child_notify (child, "tab_fill");
4127 gtk_widget_child_notify (child, "tab_pack");
4128 gtk_widget_child_notify (child, "tab_label");
4129 gtk_widget_child_notify (child, "menu_label");
4130 gtk_widget_child_notify (child, "position");
4131 gtk_widget_thaw_child_notify (child);
4135 * gtk_notebook_remove_page:
4136 * @notebook: a #GtkNotebook.
4137 * @page_num: the index of a notebook page, starting
4138 * from 0. If -1, the last page will
4141 * Removes a page from the notebook given its index
4145 gtk_notebook_remove_page (GtkNotebook *notebook,
4150 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4154 list = g_list_nth (notebook->children, page_num);
4156 gtk_notebook_real_remove (notebook, list, FALSE);
4160 list = g_list_last (notebook->children);
4162 gtk_notebook_real_remove (notebook, list, FALSE);
4166 /* Public GtkNotebook Page Switch Methods :
4167 * gtk_notebook_get_current_page
4168 * gtk_notebook_page_num
4169 * gtk_notebook_set_current_page
4170 * gtk_notebook_next_page
4171 * gtk_notebook_prev_page
4174 * gtk_notebook_get_current_page:
4175 * @notebook: a #GtkNotebook
4177 * Returns the page number of the current page.
4179 * Return value: the index (starting from 0) of the current
4180 * page in the notebook. If the notebook has no pages, then
4181 * -1 will be returned.
4184 gtk_notebook_get_current_page (GtkNotebook *notebook)
4186 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4188 if (!notebook->cur_page)
4191 return g_list_index (notebook->children, notebook->cur_page);
4195 * gtk_notebook_get_nth_page:
4196 * @notebook: a #GtkNotebook
4197 * @page_num: the index of a page in the noteobok, or -1
4198 * to get the last page.
4200 * Returns the child widget contained in page number @page_num.
4202 * Return value: the child widget, or %NULL if @page_num is
4206 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4209 GtkNotebookPage *page;
4212 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4215 list = g_list_nth (notebook->children, page_num);
4217 list = g_list_last (notebook->children);
4229 * gtk_notebook_get_n_pages:
4230 * @notebook: a #GtkNotebook
4232 * Gets the number of pages in a notebook.
4234 * Return value: the number of pages in the notebook.
4239 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4241 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4243 return g_list_length (notebook->children);
4247 * gtk_notebook_page_num:
4248 * @notebook: a #GtkNotebook
4249 * @child: a #GtkWidget
4251 * Finds the index of the page which contains the given child
4254 * Return value: the index of the page containing @child, or
4255 * -1 if @child is not in the notebook.
4258 gtk_notebook_page_num (GtkNotebook *notebook,
4264 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4267 children = notebook->children;
4270 GtkNotebookPage *page = children->data;
4272 if (page->child == child)
4275 children = children->next;
4283 * gtk_notebook_set_current_page:
4284 * @notebook: a #GtkNotebook
4285 * @page_num: index of the page to switch to, starting from 0.
4286 * If negative, the last page will be used. If greater
4287 * than the number of pages in the notebook, nothing
4290 * Switches to the page number @page_num.
4293 gtk_notebook_set_current_page (GtkNotebook *notebook,
4298 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4301 list = g_list_nth (notebook->children, page_num);
4303 list = g_list_last (notebook->children);
4305 page_num = g_list_index (notebook->children, list);
4308 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4312 * gtk_notebook_next_page:
4313 * @notebook: a #GtkNotebook
4315 * Switches to the next page. Nothing happens if the current page is
4319 gtk_notebook_next_page (GtkNotebook *notebook)
4323 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4325 list = g_list_find (notebook->children, notebook->cur_page);
4329 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4333 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4337 * gtk_notebook_prev_page:
4338 * @notebook: a #GtkNotebook
4340 * Switches to the previous page. Nothing happens if the current page
4341 * is the first page.
4344 gtk_notebook_prev_page (GtkNotebook *notebook)
4348 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4350 list = g_list_find (notebook->children, notebook->cur_page);
4354 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4358 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4361 /* Public GtkNotebook/Tab Style Functions
4363 * gtk_notebook_set_show_border
4364 * gtk_notebook_set_show_tabs
4365 * gtk_notebook_set_tab_pos
4366 * gtk_notebook_set_homogeneous_tabs
4367 * gtk_notebook_set_tab_border
4368 * gtk_notebook_set_tab_hborder
4369 * gtk_notebook_set_tab_vborder
4370 * gtk_notebook_set_scrollable
4373 * gtk_notebook_set_show_border:
4374 * @notebook: a #GtkNotebook
4375 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4377 * Sets whether a bevel will be drawn around the notebook pages.
4378 * This only has a visual effect when the tabs are not shown.
4379 * See gtk_notebook_set_show_tabs().
4382 gtk_notebook_set_show_border (GtkNotebook *notebook,
4383 gboolean show_border)
4385 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4387 if (notebook->show_border != show_border)
4389 notebook->show_border = show_border;
4391 if (GTK_WIDGET_VISIBLE (notebook))
4392 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4394 g_object_notify (G_OBJECT (notebook), "show_border");
4399 * gtk_notebook_get_show_border:
4400 * @notebook: a #GtkNotebook
4402 * Returns whether a bevel will be drawn around the notebook pages. See
4403 * gtk_notebook_set_show_border().
4405 * Return value: %TRUE if the bevel is drawn
4408 gtk_notebook_get_show_border (GtkNotebook *notebook)
4410 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4412 return notebook->show_border;
4416 * gtk_notebook_set_show_tabs:
4417 * @notebook: a #GtkNotebook
4418 * @show_tabs: %TRUE if the tabs should be shown.
4420 * Sets whether to show the tabs for the notebook or not.
4423 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4426 GtkNotebookPage *page;
4429 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4431 show_tabs = show_tabs != FALSE;
4433 if (notebook->show_tabs == show_tabs)
4436 notebook->show_tabs = show_tabs;
4437 children = notebook->children;
4441 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4445 page = children->data;
4446 children = children->next;
4447 if (page->default_tab)
4449 gtk_widget_destroy (page->tab_label);
4450 page->tab_label = NULL;
4453 gtk_widget_hide (page->tab_label);
4458 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4459 gtk_notebook_update_labels (notebook);
4461 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4463 g_object_notify (G_OBJECT (notebook), "show_tabs");
4467 * gtk_notebook_get_show_tabs:
4468 * @notebook: a #GtkNotebook
4470 * Returns whether the tabs of the notebook are shown. See
4471 * gtk_notebook_set_show_tabs().
4473 * Return value: %TRUE if the tabs are shown
4476 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4478 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4480 return notebook->show_tabs;
4484 * gtk_notebook_set_tab_pos:
4485 * @notebook: a #GtkNotebook.
4486 * @pos: the edge to draw the tabs at.
4488 * Sets the edge at which the tabs for switching pages in the
4489 * notebook are drawn.
4492 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4493 GtkPositionType pos)
4495 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4497 if (notebook->tab_pos != pos)
4499 notebook->tab_pos = pos;
4500 if (GTK_WIDGET_VISIBLE (notebook))
4501 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4504 g_object_notify (G_OBJECT (notebook), "tab_pos");
4508 * gtk_notebook_get_tab_pos:
4509 * @notebook: a #GtkNotebook
4511 * Gets the edge at which the tabs for switching pages in the
4512 * notebook are drawn.
4514 * Return value: the edge at which the tabs are drawn
4517 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4519 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4521 return notebook->tab_pos;
4525 * gtk_notebook_set_homogeneous_tabs:
4526 * @notebook: a #GtkNotebook
4527 * @homogeneous: %TRUE if all tabs should be the same size.
4529 * Sets whether the tabs must have all the same size or not.
4532 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4533 gboolean homogeneous)
4535 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4537 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4541 * gtk_notebook_set_tab_border:
4542 * @notebook: a #GtkNotebook
4543 * @border_width: width of the border around the tab labels.
4545 * Sets the width the border around the tab labels
4546 * in a notebook. This is equivalent to calling
4547 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4548 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4551 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4554 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4556 gtk_notebook_set_tab_border_internal (notebook, border_width);
4560 * gtk_notebook_set_tab_hborder:
4561 * @notebook: a #GtkNotebook
4562 * @tab_hborder: width of the horizontal border of tab labels.
4564 * Sets the width of the horizontal border of tab labels.
4567 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4570 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4572 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4576 * gtk_notebook_set_tab_vborder:
4577 * @notebook: a #GtkNotebook
4578 * @tab_vborder: width of the vertical border of tab labels.
4580 * Sets the width of the vertical border of tab labels.
4583 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4586 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4588 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4592 * gtk_notebook_set_scrollable:
4593 * @notebook: a #GtkNotebook
4594 * @scrollable: %TRUE if scroll arrows should be added
4596 * Sets whether the tab label area will have arrows for scrolling if
4597 * there are too many tabs to fit in the area.
4600 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4601 gboolean scrollable)
4603 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4605 scrollable = (scrollable != FALSE);
4607 if (scrollable != notebook->scrollable)
4609 notebook->scrollable = scrollable;
4611 if (GTK_WIDGET_VISIBLE (notebook))
4612 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4614 g_object_notify (G_OBJECT (notebook), "scrollable");
4619 * gtk_notebook_get_scrollable:
4620 * @notebook: a #GtkNotebook
4622 * Returns whether the tab label area has arrows for scrolling. See
4623 * gtk_notebook_set_scrollable().
4625 * Return value: %TRUE if arrows for scrolling are present
4628 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4630 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4632 return notebook->scrollable;
4635 /* Public GtkNotebook Popup Menu Methods:
4637 * gtk_notebook_popup_enable
4638 * gtk_notebook_popup_disable
4643 * gtk_notebook_popup_enable:
4644 * @notebook: a #GtkNotebook
4646 * Enables the popup menu: if the user clicks with the right mouse button on
4647 * the bookmarks, a menu with all the pages will be popped up.
4650 gtk_notebook_popup_enable (GtkNotebook *notebook)
4654 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4659 notebook->menu = gtk_menu_new ();
4660 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4662 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4663 gtk_notebook_menu_item_create (notebook, list);
4665 gtk_notebook_update_labels (notebook);
4666 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4667 GTK_WIDGET (notebook),
4668 gtk_notebook_menu_detacher);
4670 g_object_notify (G_OBJECT (notebook), "enable_popup");
4674 * gtk_notebook_popup_disable:
4675 * @notebook: a #GtkNotebook
4677 * Disables the popup menu.
4680 gtk_notebook_popup_disable (GtkNotebook *notebook)
4682 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4684 if (!notebook->menu)
4687 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4688 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4689 gtk_widget_destroy (notebook->menu);
4691 g_object_notify (G_OBJECT (notebook), "enable_popup");
4694 /* Public GtkNotebook Page Properties Functions:
4696 * gtk_notebook_get_tab_label
4697 * gtk_notebook_set_tab_label
4698 * gtk_notebook_set_tab_label_text
4699 * gtk_notebook_get_menu_label
4700 * gtk_notebook_set_menu_label
4701 * gtk_notebook_set_menu_label_text
4702 * gtk_notebook_set_tab_label_packing
4703 * gtk_notebook_query_tab_label_packing
4707 * gtk_notebook_get_tab_label:
4708 * @notebook: a #GtkNotebook
4711 * Returns the tab label widget for the page @child. %NULL is returned
4712 * if @child is not in @notebook or if no tab label has specifically
4713 * been set for @child.
4715 * Return value: the tab label
4718 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4723 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4724 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4726 list = CHECK_FIND_CHILD (notebook, child);
4730 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4733 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4737 * gtk_notebook_set_tab_label:
4738 * @notebook: a #GtkNotebook
4740 * @tab_label: the tab label widget to use, or %NULL for default tab
4743 * Changes the tab label for @child. If %NULL is specified
4744 * for @tab_label, then the page will have the label 'page N'.
4747 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4749 GtkWidget *tab_label)
4751 GtkNotebookPage *page;
4754 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4755 g_return_if_fail (GTK_IS_WIDGET (child));
4757 list = CHECK_FIND_CHILD (notebook, child);
4761 /* a NULL pointer indicates a default_tab setting, otherwise
4762 * we need to set the associated label
4766 if (page->tab_label == tab_label)
4770 gtk_notebook_remove_tab_label (notebook, page);
4774 page->default_tab = FALSE;
4775 page->tab_label = tab_label;
4776 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4780 page->default_tab = TRUE;
4781 page->tab_label = NULL;
4783 if (notebook->show_tabs)
4787 g_snprintf (string, sizeof(string), _("Page %u"),
4788 gtk_notebook_real_page_position (notebook, list));
4789 page->tab_label = gtk_label_new (string);
4790 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4794 if (page->tab_label)
4795 page->mnemonic_activate_signal =
4796 g_signal_connect (page->tab_label,
4797 "mnemonic_activate",
4798 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4801 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4803 gtk_widget_show (page->tab_label);
4804 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4807 gtk_notebook_update_tab_states (notebook);
4808 gtk_widget_child_notify (child, "tab_label");
4812 * gtk_notebook_set_tab_label_text:
4813 * @notebook: a #GtkNotebook
4815 * @tab_text: the label text
4817 * Creates a new label and sets it as the tab label for the page
4818 * containing @child.
4821 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4823 const gchar *tab_text)
4825 GtkWidget *tab_label = NULL;
4827 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4830 tab_label = gtk_label_new (tab_text);
4831 gtk_notebook_set_tab_label (notebook, child, tab_label);
4832 gtk_widget_child_notify (child, "tab_label");
4836 * gtk_notebook_get_tab_label_text:
4837 * @notebook: a #GtkNotebook
4838 * @child: a widget contained in a page of @notebook
4840 * Retrieves the text of the tab label for the page containing
4843 * Returns value: the text of the tab label, or %NULL if the
4844 * tab label widget is not a #GtkLabel. The
4845 * string is owned by the widget and must not
4848 G_CONST_RETURN gchar *
4849 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4852 GtkWidget *tab_label;
4854 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4855 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4857 tab_label = gtk_notebook_get_tab_label (notebook, child);
4859 if (tab_label && GTK_IS_LABEL (tab_label))
4860 return gtk_label_get_text (GTK_LABEL (tab_label));
4866 * gtk_notebook_get_menu_label:
4867 * @notebook: a #GtkNotebook
4868 * @child: a widget contained in a page of @notebook
4870 * Retrieves the menu label widget of the page containing @child.
4872 * Return value: the menu label, or %NULL if the
4873 * notebook page does not have a menu label other
4874 * than the default (the tab label).
4877 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4882 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4883 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4885 list = CHECK_FIND_CHILD (notebook, child);
4889 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4892 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4896 * gtk_notebook_set_menu_label:
4897 * @notebook: a #GtkNotebook
4898 * @child: the child widget
4899 * @menu_label: the menu label, or NULL for default
4901 * Changes the menu label for the page containing @child.
4904 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4906 GtkWidget *menu_label)
4908 GtkNotebookPage *page;
4911 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4912 g_return_if_fail (GTK_IS_WIDGET (child));
4914 list = CHECK_FIND_CHILD (notebook, child);
4919 if (page->menu_label)
4922 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4923 page->menu_label->parent);
4925 if (!page->default_menu)
4926 g_object_unref (page->menu_label);
4931 page->menu_label = menu_label;
4932 g_object_ref (page->menu_label);
4933 gtk_object_sink (GTK_OBJECT(page->menu_label));
4934 page->default_menu = FALSE;
4937 page->default_menu = TRUE;
4940 gtk_notebook_menu_item_create (notebook, list);
4941 gtk_widget_child_notify (child, "menu_label");
4945 * gtk_notebook_set_menu_label_text:
4946 * @notebook: a #GtkNotebook
4947 * @child: the child widget
4948 * @menu_text: the label text
4950 * Creates a new label and sets it as the menu label of @child.
4953 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4955 const gchar *menu_text)
4957 GtkWidget *menu_label = NULL;
4959 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4962 menu_label = gtk_label_new (menu_text);
4963 gtk_notebook_set_menu_label (notebook, child, menu_label);
4964 gtk_widget_child_notify (child, "menu_label");
4968 * gtk_notebook_get_menu_label_text:
4969 * @notebook: a #GtkNotebook
4970 * @child: the child widget of a page of the notebook.
4972 * Retrieves the text of the menu label for the page containing
4975 * Returns value: the text of the tab label, or %NULL if the
4976 * widget does not have a menu label other than
4977 * the default menu label, or the menu label widget
4978 * is not a #GtkLabel. The string is owned by
4979 * the widget and must not be freed.
4981 G_CONST_RETURN gchar *
4982 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4985 GtkWidget *menu_label;
4987 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4988 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4990 menu_label = gtk_notebook_get_menu_label (notebook, child);
4992 if (menu_label && GTK_IS_LABEL (menu_label))
4993 return gtk_label_get_text (GTK_LABEL (menu_label));
4998 /* Helper function called when pages are reordered
5001 gtk_notebook_child_reordered (GtkNotebook *notebook,
5002 GtkNotebookPage *page)
5006 GtkWidget *menu_item;
5008 menu_item = page->menu_label->parent;
5009 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5010 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5011 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5014 gtk_notebook_update_tab_states (notebook);
5015 gtk_notebook_update_labels (notebook);
5019 * gtk_notebook_set_tab_label_packing:
5020 * @notebook: a #GtkNotebook
5021 * @child: the child widget
5022 * @expand: whether to expand the bookmark or not
5023 * @fill: whether the bookmark should fill the allocated area or not
5024 * @pack_type: the position of the bookmark
5026 * Sets the packing parameters for the tab label of the page
5027 * containing @child. See gtk_box_pack_start() for the exact meaning
5028 * of the parameters.
5031 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5035 GtkPackType pack_type)
5037 GtkNotebookPage *page;
5040 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5041 g_return_if_fail (GTK_IS_WIDGET (child));
5043 list = CHECK_FIND_CHILD (notebook, child);
5048 expand = expand != FALSE;
5049 fill = fill != FALSE;
5050 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5053 gtk_widget_freeze_child_notify (child);
5054 page->expand = expand;
5055 gtk_widget_child_notify (child, "tab_expand");
5057 gtk_widget_child_notify (child, "tab_fill");
5058 if (page->pack != pack_type)
5060 page->pack = pack_type;
5061 gtk_notebook_child_reordered (notebook, page);
5063 gtk_widget_child_notify (child, "tab_pack");
5064 gtk_widget_child_notify (child, "position");
5065 if (notebook->show_tabs)
5066 gtk_notebook_pages_allocate (notebook);
5067 gtk_widget_thaw_child_notify (child);
5071 * gtk_notebook_query_tab_label_packing:
5072 * @notebook: a #GtkNotebook
5074 * @expand: location to store the expand value (or NULL)
5075 * @fill: location to store the fill value (or NULL)
5076 * @pack_type: location to store the pack_type (or NULL)
5078 * Query the packing attributes for the tab label of the page
5079 * containing @child.
5082 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5086 GtkPackType *pack_type)
5090 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5091 g_return_if_fail (GTK_IS_WIDGET (child));
5093 list = CHECK_FIND_CHILD (notebook, child);
5098 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5100 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5102 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5106 * gtk_notebook_reorder_child:
5107 * @notebook: a #GtkNotebook
5108 * @child: the child to move
5109 * @position: the new position, or -1 to move to the end
5111 * Reorders the page containing @child, so that it appears in position
5112 * @position. If @position is greater than or equal to the number of
5113 * children in the list or negative, @child will be moved to the end
5117 gtk_notebook_reorder_child (GtkNotebook *notebook,
5121 GList *list, *new_list;
5122 GtkNotebookPage *page;
5126 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5127 g_return_if_fail (GTK_IS_WIDGET (child));
5129 list = CHECK_FIND_CHILD (notebook, child);
5133 max_pos = g_list_length (notebook->children) - 1;
5134 if (position < 0 || position > max_pos)
5137 old_pos = g_list_position (notebook->children, list);
5139 if (old_pos == position)
5143 notebook->children = g_list_delete_link (notebook->children, list);
5145 notebook->children = g_list_insert (notebook->children, page, position);
5146 new_list = g_list_nth (notebook->children, position);
5148 /* Fix up GList references in GtkNotebook structure */
5149 if (notebook->first_tab == list)
5150 notebook->first_tab = new_list;
5151 if (notebook->focus_tab == list)
5152 notebook->focus_tab = new_list;
5154 gtk_widget_freeze_child_notify (child);
5156 /* Move around the menu items if necesary */
5157 gtk_notebook_child_reordered (notebook, page);
5158 gtk_widget_child_notify (child, "tab_pack");
5159 gtk_widget_child_notify (child, "position");
5161 if (notebook->show_tabs)
5162 gtk_notebook_pages_allocate (notebook);
5164 gtk_widget_thaw_child_notify (child);