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_focus_changed (GtkNotebook *notebook,
192 GtkNotebookPage *old_page);
193 static void gtk_notebook_real_remove (GtkNotebook *notebook,
195 static void gtk_notebook_update_labels (GtkNotebook *notebook);
196 static gint gtk_notebook_timer (GtkNotebook *notebook);
197 static gint gtk_notebook_page_compare (gconstpointer a,
199 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
201 const gchar *function);
202 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
204 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
207 gboolean find_visible);
209 /*** GtkNotebook Drawing Functions ***/
210 static void gtk_notebook_paint (GtkWidget *widget,
212 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
213 GtkNotebookPage *page,
215 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
218 /*** GtkNotebook Size Allocate Functions ***/
219 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
220 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
221 GtkNotebookPage *page,
222 GtkAllocation *allocation);
223 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
229 /*** GtkNotebook Page Switch Methods ***/
230 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
231 GtkNotebookPage *page,
234 /*** GtkNotebook Page Switch Functions ***/
235 static void gtk_notebook_switch_page (GtkNotebook *notebook,
236 GtkNotebookPage *page,
238 static gint gtk_notebook_page_select (GtkNotebook *notebook,
239 gboolean move_focus);
240 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
242 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
243 GtkNotebookPage *page);
245 /*** GtkNotebook Menu Functions ***/
246 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
248 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
250 static void gtk_notebook_menu_detacher (GtkWidget *widget,
253 static gboolean focus_tabs_in (GtkNotebook *notebook);
254 static gboolean focus_child_in (GtkNotebook *notebook,
255 GtkDirectionType direction);
257 static GtkContainerClass *parent_class = NULL;
258 static guint notebook_signals[LAST_SIGNAL] = { 0 };
261 gtk_notebook_get_type (void)
263 static GType notebook_type = 0;
267 static const GTypeInfo notebook_info =
269 sizeof (GtkNotebookClass),
270 NULL, /* base_init */
271 NULL, /* base_finalize */
272 (GClassInitFunc) gtk_notebook_class_init,
273 NULL, /* class_finalize */
274 NULL, /* class_data */
275 sizeof (GtkNotebook),
277 (GInstanceInitFunc) gtk_notebook_init,
280 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
284 return notebook_type;
288 add_tab_bindings (GtkBindingSet *binding_set,
289 GdkModifierType modifiers,
290 GtkDirectionType direction)
292 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
294 GTK_TYPE_DIRECTION_TYPE, direction);
295 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
297 GTK_TYPE_DIRECTION_TYPE, direction);
301 add_arrow_bindings (GtkBindingSet *binding_set,
303 GtkDirectionType direction)
305 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
307 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
309 GTK_TYPE_DIRECTION_TYPE, direction);
310 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
312 GTK_TYPE_DIRECTION_TYPE, direction);
316 gtk_notebook_class_init (GtkNotebookClass *class)
318 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
319 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
320 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
321 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
322 GtkBindingSet *binding_set;
324 parent_class = g_type_class_peek_parent (class);
326 gobject_class->set_property = gtk_notebook_set_property;
327 gobject_class->get_property = gtk_notebook_get_property;
328 object_class->destroy = gtk_notebook_destroy;
330 widget_class->map = gtk_notebook_map;
331 widget_class->unmap = gtk_notebook_unmap;
332 widget_class->realize = gtk_notebook_realize;
333 widget_class->unrealize = gtk_notebook_unrealize;
334 widget_class->size_request = gtk_notebook_size_request;
335 widget_class->size_allocate = gtk_notebook_size_allocate;
336 widget_class->expose_event = gtk_notebook_expose;
337 widget_class->button_press_event = gtk_notebook_button_press;
338 widget_class->button_release_event = gtk_notebook_button_release;
339 widget_class->enter_notify_event = gtk_notebook_enter_notify;
340 widget_class->leave_notify_event = gtk_notebook_leave_notify;
341 widget_class->motion_notify_event = gtk_notebook_motion_notify;
342 widget_class->focus_in_event = gtk_notebook_focus_in;
343 widget_class->focus = gtk_notebook_focus;
345 container_class->add = gtk_notebook_add;
346 container_class->remove = gtk_notebook_remove;
347 container_class->forall = gtk_notebook_forall;
348 container_class->set_focus_child = gtk_notebook_set_focus_child;
349 container_class->get_child_property = gtk_notebook_get_child_property;
350 container_class->set_child_property = gtk_notebook_set_child_property;
351 container_class->child_type = gtk_notebook_child_type;
353 class->switch_page = gtk_notebook_real_switch_page;
355 class->focus_tab = gtk_notebook_focus_tab;
356 class->select_page = gtk_notebook_select_page;
357 class->change_current_page = gtk_notebook_change_current_page;
358 class->move_focus_out = gtk_notebook_move_focus_out;
360 g_object_class_install_property (gobject_class,
362 g_param_spec_int ("page",
364 _("The index of the current page"),
369 g_object_class_install_property (gobject_class,
371 g_param_spec_enum ("tab_pos",
373 _("Which side of the notebook holds the tabs"),
374 GTK_TYPE_POSITION_TYPE,
377 g_object_class_install_property (gobject_class,
379 g_param_spec_uint ("tab_border",
381 _("Width of the border around the tab labels"),
386 g_object_class_install_property (gobject_class,
388 g_param_spec_uint ("tab_hborder",
389 _("Horizontal Tab Border"),
390 _("Width of the horizontal border of tab labels"),
395 g_object_class_install_property (gobject_class,
397 g_param_spec_uint ("tab_vborder",
398 _("Vertical Tab Border"),
399 _("Width of the vertical border of tab labels"),
404 g_object_class_install_property (gobject_class,
406 g_param_spec_boolean ("show_tabs",
408 _("Whether tabs should be shown or not"),
411 g_object_class_install_property (gobject_class,
413 g_param_spec_boolean ("show_border",
415 _("Whether the border should be shown or not"),
418 g_object_class_install_property (gobject_class,
420 g_param_spec_boolean ("scrollable",
422 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
425 g_object_class_install_property (gobject_class,
427 g_param_spec_boolean ("enable_popup",
429 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
432 g_object_class_install_property (gobject_class,
434 g_param_spec_boolean ("homogeneous",
436 _("Whether tabs should have homogeneous sizes"),
440 gtk_container_class_install_child_property (container_class,
441 CHILD_PROP_TAB_LABEL,
442 g_param_spec_string ("tab_label",
444 _("The string displayed on the childs tab label"),
447 gtk_container_class_install_child_property (container_class,
448 CHILD_PROP_MENU_LABEL,
449 g_param_spec_string ("menu_label",
451 _("The string displayed in the childs menu entry"),
454 gtk_container_class_install_child_property (container_class,
456 g_param_spec_int ("position",
458 _("The index of the child in the parent"),
461 gtk_container_class_install_child_property (container_class,
462 CHILD_PROP_TAB_EXPAND,
463 g_param_spec_boolean ("tab_expand",
465 _("Whether to expand the childs tab or not"),
468 gtk_container_class_install_child_property (container_class,
470 g_param_spec_boolean ("tab_fill",
472 _("Wheather the childs tab should fill the allocated area or not"),
475 gtk_container_class_install_child_property (container_class,
477 g_param_spec_enum ("tab_pack",
479 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
480 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
483 notebook_signals[SWITCH_PAGE] =
484 g_signal_new ("switch_page",
485 G_TYPE_FROM_CLASS (gobject_class),
487 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
489 _gtk_marshal_VOID__POINTER_UINT,
493 notebook_signals[FOCUS_TAB] =
494 g_signal_new ("focus_tab",
495 G_TYPE_FROM_CLASS (gobject_class),
496 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
497 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
499 _gtk_marshal_BOOLEAN__ENUM,
501 GTK_TYPE_NOTEBOOK_TAB);
502 notebook_signals[SELECT_PAGE] =
503 g_signal_new ("select_page",
504 G_TYPE_FROM_CLASS (gobject_class),
505 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
506 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
508 _gtk_marshal_BOOLEAN__BOOLEAN,
511 notebook_signals[CHANGE_CURRENT_PAGE] =
512 g_signal_new ("change_current_page",
513 G_TYPE_FROM_CLASS (gobject_class),
514 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
515 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
517 _gtk_marshal_VOID__INT,
520 notebook_signals[MOVE_FOCUS_OUT] =
521 g_signal_new ("move_focus_out",
522 G_TYPE_FROM_CLASS (gobject_class),
523 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
524 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
526 _gtk_marshal_VOID__ENUM,
528 GTK_TYPE_DIRECTION_TYPE);
531 binding_set = gtk_binding_set_by_class (class);
532 gtk_binding_entry_add_signal (binding_set,
535 G_TYPE_BOOLEAN, FALSE);
536 gtk_binding_entry_add_signal (binding_set,
539 G_TYPE_BOOLEAN, FALSE);
541 gtk_binding_entry_add_signal (binding_set,
544 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
545 gtk_binding_entry_add_signal (binding_set,
548 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
549 gtk_binding_entry_add_signal (binding_set,
552 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
553 gtk_binding_entry_add_signal (binding_set,
556 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
558 gtk_binding_entry_add_signal (binding_set,
559 GDK_Page_Up, GDK_CONTROL_MASK,
560 "change_current_page", 1,
562 gtk_binding_entry_add_signal (binding_set,
563 GDK_Page_Down, GDK_CONTROL_MASK,
564 "change_current_page", 1,
567 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
568 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
569 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
570 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
572 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
573 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
577 gtk_notebook_init (GtkNotebook *notebook)
579 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
580 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
582 notebook->cur_page = NULL;
583 notebook->children = NULL;
584 notebook->first_tab = NULL;
585 notebook->focus_tab = NULL;
586 notebook->event_window = NULL;
587 notebook->menu = NULL;
589 notebook->tab_hborder = 2;
590 notebook->tab_vborder = 2;
592 notebook->show_tabs = TRUE;
593 notebook->show_border = TRUE;
594 notebook->tab_pos = GTK_POS_TOP;
595 notebook->scrollable = FALSE;
596 notebook->in_child = 0;
597 notebook->click_child = 0;
598 notebook->button = 0;
599 notebook->need_timer = 0;
600 notebook->child_has_focus = FALSE;
601 notebook->have_visible_child = FALSE;
602 notebook->focus_out = FALSE;
606 gtk_notebook_select_page (GtkNotebook *notebook,
609 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
611 gtk_notebook_page_select (notebook, move_focus);
619 gtk_notebook_focus_tab (GtkNotebook *notebook,
624 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
628 case GTK_NOTEBOOK_TAB_FIRST:
629 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
631 gtk_notebook_switch_focus_tab (notebook, list);
633 case GTK_NOTEBOOK_TAB_LAST:
634 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
636 gtk_notebook_switch_focus_tab (notebook, list);
647 gtk_notebook_change_current_page (GtkNotebook *notebook,
650 GList *current = NULL;
652 if (notebook->cur_page)
653 current = g_list_find (notebook->children, notebook->cur_page);
657 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
658 offset += offset < 0 ? 1 : -1;
662 gtk_notebook_switch_page (notebook, current->data, -1);
664 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
667 static GtkDirectionType
668 get_effective_direction (GtkNotebook *notebook,
669 GtkDirectionType direction)
671 /* Remap the directions into the effective direction it would be for a
672 * GTK_POS_TOP notebook
674 #define D(rest) GTK_DIR_##rest
676 static const GtkDirectionType translate_direction[4][6] = {
677 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
678 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
679 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
680 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
685 return translate_direction[notebook->tab_pos][direction];
689 gtk_notebook_move_focus_out (GtkNotebook *notebook,
690 GtkDirectionType direction_type)
692 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
695 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
696 if (focus_tabs_in (notebook))
699 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
700 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
703 /* At this point, we know we should be focusing out of the notebook entirely. We
704 * do this by setting a flag, then propagating the focus motion to the notebook.
706 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
707 if (!GTK_WIDGET_TOPLEVEL (toplevel))
710 g_object_ref (notebook);
712 notebook->focus_out = TRUE;
713 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
714 notebook->focus_out = FALSE;
716 g_object_unref (notebook);
723 * Creates a new #GtkNotebook widget with no pages.
725 * Return value: the newly created #GtkNotebook
728 gtk_notebook_new (void)
730 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
733 /* Private GtkObject Methods :
735 * gtk_notebook_destroy
736 * gtk_notebook_set_arg
737 * gtk_notebook_get_arg
740 gtk_notebook_destroy (GtkObject *object)
742 GtkNotebook *notebook = GTK_NOTEBOOK (object);
745 gtk_notebook_popup_disable (notebook);
747 GTK_OBJECT_CLASS (parent_class)->destroy (object);
751 gtk_notebook_set_property (GObject *object,
756 GtkNotebook *notebook;
758 notebook = GTK_NOTEBOOK (object);
763 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
765 case PROP_SHOW_BORDER:
766 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
768 case PROP_SCROLLABLE:
769 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
771 case PROP_ENABLE_POPUP:
772 if (g_value_get_boolean (value))
773 gtk_notebook_popup_enable (notebook);
775 gtk_notebook_popup_disable (notebook);
777 case PROP_HOMOGENEOUS:
778 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
781 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
784 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
786 case PROP_TAB_BORDER:
787 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
789 case PROP_TAB_HBORDER:
790 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
792 case PROP_TAB_VBORDER:
793 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
801 gtk_notebook_get_property (GObject *object,
806 GtkNotebook *notebook;
808 notebook = GTK_NOTEBOOK (object);
813 g_value_set_boolean (value, notebook->show_tabs);
815 case PROP_SHOW_BORDER:
816 g_value_set_boolean (value, notebook->show_border);
818 case PROP_SCROLLABLE:
819 g_value_set_boolean (value, notebook->scrollable);
821 case PROP_ENABLE_POPUP:
822 g_value_set_boolean (value, notebook->menu != NULL);
824 case PROP_HOMOGENEOUS:
825 g_value_set_boolean (value, notebook->homogeneous);
828 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
831 g_value_set_enum (value, notebook->tab_pos);
833 case PROP_TAB_HBORDER:
834 g_value_set_uint (value, notebook->tab_hborder);
836 case PROP_TAB_VBORDER:
837 g_value_set_uint (value, notebook->tab_vborder);
840 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
845 /* Private GtkWidget Methods :
849 * gtk_notebook_realize
850 * gtk_notebook_size_request
851 * gtk_notebook_size_allocate
852 * gtk_notebook_expose
853 * gtk_notebook_button_press
854 * gtk_notebook_button_release
855 * gtk_notebook_enter_notify
856 * gtk_notebook_leave_notify
857 * gtk_notebook_motion_notify
858 * gtk_notebook_focus_in
859 * gtk_notebook_focus_out
860 * gtk_notebook_draw_focus
861 * gtk_notebook_style_set
864 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
865 GdkRectangle *rectangle)
867 GtkWidget *widget = GTK_WIDGET (notebook);
868 gint border_width = GTK_CONTAINER (notebook)->border_width;
869 GtkNotebookPage *visible_page = NULL;
872 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
874 GtkNotebookPage *page = tmp_list->data;
875 if (GTK_WIDGET_VISIBLE (page->child))
882 if (notebook->show_tabs && visible_page)
886 rectangle->x = widget->allocation.x + border_width;
887 rectangle->y = widget->allocation.y + border_width;
889 switch (notebook->tab_pos)
893 rectangle->width = widget->allocation.width - 2 * border_width;
894 rectangle->height = visible_page->requisition.height;
895 if (notebook->tab_pos == GTK_POS_BOTTOM)
896 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
900 rectangle->width = visible_page->requisition.width;
901 rectangle->height = widget->allocation.height - 2 * border_width;
902 if (notebook->tab_pos == GTK_POS_RIGHT)
903 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
914 rectangle->x = rectangle->y = 0;
915 rectangle->width = rectangle->height = 10;
923 gtk_notebook_map (GtkWidget *widget)
925 GtkNotebook *notebook;
926 GtkNotebookPage *page;
929 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
931 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
933 notebook = GTK_NOTEBOOK (widget);
935 if (notebook->cur_page &&
936 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
937 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
938 gtk_widget_map (notebook->cur_page->child);
940 if (notebook->scrollable)
941 gtk_notebook_pages_allocate (notebook);
944 children = notebook->children;
948 page = children->data;
949 children = children->next;
951 if (page->tab_label &&
952 GTK_WIDGET_VISIBLE (page->tab_label) &&
953 !GTK_WIDGET_MAPPED (page->tab_label))
954 gtk_widget_map (page->tab_label);
958 if (gtk_notebook_get_event_window_position (notebook, NULL))
959 gdk_window_show_unraised (notebook->event_window);
963 gtk_notebook_unmap (GtkWidget *widget)
965 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
967 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
969 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
971 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
975 gtk_notebook_realize (GtkWidget *widget)
977 GtkNotebook *notebook;
978 GdkWindowAttr attributes;
979 gint attributes_mask;
980 GdkRectangle event_window_pos;
982 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
984 notebook = GTK_NOTEBOOK (widget);
985 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
987 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
989 widget->window = gtk_widget_get_parent_window (widget);
990 g_object_ref (widget->window);
992 attributes.window_type = GDK_WINDOW_CHILD;
993 attributes.x = event_window_pos.x;
994 attributes.y = event_window_pos.y;
995 attributes.width = event_window_pos.width;
996 attributes.height = event_window_pos.height;
997 attributes.wclass = GDK_INPUT_ONLY;
998 attributes.event_mask = gtk_widget_get_events (widget);
999 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
1000 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1002 attributes_mask = GDK_WA_X | GDK_WA_Y;
1004 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1005 &attributes, attributes_mask);
1006 gdk_window_set_user_data (notebook->event_window, notebook);
1008 widget->style = gtk_style_attach (widget->style, widget->window);
1012 gtk_notebook_unrealize (GtkWidget *widget)
1014 GtkNotebook *notebook;
1016 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1018 notebook = GTK_NOTEBOOK (widget);
1020 gdk_window_set_user_data (notebook->event_window, NULL);
1021 gdk_window_destroy (notebook->event_window);
1022 notebook->event_window = NULL;
1024 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1025 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1029 gtk_notebook_size_request (GtkWidget *widget,
1030 GtkRequisition *requisition)
1032 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1033 GtkNotebookPage *page;
1035 GtkRequisition child_requisition;
1036 gboolean switch_page = FALSE;
1040 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1042 widget->requisition.width = 0;
1043 widget->requisition.height = 0;
1045 for (children = notebook->children, vis_pages = 0; children;
1046 children = children->next)
1048 page = children->data;
1050 if (GTK_WIDGET_VISIBLE (page->child))
1053 gtk_widget_size_request (page->child, &child_requisition);
1055 widget->requisition.width = MAX (widget->requisition.width,
1056 child_requisition.width);
1057 widget->requisition.height = MAX (widget->requisition.height,
1058 child_requisition.height);
1060 if (notebook->menu && page->menu_label->parent &&
1061 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1062 gtk_widget_show (page->menu_label->parent);
1066 if (page == notebook->cur_page)
1068 if (notebook->menu && page->menu_label->parent &&
1069 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1070 gtk_widget_hide (page->menu_label->parent);
1074 if (notebook->show_border || notebook->show_tabs)
1076 widget->requisition.width += widget->style->xthickness * 2;
1077 widget->requisition.height += widget->style->ythickness * 2;
1079 if (notebook->show_tabs)
1082 gint tab_height = 0;
1086 for (children = notebook->children; children;
1087 children = children->next)
1089 page = children->data;
1091 if (GTK_WIDGET_VISIBLE (page->child))
1093 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1094 gtk_widget_show (page->tab_label);
1096 gtk_widget_size_request (page->tab_label,
1097 &child_requisition);
1099 page->requisition.width =
1100 child_requisition.width +
1101 2 * widget->style->xthickness;
1102 page->requisition.height =
1103 child_requisition.height +
1104 2 * widget->style->ythickness;
1106 switch (notebook->tab_pos)
1109 case GTK_POS_BOTTOM:
1110 page->requisition.height += 2 * (notebook->tab_vborder +
1112 tab_height = MAX (tab_height, page->requisition.height);
1113 tab_max = MAX (tab_max, page->requisition.width);
1117 page->requisition.width += 2 * (notebook->tab_hborder +
1119 tab_width = MAX (tab_width, page->requisition.width);
1120 tab_max = MAX (tab_max, page->requisition.height);
1124 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1125 gtk_widget_hide (page->tab_label);
1128 children = notebook->children;
1132 switch (notebook->tab_pos)
1135 case GTK_POS_BOTTOM:
1136 if (tab_height == 0)
1139 if (notebook->scrollable && vis_pages > 1 &&
1140 widget->requisition.width < tab_width)
1141 tab_height = MAX (tab_height, ARROW_SIZE);
1143 padding = 2 * (TAB_CURVATURE + focus_width +
1144 notebook->tab_hborder) - TAB_OVERLAP;
1148 page = children->data;
1149 children = children->next;
1151 if (!GTK_WIDGET_VISIBLE (page->child))
1154 if (notebook->homogeneous)
1155 page->requisition.width = tab_max;
1157 page->requisition.width += padding;
1159 tab_width += page->requisition.width;
1160 page->requisition.height = tab_height;
1163 if (notebook->scrollable && vis_pages > 1 &&
1164 widget->requisition.width < tab_width)
1165 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1167 if (notebook->homogeneous && !notebook->scrollable)
1168 widget->requisition.width = MAX (widget->requisition.width,
1169 vis_pages * tab_max +
1172 widget->requisition.width = MAX (widget->requisition.width,
1173 tab_width + TAB_OVERLAP);
1175 widget->requisition.height += tab_height;
1182 if (notebook->scrollable && vis_pages > 1 &&
1183 widget->requisition.height < tab_height)
1184 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1186 padding = 2 * (TAB_CURVATURE + focus_width +
1187 notebook->tab_vborder) - TAB_OVERLAP;
1192 page = children->data;
1193 children = children->next;
1195 if (!GTK_WIDGET_VISIBLE (page->child))
1198 page->requisition.width = tab_width;
1200 if (notebook->homogeneous)
1201 page->requisition.height = tab_max;
1203 page->requisition.height += padding;
1205 tab_height += page->requisition.height;
1208 if (notebook->scrollable && vis_pages > 1 &&
1209 widget->requisition.height < tab_height)
1210 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1212 widget->requisition.width += tab_width;
1214 if (notebook->homogeneous && !notebook->scrollable)
1215 widget->requisition.height =
1216 MAX (widget->requisition.height,
1217 vis_pages * tab_max + TAB_OVERLAP);
1219 widget->requisition.height =
1220 MAX (widget->requisition.height,
1221 tab_height + TAB_OVERLAP);
1223 if (!notebook->homogeneous || notebook->scrollable)
1225 widget->requisition.height = MAX (widget->requisition.height,
1226 vis_pages * tab_max +
1234 for (children = notebook->children; children;
1235 children = children->next)
1237 page = children->data;
1239 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1240 gtk_widget_hide (page->tab_label);
1245 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1246 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1252 for (children = notebook->children; children;
1253 children = children->next)
1255 page = children->data;
1256 if (GTK_WIDGET_VISIBLE (page->child))
1258 gtk_notebook_switch_page (notebook, page, -1);
1263 else if (GTK_WIDGET_VISIBLE (widget))
1265 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1266 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1269 if (vis_pages && !notebook->cur_page)
1271 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1274 notebook->first_tab = children;
1275 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1281 gtk_notebook_size_allocate (GtkWidget *widget,
1282 GtkAllocation *allocation)
1284 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1287 widget->allocation = *allocation;
1288 if (GTK_WIDGET_REALIZED (widget))
1290 GdkRectangle position;
1292 if (gtk_notebook_get_event_window_position (notebook, &position))
1293 gdk_window_move_resize (notebook->event_window,
1294 position.x, position.y,
1295 position.width, position.height);
1298 if (notebook->children)
1300 gint border_width = GTK_CONTAINER (widget)->border_width;
1301 GtkNotebookPage *page;
1302 GtkAllocation child_allocation;
1305 child_allocation.x = widget->allocation.x + border_width;
1306 child_allocation.y = widget->allocation.y + border_width;
1307 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1308 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1310 if (notebook->show_tabs || notebook->show_border)
1312 child_allocation.x += widget->style->xthickness;
1313 child_allocation.y += widget->style->ythickness;
1314 child_allocation.width = MAX (1, child_allocation.width -
1315 widget->style->xthickness * 2);
1316 child_allocation.height = MAX (1, child_allocation.height -
1317 widget->style->ythickness * 2);
1319 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1321 switch (notebook->tab_pos)
1324 child_allocation.y += notebook->cur_page->requisition.height;
1325 case GTK_POS_BOTTOM:
1326 child_allocation.height =
1327 MAX (1, child_allocation.height -
1328 notebook->cur_page->requisition.height);
1331 child_allocation.x += notebook->cur_page->requisition.width;
1333 child_allocation.width =
1334 MAX (1, child_allocation.width -
1335 notebook->cur_page->requisition.width);
1341 children = notebook->children;
1344 page = children->data;
1345 children = children->next;
1347 if (GTK_WIDGET_VISIBLE (page->child))
1349 gtk_widget_size_allocate (page->child, &child_allocation);
1354 gtk_notebook_pages_allocate (notebook);
1357 if ((vis_pages != 0) != notebook->have_visible_child)
1359 notebook->have_visible_child = (vis_pages != 0);
1360 if (notebook->show_tabs)
1361 gtk_widget_queue_draw (widget);
1366 gtk_notebook_expose (GtkWidget *widget,
1367 GdkEventExpose *event)
1369 GtkNotebook *notebook;
1370 GdkRectangle child_area;
1372 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1373 g_return_val_if_fail (event != NULL, FALSE);
1375 if (GTK_WIDGET_DRAWABLE (widget))
1377 notebook = GTK_NOTEBOOK (widget);
1379 gtk_notebook_paint (widget, &event->area);
1380 if (notebook->show_tabs)
1382 if (notebook->cur_page &&
1383 gtk_widget_intersect (notebook->cur_page->tab_label,
1384 &event->area, &child_area))
1385 gtk_notebook_draw_focus (widget);
1389 if (notebook->cur_page)
1390 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1391 notebook->cur_page->child,
1399 gtk_notebook_show_arrows (GtkNotebook *notebook)
1401 gboolean show_arrow = FALSE;
1404 if (!notebook->scrollable)
1407 children = notebook->children;
1410 GtkNotebookPage *page = children->data;
1412 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1415 children = children->next;
1422 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1423 GdkRectangle *rectangle)
1425 GdkRectangle event_window_pos;
1427 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1429 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1430 rectangle->height = ARROW_SIZE;
1432 switch (notebook->tab_pos)
1436 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1437 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1440 case GTK_POS_BOTTOM:
1441 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1442 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1449 gtk_notebook_get_arrow (GtkNotebook *notebook,
1453 GdkRectangle arrow_rect;
1454 GdkRectangle event_window_pos;
1456 if (gtk_notebook_show_arrows (notebook))
1458 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1459 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1464 if (y >= 0 && y < arrow_rect.height)
1466 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1467 return GTK_ARROW_LEFT;
1468 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1469 return GTK_ARROW_RIGHT;
1477 gtk_notebook_do_arrow (GtkNotebook *notebook,
1480 GtkWidget *widget = GTK_WIDGET (notebook);
1481 GtkDirectionType dir;
1483 if (!notebook->focus_tab ||
1484 gtk_notebook_search_page (notebook, notebook->focus_tab,
1485 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1488 if (notebook->tab_pos == GTK_POS_LEFT ||
1489 notebook->tab_pos == GTK_POS_RIGHT)
1490 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1492 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1493 gtk_widget_child_focus (widget, dir);
1498 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1500 GdkEventButton *event)
1502 GtkWidget *widget = GTK_WIDGET (notebook);
1504 if (!GTK_WIDGET_HAS_FOCUS (widget))
1505 gtk_widget_grab_focus (widget);
1507 notebook->button = event->button;
1508 notebook->click_child = arrow;
1510 if (event->button == 1)
1512 gtk_notebook_do_arrow (notebook, arrow);
1514 if (!notebook->timer)
1516 notebook->timer = gtk_timeout_add
1517 (NOTEBOOK_INIT_SCROLL_DELAY,
1518 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1519 notebook->need_timer = TRUE;
1522 else if (event->button == 2)
1523 gtk_notebook_page_select (notebook, TRUE);
1524 else if (event->button == 3)
1525 gtk_notebook_switch_focus_tab (notebook,
1526 gtk_notebook_search_page (notebook,
1528 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1530 gtk_notebook_redraw_arrows (notebook);
1536 get_widget_coordinates (GtkWidget *widget,
1541 GdkWindow *window = ((GdkEventAny *)event)->window;
1544 if (!gdk_event_get_coords (event, &tx, &ty))
1547 while (window && window != widget->window)
1549 gint window_x, window_y;
1551 gdk_window_get_position (window, &window_x, &window_y);
1555 window = gdk_window_get_parent (window);
1570 gtk_notebook_button_press (GtkWidget *widget,
1571 GdkEventButton *event)
1573 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1574 GtkNotebookPage *page;
1580 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1584 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1587 arrow = gtk_notebook_get_arrow (notebook, x, y);
1589 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1591 if (event->button == 3 && notebook->menu)
1593 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1594 NULL, NULL, 3, event->time);
1598 if (event->button != 1)
1602 children = notebook->children;
1605 page = children->data;
1607 if (GTK_WIDGET_VISIBLE (page->child) &&
1608 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1609 (x >= page->allocation.x) &&
1610 (y >= page->allocation.y) &&
1611 (x <= (page->allocation.x + page->allocation.width)) &&
1612 (y <= (page->allocation.y + page->allocation.height)))
1614 if (page == notebook->cur_page && notebook->focus_tab &&
1615 notebook->focus_tab != children &&
1616 GTK_WIDGET_HAS_FOCUS (notebook))
1618 GtkNotebookPage *old_page;
1620 notebook->child_has_focus = FALSE;
1621 old_page = (GtkNotebookPage *)
1622 (notebook->focus_tab->data);
1623 gtk_notebook_switch_focus_tab (notebook, children);
1624 gtk_notebook_focus_changed (notebook, old_page);
1628 gtk_notebook_switch_focus_tab (notebook, children);
1629 gtk_widget_grab_focus (widget);
1630 gtk_notebook_switch_page (notebook, page, num);
1634 children = children->next;
1637 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1638 gtk_widget_grab_focus (widget);
1644 gtk_notebook_button_release (GtkWidget *widget,
1645 GdkEventButton *event)
1647 GtkNotebook *notebook;
1649 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1650 g_return_val_if_fail (event != NULL, FALSE);
1652 if (event->type != GDK_BUTTON_RELEASE)
1655 notebook = GTK_NOTEBOOK (widget);
1657 if (event->button == notebook->button)
1661 if (notebook->timer)
1663 gtk_timeout_remove (notebook->timer);
1664 notebook->timer = 0;
1665 notebook->need_timer = FALSE;
1667 click_child = notebook->click_child;
1668 notebook->click_child = 0;
1669 notebook->button = 0;
1670 gtk_notebook_redraw_arrows (notebook);
1679 gtk_notebook_enter_notify (GtkWidget *widget,
1680 GdkEventCrossing *event)
1682 GtkNotebook *notebook;
1686 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1687 g_return_val_if_fail (event != NULL, FALSE);
1689 notebook = GTK_NOTEBOOK (widget);
1691 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1694 arrow = gtk_notebook_get_arrow (notebook, x, y);
1696 if (arrow != notebook->in_child)
1698 notebook->in_child = arrow;
1699 gtk_notebook_redraw_arrows (notebook);
1708 gtk_notebook_leave_notify (GtkWidget *widget,
1709 GdkEventCrossing *event)
1711 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1715 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1718 arrow = gtk_notebook_get_arrow (notebook, x, y);
1720 if (notebook->in_child)
1722 notebook->in_child = 0;
1723 gtk_notebook_redraw_arrows (notebook);
1730 gtk_notebook_motion_notify (GtkWidget *widget,
1731 GdkEventMotion *event)
1733 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1737 if (notebook->button)
1740 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1743 arrow = gtk_notebook_get_arrow (notebook, x, y);
1745 if (arrow != notebook->in_child)
1747 notebook->in_child = arrow;
1748 gtk_notebook_redraw_arrows (notebook);
1755 gtk_notebook_focus_in (GtkWidget *widget,
1756 GdkEventFocus *event)
1758 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1760 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1764 gtk_notebook_draw_focus (GtkWidget *widget)
1766 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1768 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1769 notebook->focus_tab)
1771 GtkNotebookPage *page;
1775 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1777 page = notebook->focus_tab->data;
1779 area.x = page->tab_label->allocation.x - focus_width;
1780 area.y = page->tab_label->allocation.y - focus_width;
1781 area.width = page->tab_label->allocation.width + 2 * focus_width;
1782 area.height = page->tab_label->allocation.height + 2 * focus_width;
1784 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1788 /* Private GtkContainer Methods :
1790 * gtk_notebook_set_child_arg
1791 * gtk_notebook_get_child_arg
1793 * gtk_notebook_remove
1794 * gtk_notebook_focus
1795 * gtk_notebook_set_focus_child
1796 * gtk_notebook_child_type
1797 * gtk_notebook_forall
1800 gtk_notebook_set_child_property (GtkContainer *container,
1803 const GValue *value,
1808 GtkPackType pack_type;
1810 /* not finding child's page is valid for menus or labels */
1811 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1814 switch (property_id)
1816 case CHILD_PROP_TAB_LABEL:
1817 /* a NULL pointer indicates a default_tab setting, otherwise
1818 * we need to set the associated label
1820 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1821 g_value_get_string (value));
1823 case CHILD_PROP_MENU_LABEL:
1824 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1825 g_value_get_string (value));
1827 case CHILD_PROP_POSITION:
1828 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1829 g_value_get_int (value));
1831 case CHILD_PROP_TAB_EXPAND:
1832 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1833 &expand, &fill, &pack_type);
1834 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1835 g_value_get_boolean (value),
1838 case CHILD_PROP_TAB_FILL:
1839 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1840 &expand, &fill, &pack_type);
1841 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1843 g_value_get_boolean (value),
1846 case CHILD_PROP_TAB_PACK:
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,
1851 g_value_get_enum (value));
1854 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1860 gtk_notebook_get_child_property (GtkContainer *container,
1867 GtkNotebook *notebook;
1871 GtkPackType pack_type;
1873 notebook = GTK_NOTEBOOK (container);
1875 /* not finding child's page is valid for menus or labels */
1876 list = gtk_notebook_find_child (notebook, child, NULL);
1879 /* nothing to set on labels or menus */
1880 g_param_value_set_default (pspec, value);
1884 switch (property_id)
1886 case CHILD_PROP_TAB_LABEL:
1887 label = gtk_notebook_get_tab_label (notebook, child);
1889 if (label && GTK_IS_LABEL (label))
1890 g_value_set_string (value, GTK_LABEL (label)->label);
1892 g_value_set_string (value, NULL);
1894 case CHILD_PROP_MENU_LABEL:
1895 label = gtk_notebook_get_menu_label (notebook, child);
1897 if (label && GTK_IS_LABEL (label))
1898 g_value_set_string (value, GTK_LABEL (label)->label);
1900 g_value_set_string (value, NULL);
1902 case CHILD_PROP_POSITION:
1903 g_value_set_int (value, g_list_position (notebook->children, list));
1905 case CHILD_PROP_TAB_EXPAND:
1906 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1907 &expand, NULL, NULL);
1908 g_value_set_boolean (value, expand);
1910 case CHILD_PROP_TAB_FILL:
1911 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1913 g_value_set_boolean (value, fill);
1915 case CHILD_PROP_TAB_PACK:
1916 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1917 NULL, NULL, &pack_type);
1918 g_value_set_enum (value, pack_type);
1921 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1927 gtk_notebook_add (GtkContainer *container,
1930 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1932 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1937 gtk_notebook_remove (GtkContainer *container,
1940 GtkNotebook *notebook;
1941 GtkNotebookPage *page;
1945 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1946 g_return_if_fail (widget != NULL);
1948 notebook = GTK_NOTEBOOK (container);
1950 children = notebook->children;
1954 page = children->data;
1955 if (page->child == widget)
1957 gtk_notebook_real_remove (notebook, children);
1961 children = children->next;
1966 focus_tabs_in (GtkNotebook *notebook)
1968 if (notebook->show_tabs && notebook->cur_page)
1970 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1972 gtk_notebook_switch_focus_tab (notebook,
1973 g_list_find (notebook->children,
1974 notebook->cur_page));
1983 focus_tabs_move (GtkNotebook *notebook,
1984 GtkDirectionType direction,
1985 gint search_direction)
1989 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1990 search_direction, TRUE);
1992 gtk_notebook_switch_focus_tab (notebook, new_page);
1994 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2000 focus_child_in (GtkNotebook *notebook,
2001 GtkDirectionType direction)
2003 if (notebook->cur_page)
2004 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2009 /* Focus in the notebook can either be on the pages, or on
2013 gtk_notebook_focus (GtkWidget *widget,
2014 GtkDirectionType direction)
2016 GtkWidget *old_focus_child;
2017 GtkNotebook *notebook;
2018 GtkDirectionType effective_direction;
2020 gboolean widget_is_focus;
2021 GtkContainer *container;
2023 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2025 container = GTK_CONTAINER (widget);
2026 notebook = GTK_NOTEBOOK (container);
2028 if (notebook->focus_out)
2030 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2034 widget_is_focus = gtk_widget_is_focus (widget);
2035 old_focus_child = container->focus_child;
2037 effective_direction = get_effective_direction (notebook, direction);
2039 if (old_focus_child) /* Focus on page child */
2041 if (gtk_widget_child_focus (old_focus_child, direction))
2044 switch (effective_direction)
2046 case GTK_DIR_TAB_BACKWARD:
2048 /* Focus onto the tabs */
2049 return focus_tabs_in (notebook);
2051 case GTK_DIR_TAB_FORWARD:
2057 else if (widget_is_focus) /* Focus was on tabs */
2059 switch (effective_direction)
2061 case GTK_DIR_TAB_BACKWARD:
2064 case GTK_DIR_TAB_FORWARD:
2066 /* We use TAB_FORWARD rather than direction so that we focus a more
2067 * predictable widget for the user; users may be using arrow focusing
2068 * in this situation even if they don't usually use arrow focusing.
2070 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2072 return focus_tabs_move (notebook, direction, STEP_PREV);
2074 return focus_tabs_move (notebook, direction, STEP_NEXT);
2077 else /* Focus was not on widget */
2079 switch (effective_direction)
2081 case GTK_DIR_TAB_FORWARD:
2083 if (focus_tabs_in (notebook))
2085 if (focus_child_in (notebook, direction))
2088 case GTK_DIR_TAB_BACKWARD:
2090 if (focus_child_in (notebook, direction))
2092 if (focus_tabs_in (notebook))
2097 return focus_child_in (notebook, direction);
2101 g_assert_not_reached ();
2106 gtk_notebook_set_focus_child (GtkContainer *container,
2109 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2110 GtkWidget *page_child;
2111 GtkWidget *toplevel;
2113 /* If the old focus widget was within a page of the notebook,
2114 * (child may either be NULL or not in this case), record it
2115 * for future use if we switch to the page with a mnemonic.
2118 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2119 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2121 page_child = GTK_WINDOW (toplevel)->focus_widget;
2124 if (page_child->parent == GTK_WIDGET (container))
2126 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2129 GtkNotebookPage *page = list->data;
2131 if (page->last_focus_child)
2132 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2134 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2135 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2141 page_child = page_child->parent;
2147 g_return_if_fail (GTK_IS_WIDGET (child));
2149 notebook->child_has_focus = TRUE;
2150 if (!notebook->focus_tab)
2153 GtkNotebookPage *page;
2155 children = notebook->children;
2158 page = children->data;
2159 if (page->child == child || page->tab_label == child)
2160 gtk_notebook_switch_focus_tab (notebook, children);
2161 children = children->next;
2166 parent_class->set_focus_child (container, child);
2170 gtk_notebook_forall (GtkContainer *container,
2171 gboolean include_internals,
2172 GtkCallback callback,
2173 gpointer callback_data)
2175 GtkNotebook *notebook;
2178 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2179 g_return_if_fail (callback != NULL);
2181 notebook = GTK_NOTEBOOK (container);
2183 children = notebook->children;
2186 GtkNotebookPage *page;
2188 page = children->data;
2189 children = children->next;
2190 (* callback) (page->child, callback_data);
2191 if (include_internals)
2193 if (page->tab_label)
2194 (* callback) (page->tab_label, callback_data);
2195 if (page->menu_label)
2196 (* callback) (page->menu_label, callback_data);
2202 gtk_notebook_child_type (GtkContainer *container)
2204 return GTK_TYPE_WIDGET;
2207 /* Private GtkNotebook Functions:
2209 * gtk_notebook_redraw_tabs
2210 * gtk_notebook_focus_changed
2211 * gtk_notebook_real_remove
2212 * gtk_notebook_update_labels
2213 * gtk_notebook_timer
2214 * gtk_notebook_page_compare
2215 * gtk_notebook_real_page_position
2216 * gtk_notebook_search_page
2219 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2222 GtkNotebookPage *page;
2223 GdkRectangle redraw_rect;
2226 widget = GTK_WIDGET (notebook);
2227 border = GTK_CONTAINER (notebook)->border_width;
2229 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2232 page = notebook->first_tab->data;
2234 redraw_rect.x = border;
2235 redraw_rect.y = border;
2237 switch (notebook->tab_pos)
2239 case GTK_POS_BOTTOM:
2240 redraw_rect.y = (widget->allocation.height - border -
2241 page->allocation.height -
2242 widget->style->ythickness);
2243 if (page != notebook->cur_page)
2244 redraw_rect.y -= widget->style->ythickness;
2247 redraw_rect.width = widget->allocation.width - 2 * border;
2248 redraw_rect.height = (page->allocation.height +
2249 widget->style->ythickness);
2250 if (page != notebook->cur_page)
2251 redraw_rect.height += widget->style->ythickness;
2254 redraw_rect.x = (widget->allocation.width - border -
2255 page->allocation.width -
2256 widget->style->xthickness);
2257 if (page != notebook->cur_page)
2258 redraw_rect.x -= widget->style->xthickness;
2261 redraw_rect.width = (page->allocation.width +
2262 widget->style->xthickness);
2263 redraw_rect.height = widget->allocation.height - 2 * border;
2264 if (page != notebook->cur_page)
2265 redraw_rect.width += widget->style->xthickness;
2269 redraw_rect.x += widget->allocation.x;
2270 redraw_rect.y += widget->allocation.y;
2272 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2276 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2278 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2282 gtk_notebook_get_arrow_rect (notebook, &rect);
2283 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2288 gtk_notebook_focus_changed (GtkNotebook *notebook,
2289 GtkNotebookPage *old_page)
2291 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2293 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2298 gtk_widget_style_get (GTK_WIDGET (notebook), "focus-line-width", &focus_width, NULL);
2300 if (notebook->focus_tab)
2302 GtkNotebookPage *page;
2304 page = notebook->focus_tab->data;
2306 area.x = page->tab_label->allocation.x - focus_width;
2307 area.y = page->tab_label->allocation.y - focus_width;
2308 area.width = page->tab_label->allocation.width + 2 * focus_width;
2309 area.height = page->tab_label->allocation.height + 2 * focus_width;
2311 gtk_notebook_draw_tab (notebook, page, &area);
2316 area.x = old_page->tab_label->allocation.x - focus_width;
2317 area.y = old_page->tab_label->allocation.y - focus_width;
2318 area.width = old_page->tab_label->allocation.width + 2 * focus_width;
2319 area.height = old_page->tab_label->allocation.height + 2 * focus_width;
2321 gtk_notebook_draw_tab (notebook, old_page, &area);
2327 gtk_notebook_timer (GtkNotebook *notebook)
2329 gboolean retval = FALSE;
2331 GDK_THREADS_ENTER ();
2333 if (notebook->timer)
2335 gtk_notebook_do_arrow (notebook, notebook->click_child);
2337 if (notebook->need_timer)
2339 notebook->need_timer = FALSE;
2340 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2341 (GtkFunction) gtk_notebook_timer,
2342 (gpointer) notebook);
2348 GDK_THREADS_LEAVE ();
2354 gtk_notebook_page_compare (gconstpointer a,
2357 return (((GtkNotebookPage *) a)->child != b);
2361 gtk_notebook_find_child (GtkNotebook *notebook,
2363 const gchar *function)
2365 GList *list = g_list_find_custom (notebook->children, child,
2366 gtk_notebook_page_compare);
2368 #ifndef G_DISABLE_CHECKS
2369 if (!list && function)
2370 g_warning ("%s: unable to find child %p in notebook %p",
2371 function, child, notebook);
2378 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2379 GtkNotebookPage *page)
2381 if (page->tab_label)
2383 if (page->mnemonic_activate_signal)
2384 g_signal_handler_disconnect (page->tab_label,
2385 page->mnemonic_activate_signal);
2386 page->mnemonic_activate_signal = 0;
2388 gtk_widget_unparent (page->tab_label);
2393 gtk_notebook_real_remove (GtkNotebook *notebook,
2396 GtkNotebookPage *page;
2398 gint need_resize = FALSE;
2400 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2402 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2404 if (notebook->cur_page == list->data)
2406 notebook->cur_page = NULL;
2408 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2411 if (list == notebook->first_tab)
2412 notebook->first_tab = next_list;
2413 if (list == notebook->focus_tab)
2414 gtk_notebook_switch_focus_tab (notebook, next_list);
2418 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2421 gtk_widget_unparent (page->child);
2423 gtk_notebook_remove_tab_label (notebook, page);
2427 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2428 page->menu_label->parent);
2429 gtk_widget_queue_resize (notebook->menu);
2431 if (!page->default_menu)
2432 g_object_unref (page->menu_label);
2434 notebook->children = g_list_remove_link (notebook->children, list);
2437 if (page->last_focus_child)
2439 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2440 page->last_focus_child = NULL;
2445 if (!notebook->children && notebook->show_tabs &&
2446 GTK_WIDGET_MAPPED (notebook))
2447 gdk_window_hide (notebook->event_window);
2449 gtk_notebook_update_labels (notebook);
2451 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2455 gtk_notebook_update_labels (GtkNotebook *notebook)
2457 GtkNotebookPage *page;
2462 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2464 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2467 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2468 if (notebook->show_tabs)
2470 if (page->default_tab)
2472 if (!page->tab_label)
2474 page->tab_label = gtk_label_new (string);
2475 gtk_widget_set_parent (page->tab_label,
2476 GTK_WIDGET (notebook));
2479 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2482 if (GTK_WIDGET_VISIBLE (page->child) &&
2483 !GTK_WIDGET_VISIBLE (page->tab_label))
2484 gtk_widget_show (page->tab_label);
2485 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2486 GTK_WIDGET_VISIBLE (page->tab_label))
2487 gtk_widget_hide (page->tab_label);
2489 if (notebook->menu && page->default_menu)
2491 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2492 gtk_label_set_text (GTK_LABEL (page->menu_label),
2493 GTK_LABEL (page->tab_label)->label);
2495 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2501 gtk_notebook_real_page_position (GtkNotebook *notebook,
2507 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2508 g_return_val_if_fail (list != NULL, -1);
2510 for (work = notebook->children, count_start = 0;
2511 work && work != list; work = work->next)
2512 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2518 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2521 return (count_start + g_list_length (list) - 1);
2525 gtk_notebook_search_page (GtkNotebook *notebook,
2528 gboolean find_visible)
2530 GtkNotebookPage *page = NULL;
2531 GList *old_list = NULL;
2534 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2539 flag = GTK_PACK_END;
2543 flag = GTK_PACK_START;
2550 if (!page || page->pack == flag)
2558 list = notebook->children;
2563 if (page->pack == flag &&
2564 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2579 if (page->pack != flag &&
2580 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2588 /* Private GtkNotebook Drawing Functions:
2590 * gtk_notebook_paint
2591 * gtk_notebook_draw_tab
2592 * gtk_notebook_draw_arrow
2595 gtk_notebook_paint (GtkWidget *widget,
2598 GtkNotebook *notebook;
2599 GtkNotebookPage *page;
2604 gint border_width = GTK_CONTAINER (widget)->border_width;
2605 gint gap_x = 0, gap_width = 0;
2607 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2608 g_return_if_fail (area != NULL);
2610 if (!GTK_WIDGET_DRAWABLE (widget))
2613 notebook = GTK_NOTEBOOK (widget);
2615 if ((!notebook->show_tabs && !notebook->show_border) ||
2616 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2619 x = widget->allocation.x + border_width;
2620 y = widget->allocation.y + border_width;
2621 width = widget->allocation.width - border_width * 2;
2622 height = widget->allocation.height - border_width * 2;
2624 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2626 gtk_paint_box (widget->style, widget->window,
2627 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2628 area, widget, "notebook",
2629 x, y, width, height);
2634 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2636 page = notebook->first_tab->data;
2638 switch (notebook->tab_pos)
2641 y += page->allocation.height + widget->style->ythickness;
2642 case GTK_POS_BOTTOM:
2643 height -= page->allocation.height + widget->style->ythickness;
2646 x += page->allocation.width + widget->style->xthickness;
2648 width -= page->allocation.width + widget->style->xthickness;
2651 gtk_paint_box (widget->style, widget->window,
2652 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2653 area, widget, "notebook",
2654 x, y, width, height);
2658 switch (notebook->tab_pos)
2661 y += notebook->cur_page->allocation.height;
2662 case GTK_POS_BOTTOM:
2663 height -= notebook->cur_page->allocation.height;
2666 x += notebook->cur_page->allocation.width;
2668 width -= notebook->cur_page->allocation.width;
2672 switch (notebook->tab_pos)
2675 case GTK_POS_BOTTOM:
2676 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2677 gap_width = notebook->cur_page->allocation.width;
2681 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2682 gap_width = notebook->cur_page->allocation.height;
2685 gtk_paint_box_gap(widget->style, widget->window,
2686 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2687 area, widget, "notebook",
2688 x, y, width, height,
2689 notebook->tab_pos, gap_x, gap_width);
2693 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2696 page = children->data;
2697 children = gtk_notebook_search_page (notebook, children,
2699 if (!GTK_WIDGET_VISIBLE (page->child))
2701 if (!GTK_WIDGET_MAPPED (page->tab_label))
2703 else if (page != notebook->cur_page)
2704 gtk_notebook_draw_tab (notebook, page, area);
2707 if (showarrow && notebook->scrollable)
2709 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2710 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2712 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2716 gtk_notebook_draw_tab (GtkNotebook *notebook,
2717 GtkNotebookPage *page,
2720 GdkRectangle child_area;
2721 GdkRectangle page_area;
2722 GtkStateType state_type;
2723 GtkPositionType gap_side;
2725 g_return_if_fail (notebook != NULL);
2726 g_return_if_fail (page != NULL);
2727 g_return_if_fail (area != NULL);
2729 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2730 (page->allocation.width == 0) || (page->allocation.height == 0))
2733 page_area.x = page->allocation.x;
2734 page_area.y = page->allocation.y;
2735 page_area.width = page->allocation.width;
2736 page_area.height = page->allocation.height;
2738 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2742 widget = GTK_WIDGET (notebook);
2744 switch (notebook->tab_pos)
2747 gap_side = GTK_POS_BOTTOM;
2749 case GTK_POS_BOTTOM:
2750 gap_side = GTK_POS_TOP;
2753 gap_side = GTK_POS_RIGHT;
2756 gap_side = GTK_POS_LEFT;
2760 if (notebook->cur_page == page)
2761 state_type = GTK_STATE_NORMAL;
2763 state_type = GTK_STATE_ACTIVE;
2764 gtk_paint_extension(widget->style, widget->window,
2765 state_type, GTK_SHADOW_OUT,
2766 area, widget, "tab",
2767 page_area.x, page_area.y,
2768 page_area.width, page_area.height,
2770 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2771 notebook->focus_tab && (notebook->focus_tab->data == page))
2775 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2777 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2778 area, widget, "tab",
2779 page->tab_label->allocation.x - focus_width,
2780 page->tab_label->allocation.y - focus_width,
2781 page->tab_label->allocation.width + 2 * focus_width,
2782 page->tab_label->allocation.height + 2 * focus_width);
2784 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2785 GTK_WIDGET_DRAWABLE (page->tab_label))
2787 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2789 /* This is a lame hack since all this code needs rewriting anyhow */
2791 expose_event->expose.window = g_object_ref (page->tab_label->window);
2792 expose_event->expose.area = child_area;
2793 expose_event->expose.region = gdk_region_rectangle (&child_area);
2794 expose_event->expose.send_event = TRUE;
2795 expose_event->expose.count = 0;
2797 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2799 gdk_event_free (expose_event);
2805 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2808 GtkStateType state_type;
2809 GtkShadowType shadow_type;
2811 GdkRectangle arrow_rect;
2813 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2815 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2817 widget = GTK_WIDGET(notebook);
2819 if (GTK_WIDGET_DRAWABLE (notebook))
2821 if (notebook->in_child == arrow)
2823 if (notebook->click_child == arrow)
2824 state_type = GTK_STATE_ACTIVE;
2826 state_type = GTK_STATE_PRELIGHT;
2829 state_type = GTK_STATE_NORMAL;
2831 if (notebook->click_child == arrow)
2832 shadow_type = GTK_SHADOW_IN;
2834 shadow_type = GTK_SHADOW_OUT;
2836 if (arrow == GTK_ARROW_LEFT)
2838 if (notebook->focus_tab &&
2839 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2842 shadow_type = GTK_SHADOW_ETCHED_IN;
2843 state_type = GTK_STATE_INSENSITIVE;
2846 if (notebook->tab_pos == GTK_POS_LEFT ||
2847 notebook->tab_pos == GTK_POS_RIGHT)
2848 arrow = GTK_ARROW_UP;
2850 gtk_paint_arrow (widget->style, widget->window, state_type,
2851 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2853 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2857 if (notebook->focus_tab &&
2858 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2861 shadow_type = GTK_SHADOW_ETCHED_IN;
2862 state_type = GTK_STATE_INSENSITIVE;
2865 if (notebook->tab_pos == GTK_POS_LEFT ||
2866 notebook->tab_pos == GTK_POS_RIGHT)
2867 arrow = GTK_ARROW_DOWN;
2869 gtk_paint_arrow (widget->style, widget->window, state_type,
2870 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2871 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2872 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2877 /* Private GtkNotebook Size Allocate Functions:
2879 * gtk_notebook_pages_allocate
2880 * gtk_notebook_page_allocate
2881 * gtk_notebook_calc_tabs
2884 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2886 GtkWidget *widget = GTK_WIDGET (notebook);
2887 GtkContainer *container = GTK_CONTAINER (notebook);
2888 GtkNotebookPage *page = NULL;
2889 GtkAllocation *allocation = &widget->allocation;
2890 GtkAllocation child_allocation;
2891 GList *children = NULL;
2892 GList *last_child = NULL;
2893 gboolean showarrow = FALSE;
2903 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2906 child_allocation.x = widget->allocation.x + container->border_width;
2907 child_allocation.y = widget->allocation.y + container->border_width;
2909 switch (notebook->tab_pos)
2911 case GTK_POS_BOTTOM:
2912 child_allocation.y = (widget->allocation.y +
2913 allocation->height -
2914 notebook->cur_page->requisition.height -
2915 container->border_width);
2918 child_allocation.height = notebook->cur_page->requisition.height;
2922 child_allocation.x = (widget->allocation.x +
2924 notebook->cur_page->requisition.width -
2925 container->border_width);
2928 child_allocation.width = notebook->cur_page->requisition.width;
2932 if (notebook->scrollable)
2936 children = notebook->children;
2938 if (notebook->focus_tab)
2939 focus_tab = notebook->focus_tab;
2940 else if (notebook->first_tab)
2941 focus_tab = notebook->first_tab;
2943 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2945 switch (notebook->tab_pos)
2948 case GTK_POS_BOTTOM:
2951 page = children->data;
2952 children = children->next;
2954 if (GTK_WIDGET_VISIBLE (page->child))
2955 tab_space += page->requisition.width;
2958 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2961 page = focus_tab->data;
2963 tab_space = (allocation->width - TAB_OVERLAP -
2964 page->requisition.width -
2965 2 * (container->border_width + ARROW_SPACING +
2967 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2968 container->border_width);
2970 page = notebook->children->data;
2971 if (notebook->tab_pos == GTK_POS_TOP)
2972 y = (container->border_width +
2973 (page->requisition.height - ARROW_SIZE) / 2);
2975 y = (allocation->height - container->border_width -
2976 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2983 page = children->data;
2984 children = children->next;
2986 if (GTK_WIDGET_VISIBLE (page->child))
2987 tab_space += page->requisition.height;
2990 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2993 page = focus_tab->data;
2994 tab_space = (allocation->height -
2995 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2996 2 * container->border_width -
2997 page->requisition.height);
2998 y = allocation->height - container->border_width - ARROW_SIZE;
3000 page = notebook->children->data;
3001 if (notebook->tab_pos == GTK_POS_LEFT)
3002 x = (container->border_width +
3003 (page->requisition.width -
3004 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
3006 x = (allocation->width - container->border_width -
3007 (2 * ARROW_SIZE - ARROW_SPACING) -
3008 (page->requisition.width -
3009 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
3013 if (showarrow) /* first_tab <- focus_tab */
3017 notebook->first_tab = focus_tab;
3018 last_child = gtk_notebook_search_page (notebook, focus_tab,
3024 if (notebook->first_tab && notebook->first_tab != focus_tab)
3026 /* Is first_tab really predecessor of focus_tab ? */
3027 page = notebook->first_tab->data;
3028 if (GTK_WIDGET_VISIBLE (page->child))
3029 for (children = focus_tab;
3030 children && children != notebook->first_tab;
3031 children = gtk_notebook_search_page (notebook,
3037 notebook->first_tab = focus_tab;
3039 gtk_notebook_calc_tabs (notebook,
3040 gtk_notebook_search_page (notebook,
3044 &(notebook->first_tab), &tab_space,
3049 notebook->first_tab =
3050 gtk_notebook_search_page (notebook, notebook->first_tab,
3052 if (!notebook->first_tab)
3053 notebook->first_tab = focus_tab;
3054 last_child = gtk_notebook_search_page (notebook, focus_tab,
3057 else /* focus_tab -> end */
3059 if (!notebook->first_tab)
3060 notebook->first_tab = gtk_notebook_search_page (notebook,
3065 gtk_notebook_calc_tabs (notebook,
3066 gtk_notebook_search_page (notebook,
3070 &children, &tab_space, STEP_NEXT);
3073 last_child = children;
3074 else /* start <- first_tab */
3078 gtk_notebook_calc_tabs
3080 gtk_notebook_search_page (notebook,
3081 notebook->first_tab,
3084 &children, &tab_space, STEP_PREV);
3085 notebook->first_tab = gtk_notebook_search_page(notebook,
3095 tab_space = -tab_space;
3097 for (children = notebook->first_tab;
3098 children && children != last_child;
3099 children = gtk_notebook_search_page (notebook, children,
3106 /*unmap all non-visible tabs*/
3107 for (children = gtk_notebook_search_page (notebook, NULL,
3109 children && children != notebook->first_tab;
3110 children = gtk_notebook_search_page (notebook, children,
3113 page = children->data;
3114 if (page->tab_label)
3115 gtk_widget_set_child_visible (page->tab_label, FALSE);
3117 for (children = last_child; children;
3118 children = gtk_notebook_search_page (notebook, children,
3121 page = children->data;
3122 if (page->tab_label)
3123 gtk_widget_set_child_visible (page->tab_label, FALSE);
3126 else /* !showarrow */
3128 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3139 children = notebook->children;
3140 switch (notebook->tab_pos)
3143 case GTK_POS_BOTTOM:
3146 page = children->data;
3147 children = children->next;
3149 if (GTK_WIDGET_VISIBLE (page->child))
3152 tab_space += page->requisition.width;
3157 tab_space -= allocation->width;
3163 page = children->data;
3164 children = children->next;
3166 if (GTK_WIDGET_VISIBLE (page->child))
3169 tab_space += page->requisition.height;
3174 tab_space -= allocation->height;
3176 tab_space += 2 * container->border_width + TAB_OVERLAP;
3178 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3180 if (notebook->homogeneous && n)
3184 children = notebook->first_tab;
3188 if (children == last_child)
3190 /* FIXME double check */
3194 page = children->data;
3195 if (!showarrow && page->pack != GTK_PACK_START)
3197 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3200 if (n && (showarrow || page->expand || notebook->homogeneous))
3202 new_fill = (tab_space * i++) / n;
3203 delta = new_fill - old_fill;
3204 old_fill = new_fill;
3207 switch (notebook->tab_pos)
3210 case GTK_POS_BOTTOM:
3211 child_allocation.width = (page->requisition.width +
3212 TAB_OVERLAP + delta);
3216 child_allocation.height = (page->requisition.height +
3217 TAB_OVERLAP + delta);
3221 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3223 switch (notebook->tab_pos)
3226 case GTK_POS_BOTTOM:
3227 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3231 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3235 if (page->tab_label)
3236 gtk_widget_set_child_visible (page->tab_label, TRUE);
3241 children = notebook->children;
3242 switch (notebook->tab_pos)
3245 case GTK_POS_BOTTOM:
3246 child_allocation.x = (allocation->x + allocation->width -
3247 container->border_width);
3251 child_allocation.y = (allocation->y + allocation->height -
3252 container->border_width);
3256 while (children != last_child)
3258 page = children->data;
3259 children = children->next;
3261 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3265 if (n && (page->expand || notebook->homogeneous))
3267 new_fill = (tab_space * i++) / n;
3268 delta = new_fill - old_fill;
3269 old_fill = new_fill;
3272 switch (notebook->tab_pos)
3275 case GTK_POS_BOTTOM:
3276 child_allocation.width = (page->requisition.width +
3277 TAB_OVERLAP + delta);
3278 child_allocation.x -= child_allocation.width;
3282 child_allocation.height = (page->requisition.height +
3283 TAB_OVERLAP + delta);
3284 child_allocation.y -= child_allocation.height;
3288 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3290 switch (notebook->tab_pos)
3293 case GTK_POS_BOTTOM:
3294 child_allocation.x += TAB_OVERLAP;
3298 child_allocation.y += TAB_OVERLAP;
3302 if (page->tab_label)
3303 gtk_widget_set_child_visible (page->tab_label, TRUE);
3308 gtk_notebook_redraw_tabs (notebook);
3312 gtk_notebook_page_allocate (GtkNotebook *notebook,
3313 GtkNotebookPage *page,
3314 GtkAllocation *allocation)
3316 GtkWidget *widget = GTK_WIDGET (notebook);
3317 GtkAllocation child_allocation;
3318 GtkRequisition tab_requisition;
3324 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3326 xthickness = widget->style->xthickness;
3327 ythickness = widget->style->ythickness;
3329 /* If the size of the notebook tabs change, we need to queue
3330 * a redraw on the tab area
3332 if ((allocation->width != page->allocation.width) ||
3333 (allocation->height != page->allocation.height))
3335 gint x, y, width, height, border_width;
3337 border_width = GTK_CONTAINER (notebook)->border_width;
3339 switch (notebook->tab_pos)
3342 width = widget->allocation.width;
3343 height = MAX (page->allocation.height, allocation->height) + ythickness;
3348 case GTK_POS_BOTTOM:
3349 width = widget->allocation.width + xthickness;
3350 height = MAX (page->allocation.height, allocation->height) + ythickness;
3352 y = widget->allocation.height - height - border_width;
3356 width = MAX (page->allocation.width, allocation->width) + xthickness;
3357 height = widget->allocation.height;
3363 default: /* quiet gcc */
3364 width = MAX (page->allocation.width, allocation->width) + xthickness;
3365 height = widget->allocation.height;
3366 x = widget->allocation.width - width - border_width;
3371 gtk_widget_queue_draw_area (widget, x, y, width, height);
3374 page->allocation = *allocation;
3375 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3377 if (notebook->cur_page != page)
3379 switch (notebook->tab_pos)
3382 page->allocation.y += ythickness;
3383 case GTK_POS_BOTTOM:
3384 if (page->allocation.height > ythickness)
3385 page->allocation.height -= ythickness;
3388 page->allocation.x += xthickness;
3390 if (page->allocation.width > xthickness)
3391 page->allocation.width -= xthickness;
3396 switch (notebook->tab_pos)
3399 case GTK_POS_BOTTOM:
3400 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3403 child_allocation.x = (xthickness + focus_width +
3404 notebook->tab_hborder);
3405 child_allocation.width = MAX (1, (page->allocation.width -
3406 2 * child_allocation.x));
3407 child_allocation.x += page->allocation.x;
3411 child_allocation.x = (page->allocation.x +
3412 (page->allocation.width -
3413 tab_requisition.width) / 2);
3414 child_allocation.width = tab_requisition.width;
3416 child_allocation.y = (notebook->tab_vborder + focus_width +
3417 page->allocation.y);
3418 if (notebook->tab_pos == GTK_POS_TOP)
3419 child_allocation.y += ythickness;
3420 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3421 2 * (notebook->tab_vborder + focus_width)));
3425 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3428 child_allocation.y = ythickness + padding;
3429 child_allocation.height = MAX (1, (page->allocation.height -
3430 2 * child_allocation.y));
3431 child_allocation.y += page->allocation.y;
3435 child_allocation.y = (page->allocation.y + (page->allocation.height -
3436 tab_requisition.height) / 2);
3437 child_allocation.height = tab_requisition.height;
3439 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3440 if (notebook->tab_pos == GTK_POS_LEFT)
3441 child_allocation.x += xthickness;
3442 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3443 2 * (notebook->tab_hborder + focus_width)));
3447 if (page->tab_label)
3448 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3452 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3458 GtkNotebookPage *page = NULL;
3460 GList *last_list = NULL;
3467 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3468 if (pack == GTK_PACK_END)
3469 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3473 switch (notebook->tab_pos)
3476 case GTK_POS_BOTTOM:
3479 page = children->data;
3480 if (GTK_WIDGET_VISIBLE (page->child))
3482 if (page->pack == pack)
3484 *tab_space -= page->requisition.width;
3485 if (*tab_space < 0 || children == *end)
3489 *tab_space = - (*tab_space +
3490 page->requisition.width);
3496 last_list = children;
3498 if (direction == STEP_NEXT)
3499 children = children->next;
3501 children = children->prev;
3508 page = children->data;
3509 if (GTK_WIDGET_VISIBLE (page->child))
3511 if (page->pack == pack)
3513 *tab_space -= page->requisition.height;
3514 if (*tab_space < 0 || children == *end)
3518 *tab_space = - (*tab_space +
3519 page->requisition.height);
3525 last_list = children;
3527 if (direction == STEP_NEXT)
3528 children = children->next;
3530 children = children->prev;
3534 if (direction == STEP_PREV)
3536 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3537 direction = STEP_PREV;
3538 children = last_list;
3542 /* Private GtkNotebook Page Switch Methods:
3544 * gtk_notebook_real_switch_page
3547 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3548 GtkNotebookPage *page,
3551 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3552 g_return_if_fail (page != NULL);
3554 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3557 if (notebook->cur_page)
3558 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3560 notebook->cur_page = page;
3562 if (!notebook->focus_tab ||
3563 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3564 notebook->focus_tab =
3565 g_list_find (notebook->children, notebook->cur_page);
3567 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3569 /* If the focus was on the previous page, move it to the first
3570 * element on the new page, if possible, or if not, to the
3573 if (notebook->child_has_focus)
3575 if (notebook->cur_page->last_focus_child &&
3576 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3577 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3579 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3580 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3583 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3584 g_object_notify (G_OBJECT (notebook), "page");
3587 /* Private GtkNotebook Page Switch Functions:
3589 * gtk_notebook_switch_page
3590 * gtk_notebook_page_select
3591 * gtk_notebook_switch_focus_tab
3592 * gtk_notebook_menu_switch_page
3595 gtk_notebook_switch_page (GtkNotebook *notebook,
3596 GtkNotebookPage *page,
3599 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3600 g_return_if_fail (page != NULL);
3602 if (notebook->cur_page == page)
3606 page_num = g_list_index (notebook->children, page);
3608 g_signal_emit (notebook,
3609 notebook_signals[SWITCH_PAGE],
3616 gtk_notebook_page_select (GtkNotebook *notebook,
3617 gboolean move_focus)
3619 GtkNotebookPage *page;
3620 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3622 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3624 if (!notebook->focus_tab)
3627 page = notebook->focus_tab->data;
3628 gtk_notebook_switch_page (notebook, page, -1);
3632 switch (notebook->tab_pos)
3637 case GTK_POS_BOTTOM:
3641 dir = GTK_DIR_RIGHT;
3648 if (gtk_widget_child_focus (page->child, dir))
3655 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3659 GtkNotebookPage *old_page = NULL;
3660 GtkNotebookPage *page;
3662 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3664 if (notebook->focus_tab == new_child)
3667 old_child = notebook->focus_tab;
3668 notebook->focus_tab = new_child;
3670 if (notebook->scrollable)
3671 gtk_notebook_redraw_arrows (notebook);
3673 if (!notebook->show_tabs || !notebook->focus_tab)
3677 old_page = old_child->data;
3679 page = notebook->focus_tab->data;
3680 if (GTK_WIDGET_MAPPED (page->tab_label))
3681 gtk_notebook_focus_changed (notebook, old_page);
3683 gtk_notebook_pages_allocate (notebook);
3687 gtk_notebook_menu_switch_page (GtkWidget *widget,
3688 GtkNotebookPage *page)
3690 GtkNotebook *notebook;
3694 g_return_if_fail (widget != NULL);
3695 g_return_if_fail (page != NULL);
3697 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3698 (GTK_MENU (widget->parent)));
3700 if (notebook->cur_page == page)
3704 children = notebook->children;
3705 while (children && children->data != page)
3707 children = children->next;
3711 g_signal_emit (notebook,
3712 notebook_signals[SWITCH_PAGE],
3718 /* Private GtkNotebook Menu Functions:
3720 * gtk_notebook_menu_item_create
3721 * gtk_notebook_menu_label_unparent
3722 * gtk_notebook_menu_detacher
3725 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3728 GtkNotebookPage *page;
3729 GtkWidget *menu_item;
3732 if (page->default_menu)
3734 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3735 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3737 page->menu_label = gtk_label_new ("");
3738 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3741 gtk_widget_show (page->menu_label);
3742 menu_item = gtk_menu_item_new ();
3743 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3744 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3745 gtk_notebook_real_page_position (notebook, list));
3746 g_signal_connect (menu_item, "activate",
3747 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3748 if (GTK_WIDGET_VISIBLE (page->child))
3749 gtk_widget_show (menu_item);
3753 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3756 gtk_widget_unparent (GTK_BIN(widget)->child);
3757 GTK_BIN(widget)->child = NULL;
3761 gtk_notebook_menu_detacher (GtkWidget *widget,
3764 GtkNotebook *notebook;
3766 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3768 notebook = GTK_NOTEBOOK (widget);
3769 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3771 notebook->menu = NULL;
3774 /* Public GtkNotebook Page Insert/Remove Methods :
3776 * gtk_notebook_append_page
3777 * gtk_notebook_append_page_menu
3778 * gtk_notebook_prepend_page
3779 * gtk_notebook_prepend_page_menu
3780 * gtk_notebook_insert_page
3781 * gtk_notebook_insert_page_menu
3782 * gtk_notebook_remove_page
3785 * gtk_notebook_append_page:
3786 * @notebook: a #GtkNotebook
3787 * @child: the #GtkWidget to use as the contents of the page.
3788 * @tab_label: the #GtkWidget to be used as the label for the page,
3789 * or %NULL to use the default label, 'page N'.
3791 * Appends a page to @notebook.
3794 gtk_notebook_append_page (GtkNotebook *notebook,
3796 GtkWidget *tab_label)
3798 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3799 g_return_if_fail (GTK_IS_WIDGET (child));
3800 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3802 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3806 * gtk_notebook_append_page_menu:
3807 * @notebook: a #GtkNotebook
3808 * @child: the #GtkWidget to use as the contents of the page.
3809 * @tab_label: the #GtkWidget to be used as the label for the page,
3810 * or %NULL to use the default label, 'page N'.
3811 * @menu_label: the widget to use as a label for the page-switch
3812 * menu, if that is enabled. If %NULL, and @tab_label
3813 * is a #GtkLabel or %NULL, then the menu label will be
3814 * a newly created label with the same text as @tab_label;
3815 * If @tab_label is not a #GtkLabel, @menu_label must be
3816 * specified if the page-switch menu is to be used.
3818 * Appends a page to @notebook, specifying the widget to use as the
3819 * label in the popup menu.
3822 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3824 GtkWidget *tab_label,
3825 GtkWidget *menu_label)
3827 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3828 g_return_if_fail (GTK_IS_WIDGET (child));
3829 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3830 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3832 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3836 * gtk_notebook_prepend_page:
3837 * @notebook: a #GtkNotebook
3838 * @child: the #GtkWidget to use as the contents of the page.
3839 * @tab_label: the #GtkWidget to be used as the label for the page,
3840 * or %NULL to use the default label, 'page N'.
3842 * Prepends a page to @notebook.
3845 gtk_notebook_prepend_page (GtkNotebook *notebook,
3847 GtkWidget *tab_label)
3849 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3850 g_return_if_fail (GTK_IS_WIDGET (child));
3851 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3853 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3857 * gtk_notebook_prepend_page_menu:
3858 * @notebook: a #GtkNotebook
3859 * @child: the #GtkWidget to use as the contents of the page.
3860 * @tab_label: the #GtkWidget to be used as the label for the page,
3861 * or %NULL to use the default label, 'page N'.
3862 * @menu_label: the widget to use as a label for the page-switch
3863 * menu, if that is enabled. If %NULL, and @tab_label
3864 * is a #GtkLabel or %NULL, then the menu label will be
3865 * a newly created label with the same text as @tab_label;
3866 * If @tab_label is not a #GtkLabel, @menu_label must be
3867 * specified if the page-switch menu is to be used.
3869 * Prepends a page to @notebook, specifying the widget to use as the
3870 * label in the popup menu.
3873 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3875 GtkWidget *tab_label,
3876 GtkWidget *menu_label)
3878 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3879 g_return_if_fail (GTK_IS_WIDGET (child));
3880 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3881 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3883 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3887 * gtk_notebook_insert_page:
3888 * @notebook: a #GtkNotebook
3889 * @child: the #GtkWidget to use as the contents of the page.
3890 * @tab_label: the #GtkWidget to be used as the label for the page,
3891 * or %NULL to use the default label, 'page N'.
3892 * @position: the index (starting at 0) at which to insert the page,
3893 * or -1 to append the page after all other pages.
3895 * Insert a page into @notebook at the given position
3898 gtk_notebook_insert_page (GtkNotebook *notebook,
3900 GtkWidget *tab_label,
3903 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3904 g_return_if_fail (GTK_IS_WIDGET (child));
3905 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3907 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3912 gtk_notebook_page_compare_tab (gconstpointer a,
3915 return (((GtkNotebookPage *) a)->tab_label != b);
3919 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3923 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3926 list = g_list_find_custom (notebook->children, child,
3927 gtk_notebook_page_compare_tab);
3930 GtkNotebookPage *page = list->data;
3932 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3933 gtk_notebook_switch_page (notebook, page, -1);
3934 focus_tabs_in (notebook);
3941 * gtk_notebook_insert_page_menu:
3942 * @notebook: a #GtkNotebook
3943 * @child: the #GtkWidget to use as the contents of the page.
3944 * @tab_label: the #GtkWidget to be used as the label for the page,
3945 * or %NULL to use the default label, 'page N'.
3946 * @menu_label: the widget to use as a label for the page-switch
3947 * menu, if that is enabled. If %NULL, and @tab_label
3948 * is a #GtkLabel or %NULL, then the menu label will be
3949 * a newly created label with the same text as @tab_label;
3950 * If @tab_label is not a #GtkLabel, @menu_label must be
3951 * specified if the page-switch menu is to be used.
3952 * @position: the index (starting at 0) at which to insert the page,
3953 * or -1 to append the page after all other pages.
3955 * Insert a page into @notebook at the given position, specifying
3956 * the widget to use as the label in the popup menu.
3959 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3961 GtkWidget *tab_label,
3962 GtkWidget *menu_label,
3965 GtkNotebookPage *page;
3968 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3969 g_return_if_fail (GTK_IS_WIDGET (child));
3970 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3971 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3973 gtk_widget_freeze_child_notify (child);
3975 page = g_new (GtkNotebookPage, 1);
3976 page->child = child;
3977 page->last_focus_child = NULL;
3978 page->requisition.width = 0;
3979 page->requisition.height = 0;
3980 page->allocation.x = 0;
3981 page->allocation.y = 0;
3982 page->allocation.width = 0;
3983 page->allocation.height = 0;
3984 page->default_menu = FALSE;
3985 page->default_tab = FALSE;
3986 page->mnemonic_activate_signal = 0;
3988 nchildren = g_list_length (notebook->children);
3989 if ((position < 0) || (position > nchildren))
3990 position = nchildren;
3992 notebook->children = g_list_insert (notebook->children, page, position);
3996 page->default_tab = TRUE;
3997 if (notebook->show_tabs)
3998 tab_label = gtk_label_new ("");
4000 page->tab_label = tab_label;
4001 page->menu_label = menu_label;
4002 page->expand = FALSE;
4004 page->pack = GTK_PACK_START;
4007 page->default_menu = TRUE;
4010 g_object_ref (page->menu_label);
4011 gtk_object_sink (GTK_OBJECT (page->menu_label));
4015 gtk_notebook_menu_item_create (notebook,
4016 g_list_find (notebook->children, page));
4018 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4020 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4022 gtk_notebook_update_labels (notebook);
4024 if (!notebook->first_tab)
4025 notebook->first_tab = notebook->children;
4027 if (!notebook->cur_page)
4028 gtk_widget_set_child_visible (child, TRUE);
4030 gtk_widget_set_child_visible (child, FALSE);
4034 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4035 gtk_widget_show (tab_label);
4037 gtk_widget_hide (tab_label);
4040 if (!notebook->cur_page)
4042 gtk_notebook_switch_page (notebook, page, 0);
4043 gtk_notebook_switch_focus_tab (notebook, NULL);
4047 page->mnemonic_activate_signal =
4048 g_signal_connect (tab_label,
4049 "mnemonic_activate",
4050 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4053 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4054 gdk_window_show_unraised (notebook->event_window);
4056 gtk_widget_child_notify (child, "tab_expand");
4057 gtk_widget_child_notify (child, "tab_fill");
4058 gtk_widget_child_notify (child, "tab_pack");
4059 gtk_widget_child_notify (child, "tab_label");
4060 gtk_widget_child_notify (child, "menu_label");
4061 gtk_widget_child_notify (child, "position");
4062 gtk_widget_thaw_child_notify (child);
4066 * gtk_notebook_remove_page:
4067 * @notebook: a #GtkNotebook.
4068 * @page_num: the index of a notebook page, starting
4069 * from 0. If -1, the last page will
4072 * Removes a page from the notebook given its index
4076 gtk_notebook_remove_page (GtkNotebook *notebook,
4081 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4085 list = g_list_nth (notebook->children, page_num);
4087 gtk_notebook_real_remove (notebook, list);
4091 list = g_list_last (notebook->children);
4093 gtk_notebook_real_remove (notebook, list);
4097 /* Public GtkNotebook Page Switch Methods :
4098 * gtk_notebook_get_current_page
4099 * gtk_notebook_page_num
4100 * gtk_notebook_set_current_page
4101 * gtk_notebook_next_page
4102 * gtk_notebook_prev_page
4105 * gtk_notebook_get_current_page:
4106 * @notebook: a #GtkNotebook
4108 * Returns the page number of the current page.
4110 * Return value: the index (starting from 0) of the current
4111 * page in the notebook. If the notebook has no pages, then
4112 * -1 will be returned.
4115 gtk_notebook_get_current_page (GtkNotebook *notebook)
4117 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4119 if (!notebook->cur_page)
4122 return g_list_index (notebook->children, notebook->cur_page);
4126 * gtk_notebook_get_nth_page:
4127 * @notebook: a #GtkNotebook
4128 * @page_num: the index of a page in the noteobok, or -1
4129 * to get the last page.
4131 * Returns the child widget contained in page number @page_num.
4133 * Return value: the child widget, or %NULL if @page_num is
4137 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4140 GtkNotebookPage *page;
4143 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4146 list = g_list_nth (notebook->children, page_num);
4148 list = g_list_last (notebook->children);
4160 * gtk_notebook_get_n_pages:
4161 * @notebook: a #GtkNotebook
4163 * Gets the number of pages in a notebook.
4165 * Return value: the number of pages in the notebook.
4168 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4170 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4172 return g_list_length (notebook->children);
4176 * gtk_notebook_page_num:
4177 * @notebook: a #GtkNotebook
4178 * @child: a #GtkWidget
4180 * Finds the index of the page which contains the given child
4183 * Return value: the index of the page containing @child, or
4184 * -1 if @child is not in the notebook.
4187 gtk_notebook_page_num (GtkNotebook *notebook,
4193 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4196 children = notebook->children;
4199 GtkNotebookPage *page = children->data;
4201 if (page->child == child)
4204 children = children->next;
4212 * gtk_notebook_set_current_page:
4213 * @notebook: a #GtkNotebook
4214 * @page_num: index of the page to switch to, starting from 0.
4215 * If negative, the last page will be used. If greater
4216 * than the number of pages in the notebook, nothing
4219 * Switches to the page number @page_num.
4222 gtk_notebook_set_current_page (GtkNotebook *notebook,
4227 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4230 list = g_list_nth (notebook->children, page_num);
4232 list = g_list_last (notebook->children);
4234 page_num = g_list_index (notebook->children, list);
4237 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4241 * gtk_notebook_next_page:
4242 * @notebook: a #GtkNotebook
4244 * Switches to the next page. Nothing happens if the current page is
4248 gtk_notebook_next_page (GtkNotebook *notebook)
4252 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4254 list = g_list_find (notebook->children, notebook->cur_page);
4258 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4262 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4266 * gtk_notebook_prev_page:
4267 * @notebook: a #GtkNotebook
4269 * Switches to the previous page. Nothing happens if the current page
4270 * is the first page.
4273 gtk_notebook_prev_page (GtkNotebook *notebook)
4277 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4279 list = g_list_find (notebook->children, notebook->cur_page);
4283 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4287 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4290 /* Public GtkNotebook/Tab Style Functions
4292 * gtk_notebook_set_show_border
4293 * gtk_notebook_set_show_tabs
4294 * gtk_notebook_set_tab_pos
4295 * gtk_notebook_set_homogeneous_tabs
4296 * gtk_notebook_set_tab_border
4297 * gtk_notebook_set_tab_hborder
4298 * gtk_notebook_set_tab_vborder
4299 * gtk_notebook_set_scrollable
4302 * gtk_notebook_set_show_border:
4303 * @notebook: a #GtkNotebook
4304 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4306 * Sets whether a bevel will be drawn around the notebook pages.
4307 * This only has a visual effect when the tabs are not shown.
4308 * See gtk_notebook_set_show_tabs().
4311 gtk_notebook_set_show_border (GtkNotebook *notebook,
4312 gboolean show_border)
4314 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4316 if (notebook->show_border != show_border)
4318 notebook->show_border = show_border;
4320 if (GTK_WIDGET_VISIBLE (notebook))
4321 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4323 g_object_notify (G_OBJECT (notebook), "show_border");
4328 * gtk_notebook_get_show_border:
4329 * @notebook: a #GtkNotebook
4331 * Returns whether a bevel will be drawn around the notebook pages. See
4332 * gtk_notebook_set_show_border().
4334 * Return value: %TRUE if the bevel is drawn
4337 gtk_notebook_get_show_border (GtkNotebook *notebook)
4339 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4341 return notebook->show_border;
4345 * gtk_notebook_set_show_tabs:
4346 * @notebook: a #GtkNotebook
4347 * @show_tabs: %TRUE if the tabs should be shown.
4349 * Sets whether to show the tabs for the notebook or not.
4352 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4355 GtkNotebookPage *page;
4358 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4360 show_tabs = show_tabs != FALSE;
4362 if (notebook->show_tabs == show_tabs)
4365 notebook->show_tabs = show_tabs;
4366 children = notebook->children;
4370 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4374 page = children->data;
4375 children = children->next;
4376 if (page->default_tab)
4378 gtk_widget_destroy (page->tab_label);
4379 page->tab_label = NULL;
4382 gtk_widget_hide (page->tab_label);
4387 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4388 gtk_notebook_update_labels (notebook);
4390 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4392 g_object_notify (G_OBJECT (notebook), "show_tabs");
4396 * gtk_notebook_get_show_tabs:
4397 * @notebook: a #GtkNotebook
4399 * Returns whether the tabs of the notebook are shown. See
4400 * gtk_notebook_set_show_tabs().
4402 * Return value: %TRUE if the tabs are shown
4405 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4407 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4409 return notebook->show_tabs;
4413 * gtk_notebook_set_tab_pos:
4414 * @notebook: a #GtkNotebook.
4415 * @pos: the edge to draw the tabs at.
4417 * Sets the edge at which the tabs for switching pages in the
4418 * notebook are drawn.
4421 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4422 GtkPositionType pos)
4424 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4426 if (notebook->tab_pos != pos)
4428 notebook->tab_pos = pos;
4429 if (GTK_WIDGET_VISIBLE (notebook))
4430 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4433 g_object_notify (G_OBJECT (notebook), "tab_pos");
4437 * gtk_notebook_get_tab_pos:
4438 * @notebook: a #GtkNotebook
4440 * Gets the edge at which the tabs for switching pages in the
4441 * notebook are drawn.
4443 * Return value: the edge at which the tabs are drawn
4446 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4448 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4450 return notebook->tab_pos;
4454 * gtk_notebook_set_homogeneous_tabs:
4455 * @notebook: a #GtkNotebook
4456 * @homogeneous: %TRUE if all tabs should be the same size.
4458 * Sets whether the tabs must have all the same size or not.
4461 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4462 gboolean homogeneous)
4464 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4466 if (homogeneous == notebook->homogeneous)
4469 notebook->homogeneous = homogeneous;
4470 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4472 g_object_notify (G_OBJECT (notebook), "homogeneous");
4476 * gtk_notebook_set_tab_border:
4477 * @notebook: a #GtkNotebook
4478 * @border_width: width of the border around the tab labels.
4480 * Sets the width the border around the tab labels
4481 * in a notebook. This is equivalent to calling
4482 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4483 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4486 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4489 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4491 notebook->tab_hborder = border_width;
4492 notebook->tab_vborder = border_width;
4494 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4495 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4497 g_object_freeze_notify (G_OBJECT (notebook));
4498 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4499 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4500 g_object_thaw_notify (G_OBJECT (notebook));
4505 * gtk_notebook_set_tab_hborder:
4506 * @notebook: a #GtkNotebook
4507 * @tab_hborder: width of the horizontal border of tab labels.
4509 * Sets the width of the horizontal border of tab labels.
4512 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4515 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4517 if (notebook->tab_hborder == tab_hborder)
4520 notebook->tab_hborder = tab_hborder;
4522 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4523 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4525 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4529 * gtk_notebook_set_tab_vborder:
4530 * @notebook: a #GtkNotebook
4531 * @tab_vborder: width of the vertical border of tab labels.
4533 * Sets the width of the vertical border of tab labels.
4536 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4539 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4541 if (notebook->tab_vborder == tab_vborder)
4544 notebook->tab_vborder = tab_vborder;
4546 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4547 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4549 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4553 * gtk_notebook_set_scrollable:
4554 * @notebook: a #GtkNotebook
4555 * @scrollable: %TRUE if scroll arrows should be added
4557 * Sets whether the tab label area will have arrows for scrolling if
4558 * there are too many tabs to fit in the area.
4561 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4562 gboolean scrollable)
4564 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4566 scrollable = (scrollable != FALSE);
4568 if (scrollable != notebook->scrollable)
4570 notebook->scrollable = scrollable;
4572 if (GTK_WIDGET_VISIBLE (notebook))
4573 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4575 g_object_notify (G_OBJECT (notebook), "scrollable");
4580 * gtk_notebook_get_scrollable:
4581 * @notebook: a #GtkNotebook
4583 * Returns whether the tab label area has arrows for scrolling. See
4584 * gtk_notebook_set_scrollable().
4586 * Return value: %TRUE if arrows for scrolling are present
4589 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4591 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4593 return notebook->scrollable;
4596 /* Public GtkNotebook Popup Menu Methods:
4598 * gtk_notebook_popup_enable
4599 * gtk_notebook_popup_disable
4604 * gtk_notebook_popup_enable:
4605 * @notebook: a #GtkNotebook
4607 * Enables the popup menu: if the user clicks with the right mouse button on
4608 * the bookmarks, a menu with all the pages will be popped up.
4611 gtk_notebook_popup_enable (GtkNotebook *notebook)
4615 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4620 notebook->menu = gtk_menu_new ();
4621 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4623 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4624 gtk_notebook_menu_item_create (notebook, list);
4626 gtk_notebook_update_labels (notebook);
4627 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4628 GTK_WIDGET (notebook),
4629 gtk_notebook_menu_detacher);
4631 g_object_notify (G_OBJECT (notebook), "enable_popup");
4635 * gtk_notebook_popup_disable:
4636 * @notebook: a #GtkNotebook
4638 * Disables the popup menu.
4641 gtk_notebook_popup_disable (GtkNotebook *notebook)
4643 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4645 if (!notebook->menu)
4648 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4649 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4650 gtk_widget_destroy (notebook->menu);
4652 g_object_notify (G_OBJECT (notebook), "enable_popup");
4655 /* Public GtkNotebook Page Properties Functions:
4657 * gtk_notebook_get_tab_label
4658 * gtk_notebook_set_tab_label
4659 * gtk_notebook_set_tab_label_text
4660 * gtk_notebook_get_menu_label
4661 * gtk_notebook_set_menu_label
4662 * gtk_notebook_set_menu_label_text
4663 * gtk_notebook_set_tab_label_packing
4664 * gtk_notebook_query_tab_label_packing
4668 * gtk_notebook_get_tab_label:
4669 * @notebook: a #GtkNotebook
4672 * Returns the tab label widget for the page @child. %NULL is returned
4673 * if @child is not in @notebook or if no tab label has specifically
4674 * been set for @child.
4676 * Return value: the tab label
4679 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4684 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4685 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4687 list = CHECK_FIND_CHILD (notebook, child);
4691 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4694 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4698 * gtk_notebook_set_tab_label:
4699 * @notebook: a #GtkNotebook
4701 * @tab_label: the tab label widget to use, or %NULL for default tab
4704 * Changes the tab label for @child. If %NULL is specified
4705 * for @tab_label, then the page will have the label 'page N'.
4708 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4710 GtkWidget *tab_label)
4712 GtkNotebookPage *page;
4715 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4716 g_return_if_fail (GTK_IS_WIDGET (child));
4718 list = CHECK_FIND_CHILD (notebook, child);
4722 /* a NULL pointer indicates a default_tab setting, otherwise
4723 * we need to set the associated label
4727 if (page->tab_label == tab_label)
4731 gtk_notebook_remove_tab_label (notebook, page);
4735 page->default_tab = FALSE;
4736 page->tab_label = tab_label;
4737 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4741 page->default_tab = TRUE;
4742 page->tab_label = NULL;
4744 if (notebook->show_tabs)
4748 g_snprintf (string, sizeof(string), _("Page %u"),
4749 gtk_notebook_real_page_position (notebook, list));
4750 page->tab_label = gtk_label_new (string);
4751 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4755 if (page->tab_label)
4756 page->mnemonic_activate_signal =
4757 g_signal_connect (page->tab_label,
4758 "mnemonic_activate",
4759 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4762 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4764 gtk_widget_show (page->tab_label);
4765 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4767 gtk_widget_child_notify (child, "tab_label");
4771 * gtk_notebook_set_tab_label_text:
4772 * @notebook: a #GtkNotebook
4774 * @tab_text: the label text
4776 * Creates a new label and sets it as the tab label for the page
4777 * containing @child.
4780 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4782 const gchar *tab_text)
4784 GtkWidget *tab_label = NULL;
4786 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4789 tab_label = gtk_label_new (tab_text);
4790 gtk_notebook_set_tab_label (notebook, child, tab_label);
4791 gtk_widget_child_notify (child, "tab_label");
4795 * gtk_notebook_get_tab_label_text:
4796 * @notebook: a #GtkNotebook
4797 * @child: a widget contained in a page of @notebook
4799 * Retrieves the text of the tab label for the page containing
4802 * Returns value: the text of the tab label, or %NULL if the
4803 * tab label widget is not a #GtkLabel. The
4804 * string is owned by the widget and must not
4807 G_CONST_RETURN gchar *
4808 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4811 GtkWidget *tab_label;
4813 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4814 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4816 tab_label = gtk_notebook_get_tab_label (notebook, child);
4818 if (tab_label && GTK_IS_LABEL (tab_label))
4819 return gtk_label_get_text (GTK_LABEL (tab_label));
4825 * gtk_notebook_get_menu_label:
4826 * @notebook: a #GtkNotebook
4827 * @child: a widget contained in a page of @notebook
4829 * Retrieves the menu label widget of the page containing @child.
4831 * Return value: the menu label, or %NULL if the
4832 * notebook page does not have a menu label other
4833 * than the default (the tab label).
4836 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4841 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4842 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4844 list = CHECK_FIND_CHILD (notebook, child);
4848 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4851 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4855 * gtk_notebook_set_menu_label:
4856 * @notebook: a #GtkNotebook
4857 * @child: the child widget
4858 * @menu_label: the menu label, or NULL for default
4860 * Changes the menu label for the page containing @child.
4863 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4865 GtkWidget *menu_label)
4867 GtkNotebookPage *page;
4870 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4871 g_return_if_fail (GTK_IS_WIDGET (child));
4873 list = CHECK_FIND_CHILD (notebook, child);
4878 if (page->menu_label)
4881 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4882 page->menu_label->parent);
4884 if (!page->default_menu)
4885 g_object_unref (page->menu_label);
4890 page->menu_label = menu_label;
4891 g_object_ref (page->menu_label);
4892 gtk_object_sink (GTK_OBJECT(page->menu_label));
4893 page->default_menu = FALSE;
4896 page->default_menu = TRUE;
4899 gtk_notebook_menu_item_create (notebook, list);
4900 gtk_widget_child_notify (child, "menu_label");
4904 * gtk_notebook_set_menu_label_text:
4905 * @notebook: a #GtkNotebook
4906 * @child: the child widget
4907 * @menu_text: the label text
4909 * Creates a new label and sets it as the menu label of @child.
4912 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4914 const gchar *menu_text)
4916 GtkWidget *menu_label = NULL;
4918 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4921 menu_label = gtk_label_new (menu_text);
4922 gtk_notebook_set_menu_label (notebook, child, menu_label);
4923 gtk_widget_child_notify (child, "menu_label");
4927 * gtk_notebook_get_menu_label_text:
4928 * @notebook: a #GtkNotebook
4929 * @child: the child widget of a page of the notebook.
4931 * Retrieves the text of the menu label for the page containing
4934 * Returns value: the text of the tab label, or %NULL if the
4935 * widget does not have a menu label other than
4936 * the default menu label, or the menu label widget
4937 * is not a #GtkLabel. The string is owned by
4938 * the widget and must not be freed.
4940 G_CONST_RETURN gchar *
4941 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4944 GtkWidget *menu_label;
4946 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4947 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4949 menu_label = gtk_notebook_get_menu_label (notebook, child);
4951 if (menu_label && GTK_IS_LABEL (menu_label))
4952 return gtk_label_get_text (GTK_LABEL (menu_label));
4957 /* Helper function called when pages are reordered
4960 gtk_notebook_child_reordered (GtkNotebook *notebook,
4961 GtkNotebookPage *page)
4965 GtkWidget *menu_item;
4967 menu_item = page->menu_label->parent;
4968 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4969 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4970 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4973 gtk_notebook_update_labels (notebook);
4977 * gtk_notebook_set_tab_label_packing:
4978 * @notebook: a #GtkNotebook
4979 * @child: the child widget
4980 * @expand: whether to expand the bookmark or not
4981 * @fill: whether the bookmark should fill the allocated area or not
4982 * @pack_type: the position of the bookmark
4984 * Sets the packing parameters for the tab label of the page
4985 * containing @child. See gtk_box_pack_start() for the exact meaning
4986 * of the parameters.
4989 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4993 GtkPackType pack_type)
4995 GtkNotebookPage *page;
4998 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4999 g_return_if_fail (GTK_IS_WIDGET (child));
5001 list = CHECK_FIND_CHILD (notebook, child);
5006 expand = expand != FALSE;
5007 fill = fill != FALSE;
5008 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5011 gtk_widget_freeze_child_notify (child);
5012 page->expand = expand;
5013 gtk_widget_child_notify (child, "tab_expand");
5015 gtk_widget_child_notify (child, "tab_fill");
5016 if (page->pack != pack_type)
5018 page->pack = pack_type;
5019 gtk_notebook_child_reordered (notebook, page);
5021 gtk_widget_child_notify (child, "tab_pack");
5022 gtk_widget_child_notify (child, "position");
5023 if (notebook->show_tabs)
5024 gtk_notebook_pages_allocate (notebook);
5025 gtk_widget_thaw_child_notify (child);
5029 * gtk_notebook_query_tab_label_packing:
5030 * @notebook: a #GtkNotebook
5032 * @expand: location to store the expand value (or NULL)
5033 * @fill: location to store the fill value (or NULL)
5034 * @pack_type: location to store the pack_type (or NULL)
5036 * Query the packing attributes for the tab label of the page
5037 * containing @child.
5040 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5044 GtkPackType *pack_type)
5048 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5049 g_return_if_fail (GTK_IS_WIDGET (child));
5051 list = CHECK_FIND_CHILD (notebook, child);
5056 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5058 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5060 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5064 * gtk_notebook_reorder_child:
5065 * @notebook: a #GtkNotebook
5066 * @child: the child to move
5067 * @position: the new position, or -1 to move to the end
5069 * Reorders the page containing @child, so that it appears in position
5070 * @position. If @position is greater than or equal to the number of
5071 * children in the list or negative, @child will be moved to the end
5075 gtk_notebook_reorder_child (GtkNotebook *notebook,
5079 GList *list, *new_list;
5080 GtkNotebookPage *page;
5084 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5085 g_return_if_fail (GTK_IS_WIDGET (child));
5087 list = CHECK_FIND_CHILD (notebook, child);
5091 max_pos = g_list_length (notebook->children) - 1;
5092 if (position < 0 || position > max_pos)
5095 old_pos = g_list_position (notebook->children, list);
5097 if (old_pos == position)
5101 notebook->children = g_list_delete_link (notebook->children, list);
5103 notebook->children = g_list_insert (notebook->children, page, position);
5104 new_list = g_list_nth (notebook->children, position);
5106 /* Fix up GList references in GtkNotebook structure */
5107 if (notebook->first_tab == list)
5108 notebook->first_tab = new_list;
5109 if (notebook->focus_tab == list)
5110 notebook->focus_tab = new_list;
5112 gtk_widget_freeze_child_notify (child);
5114 /* Move around the menu items if necesary */
5115 gtk_notebook_child_reordered (notebook, page);
5116 gtk_widget_child_notify (child, "tab_pack");
5117 gtk_widget_child_notify (child, "position");
5119 if (notebook->show_tabs)
5120 gtk_notebook_pages_allocate (notebook);
5122 gtk_widget_thaw_child_notify (child);