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"
28 #include "gtksignal.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
36 #include "gtkmarshalers.h"
37 #include "gtkbindings.h"
41 #define TAB_CURVATURE 1
43 #define ARROW_SPACING 0
44 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
45 #define NOTEBOOK_SCROLL_DELAY (100)
79 CHILD_PROP_MENU_LABEL,
81 CHILD_PROP_TAB_EXPAND,
86 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
88 struct _GtkNotebookPage
92 GtkWidget *menu_label;
93 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
95 guint default_menu : 1; /* If true, we create the menu label ourself */
96 guint default_tab : 1; /* If true, we create the tab label ourself */
101 GtkRequisition requisition;
102 GtkAllocation allocation;
104 guint mnemonic_activate_signal;
107 #ifdef G_DISABLE_CHECKS
108 #define CHECK_FIND_CHILD(notebook, child) \
109 gtk_notebook_find_child (notebook, child, G_STRLOC)
111 #define CHECK_FIND_CHILD(notebook, child) \
112 gtk_notebook_find_child (notebook, child, NULL)
115 /*** GtkNotebook Methods ***/
116 static void gtk_notebook_class_init (GtkNotebookClass *klass);
117 static void gtk_notebook_init (GtkNotebook *notebook);
119 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
120 gboolean move_focus);
121 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
122 GtkNotebookTab type);
123 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
125 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
126 GtkDirectionType direction_type);
128 /*** GtkObject Methods ***/
129 static void gtk_notebook_destroy (GtkObject *object);
130 static void gtk_notebook_set_property (GObject *object,
134 static void gtk_notebook_get_property (GObject *object,
139 /*** GtkWidget Methods ***/
140 static void gtk_notebook_map (GtkWidget *widget);
141 static void gtk_notebook_unmap (GtkWidget *widget);
142 static void gtk_notebook_realize (GtkWidget *widget);
143 static void gtk_notebook_unrealize (GtkWidget *widget);
144 static void gtk_notebook_size_request (GtkWidget *widget,
145 GtkRequisition *requisition);
146 static void gtk_notebook_size_allocate (GtkWidget *widget,
147 GtkAllocation *allocation);
148 static gint gtk_notebook_expose (GtkWidget *widget,
149 GdkEventExpose *event);
150 static gint gtk_notebook_button_press (GtkWidget *widget,
151 GdkEventButton *event);
152 static gint gtk_notebook_button_release (GtkWidget *widget,
153 GdkEventButton *event);
154 static gint gtk_notebook_enter_notify (GtkWidget *widget,
155 GdkEventCrossing *event);
156 static gint gtk_notebook_leave_notify (GtkWidget *widget,
157 GdkEventCrossing *event);
158 static gint gtk_notebook_motion_notify (GtkWidget *widget,
159 GdkEventMotion *event);
160 static gint gtk_notebook_focus_in (GtkWidget *widget,
161 GdkEventFocus *event);
162 static void gtk_notebook_draw_focus (GtkWidget *widget);
163 static gint gtk_notebook_focus (GtkWidget *widget,
164 GtkDirectionType direction);
166 /*** GtkContainer Methods ***/
167 static void gtk_notebook_set_child_property (GtkContainer *container,
172 static void gtk_notebook_get_child_property (GtkContainer *container,
177 static void gtk_notebook_add (GtkContainer *container,
179 static void gtk_notebook_remove (GtkContainer *container,
181 static void gtk_notebook_set_focus_child (GtkContainer *container,
183 static GtkType gtk_notebook_child_type (GtkContainer *container);
184 static void gtk_notebook_forall (GtkContainer *container,
185 gboolean include_internals,
186 GtkCallback callback,
187 gpointer callback_data);
189 /*** GtkNotebook Private Functions ***/
190 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
191 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
192 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
193 GtkNotebookPage *old_page);
194 static void gtk_notebook_real_remove (GtkNotebook *notebook,
196 static void gtk_notebook_update_labels (GtkNotebook *notebook);
197 static gint gtk_notebook_timer (GtkNotebook *notebook);
198 static gint gtk_notebook_page_compare (gconstpointer a,
200 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
202 const gchar *function);
203 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
205 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
208 gboolean find_visible);
210 /*** GtkNotebook Drawing Functions ***/
211 static void gtk_notebook_paint (GtkWidget *widget,
213 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
214 GtkNotebookPage *page,
216 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
219 /*** GtkNotebook Size Allocate Functions ***/
220 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
221 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
222 GtkNotebookPage *page,
223 GtkAllocation *allocation);
224 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
230 /*** GtkNotebook Page Switch Methods ***/
231 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
232 GtkNotebookPage *page,
235 /*** GtkNotebook Page Switch Functions ***/
236 static void gtk_notebook_switch_page (GtkNotebook *notebook,
237 GtkNotebookPage *page,
239 static gint gtk_notebook_page_select (GtkNotebook *notebook,
240 gboolean move_focus);
241 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
243 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
244 GtkNotebookPage *page);
246 /*** GtkNotebook Menu Functions ***/
247 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
249 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
251 static void gtk_notebook_menu_detacher (GtkWidget *widget,
254 static gboolean focus_tabs_in (GtkNotebook *notebook);
255 static gboolean focus_child_in (GtkNotebook *notebook,
256 GtkDirectionType direction);
258 static GtkContainerClass *parent_class = NULL;
259 static guint notebook_signals[LAST_SIGNAL] = { 0 };
262 gtk_notebook_get_type (void)
264 static GtkType notebook_type = 0;
268 static const GtkTypeInfo notebook_info =
271 sizeof (GtkNotebook),
272 sizeof (GtkNotebookClass),
273 (GtkClassInitFunc) gtk_notebook_class_init,
274 (GtkObjectInitFunc) gtk_notebook_init,
275 /* reserved_1 */ NULL,
276 /* reserved_2 */ NULL,
277 (GtkClassInitFunc) NULL,
280 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
283 return notebook_type;
287 add_tab_bindings (GtkBindingSet *binding_set,
288 GdkModifierType modifiers,
289 GtkDirectionType direction)
291 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
293 GTK_TYPE_DIRECTION_TYPE, direction);
294 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
296 GTK_TYPE_DIRECTION_TYPE, direction);
300 add_arrow_bindings (GtkBindingSet *binding_set,
302 GtkDirectionType direction)
304 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
306 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
308 GTK_TYPE_DIRECTION_TYPE, direction);
309 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
311 GTK_TYPE_DIRECTION_TYPE, direction);
315 gtk_notebook_class_init (GtkNotebookClass *class)
317 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
318 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
319 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
320 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
321 GtkBindingSet *binding_set;
323 parent_class = g_type_class_peek_parent (class);
325 gobject_class->set_property = gtk_notebook_set_property;
326 gobject_class->get_property = gtk_notebook_get_property;
327 object_class->destroy = gtk_notebook_destroy;
329 widget_class->map = gtk_notebook_map;
330 widget_class->unmap = gtk_notebook_unmap;
331 widget_class->realize = gtk_notebook_realize;
332 widget_class->unrealize = gtk_notebook_unrealize;
333 widget_class->size_request = gtk_notebook_size_request;
334 widget_class->size_allocate = gtk_notebook_size_allocate;
335 widget_class->expose_event = gtk_notebook_expose;
336 widget_class->button_press_event = gtk_notebook_button_press;
337 widget_class->button_release_event = gtk_notebook_button_release;
338 widget_class->enter_notify_event = gtk_notebook_enter_notify;
339 widget_class->leave_notify_event = gtk_notebook_leave_notify;
340 widget_class->motion_notify_event = gtk_notebook_motion_notify;
341 widget_class->focus_in_event = gtk_notebook_focus_in;
342 widget_class->focus = gtk_notebook_focus;
344 container_class->add = gtk_notebook_add;
345 container_class->remove = gtk_notebook_remove;
346 container_class->forall = gtk_notebook_forall;
347 container_class->set_focus_child = gtk_notebook_set_focus_child;
348 container_class->get_child_property = gtk_notebook_get_child_property;
349 container_class->set_child_property = gtk_notebook_set_child_property;
350 container_class->child_type = gtk_notebook_child_type;
352 class->switch_page = gtk_notebook_real_switch_page;
354 class->focus_tab = gtk_notebook_focus_tab;
355 class->select_page = gtk_notebook_select_page;
356 class->change_current_page = gtk_notebook_change_current_page;
357 class->move_focus_out = gtk_notebook_move_focus_out;
359 g_object_class_install_property (gobject_class,
361 g_param_spec_int ("page",
363 _("The index of the current page"),
368 g_object_class_install_property (gobject_class,
370 g_param_spec_enum ("tab_pos",
372 _("Which side of the notebook holds the tabs"),
373 GTK_TYPE_POSITION_TYPE,
376 g_object_class_install_property (gobject_class,
378 g_param_spec_uint ("tab_border",
380 _("Width of the border around the tab labels"),
385 g_object_class_install_property (gobject_class,
387 g_param_spec_uint ("tab_hborder",
388 _("Horizontal Tab Border"),
389 _("Width of the horizontal border of tab labels"),
394 g_object_class_install_property (gobject_class,
396 g_param_spec_uint ("tab_vborder",
397 _("Vertical Tab Border"),
398 _("Width of the vertical border of tab labels"),
403 g_object_class_install_property (gobject_class,
405 g_param_spec_boolean ("show_tabs",
407 _("Whether tabs should be shown or not"),
410 g_object_class_install_property (gobject_class,
412 g_param_spec_boolean ("show_border",
414 _("Whether the border should be shown or not"),
417 g_object_class_install_property (gobject_class,
419 g_param_spec_boolean ("scrollable",
421 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
424 g_object_class_install_property (gobject_class,
426 g_param_spec_boolean ("enable_popup",
428 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
431 g_object_class_install_property (gobject_class,
433 g_param_spec_boolean ("homogeneous",
435 _("Whether tabs should have homogeneous sizes"),
439 gtk_container_class_install_child_property (container_class,
440 CHILD_PROP_TAB_LABEL,
441 g_param_spec_string ("tab_label",
443 _("The string displayed on the childs tab label"),
446 gtk_container_class_install_child_property (container_class,
447 CHILD_PROP_MENU_LABEL,
448 g_param_spec_string ("menu_label",
450 _("The string displayed in the childs menu entry"),
453 gtk_container_class_install_child_property (container_class,
455 g_param_spec_int ("position",
457 _("The index of the child in the parent"),
460 gtk_container_class_install_child_property (container_class,
461 CHILD_PROP_TAB_EXPAND,
462 g_param_spec_boolean ("tab_expand",
464 _("Whether to expand the childs tab or not"),
467 gtk_container_class_install_child_property (container_class,
469 g_param_spec_boolean ("tab_fill",
471 _("Wheather the childs tab should fill the allocated area or not"),
474 gtk_container_class_install_child_property (container_class,
476 g_param_spec_enum ("tab_pack",
478 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
479 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
482 notebook_signals[SWITCH_PAGE] =
483 gtk_signal_new ("switch_page",
485 GTK_CLASS_TYPE (object_class),
486 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
487 _gtk_marshal_VOID__POINTER_UINT,
491 notebook_signals[FOCUS_TAB] =
492 g_signal_new ("focus_tab",
493 G_TYPE_FROM_CLASS (object_class),
494 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
495 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
497 _gtk_marshal_BOOLEAN__ENUM,
499 GTK_TYPE_NOTEBOOK_TAB);
500 notebook_signals[SELECT_PAGE] =
501 g_signal_new ("select_page",
502 G_TYPE_FROM_CLASS (object_class),
503 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
504 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
506 _gtk_marshal_BOOLEAN__BOOLEAN,
509 notebook_signals[CHANGE_CURRENT_PAGE] =
510 g_signal_new ("change_current_page",
511 G_TYPE_FROM_CLASS (object_class),
512 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
513 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
515 _gtk_marshal_VOID__INT,
518 notebook_signals[MOVE_FOCUS_OUT] =
519 g_signal_new ("move_focus_out",
520 G_TYPE_FROM_CLASS (object_class),
521 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
522 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
524 _gtk_marshal_VOID__ENUM,
526 GTK_TYPE_DIRECTION_TYPE);
529 binding_set = gtk_binding_set_by_class (object_class);
530 gtk_binding_entry_add_signal (binding_set,
533 G_TYPE_BOOLEAN, FALSE);
534 gtk_binding_entry_add_signal (binding_set,
537 G_TYPE_BOOLEAN, FALSE);
539 gtk_binding_entry_add_signal (binding_set,
542 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
543 gtk_binding_entry_add_signal (binding_set,
546 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
547 gtk_binding_entry_add_signal (binding_set,
550 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
551 gtk_binding_entry_add_signal (binding_set,
554 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
556 gtk_binding_entry_add_signal (binding_set,
557 GDK_Page_Up, GDK_CONTROL_MASK,
558 "change_current_page", 1,
560 gtk_binding_entry_add_signal (binding_set,
561 GDK_Page_Down, GDK_CONTROL_MASK,
562 "change_current_page", 1,
565 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
566 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
567 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
568 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
570 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
571 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
575 gtk_notebook_init (GtkNotebook *notebook)
577 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
578 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
580 notebook->cur_page = NULL;
581 notebook->children = NULL;
582 notebook->first_tab = NULL;
583 notebook->focus_tab = NULL;
584 notebook->event_window = NULL;
585 notebook->menu = NULL;
587 notebook->tab_hborder = 2;
588 notebook->tab_vborder = 2;
590 notebook->show_tabs = TRUE;
591 notebook->show_border = TRUE;
592 notebook->tab_pos = GTK_POS_TOP;
593 notebook->scrollable = FALSE;
594 notebook->in_child = 0;
595 notebook->click_child = 0;
596 notebook->button = 0;
597 notebook->need_timer = 0;
598 notebook->child_has_focus = FALSE;
599 notebook->have_visible_child = FALSE;
600 notebook->focus_out = FALSE;
604 gtk_notebook_select_page (GtkNotebook *notebook,
607 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
609 gtk_notebook_page_select (notebook, move_focus);
617 gtk_notebook_focus_tab (GtkNotebook *notebook,
622 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
626 case GTK_NOTEBOOK_TAB_FIRST:
627 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
629 gtk_notebook_switch_focus_tab (notebook, list);
631 case GTK_NOTEBOOK_TAB_LAST:
632 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
634 gtk_notebook_switch_focus_tab (notebook, list);
645 gtk_notebook_change_current_page (GtkNotebook *notebook,
648 GList *current = NULL;
650 if (notebook->cur_page)
651 current = g_list_find (notebook->children, notebook->cur_page);
655 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
656 offset += offset < 0 ? 1 : -1;
660 gtk_notebook_switch_page (notebook, current->data, -1);
662 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
665 static GtkDirectionType
666 get_effective_direction (GtkNotebook *notebook,
667 GtkDirectionType direction)
669 /* Remap the directions into the effective direction it would be for a
670 * GTK_POS_TOP notebook
672 #define D(rest) GTK_DIR_##rest
674 static const GtkDirectionType translate_direction[4][6] = {
675 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
676 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
677 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
678 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
683 return translate_direction[notebook->tab_pos][direction];
687 gtk_notebook_move_focus_out (GtkNotebook *notebook,
688 GtkDirectionType direction_type)
690 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
693 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
694 if (focus_tabs_in (notebook))
697 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
698 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
701 /* At this point, we know we should be focusing out of the notebook entirely. We
702 * do this by setting a flag, then propagating the focus motion to the notebook.
704 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
705 if (!GTK_WIDGET_TOPLEVEL (toplevel))
708 g_object_ref (notebook);
710 notebook->focus_out = TRUE;
711 g_signal_emit_by_name (G_OBJECT (toplevel), "move_focus", direction_type);
712 notebook->focus_out = FALSE;
714 g_object_unref (notebook);
721 * Creates a new #GtkNotebook widget with no pages.
723 * Return value: the newly created #GtkNotebook
726 gtk_notebook_new (void)
728 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
731 /* Private GtkObject Methods :
733 * gtk_notebook_destroy
734 * gtk_notebook_set_arg
735 * gtk_notebook_get_arg
738 gtk_notebook_destroy (GtkObject *object)
740 GtkNotebook *notebook = GTK_NOTEBOOK (object);
743 gtk_notebook_popup_disable (notebook);
745 GTK_OBJECT_CLASS (parent_class)->destroy (object);
749 gtk_notebook_set_property (GObject *object,
754 GtkNotebook *notebook;
756 notebook = GTK_NOTEBOOK (object);
761 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
763 case PROP_SHOW_BORDER:
764 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
766 case PROP_SCROLLABLE:
767 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
769 case PROP_ENABLE_POPUP:
770 if (g_value_get_boolean (value))
771 gtk_notebook_popup_enable (notebook);
773 gtk_notebook_popup_disable (notebook);
775 case PROP_HOMOGENEOUS:
776 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
779 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
782 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
784 case PROP_TAB_BORDER:
785 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
787 case PROP_TAB_HBORDER:
788 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
790 case PROP_TAB_VBORDER:
791 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
799 gtk_notebook_get_property (GObject *object,
804 GtkNotebook *notebook;
806 notebook = GTK_NOTEBOOK (object);
811 g_value_set_boolean (value, notebook->show_tabs);
813 case PROP_SHOW_BORDER:
814 g_value_set_boolean (value, notebook->show_border);
816 case PROP_SCROLLABLE:
817 g_value_set_boolean (value, notebook->scrollable);
819 case PROP_ENABLE_POPUP:
820 g_value_set_boolean (value, notebook->menu != NULL);
822 case PROP_HOMOGENEOUS:
823 g_value_set_boolean (value, notebook->homogeneous);
826 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
829 g_value_set_enum (value, notebook->tab_pos);
831 case PROP_TAB_HBORDER:
832 g_value_set_uint (value, notebook->tab_hborder);
834 case PROP_TAB_VBORDER:
835 g_value_set_uint (value, notebook->tab_vborder);
838 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
843 /* Private GtkWidget Methods :
847 * gtk_notebook_realize
848 * gtk_notebook_size_request
849 * gtk_notebook_size_allocate
850 * gtk_notebook_expose
851 * gtk_notebook_button_press
852 * gtk_notebook_button_release
853 * gtk_notebook_enter_notify
854 * gtk_notebook_leave_notify
855 * gtk_notebook_motion_notify
856 * gtk_notebook_focus_in
857 * gtk_notebook_focus_out
858 * gtk_notebook_draw_focus
859 * gtk_notebook_style_set
862 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
863 GdkRectangle *rectangle)
865 GtkWidget *widget = GTK_WIDGET (notebook);
866 gint border_width = GTK_CONTAINER (notebook)->border_width;
868 if (notebook->show_tabs && notebook->children)
872 GtkNotebookPage *page = notebook->children->data;
874 rectangle->x = widget->allocation.x + border_width;
875 rectangle->y = widget->allocation.y + border_width;
877 switch (notebook->tab_pos)
881 rectangle->width = widget->allocation.width - 2 * border_width;
882 rectangle->height = page->requisition.height;
883 if (notebook->tab_pos == GTK_POS_BOTTOM)
884 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
888 rectangle->width = page->requisition.width;
889 rectangle->height = widget->allocation.height - 2 * border_width;
890 if (notebook->tab_pos == GTK_POS_RIGHT)
891 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
902 rectangle->x = rectangle->y = 0;
903 rectangle->width = rectangle->height = 10;
911 gtk_notebook_map (GtkWidget *widget)
913 GtkNotebook *notebook;
914 GtkNotebookPage *page;
917 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
919 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
921 notebook = GTK_NOTEBOOK (widget);
923 if (notebook->cur_page &&
924 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
925 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
926 gtk_widget_map (notebook->cur_page->child);
928 if (notebook->scrollable)
929 gtk_notebook_pages_allocate (notebook);
932 children = notebook->children;
936 page = children->data;
937 children = children->next;
939 if (page->tab_label &&
940 GTK_WIDGET_VISIBLE (page->tab_label) &&
941 !GTK_WIDGET_MAPPED (page->tab_label))
942 gtk_widget_map (page->tab_label);
946 if (gtk_notebook_get_event_window_position (notebook, NULL))
947 gdk_window_show_unraised (notebook->event_window);
951 gtk_notebook_unmap (GtkWidget *widget)
953 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
955 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
957 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
959 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
963 gtk_notebook_realize (GtkWidget *widget)
965 GtkNotebook *notebook;
966 GdkWindowAttr attributes;
967 gint attributes_mask;
968 GdkRectangle event_window_pos;
970 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
972 notebook = GTK_NOTEBOOK (widget);
973 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
975 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
977 widget->window = gtk_widget_get_parent_window (widget);
978 gdk_window_ref (widget->window);
980 attributes.window_type = GDK_WINDOW_CHILD;
981 attributes.x = event_window_pos.x;
982 attributes.y = event_window_pos.y;
983 attributes.width = event_window_pos.width;
984 attributes.height = event_window_pos.height;
985 attributes.wclass = GDK_INPUT_ONLY;
986 attributes.event_mask = gtk_widget_get_events (widget);
987 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
988 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
990 attributes_mask = GDK_WA_X | GDK_WA_Y;
992 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
993 &attributes, attributes_mask);
994 gdk_window_set_user_data (notebook->event_window, notebook);
996 widget->style = gtk_style_attach (widget->style, widget->window);
1000 gtk_notebook_unrealize (GtkWidget *widget)
1002 GtkNotebook *notebook;
1004 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1006 notebook = GTK_NOTEBOOK (widget);
1008 gdk_window_set_user_data (notebook->event_window, NULL);
1009 gdk_window_destroy (notebook->event_window);
1010 notebook->event_window = NULL;
1012 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1013 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1017 gtk_notebook_size_request (GtkWidget *widget,
1018 GtkRequisition *requisition)
1020 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1021 GtkNotebookPage *page;
1023 GtkRequisition child_requisition;
1024 gboolean switch_page = FALSE;
1028 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1030 widget->requisition.width = 0;
1031 widget->requisition.height = 0;
1033 for (children = notebook->children, vis_pages = 0; children;
1034 children = children->next)
1036 page = children->data;
1038 if (GTK_WIDGET_VISIBLE (page->child))
1041 gtk_widget_size_request (page->child, &child_requisition);
1043 widget->requisition.width = MAX (widget->requisition.width,
1044 child_requisition.width);
1045 widget->requisition.height = MAX (widget->requisition.height,
1046 child_requisition.height);
1048 if (notebook->menu && page->menu_label->parent &&
1049 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1050 gtk_widget_show (page->menu_label->parent);
1054 if (page == notebook->cur_page)
1056 if (notebook->menu && page->menu_label->parent &&
1057 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1058 gtk_widget_hide (page->menu_label->parent);
1062 if (notebook->show_border || notebook->show_tabs)
1064 widget->requisition.width += widget->style->xthickness * 2;
1065 widget->requisition.height += widget->style->ythickness * 2;
1067 if (notebook->show_tabs)
1070 gint tab_height = 0;
1074 for (children = notebook->children; children;
1075 children = children->next)
1077 page = children->data;
1079 if (GTK_WIDGET_VISIBLE (page->child))
1081 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1082 gtk_widget_show (page->tab_label);
1084 gtk_widget_size_request (page->tab_label,
1085 &child_requisition);
1087 page->requisition.width =
1088 child_requisition.width +
1089 2 * widget->style->xthickness;
1090 page->requisition.height =
1091 child_requisition.height +
1092 2 * widget->style->ythickness;
1094 switch (notebook->tab_pos)
1097 case GTK_POS_BOTTOM:
1098 page->requisition.height += 2 * (notebook->tab_vborder +
1100 tab_height = MAX (tab_height, page->requisition.height);
1101 tab_max = MAX (tab_max, page->requisition.width);
1105 page->requisition.width += 2 * (notebook->tab_hborder +
1107 tab_width = MAX (tab_width, page->requisition.width);
1108 tab_max = MAX (tab_max, page->requisition.height);
1112 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1113 gtk_widget_hide (page->tab_label);
1116 children = notebook->children;
1120 switch (notebook->tab_pos)
1123 case GTK_POS_BOTTOM:
1124 if (tab_height == 0)
1127 if (notebook->scrollable && vis_pages > 1 &&
1128 widget->requisition.width < tab_width)
1129 tab_height = MAX (tab_height, ARROW_SIZE);
1131 padding = 2 * (TAB_CURVATURE + focus_width +
1132 notebook->tab_hborder) - TAB_OVERLAP;
1136 page = children->data;
1137 children = children->next;
1139 if (!GTK_WIDGET_VISIBLE (page->child))
1142 if (notebook->homogeneous)
1143 page->requisition.width = tab_max;
1145 page->requisition.width += padding;
1147 tab_width += page->requisition.width;
1148 page->requisition.height = tab_height;
1151 if (notebook->scrollable && vis_pages > 1 &&
1152 widget->requisition.width < tab_width)
1153 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1155 if (notebook->homogeneous && !notebook->scrollable)
1156 widget->requisition.width = MAX (widget->requisition.width,
1157 vis_pages * tab_max +
1160 widget->requisition.width = MAX (widget->requisition.width,
1161 tab_width + TAB_OVERLAP);
1163 widget->requisition.height += tab_height;
1170 if (notebook->scrollable && vis_pages > 1 &&
1171 widget->requisition.height < tab_height)
1172 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1174 padding = 2 * (TAB_CURVATURE + focus_width +
1175 notebook->tab_vborder) - TAB_OVERLAP;
1180 page = children->data;
1181 children = children->next;
1183 if (!GTK_WIDGET_VISIBLE (page->child))
1186 page->requisition.width = tab_width;
1188 if (notebook->homogeneous)
1189 page->requisition.height = tab_max;
1191 page->requisition.height += padding;
1193 tab_height += page->requisition.height;
1196 if (notebook->scrollable && vis_pages > 1 &&
1197 widget->requisition.height < tab_height)
1198 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1200 widget->requisition.width += tab_width;
1202 if (notebook->homogeneous && !notebook->scrollable)
1203 widget->requisition.height =
1204 MAX (widget->requisition.height,
1205 vis_pages * tab_max + TAB_OVERLAP);
1207 widget->requisition.height =
1208 MAX (widget->requisition.height,
1209 tab_height + TAB_OVERLAP);
1211 if (!notebook->homogeneous || notebook->scrollable)
1213 widget->requisition.height = MAX (widget->requisition.height,
1214 vis_pages * tab_max +
1222 for (children = notebook->children; children;
1223 children = children->next)
1225 page = children->data;
1227 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1228 gtk_widget_hide (page->tab_label);
1233 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1234 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1240 for (children = notebook->children; children;
1241 children = children->next)
1243 page = children->data;
1244 if (GTK_WIDGET_VISIBLE (page->child))
1246 gtk_notebook_switch_page (notebook, page, -1);
1251 else if (GTK_WIDGET_VISIBLE (widget))
1253 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1254 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1257 if (vis_pages && !notebook->cur_page)
1259 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1262 notebook->first_tab = children;
1263 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1269 gtk_notebook_size_allocate (GtkWidget *widget,
1270 GtkAllocation *allocation)
1272 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1275 widget->allocation = *allocation;
1276 if (GTK_WIDGET_REALIZED (widget))
1278 GdkRectangle position;
1280 if (gtk_notebook_get_event_window_position (notebook, &position))
1281 gdk_window_move_resize (notebook->event_window,
1282 position.x, position.y,
1283 position.width, position.height);
1286 if (notebook->children)
1288 gint border_width = GTK_CONTAINER (widget)->border_width;
1289 GtkNotebookPage *page;
1290 GtkAllocation child_allocation;
1293 child_allocation.x = widget->allocation.x + border_width;
1294 child_allocation.y = widget->allocation.y + border_width;
1295 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1296 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1298 if (notebook->show_tabs || notebook->show_border)
1300 child_allocation.x += widget->style->xthickness;
1301 child_allocation.y += widget->style->ythickness;
1302 child_allocation.width = MAX (1, child_allocation.width -
1303 widget->style->xthickness * 2);
1304 child_allocation.height = MAX (1, child_allocation.height -
1305 widget->style->ythickness * 2);
1307 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1309 switch (notebook->tab_pos)
1312 child_allocation.y += notebook->cur_page->requisition.height;
1313 case GTK_POS_BOTTOM:
1314 child_allocation.height =
1315 MAX (1, child_allocation.height -
1316 notebook->cur_page->requisition.height);
1319 child_allocation.x += notebook->cur_page->requisition.width;
1321 child_allocation.width =
1322 MAX (1, child_allocation.width -
1323 notebook->cur_page->requisition.width);
1329 children = notebook->children;
1332 page = children->data;
1333 children = children->next;
1335 if (GTK_WIDGET_VISIBLE (page->child))
1337 gtk_widget_size_allocate (page->child, &child_allocation);
1342 gtk_notebook_pages_allocate (notebook);
1345 if ((vis_pages != 0) != notebook->have_visible_child)
1347 notebook->have_visible_child = (vis_pages != 0);
1348 if (notebook->show_tabs)
1349 gtk_widget_queue_draw (widget);
1354 gtk_notebook_expose (GtkWidget *widget,
1355 GdkEventExpose *event)
1357 GtkNotebook *notebook;
1358 GdkRectangle child_area;
1360 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1361 g_return_val_if_fail (event != NULL, FALSE);
1363 if (GTK_WIDGET_DRAWABLE (widget))
1365 notebook = GTK_NOTEBOOK (widget);
1367 gtk_notebook_paint (widget, &event->area);
1368 if (notebook->show_tabs)
1370 if (notebook->cur_page &&
1371 gtk_widget_intersect (notebook->cur_page->tab_label,
1372 &event->area, &child_area))
1373 gtk_notebook_draw_focus (widget);
1377 if (notebook->cur_page)
1378 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1379 notebook->cur_page->child,
1387 gtk_notebook_show_arrows (GtkNotebook *notebook)
1389 gboolean show_arrow = FALSE;
1392 if (!notebook->scrollable)
1395 children = notebook->children;
1398 GtkNotebookPage *page = children->data;
1400 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1403 children = children->next;
1410 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1411 GdkRectangle *rectangle)
1413 GdkRectangle event_window_pos;
1415 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1417 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1418 rectangle->height = ARROW_SIZE;
1420 switch (notebook->tab_pos)
1424 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1425 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1428 case GTK_POS_BOTTOM:
1429 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1430 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1437 gtk_notebook_get_arrow (GtkNotebook *notebook,
1441 GdkRectangle arrow_rect;
1442 GdkRectangle event_window_pos;
1444 if (gtk_notebook_show_arrows (notebook))
1446 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1447 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1452 if (y >= 0 && y < arrow_rect.height)
1454 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1455 return GTK_ARROW_LEFT;
1456 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1457 return GTK_ARROW_RIGHT;
1465 gtk_notebook_do_arrow (GtkNotebook *notebook,
1468 GtkWidget *widget = GTK_WIDGET (notebook);
1469 GtkDirectionType dir;
1471 if (!notebook->focus_tab ||
1472 gtk_notebook_search_page (notebook, notebook->focus_tab,
1473 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1476 if (notebook->tab_pos == GTK_POS_LEFT ||
1477 notebook->tab_pos == GTK_POS_RIGHT)
1478 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1480 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1481 gtk_widget_child_focus (widget, dir);
1486 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1488 GdkEventButton *event)
1490 GtkWidget *widget = GTK_WIDGET (notebook);
1492 if (!GTK_WIDGET_HAS_FOCUS (widget))
1493 gtk_widget_grab_focus (widget);
1495 notebook->button = event->button;
1496 notebook->click_child = arrow;
1498 if (event->button == 1)
1500 gtk_notebook_do_arrow (notebook, arrow);
1502 if (!notebook->timer)
1504 notebook->timer = gtk_timeout_add
1505 (NOTEBOOK_INIT_SCROLL_DELAY,
1506 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1507 notebook->need_timer = TRUE;
1510 else if (event->button == 2)
1511 gtk_notebook_page_select (notebook, TRUE);
1512 else if (event->button == 3)
1513 gtk_notebook_switch_focus_tab (notebook,
1514 gtk_notebook_search_page (notebook,
1516 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1518 gtk_notebook_redraw_arrows (notebook);
1524 get_widget_coordinates (GtkWidget *widget,
1529 GdkWindow *window = ((GdkEventAny *)event)->window;
1532 if (!gdk_event_get_coords (event, &tx, &ty))
1535 while (window && window != widget->window)
1537 gint window_x, window_y;
1539 gdk_window_get_position (window, &window_x, &window_y);
1543 window = gdk_window_get_parent (window);
1558 gtk_notebook_button_press (GtkWidget *widget,
1559 GdkEventButton *event)
1561 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1562 GtkNotebookPage *page;
1568 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1572 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1575 arrow = gtk_notebook_get_arrow (notebook, x, y);
1577 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1579 if (event->button == 3 && notebook->menu)
1581 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1582 NULL, NULL, 3, event->time);
1587 children = notebook->children;
1590 page = children->data;
1592 if (GTK_WIDGET_VISIBLE (page->child) &&
1593 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1594 (x >= page->allocation.x) &&
1595 (y >= page->allocation.y) &&
1596 (x <= (page->allocation.x + page->allocation.width)) &&
1597 (y <= (page->allocation.y + page->allocation.height)))
1599 if (page == notebook->cur_page && notebook->focus_tab &&
1600 notebook->focus_tab != children &&
1601 GTK_WIDGET_HAS_FOCUS (notebook))
1603 GtkNotebookPage *old_page;
1605 notebook->child_has_focus = FALSE;
1606 old_page = (GtkNotebookPage *)
1607 (notebook->focus_tab->data);
1608 gtk_notebook_switch_focus_tab (notebook, children);
1609 gtk_notebook_focus_changed (notebook, old_page);
1613 gtk_notebook_switch_focus_tab (notebook, children);
1614 gtk_widget_grab_focus (widget);
1615 gtk_notebook_switch_page (notebook, page, num);
1619 children = children->next;
1622 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1623 gtk_widget_grab_focus (widget);
1629 gtk_notebook_button_release (GtkWidget *widget,
1630 GdkEventButton *event)
1632 GtkNotebook *notebook;
1634 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1635 g_return_val_if_fail (event != NULL, FALSE);
1637 if (event->type != GDK_BUTTON_RELEASE)
1640 notebook = GTK_NOTEBOOK (widget);
1642 if (event->button == notebook->button)
1646 if (notebook->timer)
1648 gtk_timeout_remove (notebook->timer);
1649 notebook->timer = 0;
1650 notebook->need_timer = FALSE;
1652 click_child = notebook->click_child;
1653 notebook->click_child = 0;
1654 notebook->button = 0;
1655 gtk_notebook_redraw_arrows (notebook);
1664 gtk_notebook_enter_notify (GtkWidget *widget,
1665 GdkEventCrossing *event)
1667 GtkNotebook *notebook;
1671 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1672 g_return_val_if_fail (event != NULL, FALSE);
1674 notebook = GTK_NOTEBOOK (widget);
1676 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1679 arrow = gtk_notebook_get_arrow (notebook, x, y);
1681 if (arrow != notebook->in_child)
1683 notebook->in_child = arrow;
1684 gtk_notebook_redraw_arrows (notebook);
1693 gtk_notebook_leave_notify (GtkWidget *widget,
1694 GdkEventCrossing *event)
1696 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1700 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1703 arrow = gtk_notebook_get_arrow (notebook, x, y);
1705 if (notebook->in_child)
1707 notebook->in_child = 0;
1708 gtk_notebook_redraw_arrows (notebook);
1715 gtk_notebook_motion_notify (GtkWidget *widget,
1716 GdkEventMotion *event)
1718 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1722 if (notebook->button)
1725 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1728 arrow = gtk_notebook_get_arrow (notebook, x, y);
1730 if (arrow != notebook->in_child)
1732 notebook->in_child = arrow;
1733 gtk_notebook_redraw_arrows (notebook);
1740 gtk_notebook_focus_in (GtkWidget *widget,
1741 GdkEventFocus *event)
1743 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1745 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1749 gtk_notebook_draw_focus (GtkWidget *widget)
1751 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1753 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1754 notebook->focus_tab)
1756 GtkNotebookPage *page;
1760 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1762 page = notebook->focus_tab->data;
1764 area.x = page->tab_label->allocation.x - focus_width;
1765 area.y = page->tab_label->allocation.y - focus_width;
1766 area.width = page->tab_label->allocation.width + 2 * focus_width;
1767 area.height = page->tab_label->allocation.height + 2 * focus_width;
1769 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1773 /* Private GtkContainer Methods :
1775 * gtk_notebook_set_child_arg
1776 * gtk_notebook_get_child_arg
1778 * gtk_notebook_remove
1779 * gtk_notebook_focus
1780 * gtk_notebook_set_focus_child
1781 * gtk_notebook_child_type
1782 * gtk_notebook_forall
1785 gtk_notebook_set_child_property (GtkContainer *container,
1788 const GValue *value,
1793 GtkPackType pack_type;
1795 /* not finding child's page is valid for menus or labels */
1796 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1799 switch (property_id)
1801 case CHILD_PROP_TAB_LABEL:
1802 /* a NULL pointer indicates a default_tab setting, otherwise
1803 * we need to set the associated label
1805 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1806 g_value_get_string (value));
1808 case CHILD_PROP_MENU_LABEL:
1809 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1810 g_value_get_string (value));
1812 case CHILD_PROP_POSITION:
1813 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1814 g_value_get_int (value));
1816 case CHILD_PROP_TAB_EXPAND:
1817 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1818 &expand, &fill, &pack_type);
1819 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1820 g_value_get_boolean (value),
1823 case CHILD_PROP_TAB_FILL:
1824 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1825 &expand, &fill, &pack_type);
1826 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1828 g_value_get_boolean (value),
1831 case CHILD_PROP_TAB_PACK:
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,
1836 g_value_get_enum (value));
1839 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1845 gtk_notebook_get_child_property (GtkContainer *container,
1852 GtkNotebook *notebook;
1856 GtkPackType pack_type;
1858 notebook = GTK_NOTEBOOK (container);
1860 /* not finding child's page is valid for menus or labels */
1861 list = gtk_notebook_find_child (notebook, child, NULL);
1864 /* nothing to set on labels or menus */
1865 g_param_value_set_default (pspec, value);
1869 switch (property_id)
1871 case CHILD_PROP_TAB_LABEL:
1872 label = gtk_notebook_get_tab_label (notebook, child);
1874 if (label && GTK_IS_LABEL (label))
1875 g_value_set_string (value, GTK_LABEL (label)->label);
1877 g_value_set_string (value, NULL);
1879 case CHILD_PROP_MENU_LABEL:
1880 label = gtk_notebook_get_menu_label (notebook, child);
1882 if (label && GTK_IS_LABEL (label))
1883 g_value_set_string (value, GTK_LABEL (label)->label);
1885 g_value_set_string (value, NULL);
1887 case CHILD_PROP_POSITION:
1888 g_value_set_int (value, g_list_position (notebook->children, list));
1890 case CHILD_PROP_TAB_EXPAND:
1891 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1892 &expand, NULL, NULL);
1893 g_value_set_boolean (value, expand);
1895 case CHILD_PROP_TAB_FILL:
1896 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1898 g_value_set_boolean (value, fill);
1900 case CHILD_PROP_TAB_PACK:
1901 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1902 NULL, NULL, &pack_type);
1903 g_value_set_enum (value, pack_type);
1906 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1912 gtk_notebook_add (GtkContainer *container,
1915 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1917 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1922 gtk_notebook_remove (GtkContainer *container,
1925 GtkNotebook *notebook;
1926 GtkNotebookPage *page;
1930 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1931 g_return_if_fail (widget != NULL);
1933 notebook = GTK_NOTEBOOK (container);
1935 children = notebook->children;
1939 page = children->data;
1940 if (page->child == widget)
1942 gtk_notebook_real_remove (notebook, children);
1946 children = children->next;
1951 focus_tabs_in (GtkNotebook *notebook)
1953 if (notebook->show_tabs && notebook->cur_page)
1955 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1957 gtk_notebook_switch_focus_tab (notebook,
1958 g_list_find (notebook->children,
1959 notebook->cur_page));
1968 focus_tabs_move (GtkNotebook *notebook,
1969 GtkDirectionType direction,
1970 gint search_direction)
1974 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1975 search_direction, TRUE);
1977 gtk_notebook_switch_focus_tab (notebook, new_page);
1979 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1985 focus_child_in (GtkNotebook *notebook,
1986 GtkDirectionType direction)
1988 if (notebook->cur_page)
1989 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1994 /* Focus in the notebook can either be on the pages, or on
1998 gtk_notebook_focus (GtkWidget *widget,
1999 GtkDirectionType direction)
2001 GtkWidget *old_focus_child;
2002 GtkNotebook *notebook;
2003 GtkDirectionType effective_direction;
2005 gboolean widget_is_focus;
2006 GtkContainer *container;
2008 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2010 container = GTK_CONTAINER (widget);
2011 notebook = GTK_NOTEBOOK (container);
2013 if (notebook->focus_out)
2015 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2019 widget_is_focus = gtk_widget_is_focus (widget);
2020 old_focus_child = container->focus_child;
2022 effective_direction = get_effective_direction (notebook, direction);
2024 if (old_focus_child) /* Focus on page child */
2026 if (gtk_widget_child_focus (old_focus_child, direction))
2029 switch (effective_direction)
2031 case GTK_DIR_TAB_BACKWARD:
2033 /* Focus onto the tabs */
2034 return focus_tabs_in (notebook);
2036 case GTK_DIR_TAB_FORWARD:
2042 else if (widget_is_focus) /* Focus was on tabs */
2044 switch (effective_direction)
2046 case GTK_DIR_TAB_BACKWARD:
2049 case GTK_DIR_TAB_FORWARD:
2051 /* We use TAB_FORWARD rather than direction so that we focus a more
2052 * predictable widget for the user; users may be using arrow focusing
2053 * in this situation even if they don't usually use arrow focusing.
2055 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2057 return focus_tabs_move (notebook, direction, STEP_PREV);
2059 return focus_tabs_move (notebook, direction, STEP_NEXT);
2062 else /* Focus was not on widget */
2064 switch (effective_direction)
2066 case GTK_DIR_TAB_FORWARD:
2068 if (focus_tabs_in (notebook))
2070 if (focus_child_in (notebook, direction))
2073 case GTK_DIR_TAB_BACKWARD:
2075 if (focus_child_in (notebook, direction))
2077 if (focus_tabs_in (notebook))
2082 return focus_child_in (notebook, direction);
2086 g_assert_not_reached ();
2091 gtk_notebook_set_focus_child (GtkContainer *container,
2094 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2095 GtkWidget *page_child;
2096 GtkWidget *toplevel;
2098 /* If the old focus widget was within a page of the notebook,
2099 * (child may either be NULL or not in this case), record it
2100 * for future use if we switch to the page with a mnemonic.
2103 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2104 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2106 page_child = GTK_WINDOW (toplevel)->focus_widget;
2109 if (page_child->parent == GTK_WIDGET (container))
2111 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2114 GtkNotebookPage *page = list->data;
2116 if (page->last_focus_child)
2117 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2119 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2120 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2126 page_child = page_child->parent;
2132 g_return_if_fail (GTK_IS_WIDGET (child));
2134 notebook->child_has_focus = TRUE;
2135 if (!notebook->focus_tab)
2138 GtkNotebookPage *page;
2140 children = notebook->children;
2143 page = children->data;
2144 if (page->child == child || page->tab_label == child)
2145 gtk_notebook_switch_focus_tab (notebook, children);
2146 children = children->next;
2151 parent_class->set_focus_child (container, child);
2155 gtk_notebook_forall (GtkContainer *container,
2156 gboolean include_internals,
2157 GtkCallback callback,
2158 gpointer callback_data)
2160 GtkNotebook *notebook;
2163 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2164 g_return_if_fail (callback != NULL);
2166 notebook = GTK_NOTEBOOK (container);
2168 children = notebook->children;
2171 GtkNotebookPage *page;
2173 page = children->data;
2174 children = children->next;
2175 (* callback) (page->child, callback_data);
2176 if (include_internals)
2178 if (page->tab_label)
2179 (* callback) (page->tab_label, callback_data);
2180 if (page->menu_label)
2181 (* callback) (page->menu_label, callback_data);
2187 gtk_notebook_child_type (GtkContainer *container)
2189 return GTK_TYPE_WIDGET;
2192 /* Private GtkNotebook Functions:
2194 * gtk_notebook_redraw_tabs
2195 * gtk_notebook_focus_changed
2196 * gtk_notebook_real_remove
2197 * gtk_notebook_update_labels
2198 * gtk_notebook_timer
2199 * gtk_notebook_page_compare
2200 * gtk_notebook_real_page_position
2201 * gtk_notebook_search_page
2204 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2207 GtkNotebookPage *page;
2208 GdkRectangle redraw_rect;
2211 widget = GTK_WIDGET (notebook);
2212 border = GTK_CONTAINER (notebook)->border_width;
2214 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2217 page = notebook->first_tab->data;
2219 redraw_rect.x = border;
2220 redraw_rect.y = border;
2222 switch (notebook->tab_pos)
2224 case GTK_POS_BOTTOM:
2225 redraw_rect.y = (widget->allocation.height - border -
2226 page->allocation.height -
2227 widget->style->ythickness);
2228 if (page != notebook->cur_page)
2229 redraw_rect.y -= widget->style->ythickness;
2232 redraw_rect.width = widget->allocation.width - 2 * border;
2233 redraw_rect.height = (page->allocation.height +
2234 widget->style->ythickness);
2235 if (page != notebook->cur_page)
2236 redraw_rect.height += widget->style->ythickness;
2239 redraw_rect.x = (widget->allocation.width - border -
2240 page->allocation.width -
2241 widget->style->xthickness);
2242 if (page != notebook->cur_page)
2243 redraw_rect.x -= widget->style->xthickness;
2246 redraw_rect.width = (page->allocation.width +
2247 widget->style->xthickness);
2248 redraw_rect.height = widget->allocation.height - 2 * border;
2249 if (page != notebook->cur_page)
2250 redraw_rect.width += widget->style->xthickness;
2254 redraw_rect.x += widget->allocation.x;
2255 redraw_rect.y += widget->allocation.y;
2257 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2261 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2263 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2267 gtk_notebook_get_arrow_rect (notebook, &rect);
2268 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2273 gtk_notebook_focus_changed (GtkNotebook *notebook,
2274 GtkNotebookPage *old_page)
2276 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2278 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2283 gtk_widget_style_get (GTK_WIDGET (notebook), "focus-line-width", &focus_width, NULL);
2285 if (notebook->focus_tab)
2287 GtkNotebookPage *page;
2289 page = notebook->focus_tab->data;
2291 area.x = page->tab_label->allocation.x - focus_width;
2292 area.y = page->tab_label->allocation.y - focus_width;
2293 area.width = page->tab_label->allocation.width + 2 * focus_width;
2294 area.height = page->tab_label->allocation.height + 2 * focus_width;
2296 gtk_notebook_draw_tab (notebook, page, &area);
2301 area.x = old_page->tab_label->allocation.x - focus_width;
2302 area.y = old_page->tab_label->allocation.y - focus_width;
2303 area.width = old_page->tab_label->allocation.width + 2 * focus_width;
2304 area.height = old_page->tab_label->allocation.height + 2 * focus_width;
2306 gtk_notebook_draw_tab (notebook, old_page, &area);
2312 gtk_notebook_timer (GtkNotebook *notebook)
2314 gboolean retval = FALSE;
2316 GDK_THREADS_ENTER ();
2318 if (notebook->timer)
2320 gtk_notebook_do_arrow (notebook, notebook->click_child);
2322 if (notebook->need_timer)
2324 notebook->need_timer = FALSE;
2325 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2326 (GtkFunction) gtk_notebook_timer,
2327 (gpointer) notebook);
2333 GDK_THREADS_LEAVE ();
2339 gtk_notebook_page_compare (gconstpointer a,
2342 return (((GtkNotebookPage *) a)->child != b);
2346 gtk_notebook_find_child (GtkNotebook *notebook,
2348 const gchar *function)
2350 GList *list = g_list_find_custom (notebook->children, child,
2351 gtk_notebook_page_compare);
2353 #ifndef G_DISABLE_CHECKS
2354 if (!list && function)
2355 g_warning ("%s: unable to find child %p in notebook %p",
2356 function, child, notebook);
2363 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2364 GtkNotebookPage *page)
2366 if (page->tab_label)
2368 if (page->mnemonic_activate_signal)
2369 gtk_signal_disconnect (page->tab_label,
2370 page->mnemonic_activate_signal);
2371 page->mnemonic_activate_signal = 0;
2373 gtk_widget_unparent (page->tab_label);
2378 gtk_notebook_real_remove (GtkNotebook *notebook,
2381 GtkNotebookPage *page;
2383 gint need_resize = FALSE;
2385 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2387 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2389 if (notebook->cur_page == list->data)
2391 notebook->cur_page = NULL;
2393 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2396 if (list == notebook->first_tab)
2397 notebook->first_tab = next_list;
2398 if (list == notebook->focus_tab)
2399 gtk_notebook_switch_focus_tab (notebook, next_list);
2403 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2406 gtk_widget_unparent (page->child);
2408 gtk_notebook_remove_tab_label (notebook, page);
2412 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2413 page->menu_label->parent);
2414 gtk_widget_queue_resize (notebook->menu);
2416 if (!page->default_menu)
2417 gtk_widget_unref (page->menu_label);
2419 notebook->children = g_list_remove_link (notebook->children, list);
2422 if (page->last_focus_child)
2424 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2425 page->last_focus_child = NULL;
2430 if (!notebook->children && notebook->show_tabs &&
2431 GTK_WIDGET_MAPPED (notebook))
2432 gdk_window_hide (notebook->event_window);
2434 gtk_notebook_update_labels (notebook);
2436 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2440 gtk_notebook_update_labels (GtkNotebook *notebook)
2442 GtkNotebookPage *page;
2447 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2449 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2452 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2453 if (notebook->show_tabs)
2455 if (page->default_tab)
2457 if (!page->tab_label)
2459 page->tab_label = gtk_label_new (string);
2460 gtk_widget_set_parent (page->tab_label,
2461 GTK_WIDGET (notebook));
2464 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2467 if (GTK_WIDGET_VISIBLE (page->child) &&
2468 !GTK_WIDGET_VISIBLE (page->tab_label))
2469 gtk_widget_show (page->tab_label);
2470 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2471 GTK_WIDGET_VISIBLE (page->tab_label))
2472 gtk_widget_hide (page->tab_label);
2474 if (notebook->menu && page->default_menu)
2476 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2477 gtk_label_set_text (GTK_LABEL (page->menu_label),
2478 GTK_LABEL (page->tab_label)->label);
2480 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2486 gtk_notebook_real_page_position (GtkNotebook *notebook,
2492 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2493 g_return_val_if_fail (list != NULL, -1);
2495 for (work = notebook->children, count_start = 0;
2496 work && work != list; work = work->next)
2497 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2503 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2506 return (count_start + g_list_length (list) - 1);
2510 gtk_notebook_search_page (GtkNotebook *notebook,
2513 gboolean find_visible)
2515 GtkNotebookPage *page = NULL;
2516 GList *old_list = NULL;
2519 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2524 flag = GTK_PACK_END;
2528 flag = GTK_PACK_START;
2535 if (!page || page->pack == flag)
2543 list = notebook->children;
2548 if (page->pack == flag &&
2549 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2564 if (page->pack != flag &&
2565 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2573 /* Private GtkNotebook Drawing Functions:
2575 * gtk_notebook_paint
2576 * gtk_notebook_draw_tab
2577 * gtk_notebook_draw_arrow
2580 gtk_notebook_paint (GtkWidget *widget,
2583 GtkNotebook *notebook;
2584 GtkNotebookPage *page;
2589 gint border_width = GTK_CONTAINER (widget)->border_width;
2590 gint gap_x = 0, gap_width = 0;
2592 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2593 g_return_if_fail (area != NULL);
2595 if (!GTK_WIDGET_DRAWABLE (widget))
2598 notebook = GTK_NOTEBOOK (widget);
2600 if ((!notebook->show_tabs && !notebook->show_border) ||
2601 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2604 x = widget->allocation.x + border_width;
2605 y = widget->allocation.y + border_width;
2606 width = widget->allocation.width - border_width * 2;
2607 height = widget->allocation.height - border_width * 2;
2609 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2611 gtk_paint_box (widget->style, widget->window,
2612 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2613 area, widget, "notebook",
2614 x, y, width, height);
2619 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2621 page = notebook->first_tab->data;
2623 switch (notebook->tab_pos)
2626 y += page->allocation.height + widget->style->ythickness;
2627 case GTK_POS_BOTTOM:
2628 height -= page->allocation.height + widget->style->ythickness;
2631 x += page->allocation.width + widget->style->xthickness;
2633 width -= page->allocation.width + widget->style->xthickness;
2636 gtk_paint_box (widget->style, widget->window,
2637 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2638 area, widget, "notebook",
2639 x, y, width, height);
2643 switch (notebook->tab_pos)
2646 y += notebook->cur_page->allocation.height;
2647 case GTK_POS_BOTTOM:
2648 height -= notebook->cur_page->allocation.height;
2651 x += notebook->cur_page->allocation.width;
2653 width -= notebook->cur_page->allocation.width;
2657 switch (notebook->tab_pos)
2660 case GTK_POS_BOTTOM:
2661 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2662 gap_width = notebook->cur_page->allocation.width;
2666 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2667 gap_width = notebook->cur_page->allocation.height;
2670 gtk_paint_box_gap(widget->style, widget->window,
2671 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2672 area, widget, "notebook",
2673 x, y, width, height,
2674 notebook->tab_pos, gap_x, gap_width);
2678 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2681 page = children->data;
2682 children = gtk_notebook_search_page (notebook, children,
2684 if (!GTK_WIDGET_VISIBLE (page->child))
2686 if (!GTK_WIDGET_MAPPED (page->tab_label))
2688 else if (page != notebook->cur_page)
2689 gtk_notebook_draw_tab (notebook, page, area);
2692 if (showarrow && notebook->scrollable)
2694 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2695 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2697 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2701 gtk_notebook_draw_tab (GtkNotebook *notebook,
2702 GtkNotebookPage *page,
2705 GdkRectangle child_area;
2706 GdkRectangle page_area;
2707 GtkStateType state_type;
2708 GtkPositionType gap_side;
2710 g_return_if_fail (notebook != NULL);
2711 g_return_if_fail (page != NULL);
2712 g_return_if_fail (area != NULL);
2714 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2715 (page->allocation.width == 0) || (page->allocation.height == 0))
2718 page_area.x = page->allocation.x;
2719 page_area.y = page->allocation.y;
2720 page_area.width = page->allocation.width;
2721 page_area.height = page->allocation.height;
2723 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2727 widget = GTK_WIDGET (notebook);
2729 switch (notebook->tab_pos)
2732 gap_side = GTK_POS_BOTTOM;
2734 case GTK_POS_BOTTOM:
2735 gap_side = GTK_POS_TOP;
2738 gap_side = GTK_POS_RIGHT;
2741 gap_side = GTK_POS_LEFT;
2745 if (notebook->cur_page == page)
2746 state_type = GTK_STATE_NORMAL;
2748 state_type = GTK_STATE_ACTIVE;
2749 gtk_paint_extension(widget->style, widget->window,
2750 state_type, GTK_SHADOW_OUT,
2751 area, widget, "tab",
2752 page_area.x, page_area.y,
2753 page_area.width, page_area.height,
2755 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2756 notebook->focus_tab && (notebook->focus_tab->data == page))
2760 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2762 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2763 area, widget, "tab",
2764 page->tab_label->allocation.x - focus_width,
2765 page->tab_label->allocation.y - focus_width,
2766 page->tab_label->allocation.width + 2 * focus_width,
2767 page->tab_label->allocation.height + 2 * focus_width);
2769 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2770 GTK_WIDGET_DRAWABLE (page->tab_label))
2772 GdkEventExpose expose_event;
2774 /* This is a lame hack since all this code needs rewriting anyhow */
2776 expose_event.window = page->tab_label->window;
2777 expose_event.area = child_area;
2778 expose_event.region = gdk_region_rectangle (&child_area);
2779 expose_event.send_event = TRUE;
2780 expose_event.type = GDK_EXPOSE;
2781 expose_event.count = 0;
2783 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
2785 gdk_region_destroy (expose_event.region);
2791 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2794 GtkStateType state_type;
2795 GtkShadowType shadow_type;
2797 GdkRectangle arrow_rect;
2799 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2801 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2803 widget = GTK_WIDGET(notebook);
2805 if (GTK_WIDGET_DRAWABLE (notebook))
2807 if (notebook->in_child == arrow)
2809 if (notebook->click_child == arrow)
2810 state_type = GTK_STATE_ACTIVE;
2812 state_type = GTK_STATE_PRELIGHT;
2815 state_type = GTK_STATE_NORMAL;
2817 if (notebook->click_child == arrow)
2818 shadow_type = GTK_SHADOW_IN;
2820 shadow_type = GTK_SHADOW_OUT;
2822 if (arrow == GTK_ARROW_LEFT)
2824 if (notebook->focus_tab &&
2825 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2828 shadow_type = GTK_SHADOW_ETCHED_IN;
2829 state_type = GTK_STATE_INSENSITIVE;
2832 if (notebook->tab_pos == GTK_POS_LEFT ||
2833 notebook->tab_pos == GTK_POS_RIGHT)
2834 arrow = GTK_ARROW_UP;
2836 gtk_paint_arrow (widget->style, widget->window, state_type,
2837 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2839 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2843 if (notebook->focus_tab &&
2844 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2847 shadow_type = GTK_SHADOW_ETCHED_IN;
2848 state_type = GTK_STATE_INSENSITIVE;
2851 if (notebook->tab_pos == GTK_POS_LEFT ||
2852 notebook->tab_pos == GTK_POS_RIGHT)
2853 arrow = GTK_ARROW_DOWN;
2855 gtk_paint_arrow (widget->style, widget->window, state_type,
2856 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2857 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2858 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2863 /* Private GtkNotebook Size Allocate Functions:
2865 * gtk_notebook_pages_allocate
2866 * gtk_notebook_page_allocate
2867 * gtk_notebook_calc_tabs
2870 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2872 GtkWidget *widget = GTK_WIDGET (notebook);
2873 GtkContainer *container = GTK_CONTAINER (notebook);
2874 GtkNotebookPage *page = NULL;
2875 GtkAllocation *allocation = &widget->allocation;
2876 GtkAllocation child_allocation;
2877 GList *children = NULL;
2878 GList *last_child = NULL;
2879 gboolean showarrow = FALSE;
2889 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2892 child_allocation.x = widget->allocation.x + container->border_width;
2893 child_allocation.y = widget->allocation.y + container->border_width;
2895 switch (notebook->tab_pos)
2897 case GTK_POS_BOTTOM:
2898 child_allocation.y = (widget->allocation.y +
2899 allocation->height -
2900 notebook->cur_page->requisition.height -
2901 container->border_width);
2904 child_allocation.height = notebook->cur_page->requisition.height;
2908 child_allocation.x = (widget->allocation.x +
2910 notebook->cur_page->requisition.width -
2911 container->border_width);
2914 child_allocation.width = notebook->cur_page->requisition.width;
2918 if (notebook->scrollable)
2922 children = notebook->children;
2924 if (notebook->focus_tab)
2925 focus_tab = notebook->focus_tab;
2926 else if (notebook->first_tab)
2927 focus_tab = notebook->first_tab;
2929 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2931 switch (notebook->tab_pos)
2934 case GTK_POS_BOTTOM:
2937 page = children->data;
2938 children = children->next;
2940 if (GTK_WIDGET_VISIBLE (page->child))
2941 tab_space += page->requisition.width;
2944 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2947 page = focus_tab->data;
2949 tab_space = (allocation->width - TAB_OVERLAP -
2950 page->requisition.width -
2951 2 * (container->border_width + ARROW_SPACING +
2953 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2954 container->border_width);
2956 page = notebook->children->data;
2957 if (notebook->tab_pos == GTK_POS_TOP)
2958 y = (container->border_width +
2959 (page->requisition.height - ARROW_SIZE) / 2);
2961 y = (allocation->height - container->border_width -
2962 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2969 page = children->data;
2970 children = children->next;
2972 if (GTK_WIDGET_VISIBLE (page->child))
2973 tab_space += page->requisition.height;
2976 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2979 page = focus_tab->data;
2980 tab_space = (allocation->height -
2981 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2982 2 * container->border_width -
2983 page->requisition.height);
2984 y = allocation->height - container->border_width - ARROW_SIZE;
2986 page = notebook->children->data;
2987 if (notebook->tab_pos == GTK_POS_LEFT)
2988 x = (container->border_width +
2989 (page->requisition.width -
2990 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2992 x = (allocation->width - container->border_width -
2993 (2 * ARROW_SIZE - ARROW_SPACING) -
2994 (page->requisition.width -
2995 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2999 if (showarrow) /* first_tab <- focus_tab */
3003 notebook->first_tab = focus_tab;
3004 last_child = gtk_notebook_search_page (notebook, focus_tab,
3010 if (notebook->first_tab && notebook->first_tab != focus_tab)
3012 /* Is first_tab really predecessor of focus_tab ? */
3013 page = notebook->first_tab->data;
3014 if (GTK_WIDGET_VISIBLE (page->child))
3015 for (children = focus_tab;
3016 children && children != notebook->first_tab;
3017 children = gtk_notebook_search_page (notebook,
3023 notebook->first_tab = focus_tab;
3025 gtk_notebook_calc_tabs (notebook,
3026 gtk_notebook_search_page (notebook,
3030 &(notebook->first_tab), &tab_space,
3035 notebook->first_tab =
3036 gtk_notebook_search_page (notebook, notebook->first_tab,
3038 if (!notebook->first_tab)
3039 notebook->first_tab = focus_tab;
3040 last_child = gtk_notebook_search_page (notebook, focus_tab,
3043 else /* focus_tab -> end */
3045 if (!notebook->first_tab)
3046 notebook->first_tab = gtk_notebook_search_page (notebook,
3051 gtk_notebook_calc_tabs (notebook,
3052 gtk_notebook_search_page (notebook,
3056 &children, &tab_space, STEP_NEXT);
3059 last_child = children;
3060 else /* start <- first_tab */
3064 gtk_notebook_calc_tabs
3066 gtk_notebook_search_page (notebook,
3067 notebook->first_tab,
3070 &children, &tab_space, STEP_PREV);
3071 notebook->first_tab = gtk_notebook_search_page(notebook,
3081 tab_space = -tab_space;
3083 for (children = notebook->first_tab;
3084 children && children != last_child;
3085 children = gtk_notebook_search_page (notebook, children,
3092 /*unmap all non-visible tabs*/
3093 for (children = gtk_notebook_search_page (notebook, NULL,
3095 children && children != notebook->first_tab;
3096 children = gtk_notebook_search_page (notebook, children,
3099 page = children->data;
3100 if (page->tab_label)
3101 gtk_widget_set_child_visible (page->tab_label, FALSE);
3103 for (children = last_child; children;
3104 children = gtk_notebook_search_page (notebook, children,
3107 page = children->data;
3108 if (page->tab_label)
3109 gtk_widget_set_child_visible (page->tab_label, FALSE);
3112 else /* !showarrow */
3114 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3125 children = notebook->children;
3126 switch (notebook->tab_pos)
3129 case GTK_POS_BOTTOM:
3132 page = children->data;
3133 children = children->next;
3135 if (GTK_WIDGET_VISIBLE (page->child))
3138 tab_space += page->requisition.width;
3143 tab_space -= allocation->width;
3149 page = children->data;
3150 children = children->next;
3152 if (GTK_WIDGET_VISIBLE (page->child))
3155 tab_space += page->requisition.height;
3160 tab_space -= allocation->height;
3162 tab_space += 2 * container->border_width + TAB_OVERLAP;
3164 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3166 if (notebook->homogeneous && n)
3170 children = notebook->first_tab;
3174 if (children == last_child)
3176 /* FIXME double check */
3180 page = children->data;
3181 if (!showarrow && page->pack != GTK_PACK_START)
3183 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3186 if (n && (showarrow || page->expand || notebook->homogeneous))
3188 new_fill = (tab_space * i++) / n;
3189 delta = new_fill - old_fill;
3190 old_fill = new_fill;
3193 switch (notebook->tab_pos)
3196 case GTK_POS_BOTTOM:
3197 child_allocation.width = (page->requisition.width +
3198 TAB_OVERLAP + delta);
3202 child_allocation.height = (page->requisition.height +
3203 TAB_OVERLAP + delta);
3207 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3209 switch (notebook->tab_pos)
3212 case GTK_POS_BOTTOM:
3213 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3217 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3221 if (page->tab_label)
3222 gtk_widget_set_child_visible (page->tab_label, TRUE);
3227 children = notebook->children;
3228 switch (notebook->tab_pos)
3231 case GTK_POS_BOTTOM:
3232 child_allocation.x = (allocation->x + allocation->width -
3233 container->border_width);
3237 child_allocation.y = (allocation->y + allocation->height -
3238 container->border_width);
3242 while (children != last_child)
3244 page = children->data;
3245 children = children->next;
3247 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3251 if (n && (page->expand || notebook->homogeneous))
3253 new_fill = (tab_space * i++) / n;
3254 delta = new_fill - old_fill;
3255 old_fill = new_fill;
3258 switch (notebook->tab_pos)
3261 case GTK_POS_BOTTOM:
3262 child_allocation.width = (page->requisition.width +
3263 TAB_OVERLAP + delta);
3264 child_allocation.x -= child_allocation.width;
3268 child_allocation.height = (page->requisition.height +
3269 TAB_OVERLAP + delta);
3270 child_allocation.y -= child_allocation.height;
3274 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3276 switch (notebook->tab_pos)
3279 case GTK_POS_BOTTOM:
3280 child_allocation.x += TAB_OVERLAP;
3284 child_allocation.y += TAB_OVERLAP;
3288 if (page->tab_label)
3289 gtk_widget_set_child_visible (page->tab_label, TRUE);
3294 gtk_notebook_redraw_tabs (notebook);
3298 gtk_notebook_page_allocate (GtkNotebook *notebook,
3299 GtkNotebookPage *page,
3300 GtkAllocation *allocation)
3302 GtkWidget *widget = GTK_WIDGET (notebook);
3303 GtkAllocation child_allocation;
3304 GtkRequisition tab_requisition;
3310 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3312 xthickness = widget->style->xthickness;
3313 ythickness = widget->style->ythickness;
3315 /* If the size of the notebook tabs change, we need to queue
3316 * a redraw on the tab area
3318 if ((allocation->width != page->allocation.width) ||
3319 (allocation->height != page->allocation.height))
3321 gint x, y, width, height, border_width;
3323 border_width = GTK_CONTAINER (notebook)->border_width;
3325 switch (notebook->tab_pos)
3328 width = widget->allocation.width;
3329 height = MAX (page->allocation.height, allocation->height) + ythickness;
3334 case GTK_POS_BOTTOM:
3335 width = widget->allocation.width + xthickness;
3336 height = MAX (page->allocation.height, allocation->height) + ythickness;
3338 y = widget->allocation.height - height - border_width;
3342 width = MAX (page->allocation.width, allocation->width) + xthickness;
3343 height = widget->allocation.height;
3349 default: /* quiet gcc */
3350 width = MAX (page->allocation.width, allocation->width) + xthickness;
3351 height = widget->allocation.height;
3352 x = widget->allocation.width - width - border_width;
3357 gtk_widget_queue_clear_area (widget, x, y, width, height);
3360 page->allocation = *allocation;
3361 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3363 if (notebook->cur_page != page)
3365 switch (notebook->tab_pos)
3368 page->allocation.y += ythickness;
3369 case GTK_POS_BOTTOM:
3370 if (page->allocation.height > ythickness)
3371 page->allocation.height -= ythickness;
3374 page->allocation.x += xthickness;
3376 if (page->allocation.width > xthickness)
3377 page->allocation.width -= xthickness;
3382 switch (notebook->tab_pos)
3385 case GTK_POS_BOTTOM:
3386 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3389 child_allocation.x = (xthickness + focus_width +
3390 notebook->tab_hborder);
3391 child_allocation.width = MAX (1, (page->allocation.width -
3392 2 * child_allocation.x));
3393 child_allocation.x += page->allocation.x;
3397 child_allocation.x = (page->allocation.x +
3398 (page->allocation.width -
3399 tab_requisition.width) / 2);
3400 child_allocation.width = tab_requisition.width;
3402 child_allocation.y = (notebook->tab_vborder + focus_width +
3403 page->allocation.y);
3404 if (notebook->tab_pos == GTK_POS_TOP)
3405 child_allocation.y += ythickness;
3406 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3407 2 * (notebook->tab_vborder + focus_width)));
3411 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3414 child_allocation.y = ythickness + padding;
3415 child_allocation.height = MAX (1, (page->allocation.height -
3416 2 * child_allocation.y));
3417 child_allocation.y += page->allocation.y;
3421 child_allocation.y = (page->allocation.y + (page->allocation.height -
3422 tab_requisition.height) / 2);
3423 child_allocation.height = tab_requisition.height;
3425 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3426 if (notebook->tab_pos == GTK_POS_LEFT)
3427 child_allocation.x += xthickness;
3428 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3429 2 * (notebook->tab_hborder + focus_width)));
3433 if (page->tab_label)
3434 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3438 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3444 GtkNotebookPage *page = NULL;
3446 GList *last_list = NULL;
3453 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3454 if (pack == GTK_PACK_END)
3455 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3459 switch (notebook->tab_pos)
3462 case GTK_POS_BOTTOM:
3465 page = children->data;
3466 if (GTK_WIDGET_VISIBLE (page->child))
3468 if (page->pack == pack)
3470 *tab_space -= page->requisition.width;
3471 if (*tab_space < 0 || children == *end)
3475 *tab_space = - (*tab_space +
3476 page->requisition.width);
3482 last_list = children;
3484 if (direction == STEP_NEXT)
3485 children = children->next;
3487 children = children->prev;
3494 page = children->data;
3495 if (GTK_WIDGET_VISIBLE (page->child))
3497 if (page->pack == pack)
3499 *tab_space -= page->requisition.height;
3500 if (*tab_space < 0 || children == *end)
3504 *tab_space = - (*tab_space +
3505 page->requisition.height);
3511 last_list = children;
3513 if (direction == STEP_NEXT)
3514 children = children->next;
3516 children = children->prev;
3520 if (direction == STEP_PREV)
3522 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3523 direction = STEP_PREV;
3524 children = last_list;
3528 /* Private GtkNotebook Page Switch Methods:
3530 * gtk_notebook_real_switch_page
3533 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3534 GtkNotebookPage *page,
3537 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3538 g_return_if_fail (page != NULL);
3540 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3543 if (notebook->cur_page)
3544 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3546 notebook->cur_page = page;
3548 if (!notebook->focus_tab ||
3549 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3550 notebook->focus_tab =
3551 g_list_find (notebook->children, notebook->cur_page);
3553 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3555 /* If the focus was on the previous page, move it to the first
3556 * element on the new page, if possible, or if not, to the
3559 if (notebook->child_has_focus)
3561 if (notebook->cur_page->last_focus_child &&
3562 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3563 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3565 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3566 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3569 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3570 g_object_notify (G_OBJECT (notebook), "page");
3573 /* Private GtkNotebook Page Switch Functions:
3575 * gtk_notebook_switch_page
3576 * gtk_notebook_page_select
3577 * gtk_notebook_switch_focus_tab
3578 * gtk_notebook_menu_switch_page
3581 gtk_notebook_switch_page (GtkNotebook *notebook,
3582 GtkNotebookPage *page,
3585 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3586 g_return_if_fail (page != NULL);
3588 if (notebook->cur_page == page)
3592 page_num = g_list_index (notebook->children, page);
3594 gtk_signal_emit (GTK_OBJECT (notebook),
3595 notebook_signals[SWITCH_PAGE],
3601 gtk_notebook_page_select (GtkNotebook *notebook,
3602 gboolean move_focus)
3604 GtkNotebookPage *page;
3605 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3607 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3609 if (!notebook->focus_tab)
3612 page = notebook->focus_tab->data;
3613 gtk_notebook_switch_page (notebook, page, -1);
3617 switch (notebook->tab_pos)
3622 case GTK_POS_BOTTOM:
3626 dir = GTK_DIR_RIGHT;
3633 if (gtk_widget_child_focus (page->child, dir))
3640 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3644 GtkNotebookPage *old_page = NULL;
3645 GtkNotebookPage *page;
3647 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3649 if (notebook->focus_tab == new_child)
3652 old_child = notebook->focus_tab;
3653 notebook->focus_tab = new_child;
3655 if (notebook->scrollable)
3656 gtk_notebook_redraw_arrows (notebook);
3658 if (!notebook->show_tabs || !notebook->focus_tab)
3662 old_page = old_child->data;
3664 page = notebook->focus_tab->data;
3665 if (GTK_WIDGET_MAPPED (page->tab_label))
3666 gtk_notebook_focus_changed (notebook, old_page);
3668 gtk_notebook_pages_allocate (notebook);
3672 gtk_notebook_menu_switch_page (GtkWidget *widget,
3673 GtkNotebookPage *page)
3675 GtkNotebook *notebook;
3679 g_return_if_fail (widget != NULL);
3680 g_return_if_fail (page != NULL);
3682 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3683 (GTK_MENU (widget->parent)));
3685 if (notebook->cur_page == page)
3689 children = notebook->children;
3690 while (children && children->data != page)
3692 children = children->next;
3696 gtk_signal_emit (GTK_OBJECT (notebook),
3697 notebook_signals[SWITCH_PAGE],
3702 /* Private GtkNotebook Menu Functions:
3704 * gtk_notebook_menu_item_create
3705 * gtk_notebook_menu_label_unparent
3706 * gtk_notebook_menu_detacher
3709 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3712 GtkNotebookPage *page;
3713 GtkWidget *menu_item;
3716 if (page->default_menu)
3718 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3719 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3721 page->menu_label = gtk_label_new ("");
3722 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3725 gtk_widget_show (page->menu_label);
3726 menu_item = gtk_menu_item_new ();
3727 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3728 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3729 gtk_notebook_real_page_position (notebook, list));
3730 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3731 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3732 if (GTK_WIDGET_VISIBLE (page->child))
3733 gtk_widget_show (menu_item);
3737 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3740 gtk_widget_unparent (GTK_BIN(widget)->child);
3741 GTK_BIN(widget)->child = NULL;
3745 gtk_notebook_menu_detacher (GtkWidget *widget,
3748 GtkNotebook *notebook;
3750 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3752 notebook = GTK_NOTEBOOK (widget);
3753 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3755 notebook->menu = NULL;
3758 /* Public GtkNotebook Page Insert/Remove Methods :
3760 * gtk_notebook_append_page
3761 * gtk_notebook_append_page_menu
3762 * gtk_notebook_prepend_page
3763 * gtk_notebook_prepend_page_menu
3764 * gtk_notebook_insert_page
3765 * gtk_notebook_insert_page_menu
3766 * gtk_notebook_remove_page
3769 * gtk_notebook_append_page:
3770 * @notebook: a #GtkNotebook
3771 * @child: the #GtkWidget to use as the contents of the page.
3772 * @tab_label: the #GtkWidget to be used as the label for the page,
3773 * or %NULL to use the default label, 'page N'.
3775 * Appends a page to @notebook.
3778 gtk_notebook_append_page (GtkNotebook *notebook,
3780 GtkWidget *tab_label)
3782 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3783 g_return_if_fail (GTK_IS_WIDGET (child));
3784 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3786 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3790 * gtk_notebook_append_page_menu:
3791 * @notebook: a #GtkNotebook
3792 * @child: the #GtkWidget to use as the contents of the page.
3793 * @tab_label: the #GtkWidget to be used as the label for the page,
3794 * or %NULL to use the default label, 'page N'.
3795 * @menu_label: the widget to use as a label for the page-switch
3796 * menu, if that is enabled. If %NULL, and @tab_label
3797 * is a #GtkLabel or %NULL, then the menu label will be
3798 * a newly created label with the same text as @tab_label;
3799 * If @tab_label is not a #GtkLabel, @menu_label must be
3800 * specified if the page-switch menu is to be used.
3802 * Appends a page to @notebook, specifying the widget to use as the
3803 * label in the popup menu.
3806 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3808 GtkWidget *tab_label,
3809 GtkWidget *menu_label)
3811 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3812 g_return_if_fail (GTK_IS_WIDGET (child));
3813 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3814 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3816 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3820 * gtk_notebook_prepend_page:
3821 * @notebook: a #GtkNotebook
3822 * @child: the #GtkWidget to use as the contents of the page.
3823 * @tab_label: the #GtkWidget to be used as the label for the page,
3824 * or %NULL to use the default label, 'page N'.
3826 * Prepends a page to @notebook.
3829 gtk_notebook_prepend_page (GtkNotebook *notebook,
3831 GtkWidget *tab_label)
3833 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3834 g_return_if_fail (GTK_IS_WIDGET (child));
3835 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3837 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3841 * gtk_notebook_prepend_page_menu:
3842 * @notebook: a #GtkNotebook
3843 * @child: the #GtkWidget to use as the contents of the page.
3844 * @tab_label: the #GtkWidget to be used as the label for the page,
3845 * or %NULL to use the default label, 'page N'.
3846 * @menu_label: the widget to use as a label for the page-switch
3847 * menu, if that is enabled. If %NULL, and @tab_label
3848 * is a #GtkLabel or %NULL, then the menu label will be
3849 * a newly created label with the same text as @tab_label;
3850 * If @tab_label is not a #GtkLabel, @menu_label must be
3851 * specified if the page-switch menu is to be used.
3853 * Prepends a page to @notebook, specifying the widget to use as the
3854 * label in the popup menu.
3857 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3859 GtkWidget *tab_label,
3860 GtkWidget *menu_label)
3862 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3863 g_return_if_fail (GTK_IS_WIDGET (child));
3864 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3865 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3867 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3871 * gtk_notebook_insert_page:
3872 * @notebook: a #GtkNotebook
3873 * @child: the #GtkWidget to use as the contents of the page.
3874 * @tab_label: the #GtkWidget to be used as the label for the page,
3875 * or %NULL to use the default label, 'page N'.
3876 * @position: the index (starting at 0) at which to insert the page,
3877 * or -1 to append the page after all other pages.
3879 * Insert a page into @notebook at the given position
3882 gtk_notebook_insert_page (GtkNotebook *notebook,
3884 GtkWidget *tab_label,
3887 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3888 g_return_if_fail (GTK_IS_WIDGET (child));
3889 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3891 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3896 gtk_notebook_page_compare_tab (gconstpointer a,
3899 return (((GtkNotebookPage *) a)->tab_label != b);
3903 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3907 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3910 list = g_list_find_custom (notebook->children, child,
3911 gtk_notebook_page_compare_tab);
3914 GtkNotebookPage *page = list->data;
3916 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3917 gtk_notebook_switch_page (notebook, page, -1);
3918 focus_tabs_in (notebook);
3925 * gtk_notebook_insert_page_menu:
3926 * @notebook: a #GtkNotebook
3927 * @child: the #GtkWidget to use as the contents of the page.
3928 * @tab_label: the #GtkWidget to be used as the label for the page,
3929 * or %NULL to use the default label, 'page N'.
3930 * @menu_label: the widget to use as a label for the page-switch
3931 * menu, if that is enabled. If %NULL, and @tab_label
3932 * is a #GtkLabel or %NULL, then the menu label will be
3933 * a newly created label with the same text as @tab_label;
3934 * If @tab_label is not a #GtkLabel, @menu_label must be
3935 * specified if the page-switch menu is to be used.
3936 * @position: the index (starting at 0) at which to insert the page,
3937 * or -1 to append the page after all other pages.
3939 * Insert a page into @notebook at the given position, specifying
3940 * the widget to use as the label in the popup menu.
3943 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3945 GtkWidget *tab_label,
3946 GtkWidget *menu_label,
3949 GtkNotebookPage *page;
3952 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3953 g_return_if_fail (GTK_IS_WIDGET (child));
3954 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3955 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3957 gtk_widget_freeze_child_notify (child);
3959 page = g_new (GtkNotebookPage, 1);
3960 page->child = child;
3961 page->last_focus_child = NULL;
3962 page->requisition.width = 0;
3963 page->requisition.height = 0;
3964 page->allocation.x = 0;
3965 page->allocation.y = 0;
3966 page->allocation.width = 0;
3967 page->allocation.height = 0;
3968 page->default_menu = FALSE;
3969 page->default_tab = FALSE;
3970 page->mnemonic_activate_signal = 0;
3972 nchildren = g_list_length (notebook->children);
3973 if ((position < 0) || (position > nchildren))
3974 position = nchildren;
3976 notebook->children = g_list_insert (notebook->children, page, position);
3980 page->default_tab = TRUE;
3981 if (notebook->show_tabs)
3982 tab_label = gtk_label_new ("");
3984 page->tab_label = tab_label;
3985 page->menu_label = menu_label;
3986 page->expand = FALSE;
3988 page->pack = GTK_PACK_START;
3991 page->default_menu = TRUE;
3994 gtk_widget_ref (page->menu_label);
3995 gtk_object_sink (GTK_OBJECT (page->menu_label));
3999 gtk_notebook_menu_item_create (notebook,
4000 g_list_find (notebook->children, page));
4002 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4004 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4006 gtk_notebook_update_labels (notebook);
4008 if (!notebook->first_tab)
4009 notebook->first_tab = notebook->children;
4011 if (!notebook->cur_page)
4012 gtk_widget_set_child_visible (child, TRUE);
4014 gtk_widget_set_child_visible (child, FALSE);
4018 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4019 gtk_widget_show (tab_label);
4021 gtk_widget_hide (tab_label);
4024 if (!notebook->cur_page)
4026 gtk_notebook_switch_page (notebook, page, 0);
4027 gtk_notebook_switch_focus_tab (notebook, NULL);
4031 page->mnemonic_activate_signal =
4032 gtk_signal_connect (GTK_OBJECT (tab_label),
4033 "mnemonic_activate",
4034 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
4037 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4038 gdk_window_show_unraised (notebook->event_window);
4040 gtk_widget_child_notify (child, "tab_expand");
4041 gtk_widget_child_notify (child, "tab_fill");
4042 gtk_widget_child_notify (child, "tab_pack");
4043 gtk_widget_child_notify (child, "tab_label");
4044 gtk_widget_child_notify (child, "menu_label");
4045 gtk_widget_child_notify (child, "position");
4046 gtk_widget_thaw_child_notify (child);
4050 * gtk_notebook_remove_page:
4051 * @notebook: a #GtkNotebook.
4052 * @page_num: the index of a notebook page, starting
4053 * from 0. If -1, the last page will
4056 * Removes a page from the notebook given its index
4060 gtk_notebook_remove_page (GtkNotebook *notebook,
4065 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4069 list = g_list_nth (notebook->children, page_num);
4071 gtk_notebook_real_remove (notebook, list);
4075 list = g_list_last (notebook->children);
4077 gtk_notebook_real_remove (notebook, list);
4081 /* Public GtkNotebook Page Switch Methods :
4082 * gtk_notebook_get_current_page
4083 * gtk_notebook_page_num
4084 * gtk_notebook_set_current_page
4085 * gtk_notebook_next_page
4086 * gtk_notebook_prev_page
4089 * gtk_notebook_get_current_page:
4090 * @notebook: a #GtkNotebook
4092 * Returns the page number of the current page.
4094 * Return value: the index (starting from 0) of the current
4095 * page in the notebook. If the notebook has no pages, then
4096 * -1 will be returned.
4099 gtk_notebook_get_current_page (GtkNotebook *notebook)
4101 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4103 if (!notebook->cur_page)
4106 return g_list_index (notebook->children, notebook->cur_page);
4110 * gtk_notebook_get_nth_page:
4111 * @notebook: a #GtkNotebook
4112 * @page_num: the index of a page in the noteobok
4114 * Returns the child widget contained in page number @page_num.
4116 * Return value: the child widget, or %NULL if @page_num is
4120 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4123 GtkNotebookPage *page;
4125 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4127 page = g_list_nth_data (notebook->children, page_num);
4136 * gtk_notebook_page_num:
4137 * @notebook: a #GtkNotebook
4138 * @child: a #GtkWidget
4140 * Finds the index of the page which contains the given child
4143 * Return value: the index of the page containing @child, or
4144 * -1 if @child is not in the notebook.
4147 gtk_notebook_page_num (GtkNotebook *notebook,
4153 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4156 children = notebook->children;
4159 GtkNotebookPage *page = children->data;
4161 if (page->child == child)
4164 children = children->next;
4172 * gtk_notebook_set_current_page:
4173 * @notebook: a #GtkNotebook
4174 * @page_num: index of the page to switch to, starting from 0.
4175 * If negative, the last page will be used. If greater
4176 * than the number of pages in the notebook, nothing
4179 * Switches to the page number @page_num.
4182 gtk_notebook_set_current_page (GtkNotebook *notebook,
4187 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4190 list = g_list_nth (notebook->children, page_num);
4192 list = g_list_last (notebook->children);
4194 page_num = g_list_index (notebook->children, list);
4197 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4201 * gtk_notebook_next_page:
4202 * @notebook: a #GtkNotebook
4204 * Switches to the next page. Nothing happens if the current page is
4208 gtk_notebook_next_page (GtkNotebook *notebook)
4212 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4214 list = g_list_find (notebook->children, notebook->cur_page);
4218 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4222 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4226 * gtk_notebook_prev_page:
4227 * @notebook: a #GtkNotebook
4229 * Switches to the previous page. Nothing happens if the current page
4230 * is the first page.
4233 gtk_notebook_prev_page (GtkNotebook *notebook)
4237 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4239 list = g_list_find (notebook->children, notebook->cur_page);
4243 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4247 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4250 /* Public GtkNotebook/Tab Style Functions
4252 * gtk_notebook_set_show_border
4253 * gtk_notebook_set_show_tabs
4254 * gtk_notebook_set_tab_pos
4255 * gtk_notebook_set_homogeneous_tabs
4256 * gtk_notebook_set_tab_border
4257 * gtk_notebook_set_tab_hborder
4258 * gtk_notebook_set_tab_vborder
4259 * gtk_notebook_set_scrollable
4262 * gtk_notebook_set_show_border:
4263 * @notebook: a #GtkNotebook
4264 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4266 * Sets whether a bevel will be drawn around the notebook pages.
4267 * This is only has a visual effect when the tabs are not shown.
4268 * See gtk_notebook_set_show_tabs().
4271 gtk_notebook_set_show_border (GtkNotebook *notebook,
4272 gboolean show_border)
4274 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4276 if (notebook->show_border != show_border)
4278 notebook->show_border = show_border;
4280 if (GTK_WIDGET_VISIBLE (notebook))
4281 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4283 g_object_notify (G_OBJECT (notebook), "show_border");
4288 * gtk_notebook_get_show_border:
4289 * @notebook: a #GtkNotebook
4291 * Returns whether a bevel will be drawn around the notebook pages. See
4292 * gtk_notebook_set_show_border().
4294 * Return value: %TRUE if the bevel is drawn
4297 gtk_notebook_get_show_border (GtkNotebook *notebook)
4299 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4301 return notebook->show_border;
4305 * gtk_notebook_set_show_tabs:
4306 * @notebook: a #GtkNotebook
4307 * @show_tabs: %TRUE if the tabs should be shown.
4309 * Sets whether to show the tabs for the notebook or not.
4312 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4315 GtkNotebookPage *page;
4318 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4320 show_tabs = show_tabs != FALSE;
4322 if (notebook->show_tabs == show_tabs)
4325 notebook->show_tabs = show_tabs;
4326 children = notebook->children;
4330 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4334 page = children->data;
4335 children = children->next;
4336 if (page->default_tab)
4338 gtk_widget_destroy (page->tab_label);
4339 page->tab_label = NULL;
4342 gtk_widget_hide (page->tab_label);
4347 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4348 gtk_notebook_update_labels (notebook);
4350 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4352 g_object_notify (G_OBJECT (notebook), "show_tabs");
4356 * gtk_notebook_get_show_tabs:
4357 * @notebook: a #GtkNotebook
4359 * Returns whether the tabs of the notebook are shown. See
4360 * gtk_notebook_set_show_tabs().
4362 * Return value: %TRUE if the tabs are shown
4365 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4367 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4369 return notebook->show_tabs;
4373 * gtk_notebook_set_tab_pos:
4374 * @notebook: a #GtkNotebook.
4375 * @pos: the edge to draw the tabs at.
4377 * Sets the edge at which the tabs for switching pages in the
4378 * notebook are drawn.
4381 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4382 GtkPositionType pos)
4384 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4386 if (notebook->tab_pos != pos)
4388 notebook->tab_pos = pos;
4389 if (GTK_WIDGET_VISIBLE (notebook))
4390 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4393 g_object_notify (G_OBJECT (notebook), "tab_pos");
4397 * gtk_notebook_get_tab_pos:
4398 * @notebook: a #GtkNotebook
4400 * Gets the edge at which the tabs for switching pages in the
4401 * notebook are drawn.
4403 * Return value: the edge at which the tabs are drawn
4406 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4408 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4410 return notebook->tab_pos;
4414 * gtk_notebook_set_homogeneous_tabs:
4415 * @notebook: a #GtkNotebook
4416 * @homogeneous: %TRUE if all tabs should be the same size.
4418 * Sets whether the tabs must have all the same size or not.
4421 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4422 gboolean homogeneous)
4424 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4426 if (homogeneous == notebook->homogeneous)
4429 notebook->homogeneous = homogeneous;
4430 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4432 g_object_notify (G_OBJECT (notebook), "homogeneous");
4436 * gtk_notebook_set_tab_border:
4437 * @notebook: a #GtkNotebook
4438 * @border_width: width of the border around the tab labels.
4440 * Sets the width the border around the tab labels
4441 * in a notebook. This is equivalent to calling
4442 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4443 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4446 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4449 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4451 notebook->tab_hborder = border_width;
4452 notebook->tab_vborder = border_width;
4454 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4455 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4457 g_object_freeze_notify (G_OBJECT (notebook));
4458 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4459 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4460 g_object_thaw_notify (G_OBJECT (notebook));
4465 * gtk_notebook_set_tab_hborder:
4466 * @notebook: a #GtkNotebook
4467 * @tab_hborder: width of the horizontal border of tab labels.
4469 * Sets the width of the horizontal border of tab labels.
4472 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4475 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4477 if (notebook->tab_hborder == tab_hborder)
4480 notebook->tab_hborder = tab_hborder;
4482 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4483 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4485 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4489 * gtk_notebook_set_tab_vborder:
4490 * @notebook: a #GtkNotebook
4491 * @tab_vborder: width of the vertical border of tab labels.
4493 * Sets the width of the vertical border of tab labels.
4496 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4499 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4501 if (notebook->tab_vborder == tab_vborder)
4504 notebook->tab_vborder = tab_vborder;
4506 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4507 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4509 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4513 * gtk_notebook_set_scrollable:
4514 * @notebook: a #GtkNotebook
4515 * @scrollable: %TRUE if scroll arrows should be added
4517 * Sets whether the tab label area will have arrows for scrolling if
4518 * there are too many tabs to fit in the area.
4521 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4522 gboolean scrollable)
4524 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4526 scrollable = (scrollable != FALSE);
4528 if (scrollable != notebook->scrollable)
4530 notebook->scrollable = scrollable;
4532 if (GTK_WIDGET_VISIBLE (notebook))
4533 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4535 g_object_notify (G_OBJECT (notebook), "scrollable");
4540 * gtk_notebook_get_scrollable:
4541 * @notebook: a #GtkNotebook
4543 * Returns whether the tab label area has arrows for scrolling. See
4544 * gtk_notebook_set_scrollable().
4546 * Return value: %TRUE if arrows for scrolling are present
4549 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4551 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4553 return notebook->scrollable;
4556 /* Public GtkNotebook Popup Menu Methods:
4558 * gtk_notebook_popup_enable
4559 * gtk_notebook_popup_disable
4564 * gtk_notebook_popup_enable:
4565 * @notebook: a #GtkNotebook
4567 * Enables the popup menu: if the user clicks with the right mouse button on
4568 * the bookmarks, a menu with all the pages will be popped up.
4571 gtk_notebook_popup_enable (GtkNotebook *notebook)
4575 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4580 notebook->menu = gtk_menu_new ();
4581 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4583 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4584 gtk_notebook_menu_item_create (notebook, list);
4586 gtk_notebook_update_labels (notebook);
4587 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4588 GTK_WIDGET (notebook),
4589 gtk_notebook_menu_detacher);
4591 g_object_notify (G_OBJECT (notebook), "enable_popup");
4595 * gtk_notebook_popup_disable:
4596 * @notebook: a #GtkNotebook
4598 * Disables the popup menu.
4601 gtk_notebook_popup_disable (GtkNotebook *notebook)
4603 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4605 if (!notebook->menu)
4608 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4609 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4610 gtk_widget_destroy (notebook->menu);
4612 g_object_notify (G_OBJECT (notebook), "enable_popup");
4615 /* Public GtkNotebook Page Properties Functions:
4617 * gtk_notebook_get_tab_label
4618 * gtk_notebook_set_tab_label
4619 * gtk_notebook_set_tab_label_text
4620 * gtk_notebook_get_menu_label
4621 * gtk_notebook_set_menu_label
4622 * gtk_notebook_set_menu_label_text
4623 * gtk_notebook_set_tab_label_packing
4624 * gtk_notebook_query_tab_label_packing
4628 * gtk_notebook_get_tab_label:
4629 * @notebook: a #GtkNotebook
4632 * Returns the tab label widget for the page @child. %NULL is returned
4633 * if @child is not in @notebook or if no tab label has specifically
4634 * been set for @child.
4636 * Return value: the tab label
4639 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4644 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4645 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4647 list = CHECK_FIND_CHILD (notebook, child);
4651 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4654 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4658 * gtk_notebook_set_tab_label:
4659 * @notebook: a #GtkNotebook
4661 * @tab_label: the tab label widget to use, or %NULL for default tab
4664 * Changes the tab label for @child. If %NULL is specified
4665 * for @tab_label, then the page will have the label 'page N'.
4668 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4670 GtkWidget *tab_label)
4672 GtkNotebookPage *page;
4675 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4676 g_return_if_fail (GTK_IS_WIDGET (child));
4678 list = CHECK_FIND_CHILD (notebook, child);
4682 /* a NULL pointer indicates a default_tab setting, otherwise
4683 * we need to set the associated label
4687 if (page->tab_label == tab_label)
4691 gtk_notebook_remove_tab_label (notebook, page);
4695 page->default_tab = FALSE;
4696 page->tab_label = tab_label;
4697 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4701 page->default_tab = TRUE;
4702 page->tab_label = NULL;
4704 if (notebook->show_tabs)
4708 g_snprintf (string, sizeof(string), _("Page %u"),
4709 gtk_notebook_real_page_position (notebook, list));
4710 page->tab_label = gtk_label_new (string);
4711 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4715 if (page->tab_label)
4716 page->mnemonic_activate_signal =
4717 gtk_signal_connect (GTK_OBJECT (page->tab_label),
4718 "mnemonic_activate",
4719 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
4722 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4724 gtk_widget_show (page->tab_label);
4725 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4727 gtk_widget_child_notify (child, "tab_label");
4731 * gtk_notebook_set_tab_label_text:
4732 * @notebook: a #GtkNotebook
4734 * @tab_text: the label text
4736 * Creates a new label and sets it as the tab label for the page
4737 * containing @child.
4740 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4742 const gchar *tab_text)
4744 GtkWidget *tab_label = NULL;
4746 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4749 tab_label = gtk_label_new (tab_text);
4750 gtk_notebook_set_tab_label (notebook, child, tab_label);
4751 gtk_widget_child_notify (child, "tab_label");
4755 * gtk_notebook_get_tab_label_text:
4756 * @notebook: a #GtkNotebook
4757 * @child: a widget contained in a page of @notebook
4759 * Retrieves the text of the tab label for the page containing
4762 * Returns value: the text of the tab label, or %NULL if the
4763 * tab label widget is not a #GtkLabel. The
4764 * string is owned by the widget and must not
4767 G_CONST_RETURN gchar *
4768 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4771 GtkWidget *tab_label;
4773 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4774 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4776 tab_label = gtk_notebook_get_tab_label (notebook, child);
4778 if (tab_label && GTK_IS_LABEL (tab_label))
4779 return gtk_label_get_text (GTK_LABEL (tab_label));
4785 * gtk_notebook_get_menu_label:
4786 * @notebook: a #GtkNotebook
4787 * @child: a widget contained in a page of @notebook
4789 * Retrieves the menu label widget of the page containing @child.
4791 * Return value: the menu label, or %NULL if the
4792 * notebook page does not have a menu label other
4793 * than the default (the tab label).
4796 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4801 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4802 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4804 list = CHECK_FIND_CHILD (notebook, child);
4808 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4811 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4815 * gtk_notebook_set_menu_label:
4816 * @notebook: a #GtkNotebook
4817 * @child: the child widget
4818 * @menu_label: the menu label, or NULL for default
4820 * Changes the menu label for the page containing @child.
4823 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4825 GtkWidget *menu_label)
4827 GtkNotebookPage *page;
4830 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4831 g_return_if_fail (GTK_IS_WIDGET (child));
4833 list = CHECK_FIND_CHILD (notebook, child);
4838 if (page->menu_label)
4841 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4842 page->menu_label->parent);
4844 if (!page->default_menu)
4845 gtk_widget_unref (page->menu_label);
4850 page->menu_label = menu_label;
4851 gtk_widget_ref (page->menu_label);
4852 gtk_object_sink (GTK_OBJECT(page->menu_label));
4853 page->default_menu = FALSE;
4856 page->default_menu = TRUE;
4859 gtk_notebook_menu_item_create (notebook, list);
4860 gtk_widget_child_notify (child, "menu_label");
4864 * gtk_notebook_set_menu_label_text:
4865 * @notebook: a #GtkNotebook
4866 * @child: the child widget
4867 * @menu_text: the label text
4869 * Creates a new label and sets it as the menu label of @child.
4872 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4874 const gchar *menu_text)
4876 GtkWidget *menu_label = NULL;
4878 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4881 menu_label = gtk_label_new (menu_text);
4882 gtk_notebook_set_menu_label (notebook, child, menu_label);
4883 gtk_widget_child_notify (child, "menu_label");
4887 * gtk_notebook_get_menu_label_text:
4888 * @notebook: a #GtkNotebook
4889 * @child: the child widget of a page of the notebook.
4891 * Retrieves the text of the menu label for the page containing
4894 * Returns value: the text of the tab label, or %NULL if the
4895 * widget does not have a menu label other than
4896 * the default menu label, or the menu label widget
4897 * is not a #GtkLabel. The string is owned by
4898 * the widget and must not be freed.
4900 G_CONST_RETURN gchar *
4901 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4904 GtkWidget *menu_label;
4906 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4907 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4909 menu_label = gtk_notebook_get_menu_label (notebook, child);
4911 if (menu_label && GTK_IS_LABEL (menu_label))
4912 return gtk_label_get_text (GTK_LABEL (menu_label));
4917 /* Helper function called when pages are reordered
4920 gtk_notebook_child_reordered (GtkNotebook *notebook,
4921 GtkNotebookPage *page)
4925 GtkWidget *menu_item;
4927 menu_item = page->menu_label->parent;
4928 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4929 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4930 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4933 gtk_notebook_update_labels (notebook);
4937 * gtk_notebook_set_tab_label_packing:
4938 * @notebook: a #GtkNotebook
4939 * @child: the child widget
4940 * @expand: whether to expand the bookmark or not
4941 * @fill: whether the bookmark should fill the allocated area or not
4942 * @pack_type: the position of the bookmark
4944 * Sets the packing parameters for the tab label of the page
4945 * containing @child. See gtk_box_pack_start() for the exact meaning
4946 * of the parameters.
4949 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4953 GtkPackType pack_type)
4955 GtkNotebookPage *page;
4958 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4959 g_return_if_fail (GTK_IS_WIDGET (child));
4961 list = CHECK_FIND_CHILD (notebook, child);
4966 expand = expand != FALSE;
4967 fill = fill != FALSE;
4968 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4971 gtk_widget_freeze_child_notify (child);
4972 page->expand = expand;
4973 gtk_widget_child_notify (child, "tab_expand");
4975 gtk_widget_child_notify (child, "tab_fill");
4976 if (page->pack != pack_type)
4978 page->pack = pack_type;
4979 gtk_notebook_child_reordered (notebook, page);
4981 gtk_widget_child_notify (child, "tab_pack");
4982 gtk_widget_child_notify (child, "position");
4983 if (notebook->show_tabs)
4984 gtk_notebook_pages_allocate (notebook);
4985 gtk_widget_thaw_child_notify (child);
4989 * gtk_notebook_query_tab_label_packing:
4990 * @notebook: a #GtkNotebook
4992 * @expand: location to store the expand value (or NULL)
4993 * @fill: location to store the fill value (or NULL)
4994 * @pack_type: location to store the pack_type (or NULL)
4996 * Query the packing attributes for the tab label of the page
4997 * containing @child.
5000 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5004 GtkPackType *pack_type)
5008 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5009 g_return_if_fail (GTK_IS_WIDGET (child));
5011 list = CHECK_FIND_CHILD (notebook, child);
5016 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5018 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5020 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5024 * gtk_notebook_reorder_child:
5025 * @notebook: a #GtkNotebook
5026 * @child: the child to move
5027 * @position: the new position, or -1 to move to the end
5029 * Reorders the page containing @child, so that it appears in position
5030 * @position. If @position is greater than or equal to the number of
5031 * children in the list or negative, @child will be moved to the end
5035 gtk_notebook_reorder_child (GtkNotebook *notebook,
5039 GList *list, *new_list;
5040 GtkNotebookPage *page;
5044 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5045 g_return_if_fail (GTK_IS_WIDGET (child));
5047 list = CHECK_FIND_CHILD (notebook, child);
5051 max_pos = g_list_length (notebook->children) - 1;
5052 if (position < 0 || position > max_pos)
5055 old_pos = g_list_position (notebook->children, list);
5057 if (old_pos == position)
5061 notebook->children = g_list_delete_link (notebook->children, list);
5063 notebook->children = g_list_insert (notebook->children, page, position);
5064 new_list = g_list_nth (notebook->children, position);
5066 /* Fix up GList references in GtkNotebook structure */
5067 if (notebook->first_tab == list)
5068 notebook->first_tab = new_list;
5069 if (notebook->focus_tab == list)
5070 notebook->focus_tab = new_list;
5072 gtk_widget_freeze_child_notify (child);
5074 /* Move around the menu items if necesary */
5075 gtk_notebook_child_reordered (notebook, page);
5076 gtk_widget_child_notify (child, "tab_pack");
5077 gtk_widget_child_notify (child, "position");
5079 if (notebook->show_tabs)
5080 gtk_notebook_pages_allocate (notebook);
5082 gtk_widget_thaw_child_notify (child);