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", NULL, NULL,
444 gtk_container_class_install_child_property (container_class,
445 CHILD_PROP_MENU_LABEL,
446 g_param_spec_string ("menu_label", NULL, NULL,
449 gtk_container_class_install_child_property (container_class,
451 g_param_spec_int ("position", NULL, NULL,
454 gtk_container_class_install_child_property (container_class,
455 CHILD_PROP_TAB_EXPAND,
456 g_param_spec_boolean ("tab_expand", NULL, NULL,
459 gtk_container_class_install_child_property (container_class,
461 g_param_spec_boolean ("tab_fill", NULL, NULL,
464 gtk_container_class_install_child_property (container_class,
466 g_param_spec_enum ("tab_pack", NULL, NULL,
467 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
470 notebook_signals[SWITCH_PAGE] =
471 gtk_signal_new ("switch_page",
473 GTK_CLASS_TYPE (object_class),
474 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
475 _gtk_marshal_VOID__POINTER_UINT,
479 notebook_signals[FOCUS_TAB] =
480 g_signal_new ("focus_tab",
481 G_TYPE_FROM_CLASS (object_class),
482 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
483 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
485 _gtk_marshal_BOOLEAN__ENUM,
487 GTK_TYPE_NOTEBOOK_TAB);
488 notebook_signals[SELECT_PAGE] =
489 g_signal_new ("select_page",
490 G_TYPE_FROM_CLASS (object_class),
491 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
492 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
494 _gtk_marshal_BOOLEAN__BOOLEAN,
497 notebook_signals[CHANGE_CURRENT_PAGE] =
498 g_signal_new ("change_current_page",
499 G_TYPE_FROM_CLASS (object_class),
500 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
501 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
503 _gtk_marshal_VOID__INT,
506 notebook_signals[MOVE_FOCUS_OUT] =
507 g_signal_new ("move_focus_out",
508 G_TYPE_FROM_CLASS (object_class),
509 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
510 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
512 _gtk_marshal_VOID__ENUM,
514 GTK_TYPE_DIRECTION_TYPE);
517 binding_set = gtk_binding_set_by_class (object_class);
518 gtk_binding_entry_add_signal (binding_set,
521 G_TYPE_BOOLEAN, FALSE);
522 gtk_binding_entry_add_signal (binding_set,
525 G_TYPE_BOOLEAN, FALSE);
527 gtk_binding_entry_add_signal (binding_set,
530 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
531 gtk_binding_entry_add_signal (binding_set,
534 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
535 gtk_binding_entry_add_signal (binding_set,
538 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
539 gtk_binding_entry_add_signal (binding_set,
542 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
544 gtk_binding_entry_add_signal (binding_set,
545 GDK_Page_Up, GDK_CONTROL_MASK,
546 "change_current_page", 1,
548 gtk_binding_entry_add_signal (binding_set,
549 GDK_Page_Down, GDK_CONTROL_MASK,
550 "change_current_page", 1,
553 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
554 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
555 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
556 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
558 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
559 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
563 gtk_notebook_init (GtkNotebook *notebook)
565 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
566 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
568 notebook->cur_page = NULL;
569 notebook->children = NULL;
570 notebook->first_tab = NULL;
571 notebook->focus_tab = NULL;
572 notebook->event_window = NULL;
573 notebook->menu = NULL;
575 notebook->tab_hborder = 2;
576 notebook->tab_vborder = 2;
578 notebook->show_tabs = TRUE;
579 notebook->show_border = TRUE;
580 notebook->tab_pos = GTK_POS_TOP;
581 notebook->scrollable = FALSE;
582 notebook->in_child = 0;
583 notebook->click_child = 0;
584 notebook->button = 0;
585 notebook->need_timer = 0;
586 notebook->child_has_focus = FALSE;
587 notebook->have_visible_child = FALSE;
588 notebook->focus_out = FALSE;
592 gtk_notebook_select_page (GtkNotebook *notebook,
595 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
597 gtk_notebook_page_select (notebook, move_focus);
605 gtk_notebook_focus_tab (GtkNotebook *notebook,
610 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
614 case GTK_NOTEBOOK_TAB_FIRST:
615 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
617 gtk_notebook_switch_focus_tab (notebook, list);
619 case GTK_NOTEBOOK_TAB_LAST:
620 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
622 gtk_notebook_switch_focus_tab (notebook, list);
633 gtk_notebook_change_current_page (GtkNotebook *notebook,
636 GList *current = NULL;
638 if (notebook->cur_page)
639 current = g_list_find (notebook->children, notebook->cur_page);
643 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
644 offset += offset < 0 ? 1 : -1;
648 gtk_notebook_switch_page (notebook, current->data, -1);
650 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
653 static GtkDirectionType
654 get_effective_direction (GtkNotebook *notebook,
655 GtkDirectionType direction)
657 /* Remap the directions into the effective direction it would be for a
658 * GTK_POS_TOP notebook
660 #define D(rest) GTK_DIR_##rest
662 static const GtkDirectionType translate_direction[4][6] = {
663 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
664 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
665 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
666 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
671 return translate_direction[notebook->tab_pos][direction];
675 gtk_notebook_move_focus_out (GtkNotebook *notebook,
676 GtkDirectionType direction_type)
678 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
681 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
682 if (focus_tabs_in (notebook))
685 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
686 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
689 /* At this point, we know we should be focusing out of the notebook entirely. We
690 * do this by setting a flag, then propagating the focus motion to the notebook.
692 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
693 if (!GTK_WIDGET_TOPLEVEL (toplevel))
696 g_object_ref (notebook);
698 notebook->focus_out = TRUE;
699 g_signal_emit_by_name (G_OBJECT (toplevel), "move_focus", direction_type);
700 notebook->focus_out = FALSE;
702 g_object_unref (notebook);
709 * Creates a new #GtkNotebook widget with no pages.
711 * Return value: the newly created #GtkNotebook
714 gtk_notebook_new (void)
716 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
719 /* Private GtkObject Methods :
721 * gtk_notebook_destroy
722 * gtk_notebook_set_arg
723 * gtk_notebook_get_arg
726 gtk_notebook_destroy (GtkObject *object)
728 GtkNotebook *notebook = GTK_NOTEBOOK (object);
731 gtk_notebook_popup_disable (notebook);
733 GTK_OBJECT_CLASS (parent_class)->destroy (object);
737 gtk_notebook_set_property (GObject *object,
742 GtkNotebook *notebook;
744 notebook = GTK_NOTEBOOK (object);
749 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
751 case PROP_SHOW_BORDER:
752 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
754 case PROP_SCROLLABLE:
755 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
757 case PROP_ENABLE_POPUP:
758 if (g_value_get_boolean (value))
759 gtk_notebook_popup_enable (notebook);
761 gtk_notebook_popup_disable (notebook);
763 case PROP_HOMOGENEOUS:
764 gtk_notebook_set_homogeneous_tabs (notebook, g_value_get_boolean (value));
767 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
770 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
772 case PROP_TAB_BORDER:
773 gtk_notebook_set_tab_border (notebook, g_value_get_uint (value));
775 case PROP_TAB_HBORDER:
776 gtk_notebook_set_tab_hborder (notebook, g_value_get_uint (value));
778 case PROP_TAB_VBORDER:
779 gtk_notebook_set_tab_vborder (notebook, g_value_get_uint (value));
787 gtk_notebook_get_property (GObject *object,
792 GtkNotebook *notebook;
794 notebook = GTK_NOTEBOOK (object);
799 g_value_set_boolean (value, notebook->show_tabs);
801 case PROP_SHOW_BORDER:
802 g_value_set_boolean (value, notebook->show_border);
804 case PROP_SCROLLABLE:
805 g_value_set_boolean (value, notebook->scrollable);
807 case PROP_ENABLE_POPUP:
808 g_value_set_boolean (value, notebook->menu != NULL);
810 case PROP_HOMOGENEOUS:
811 g_value_set_boolean (value, notebook->homogeneous);
814 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
817 g_value_set_enum (value, notebook->tab_pos);
819 case PROP_TAB_HBORDER:
820 g_value_set_uint (value, notebook->tab_hborder);
822 case PROP_TAB_VBORDER:
823 g_value_set_uint (value, notebook->tab_vborder);
826 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
831 /* Private GtkWidget Methods :
835 * gtk_notebook_realize
836 * gtk_notebook_size_request
837 * gtk_notebook_size_allocate
838 * gtk_notebook_expose
839 * gtk_notebook_button_press
840 * gtk_notebook_button_release
841 * gtk_notebook_enter_notify
842 * gtk_notebook_leave_notify
843 * gtk_notebook_motion_notify
844 * gtk_notebook_focus_in
845 * gtk_notebook_focus_out
846 * gtk_notebook_draw_focus
847 * gtk_notebook_style_set
850 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
851 GdkRectangle *rectangle)
853 GtkWidget *widget = GTK_WIDGET (notebook);
854 gint border_width = GTK_CONTAINER (notebook)->border_width;
856 if (notebook->show_tabs && notebook->children)
860 GtkNotebookPage *page = notebook->children->data;
862 rectangle->x = widget->allocation.x + border_width;
863 rectangle->y = widget->allocation.y + border_width;
865 switch (notebook->tab_pos)
869 rectangle->width = widget->allocation.width - 2 * border_width;
870 rectangle->height = page->requisition.height;
871 if (notebook->tab_pos == GTK_POS_BOTTOM)
872 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
876 rectangle->width = page->requisition.width;
877 rectangle->height = widget->allocation.height - 2 * border_width;
878 if (notebook->tab_pos == GTK_POS_RIGHT)
879 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
890 rectangle->x = rectangle->y = 0;
891 rectangle->width = rectangle->height = 10;
899 gtk_notebook_map (GtkWidget *widget)
901 GtkNotebook *notebook;
902 GtkNotebookPage *page;
905 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
907 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
909 notebook = GTK_NOTEBOOK (widget);
911 if (notebook->cur_page &&
912 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
913 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
914 gtk_widget_map (notebook->cur_page->child);
916 if (notebook->scrollable)
917 gtk_notebook_pages_allocate (notebook);
920 children = notebook->children;
924 page = children->data;
925 children = children->next;
927 if (page->tab_label &&
928 GTK_WIDGET_VISIBLE (page->tab_label) &&
929 !GTK_WIDGET_MAPPED (page->tab_label))
930 gtk_widget_map (page->tab_label);
934 if (gtk_notebook_get_event_window_position (notebook, NULL))
935 gdk_window_show_unraised (notebook->event_window);
939 gtk_notebook_unmap (GtkWidget *widget)
941 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
943 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
945 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
947 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
951 gtk_notebook_realize (GtkWidget *widget)
953 GtkNotebook *notebook;
954 GdkWindowAttr attributes;
955 gint attributes_mask;
956 GdkRectangle event_window_pos;
958 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
960 notebook = GTK_NOTEBOOK (widget);
961 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
963 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
965 widget->window = gtk_widget_get_parent_window (widget);
966 gdk_window_ref (widget->window);
968 attributes.window_type = GDK_WINDOW_CHILD;
969 attributes.x = event_window_pos.x;
970 attributes.y = event_window_pos.y;
971 attributes.width = event_window_pos.width;
972 attributes.height = event_window_pos.height;
973 attributes.wclass = GDK_INPUT_ONLY;
974 attributes.event_mask = gtk_widget_get_events (widget);
975 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
976 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
978 attributes_mask = GDK_WA_X | GDK_WA_Y;
980 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
981 &attributes, attributes_mask);
982 gdk_window_set_user_data (notebook->event_window, notebook);
984 widget->style = gtk_style_attach (widget->style, widget->window);
988 gtk_notebook_unrealize (GtkWidget *widget)
990 GtkNotebook *notebook;
992 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
994 notebook = GTK_NOTEBOOK (widget);
996 gdk_window_set_user_data (notebook->event_window, NULL);
997 gdk_window_destroy (notebook->event_window);
998 notebook->event_window = NULL;
1000 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1001 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1005 gtk_notebook_size_request (GtkWidget *widget,
1006 GtkRequisition *requisition)
1008 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1009 GtkNotebookPage *page;
1011 GtkRequisition child_requisition;
1012 gboolean switch_page = FALSE;
1016 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1018 widget->requisition.width = 0;
1019 widget->requisition.height = 0;
1021 for (children = notebook->children, vis_pages = 0; children;
1022 children = children->next)
1024 page = children->data;
1026 if (GTK_WIDGET_VISIBLE (page->child))
1029 gtk_widget_size_request (page->child, &child_requisition);
1031 widget->requisition.width = MAX (widget->requisition.width,
1032 child_requisition.width);
1033 widget->requisition.height = MAX (widget->requisition.height,
1034 child_requisition.height);
1036 if (notebook->menu && page->menu_label->parent &&
1037 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1038 gtk_widget_show (page->menu_label->parent);
1042 if (page == notebook->cur_page)
1044 if (notebook->menu && page->menu_label->parent &&
1045 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1046 gtk_widget_hide (page->menu_label->parent);
1050 if (notebook->show_border || notebook->show_tabs)
1052 widget->requisition.width += widget->style->xthickness * 2;
1053 widget->requisition.height += widget->style->ythickness * 2;
1055 if (notebook->show_tabs)
1058 gint tab_height = 0;
1062 for (children = notebook->children; children;
1063 children = children->next)
1065 page = children->data;
1067 if (GTK_WIDGET_VISIBLE (page->child))
1069 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1070 gtk_widget_show (page->tab_label);
1072 gtk_widget_size_request (page->tab_label,
1073 &child_requisition);
1075 page->requisition.width =
1076 child_requisition.width +
1077 2 * widget->style->xthickness;
1078 page->requisition.height =
1079 child_requisition.height +
1080 2 * widget->style->ythickness;
1082 switch (notebook->tab_pos)
1085 case GTK_POS_BOTTOM:
1086 page->requisition.height += 2 * (notebook->tab_vborder +
1088 tab_height = MAX (tab_height, page->requisition.height);
1089 tab_max = MAX (tab_max, page->requisition.width);
1093 page->requisition.width += 2 * (notebook->tab_hborder +
1095 tab_width = MAX (tab_width, page->requisition.width);
1096 tab_max = MAX (tab_max, page->requisition.height);
1100 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1101 gtk_widget_hide (page->tab_label);
1104 children = notebook->children;
1108 switch (notebook->tab_pos)
1111 case GTK_POS_BOTTOM:
1112 if (tab_height == 0)
1115 if (notebook->scrollable && vis_pages > 1 &&
1116 widget->requisition.width < tab_width)
1117 tab_height = MAX (tab_height, ARROW_SIZE);
1119 padding = 2 * (TAB_CURVATURE + focus_width +
1120 notebook->tab_hborder) - TAB_OVERLAP;
1124 page = children->data;
1125 children = children->next;
1127 if (!GTK_WIDGET_VISIBLE (page->child))
1130 if (notebook->homogeneous)
1131 page->requisition.width = tab_max;
1133 page->requisition.width += padding;
1135 tab_width += page->requisition.width;
1136 page->requisition.height = tab_height;
1139 if (notebook->scrollable && vis_pages > 1 &&
1140 widget->requisition.width < tab_width)
1141 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1143 if (notebook->homogeneous && !notebook->scrollable)
1144 widget->requisition.width = MAX (widget->requisition.width,
1145 vis_pages * tab_max +
1148 widget->requisition.width = MAX (widget->requisition.width,
1149 tab_width + TAB_OVERLAP);
1151 widget->requisition.height += tab_height;
1158 if (notebook->scrollable && vis_pages > 1 &&
1159 widget->requisition.height < tab_height)
1160 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
1162 padding = 2 * (TAB_CURVATURE + focus_width +
1163 notebook->tab_vborder) - TAB_OVERLAP;
1168 page = children->data;
1169 children = children->next;
1171 if (!GTK_WIDGET_VISIBLE (page->child))
1174 page->requisition.width = tab_width;
1176 if (notebook->homogeneous)
1177 page->requisition.height = tab_max;
1179 page->requisition.height += padding;
1181 tab_height += page->requisition.height;
1184 if (notebook->scrollable && vis_pages > 1 &&
1185 widget->requisition.height < tab_height)
1186 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1188 widget->requisition.width += tab_width;
1190 if (notebook->homogeneous && !notebook->scrollable)
1191 widget->requisition.height =
1192 MAX (widget->requisition.height,
1193 vis_pages * tab_max + TAB_OVERLAP);
1195 widget->requisition.height =
1196 MAX (widget->requisition.height,
1197 tab_height + TAB_OVERLAP);
1199 if (!notebook->homogeneous || notebook->scrollable)
1201 widget->requisition.height = MAX (widget->requisition.height,
1202 vis_pages * tab_max +
1210 for (children = notebook->children; children;
1211 children = children->next)
1213 page = children->data;
1215 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1216 gtk_widget_hide (page->tab_label);
1221 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1222 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1228 for (children = notebook->children; children;
1229 children = children->next)
1231 page = children->data;
1232 if (GTK_WIDGET_VISIBLE (page->child))
1234 gtk_notebook_switch_page (notebook, page, -1);
1239 else if (GTK_WIDGET_VISIBLE (widget))
1241 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1242 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1245 if (vis_pages && !notebook->cur_page)
1247 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1250 notebook->first_tab = children;
1251 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1257 gtk_notebook_size_allocate (GtkWidget *widget,
1258 GtkAllocation *allocation)
1260 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1263 widget->allocation = *allocation;
1264 if (GTK_WIDGET_REALIZED (widget))
1266 GdkRectangle position;
1268 if (gtk_notebook_get_event_window_position (notebook, &position))
1269 gdk_window_move_resize (notebook->event_window,
1270 position.x, position.y,
1271 position.width, position.height);
1274 if (notebook->children)
1276 gint border_width = GTK_CONTAINER (widget)->border_width;
1277 GtkNotebookPage *page;
1278 GtkAllocation child_allocation;
1281 child_allocation.x = widget->allocation.x + border_width;
1282 child_allocation.y = widget->allocation.y + border_width;
1283 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1284 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1286 if (notebook->show_tabs || notebook->show_border)
1288 child_allocation.x += widget->style->xthickness;
1289 child_allocation.y += widget->style->ythickness;
1290 child_allocation.width = MAX (1, child_allocation.width -
1291 widget->style->xthickness * 2);
1292 child_allocation.height = MAX (1, child_allocation.height -
1293 widget->style->ythickness * 2);
1295 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1297 switch (notebook->tab_pos)
1300 child_allocation.y += notebook->cur_page->requisition.height;
1301 case GTK_POS_BOTTOM:
1302 child_allocation.height =
1303 MAX (1, child_allocation.height -
1304 notebook->cur_page->requisition.height);
1307 child_allocation.x += notebook->cur_page->requisition.width;
1309 child_allocation.width =
1310 MAX (1, child_allocation.width -
1311 notebook->cur_page->requisition.width);
1317 children = notebook->children;
1320 page = children->data;
1321 children = children->next;
1323 if (GTK_WIDGET_VISIBLE (page->child))
1325 gtk_widget_size_allocate (page->child, &child_allocation);
1330 gtk_notebook_pages_allocate (notebook);
1333 if ((vis_pages != 0) != notebook->have_visible_child)
1335 notebook->have_visible_child = (vis_pages != 0);
1336 if (notebook->show_tabs)
1337 gtk_widget_queue_draw (widget);
1342 gtk_notebook_expose (GtkWidget *widget,
1343 GdkEventExpose *event)
1345 GtkNotebook *notebook;
1346 GdkRectangle child_area;
1348 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1349 g_return_val_if_fail (event != NULL, FALSE);
1351 if (GTK_WIDGET_DRAWABLE (widget))
1353 notebook = GTK_NOTEBOOK (widget);
1355 gtk_notebook_paint (widget, &event->area);
1356 if (notebook->show_tabs)
1358 if (notebook->cur_page &&
1359 gtk_widget_intersect (notebook->cur_page->tab_label,
1360 &event->area, &child_area))
1361 gtk_notebook_draw_focus (widget);
1365 if (notebook->cur_page)
1366 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1367 notebook->cur_page->child,
1375 gtk_notebook_show_arrows (GtkNotebook *notebook)
1377 gboolean show_arrow = FALSE;
1380 if (!notebook->scrollable)
1383 children = notebook->children;
1386 GtkNotebookPage *page = children->data;
1388 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1391 children = children->next;
1398 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1399 GdkRectangle *rectangle)
1401 GdkRectangle event_window_pos;
1403 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1405 rectangle->width = 2 * ARROW_SIZE + ARROW_SPACING;
1406 rectangle->height = ARROW_SIZE;
1408 switch (notebook->tab_pos)
1412 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1413 rectangle->y = event_window_pos.y + event_window_pos.height - rectangle->height;
1416 case GTK_POS_BOTTOM:
1417 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1418 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1425 gtk_notebook_get_arrow (GtkNotebook *notebook,
1429 GdkRectangle arrow_rect;
1430 GdkRectangle event_window_pos;
1432 if (gtk_notebook_show_arrows (notebook))
1434 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1435 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
1440 if (y >= 0 && y < arrow_rect.height)
1442 if (x >= 0 && x < ARROW_SIZE + ARROW_SPACING / 2)
1443 return GTK_ARROW_LEFT;
1444 else if (x >= ARROW_SIZE + ARROW_SPACING / 2 && x < arrow_rect.width)
1445 return GTK_ARROW_RIGHT;
1453 gtk_notebook_do_arrow (GtkNotebook *notebook,
1456 GtkWidget *widget = GTK_WIDGET (notebook);
1457 GtkDirectionType dir;
1459 if (!notebook->focus_tab ||
1460 gtk_notebook_search_page (notebook, notebook->focus_tab,
1461 arrow == GTK_ARROW_LEFT ? STEP_PREV : STEP_NEXT,
1464 if (notebook->tab_pos == GTK_POS_LEFT ||
1465 notebook->tab_pos == GTK_POS_RIGHT)
1466 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_UP : GTK_DIR_DOWN;
1468 dir = (arrow == GTK_ARROW_LEFT) ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1469 gtk_widget_child_focus (widget, dir);
1474 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1476 GdkEventButton *event)
1478 GtkWidget *widget = GTK_WIDGET (notebook);
1480 if (!GTK_WIDGET_HAS_FOCUS (widget))
1481 gtk_widget_grab_focus (widget);
1483 notebook->button = event->button;
1484 notebook->click_child = arrow;
1486 if (event->button == 1)
1488 gtk_notebook_do_arrow (notebook, arrow);
1490 if (!notebook->timer)
1492 notebook->timer = gtk_timeout_add
1493 (NOTEBOOK_INIT_SCROLL_DELAY,
1494 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1495 notebook->need_timer = TRUE;
1498 else if (event->button == 2)
1499 gtk_notebook_page_select (notebook, TRUE);
1500 else if (event->button == 3)
1501 gtk_notebook_switch_focus_tab (notebook,
1502 gtk_notebook_search_page (notebook,
1504 arrow == GTK_ARROW_LEFT ? STEP_NEXT : STEP_PREV,
1506 gtk_notebook_redraw_arrows (notebook);
1512 get_widget_coordinates (GtkWidget *widget,
1517 GdkWindow *window = ((GdkEventAny *)event)->window;
1520 if (!gdk_event_get_coords (event, &tx, &ty))
1523 while (window && window != widget->window)
1525 gint window_x, window_y;
1527 gdk_window_get_position (window, &window_x, &window_y);
1531 window = gdk_window_get_parent (window);
1546 gtk_notebook_button_press (GtkWidget *widget,
1547 GdkEventButton *event)
1549 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1550 GtkNotebookPage *page;
1556 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1560 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1563 arrow = gtk_notebook_get_arrow (notebook, x, y);
1565 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1567 if (event->button == 3 && notebook->menu)
1569 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1570 NULL, NULL, 3, event->time);
1575 children = notebook->children;
1578 page = children->data;
1580 if (GTK_WIDGET_VISIBLE (page->child) &&
1581 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1582 (x >= page->allocation.x) &&
1583 (y >= page->allocation.y) &&
1584 (x <= (page->allocation.x + page->allocation.width)) &&
1585 (y <= (page->allocation.y + page->allocation.height)))
1587 if (page == notebook->cur_page && notebook->focus_tab &&
1588 notebook->focus_tab != children &&
1589 GTK_WIDGET_HAS_FOCUS (notebook))
1591 GtkNotebookPage *old_page;
1593 notebook->child_has_focus = FALSE;
1594 old_page = (GtkNotebookPage *)
1595 (notebook->focus_tab->data);
1596 gtk_notebook_switch_focus_tab (notebook, children);
1597 gtk_notebook_focus_changed (notebook, old_page);
1601 gtk_notebook_switch_focus_tab (notebook, children);
1602 gtk_widget_grab_focus (widget);
1603 gtk_notebook_switch_page (notebook, page, num);
1607 children = children->next;
1610 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1611 gtk_widget_grab_focus (widget);
1617 gtk_notebook_button_release (GtkWidget *widget,
1618 GdkEventButton *event)
1620 GtkNotebook *notebook;
1622 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1623 g_return_val_if_fail (event != NULL, FALSE);
1625 if (event->type != GDK_BUTTON_RELEASE)
1628 notebook = GTK_NOTEBOOK (widget);
1630 if (event->button == notebook->button)
1634 if (notebook->timer)
1636 gtk_timeout_remove (notebook->timer);
1637 notebook->timer = 0;
1638 notebook->need_timer = FALSE;
1640 click_child = notebook->click_child;
1641 notebook->click_child = 0;
1642 notebook->button = 0;
1643 gtk_notebook_redraw_arrows (notebook);
1652 gtk_notebook_enter_notify (GtkWidget *widget,
1653 GdkEventCrossing *event)
1655 GtkNotebook *notebook;
1659 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1660 g_return_val_if_fail (event != NULL, FALSE);
1662 notebook = GTK_NOTEBOOK (widget);
1664 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1667 arrow = gtk_notebook_get_arrow (notebook, x, y);
1669 if (arrow != notebook->in_child)
1671 notebook->in_child = arrow;
1672 gtk_notebook_redraw_arrows (notebook);
1681 gtk_notebook_leave_notify (GtkWidget *widget,
1682 GdkEventCrossing *event)
1684 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1688 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1691 arrow = gtk_notebook_get_arrow (notebook, x, y);
1693 if (notebook->in_child)
1695 notebook->in_child = 0;
1696 gtk_notebook_redraw_arrows (notebook);
1703 gtk_notebook_motion_notify (GtkWidget *widget,
1704 GdkEventMotion *event)
1706 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1710 if (notebook->button)
1713 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1716 arrow = gtk_notebook_get_arrow (notebook, x, y);
1718 if (arrow != notebook->in_child)
1720 notebook->in_child = arrow;
1721 gtk_notebook_redraw_arrows (notebook);
1728 gtk_notebook_focus_in (GtkWidget *widget,
1729 GdkEventFocus *event)
1731 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1733 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1737 gtk_notebook_draw_focus (GtkWidget *widget)
1739 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1741 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1742 notebook->focus_tab)
1744 GtkNotebookPage *page;
1748 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1750 page = notebook->focus_tab->data;
1752 area.x = page->tab_label->allocation.x - focus_width;
1753 area.y = page->tab_label->allocation.y - focus_width;
1754 area.width = page->tab_label->allocation.width + 2 * focus_width;
1755 area.height = page->tab_label->allocation.height + 2 * focus_width;
1757 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1761 /* Private GtkContainer Methods :
1763 * gtk_notebook_set_child_arg
1764 * gtk_notebook_get_child_arg
1766 * gtk_notebook_remove
1767 * gtk_notebook_focus
1768 * gtk_notebook_set_focus_child
1769 * gtk_notebook_child_type
1770 * gtk_notebook_forall
1773 gtk_notebook_set_child_property (GtkContainer *container,
1776 const GValue *value,
1781 GtkPackType pack_type;
1783 /* not finding child's page is valid for menus or labels */
1784 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1787 switch (property_id)
1789 case CHILD_PROP_TAB_LABEL:
1790 /* a NULL pointer indicates a default_tab setting, otherwise
1791 * we need to set the associated label
1793 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1794 g_value_get_string (value));
1796 case CHILD_PROP_MENU_LABEL:
1797 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1798 g_value_get_string (value));
1800 case CHILD_PROP_POSITION:
1801 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1802 g_value_get_int (value));
1804 case CHILD_PROP_TAB_EXPAND:
1805 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1806 &expand, &fill, &pack_type);
1807 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1808 g_value_get_boolean (value),
1811 case CHILD_PROP_TAB_FILL:
1812 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1813 &expand, &fill, &pack_type);
1814 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1816 g_value_get_boolean (value),
1819 case CHILD_PROP_TAB_PACK:
1820 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1821 &expand, &fill, &pack_type);
1822 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1824 g_value_get_enum (value));
1827 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1833 gtk_notebook_get_child_property (GtkContainer *container,
1840 GtkNotebook *notebook;
1844 GtkPackType pack_type;
1846 notebook = GTK_NOTEBOOK (container);
1848 /* not finding child's page is valid for menus or labels */
1849 list = gtk_notebook_find_child (notebook, child, NULL);
1852 /* nothing to set on labels or menus */
1853 g_param_value_set_default (pspec, value);
1857 switch (property_id)
1859 case CHILD_PROP_TAB_LABEL:
1860 label = gtk_notebook_get_tab_label (notebook, child);
1862 if (label && GTK_IS_LABEL (label))
1863 g_value_set_string (value, GTK_LABEL (label)->label);
1865 g_value_set_string (value, NULL);
1867 case CHILD_PROP_MENU_LABEL:
1868 label = gtk_notebook_get_menu_label (notebook, child);
1870 if (label && GTK_IS_LABEL (label))
1871 g_value_set_string (value, GTK_LABEL (label)->label);
1873 g_value_set_string (value, NULL);
1875 case CHILD_PROP_POSITION:
1876 g_value_set_int (value, g_list_position (notebook->children, list));
1878 case CHILD_PROP_TAB_EXPAND:
1879 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1880 &expand, NULL, NULL);
1881 g_value_set_boolean (value, expand);
1883 case CHILD_PROP_TAB_FILL:
1884 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1886 g_value_set_boolean (value, fill);
1888 case CHILD_PROP_TAB_PACK:
1889 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1890 NULL, NULL, &pack_type);
1891 g_value_set_enum (value, pack_type);
1894 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1900 gtk_notebook_add (GtkContainer *container,
1903 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1905 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1910 gtk_notebook_remove (GtkContainer *container,
1913 GtkNotebook *notebook;
1914 GtkNotebookPage *page;
1918 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1919 g_return_if_fail (widget != NULL);
1921 notebook = GTK_NOTEBOOK (container);
1923 children = notebook->children;
1927 page = children->data;
1928 if (page->child == widget)
1930 gtk_notebook_real_remove (notebook, children);
1934 children = children->next;
1939 focus_tabs_in (GtkNotebook *notebook)
1941 if (notebook->show_tabs && notebook->cur_page)
1943 gtk_widget_grab_focus (GTK_WIDGET (notebook));
1945 gtk_notebook_switch_focus_tab (notebook,
1946 g_list_find (notebook->children,
1947 notebook->cur_page));
1956 focus_tabs_move (GtkNotebook *notebook,
1957 GtkDirectionType direction,
1958 gint search_direction)
1962 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
1963 search_direction, TRUE);
1965 gtk_notebook_switch_focus_tab (notebook, new_page);
1967 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
1973 focus_child_in (GtkNotebook *notebook,
1974 GtkDirectionType direction)
1976 if (notebook->cur_page)
1977 return gtk_widget_child_focus (notebook->cur_page->child, direction);
1982 /* Focus in the notebook can either be on the pages, or on
1986 gtk_notebook_focus (GtkWidget *widget,
1987 GtkDirectionType direction)
1989 GtkWidget *old_focus_child;
1990 GtkNotebook *notebook;
1991 GtkDirectionType effective_direction;
1993 gboolean widget_is_focus;
1994 GtkContainer *container;
1996 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1998 container = GTK_CONTAINER (widget);
1999 notebook = GTK_NOTEBOOK (container);
2001 if (notebook->focus_out)
2003 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2007 widget_is_focus = gtk_widget_is_focus (widget);
2008 old_focus_child = container->focus_child;
2010 effective_direction = get_effective_direction (notebook, direction);
2012 if (old_focus_child) /* Focus on page child */
2014 if (gtk_widget_child_focus (old_focus_child, direction))
2017 switch (effective_direction)
2019 case GTK_DIR_TAB_BACKWARD:
2021 /* Focus onto the tabs */
2022 return focus_tabs_in (notebook);
2024 case GTK_DIR_TAB_FORWARD:
2030 else if (widget_is_focus) /* Focus was on tabs */
2032 switch (effective_direction)
2034 case GTK_DIR_TAB_BACKWARD:
2037 case GTK_DIR_TAB_FORWARD:
2039 /* We use TAB_FORWARD rather than direction so that we focus a more
2040 * predictable widget for the user; users may be using arrow focusing
2041 * in this situation even if they don't usually use arrow focusing.
2043 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2045 return focus_tabs_move (notebook, direction, STEP_PREV);
2047 return focus_tabs_move (notebook, direction, STEP_NEXT);
2050 else /* Focus was not on widget */
2052 switch (effective_direction)
2054 case GTK_DIR_TAB_FORWARD:
2056 if (focus_tabs_in (notebook))
2058 if (focus_child_in (notebook, direction))
2061 case GTK_DIR_TAB_BACKWARD:
2063 if (focus_child_in (notebook, direction))
2065 if (focus_tabs_in (notebook))
2070 return focus_child_in (notebook, direction);
2074 g_assert_not_reached ();
2079 gtk_notebook_set_focus_child (GtkContainer *container,
2082 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2083 GtkWidget *page_child;
2084 GtkWidget *toplevel;
2086 /* If the old focus widget was within a page of the notebook,
2087 * (child may either be NULL or not in this case), record it
2088 * for future use if we switch to the page with a mnemonic.
2091 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2092 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2094 page_child = GTK_WINDOW (toplevel)->focus_widget;
2097 if (page_child->parent == GTK_WIDGET (container))
2099 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2102 GtkNotebookPage *page = list->data;
2104 if (page->last_focus_child)
2105 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2107 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2108 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2114 page_child = page_child->parent;
2120 g_return_if_fail (GTK_IS_WIDGET (child));
2122 notebook->child_has_focus = TRUE;
2123 if (!notebook->focus_tab)
2126 GtkNotebookPage *page;
2128 children = notebook->children;
2131 page = children->data;
2132 if (page->child == child || page->tab_label == child)
2133 gtk_notebook_switch_focus_tab (notebook, children);
2134 children = children->next;
2139 parent_class->set_focus_child (container, child);
2143 gtk_notebook_forall (GtkContainer *container,
2144 gboolean include_internals,
2145 GtkCallback callback,
2146 gpointer callback_data)
2148 GtkNotebook *notebook;
2151 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2152 g_return_if_fail (callback != NULL);
2154 notebook = GTK_NOTEBOOK (container);
2156 children = notebook->children;
2159 GtkNotebookPage *page;
2161 page = children->data;
2162 children = children->next;
2163 (* callback) (page->child, callback_data);
2164 if (include_internals)
2166 if (page->tab_label)
2167 (* callback) (page->tab_label, callback_data);
2168 if (page->menu_label)
2169 (* callback) (page->menu_label, callback_data);
2175 gtk_notebook_child_type (GtkContainer *container)
2177 return GTK_TYPE_WIDGET;
2180 /* Private GtkNotebook Functions:
2182 * gtk_notebook_redraw_tabs
2183 * gtk_notebook_focus_changed
2184 * gtk_notebook_real_remove
2185 * gtk_notebook_update_labels
2186 * gtk_notebook_timer
2187 * gtk_notebook_page_compare
2188 * gtk_notebook_real_page_position
2189 * gtk_notebook_search_page
2192 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2195 GtkNotebookPage *page;
2196 GdkRectangle redraw_rect;
2199 widget = GTK_WIDGET (notebook);
2200 border = GTK_CONTAINER (notebook)->border_width;
2202 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2205 page = notebook->first_tab->data;
2207 redraw_rect.x = border;
2208 redraw_rect.y = border;
2210 switch (notebook->tab_pos)
2212 case GTK_POS_BOTTOM:
2213 redraw_rect.y = (widget->allocation.height - border -
2214 page->allocation.height -
2215 widget->style->ythickness);
2216 if (page != notebook->cur_page)
2217 redraw_rect.y -= widget->style->ythickness;
2220 redraw_rect.width = widget->allocation.width - 2 * border;
2221 redraw_rect.height = (page->allocation.height +
2222 widget->style->ythickness);
2223 if (page != notebook->cur_page)
2224 redraw_rect.height += widget->style->ythickness;
2227 redraw_rect.x = (widget->allocation.width - border -
2228 page->allocation.width -
2229 widget->style->xthickness);
2230 if (page != notebook->cur_page)
2231 redraw_rect.x -= widget->style->xthickness;
2234 redraw_rect.width = (page->allocation.width +
2235 widget->style->xthickness);
2236 redraw_rect.height = widget->allocation.height - 2 * border;
2237 if (page != notebook->cur_page)
2238 redraw_rect.width += widget->style->xthickness;
2242 redraw_rect.x += widget->allocation.x;
2243 redraw_rect.y += widget->allocation.y;
2245 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2249 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2251 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2255 gtk_notebook_get_arrow_rect (notebook, &rect);
2256 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window, &rect, FALSE);
2261 gtk_notebook_focus_changed (GtkNotebook *notebook,
2262 GtkNotebookPage *old_page)
2264 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2266 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
2271 gtk_widget_style_get (GTK_WIDGET (notebook), "focus-line-width", &focus_width, NULL);
2273 if (notebook->focus_tab)
2275 GtkNotebookPage *page;
2277 page = notebook->focus_tab->data;
2279 area.x = page->tab_label->allocation.x - focus_width;
2280 area.y = page->tab_label->allocation.y - focus_width;
2281 area.width = page->tab_label->allocation.width + 2 * focus_width;
2282 area.height = page->tab_label->allocation.height + 2 * focus_width;
2284 gtk_notebook_draw_tab (notebook, page, &area);
2289 area.x = old_page->tab_label->allocation.x - focus_width;
2290 area.y = old_page->tab_label->allocation.y - focus_width;
2291 area.width = old_page->tab_label->allocation.width + 2 * focus_width;
2292 area.height = old_page->tab_label->allocation.height + 2 * focus_width;
2294 gtk_notebook_draw_tab (notebook, old_page, &area);
2300 gtk_notebook_timer (GtkNotebook *notebook)
2302 gboolean retval = FALSE;
2304 GDK_THREADS_ENTER ();
2306 if (notebook->timer)
2308 gtk_notebook_do_arrow (notebook, notebook->click_child);
2310 if (notebook->need_timer)
2312 notebook->need_timer = FALSE;
2313 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
2314 (GtkFunction) gtk_notebook_timer,
2315 (gpointer) notebook);
2321 GDK_THREADS_LEAVE ();
2327 gtk_notebook_page_compare (gconstpointer a,
2330 return (((GtkNotebookPage *) a)->child != b);
2334 gtk_notebook_find_child (GtkNotebook *notebook,
2336 const gchar *function)
2338 GList *list = g_list_find_custom (notebook->children, child,
2339 gtk_notebook_page_compare);
2341 #ifndef G_DISABLE_CHECKS
2342 if (!list && function)
2343 g_warning ("%s: unable to find child %p in notebook %p",
2344 function, child, notebook);
2351 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2352 GtkNotebookPage *page)
2354 if (page->tab_label)
2356 if (page->mnemonic_activate_signal)
2357 gtk_signal_disconnect (page->tab_label,
2358 page->mnemonic_activate_signal);
2359 page->mnemonic_activate_signal = 0;
2361 gtk_widget_unparent (page->tab_label);
2366 gtk_notebook_real_remove (GtkNotebook *notebook,
2369 GtkNotebookPage *page;
2371 gint need_resize = FALSE;
2373 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2375 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2377 if (notebook->cur_page == list->data)
2379 notebook->cur_page = NULL;
2381 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2384 if (list == notebook->first_tab)
2385 notebook->first_tab = next_list;
2386 if (list == notebook->focus_tab)
2387 gtk_notebook_switch_focus_tab (notebook, next_list);
2391 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2394 gtk_widget_unparent (page->child);
2396 gtk_notebook_remove_tab_label (notebook, page);
2400 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2401 page->menu_label->parent);
2402 gtk_widget_queue_resize (notebook->menu);
2404 if (!page->default_menu)
2405 gtk_widget_unref (page->menu_label);
2407 notebook->children = g_list_remove_link (notebook->children, list);
2410 if (page->last_focus_child)
2412 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2413 page->last_focus_child = NULL;
2418 if (!notebook->children && notebook->show_tabs &&
2419 GTK_WIDGET_MAPPED (notebook))
2420 gdk_window_hide (notebook->event_window);
2422 gtk_notebook_update_labels (notebook);
2424 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2428 gtk_notebook_update_labels (GtkNotebook *notebook)
2430 GtkNotebookPage *page;
2435 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2437 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2440 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2441 if (notebook->show_tabs)
2443 if (page->default_tab)
2445 if (!page->tab_label)
2447 page->tab_label = gtk_label_new (string);
2448 gtk_widget_set_parent (page->tab_label,
2449 GTK_WIDGET (notebook));
2452 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2455 if (GTK_WIDGET_VISIBLE (page->child) &&
2456 !GTK_WIDGET_VISIBLE (page->tab_label))
2457 gtk_widget_show (page->tab_label);
2458 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2459 GTK_WIDGET_VISIBLE (page->tab_label))
2460 gtk_widget_hide (page->tab_label);
2462 if (notebook->menu && page->default_menu)
2464 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2465 gtk_label_set_text (GTK_LABEL (page->menu_label),
2466 GTK_LABEL (page->tab_label)->label);
2468 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2474 gtk_notebook_real_page_position (GtkNotebook *notebook,
2480 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2481 g_return_val_if_fail (list != NULL, -1);
2483 for (work = notebook->children, count_start = 0;
2484 work && work != list; work = work->next)
2485 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2491 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2494 return (count_start + g_list_length (list) - 1);
2498 gtk_notebook_search_page (GtkNotebook *notebook,
2501 gboolean find_visible)
2503 GtkNotebookPage *page = NULL;
2504 GList *old_list = NULL;
2507 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2512 flag = GTK_PACK_END;
2516 flag = GTK_PACK_START;
2523 if (!page || page->pack == flag)
2531 list = notebook->children;
2536 if (page->pack == flag &&
2537 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2552 if (page->pack != flag &&
2553 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2561 /* Private GtkNotebook Drawing Functions:
2563 * gtk_notebook_paint
2564 * gtk_notebook_draw_tab
2565 * gtk_notebook_draw_arrow
2568 gtk_notebook_paint (GtkWidget *widget,
2571 GtkNotebook *notebook;
2572 GtkNotebookPage *page;
2577 gint border_width = GTK_CONTAINER (widget)->border_width;
2578 gint gap_x = 0, gap_width = 0;
2580 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2581 g_return_if_fail (area != NULL);
2583 if (!GTK_WIDGET_DRAWABLE (widget))
2586 notebook = GTK_NOTEBOOK (widget);
2588 if ((!notebook->show_tabs && !notebook->show_border) ||
2589 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2592 x = widget->allocation.x + border_width;
2593 y = widget->allocation.y + border_width;
2594 width = widget->allocation.width - border_width * 2;
2595 height = widget->allocation.height - border_width * 2;
2597 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2599 gtk_paint_box (widget->style, widget->window,
2600 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2601 area, widget, "notebook",
2602 x, y, width, height);
2607 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2609 page = notebook->first_tab->data;
2611 switch (notebook->tab_pos)
2614 y += page->allocation.height + widget->style->ythickness;
2615 case GTK_POS_BOTTOM:
2616 height -= page->allocation.height + widget->style->ythickness;
2619 x += page->allocation.width + widget->style->xthickness;
2621 width -= page->allocation.width + widget->style->xthickness;
2624 gtk_paint_box (widget->style, widget->window,
2625 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2626 area, widget, "notebook",
2627 x, y, width, height);
2631 switch (notebook->tab_pos)
2634 y += notebook->cur_page->allocation.height;
2635 case GTK_POS_BOTTOM:
2636 height -= notebook->cur_page->allocation.height;
2639 x += notebook->cur_page->allocation.width;
2641 width -= notebook->cur_page->allocation.width;
2645 switch (notebook->tab_pos)
2648 case GTK_POS_BOTTOM:
2649 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2650 gap_width = notebook->cur_page->allocation.width;
2654 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2655 gap_width = notebook->cur_page->allocation.height;
2658 gtk_paint_box_gap(widget->style, widget->window,
2659 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2660 area, widget, "notebook",
2661 x, y, width, height,
2662 notebook->tab_pos, gap_x, gap_width);
2666 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2669 page = children->data;
2670 children = gtk_notebook_search_page (notebook, children,
2672 if (!GTK_WIDGET_VISIBLE (page->child))
2674 if (!GTK_WIDGET_MAPPED (page->tab_label))
2676 else if (page != notebook->cur_page)
2677 gtk_notebook_draw_tab (notebook, page, area);
2680 if (showarrow && notebook->scrollable)
2682 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2683 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2685 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2689 gtk_notebook_draw_tab (GtkNotebook *notebook,
2690 GtkNotebookPage *page,
2693 GdkRectangle child_area;
2694 GdkRectangle page_area;
2695 GtkStateType state_type;
2696 GtkPositionType gap_side;
2698 g_return_if_fail (notebook != NULL);
2699 g_return_if_fail (page != NULL);
2700 g_return_if_fail (area != NULL);
2702 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2703 (page->allocation.width == 0) || (page->allocation.height == 0))
2706 page_area.x = page->allocation.x;
2707 page_area.y = page->allocation.y;
2708 page_area.width = page->allocation.width;
2709 page_area.height = page->allocation.height;
2711 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2715 widget = GTK_WIDGET (notebook);
2717 switch (notebook->tab_pos)
2720 gap_side = GTK_POS_BOTTOM;
2722 case GTK_POS_BOTTOM:
2723 gap_side = GTK_POS_TOP;
2726 gap_side = GTK_POS_RIGHT;
2729 gap_side = GTK_POS_LEFT;
2733 if (notebook->cur_page == page)
2734 state_type = GTK_STATE_NORMAL;
2736 state_type = GTK_STATE_ACTIVE;
2737 gtk_paint_extension(widget->style, widget->window,
2738 state_type, GTK_SHADOW_OUT,
2739 area, widget, "tab",
2740 page_area.x, page_area.y,
2741 page_area.width, page_area.height,
2743 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2744 notebook->focus_tab && (notebook->focus_tab->data == page))
2748 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2750 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2751 area, widget, "tab",
2752 page->tab_label->allocation.x - focus_width,
2753 page->tab_label->allocation.y - focus_width,
2754 page->tab_label->allocation.width + 2 * focus_width,
2755 page->tab_label->allocation.height + 2 * focus_width);
2757 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2758 GTK_WIDGET_DRAWABLE (page->tab_label))
2760 GdkEventExpose expose_event;
2762 /* This is a lame hack since all this code needs rewriting anyhow */
2764 expose_event.window = page->tab_label->window;
2765 expose_event.area = child_area;
2766 expose_event.region = gdk_region_rectangle (&child_area);
2767 expose_event.send_event = TRUE;
2768 expose_event.type = GDK_EXPOSE;
2769 expose_event.count = 0;
2771 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, &expose_event);
2773 gdk_region_destroy (expose_event.region);
2779 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2782 GtkStateType state_type;
2783 GtkShadowType shadow_type;
2785 GdkRectangle arrow_rect;
2787 gtk_notebook_get_arrow_rect (notebook, &arrow_rect);
2789 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2791 widget = GTK_WIDGET(notebook);
2793 if (GTK_WIDGET_DRAWABLE (notebook))
2795 if (notebook->in_child == arrow)
2797 if (notebook->click_child == arrow)
2798 state_type = GTK_STATE_ACTIVE;
2800 state_type = GTK_STATE_PRELIGHT;
2803 state_type = GTK_STATE_NORMAL;
2805 if (notebook->click_child == arrow)
2806 shadow_type = GTK_SHADOW_IN;
2808 shadow_type = GTK_SHADOW_OUT;
2810 if (arrow == GTK_ARROW_LEFT)
2812 if (notebook->focus_tab &&
2813 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2816 shadow_type = GTK_SHADOW_ETCHED_IN;
2817 state_type = GTK_STATE_INSENSITIVE;
2820 if (notebook->tab_pos == GTK_POS_LEFT ||
2821 notebook->tab_pos == GTK_POS_RIGHT)
2822 arrow = GTK_ARROW_UP;
2824 gtk_paint_arrow (widget->style, widget->window, state_type,
2825 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2827 arrow_rect.x, arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2831 if (notebook->focus_tab &&
2832 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2835 shadow_type = GTK_SHADOW_ETCHED_IN;
2836 state_type = GTK_STATE_INSENSITIVE;
2839 if (notebook->tab_pos == GTK_POS_LEFT ||
2840 notebook->tab_pos == GTK_POS_RIGHT)
2841 arrow = GTK_ARROW_DOWN;
2843 gtk_paint_arrow (widget->style, widget->window, state_type,
2844 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2845 arrow, TRUE, arrow_rect.x + ARROW_SIZE + ARROW_SPACING,
2846 arrow_rect.y, ARROW_SIZE, ARROW_SIZE);
2851 /* Private GtkNotebook Size Allocate Functions:
2853 * gtk_notebook_pages_allocate
2854 * gtk_notebook_page_allocate
2855 * gtk_notebook_calc_tabs
2858 gtk_notebook_pages_allocate (GtkNotebook *notebook)
2860 GtkWidget *widget = GTK_WIDGET (notebook);
2861 GtkContainer *container = GTK_CONTAINER (notebook);
2862 GtkNotebookPage *page = NULL;
2863 GtkAllocation *allocation = &widget->allocation;
2864 GtkAllocation child_allocation;
2865 GList *children = NULL;
2866 GList *last_child = NULL;
2867 gboolean showarrow = FALSE;
2877 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2880 child_allocation.x = widget->allocation.x + container->border_width;
2881 child_allocation.y = widget->allocation.y + container->border_width;
2883 switch (notebook->tab_pos)
2885 case GTK_POS_BOTTOM:
2886 child_allocation.y = (widget->allocation.y +
2887 allocation->height -
2888 notebook->cur_page->requisition.height -
2889 container->border_width);
2892 child_allocation.height = notebook->cur_page->requisition.height;
2896 child_allocation.x = (widget->allocation.x +
2898 notebook->cur_page->requisition.width -
2899 container->border_width);
2902 child_allocation.width = notebook->cur_page->requisition.width;
2906 if (notebook->scrollable)
2910 children = notebook->children;
2912 if (notebook->focus_tab)
2913 focus_tab = notebook->focus_tab;
2914 else if (notebook->first_tab)
2915 focus_tab = notebook->first_tab;
2917 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2919 switch (notebook->tab_pos)
2922 case GTK_POS_BOTTOM:
2925 page = children->data;
2926 children = children->next;
2928 if (GTK_WIDGET_VISIBLE (page->child))
2929 tab_space += page->requisition.width;
2932 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2935 page = focus_tab->data;
2937 tab_space = (allocation->width - TAB_OVERLAP -
2938 page->requisition.width -
2939 2 * (container->border_width + ARROW_SPACING +
2941 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2942 container->border_width);
2944 page = notebook->children->data;
2945 if (notebook->tab_pos == GTK_POS_TOP)
2946 y = (container->border_width +
2947 (page->requisition.height - ARROW_SIZE) / 2);
2949 y = (allocation->height - container->border_width -
2950 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2957 page = children->data;
2958 children = children->next;
2960 if (GTK_WIDGET_VISIBLE (page->child))
2961 tab_space += page->requisition.height;
2964 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2967 page = focus_tab->data;
2968 tab_space = (allocation->height -
2969 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2970 2 * container->border_width -
2971 page->requisition.height);
2972 y = allocation->height - container->border_width - ARROW_SIZE;
2974 page = notebook->children->data;
2975 if (notebook->tab_pos == GTK_POS_LEFT)
2976 x = (container->border_width +
2977 (page->requisition.width -
2978 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2980 x = (allocation->width - container->border_width -
2981 (2 * ARROW_SIZE - ARROW_SPACING) -
2982 (page->requisition.width -
2983 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2987 if (showarrow) /* first_tab <- focus_tab */
2991 notebook->first_tab = focus_tab;
2992 last_child = gtk_notebook_search_page (notebook, focus_tab,
2998 if (notebook->first_tab && notebook->first_tab != focus_tab)
3000 /* Is first_tab really predecessor of focus_tab ? */
3001 page = notebook->first_tab->data;
3002 if (GTK_WIDGET_VISIBLE (page->child))
3003 for (children = focus_tab;
3004 children && children != notebook->first_tab;
3005 children = gtk_notebook_search_page (notebook,
3011 notebook->first_tab = focus_tab;
3013 gtk_notebook_calc_tabs (notebook,
3014 gtk_notebook_search_page (notebook,
3018 &(notebook->first_tab), &tab_space,
3023 notebook->first_tab =
3024 gtk_notebook_search_page (notebook, notebook->first_tab,
3026 if (!notebook->first_tab)
3027 notebook->first_tab = focus_tab;
3028 last_child = gtk_notebook_search_page (notebook, focus_tab,
3031 else /* focus_tab -> end */
3033 if (!notebook->first_tab)
3034 notebook->first_tab = gtk_notebook_search_page (notebook,
3039 gtk_notebook_calc_tabs (notebook,
3040 gtk_notebook_search_page (notebook,
3044 &children, &tab_space, STEP_NEXT);
3047 last_child = children;
3048 else /* start <- first_tab */
3052 gtk_notebook_calc_tabs
3054 gtk_notebook_search_page (notebook,
3055 notebook->first_tab,
3058 &children, &tab_space, STEP_PREV);
3059 notebook->first_tab = gtk_notebook_search_page(notebook,
3069 tab_space = -tab_space;
3071 for (children = notebook->first_tab;
3072 children && children != last_child;
3073 children = gtk_notebook_search_page (notebook, children,
3080 /*unmap all non-visible tabs*/
3081 for (children = gtk_notebook_search_page (notebook, NULL,
3083 children && children != notebook->first_tab;
3084 children = gtk_notebook_search_page (notebook, children,
3087 page = children->data;
3088 if (page->tab_label)
3089 gtk_widget_set_child_visible (page->tab_label, FALSE);
3091 for (children = last_child; children;
3092 children = gtk_notebook_search_page (notebook, children,
3095 page = children->data;
3096 if (page->tab_label)
3097 gtk_widget_set_child_visible (page->tab_label, FALSE);
3100 else /* !showarrow */
3102 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3113 children = notebook->children;
3114 switch (notebook->tab_pos)
3117 case GTK_POS_BOTTOM:
3120 page = children->data;
3121 children = children->next;
3123 if (GTK_WIDGET_VISIBLE (page->child))
3126 tab_space += page->requisition.width;
3131 tab_space -= allocation->width;
3137 page = children->data;
3138 children = children->next;
3140 if (GTK_WIDGET_VISIBLE (page->child))
3143 tab_space += page->requisition.height;
3148 tab_space -= allocation->height;
3150 tab_space += 2 * container->border_width + TAB_OVERLAP;
3152 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3154 if (notebook->homogeneous && n)
3158 children = notebook->first_tab;
3162 if (children == last_child)
3164 /* FIXME double check */
3168 page = children->data;
3169 if (!showarrow && page->pack != GTK_PACK_START)
3171 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3174 if (n && (showarrow || page->expand || notebook->homogeneous))
3176 new_fill = (tab_space * i++) / n;
3177 delta = new_fill - old_fill;
3178 old_fill = new_fill;
3181 switch (notebook->tab_pos)
3184 case GTK_POS_BOTTOM:
3185 child_allocation.width = (page->requisition.width +
3186 TAB_OVERLAP + delta);
3190 child_allocation.height = (page->requisition.height +
3191 TAB_OVERLAP + delta);
3195 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3197 switch (notebook->tab_pos)
3200 case GTK_POS_BOTTOM:
3201 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3205 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3209 if (page->tab_label)
3210 gtk_widget_set_child_visible (page->tab_label, TRUE);
3215 children = notebook->children;
3216 switch (notebook->tab_pos)
3219 case GTK_POS_BOTTOM:
3220 child_allocation.x = (allocation->x + allocation->width -
3221 container->border_width);
3225 child_allocation.y = (allocation->y + allocation->height -
3226 container->border_width);
3230 while (children != last_child)
3232 page = children->data;
3233 children = children->next;
3235 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3239 if (n && (page->expand || notebook->homogeneous))
3241 new_fill = (tab_space * i++) / n;
3242 delta = new_fill - old_fill;
3243 old_fill = new_fill;
3246 switch (notebook->tab_pos)
3249 case GTK_POS_BOTTOM:
3250 child_allocation.width = (page->requisition.width +
3251 TAB_OVERLAP + delta);
3252 child_allocation.x -= child_allocation.width;
3256 child_allocation.height = (page->requisition.height +
3257 TAB_OVERLAP + delta);
3258 child_allocation.y -= child_allocation.height;
3262 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3264 switch (notebook->tab_pos)
3267 case GTK_POS_BOTTOM:
3268 child_allocation.x += TAB_OVERLAP;
3272 child_allocation.y += TAB_OVERLAP;
3276 if (page->tab_label)
3277 gtk_widget_set_child_visible (page->tab_label, TRUE);
3282 gtk_notebook_redraw_tabs (notebook);
3286 gtk_notebook_page_allocate (GtkNotebook *notebook,
3287 GtkNotebookPage *page,
3288 GtkAllocation *allocation)
3290 GtkWidget *widget = GTK_WIDGET (notebook);
3291 GtkAllocation child_allocation;
3292 GtkRequisition tab_requisition;
3298 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3300 xthickness = widget->style->xthickness;
3301 ythickness = widget->style->ythickness;
3303 /* If the size of the notebook tabs change, we need to queue
3304 * a redraw on the tab area
3306 if ((allocation->width != page->allocation.width) ||
3307 (allocation->height != page->allocation.height))
3309 gint x, y, width, height, border_width;
3311 border_width = GTK_CONTAINER (notebook)->border_width;
3313 switch (notebook->tab_pos)
3316 width = widget->allocation.width;
3317 height = MAX (page->allocation.height, allocation->height) + ythickness;
3322 case GTK_POS_BOTTOM:
3323 width = widget->allocation.width + xthickness;
3324 height = MAX (page->allocation.height, allocation->height) + ythickness;
3326 y = widget->allocation.height - height - border_width;
3330 width = MAX (page->allocation.width, allocation->width) + xthickness;
3331 height = widget->allocation.height;
3337 default: /* quiet gcc */
3338 width = MAX (page->allocation.width, allocation->width) + xthickness;
3339 height = widget->allocation.height;
3340 x = widget->allocation.width - width - border_width;
3345 gtk_widget_queue_clear_area (widget, x, y, width, height);
3348 page->allocation = *allocation;
3349 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3351 if (notebook->cur_page != page)
3353 switch (notebook->tab_pos)
3356 page->allocation.y += ythickness;
3357 case GTK_POS_BOTTOM:
3358 if (page->allocation.height > ythickness)
3359 page->allocation.height -= ythickness;
3362 page->allocation.x += xthickness;
3364 if (page->allocation.width > xthickness)
3365 page->allocation.width -= xthickness;
3370 switch (notebook->tab_pos)
3373 case GTK_POS_BOTTOM:
3374 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3377 child_allocation.x = (xthickness + focus_width +
3378 notebook->tab_hborder);
3379 child_allocation.width = MAX (1, (page->allocation.width -
3380 2 * child_allocation.x));
3381 child_allocation.x += page->allocation.x;
3385 child_allocation.x = (page->allocation.x +
3386 (page->allocation.width -
3387 tab_requisition.width) / 2);
3388 child_allocation.width = tab_requisition.width;
3390 child_allocation.y = (notebook->tab_vborder + focus_width +
3391 page->allocation.y);
3392 if (notebook->tab_pos == GTK_POS_TOP)
3393 child_allocation.y += ythickness;
3394 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3395 2 * (notebook->tab_vborder + focus_width)));
3399 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3402 child_allocation.y = ythickness + padding;
3403 child_allocation.height = MAX (1, (page->allocation.height -
3404 2 * child_allocation.y));
3405 child_allocation.y += page->allocation.y;
3409 child_allocation.y = (page->allocation.y + (page->allocation.height -
3410 tab_requisition.height) / 2);
3411 child_allocation.height = tab_requisition.height;
3413 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3414 if (notebook->tab_pos == GTK_POS_LEFT)
3415 child_allocation.x += xthickness;
3416 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3417 2 * (notebook->tab_hborder + focus_width)));
3421 if (page->tab_label)
3422 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3426 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3432 GtkNotebookPage *page = NULL;
3434 GList *last_list = NULL;
3441 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3442 if (pack == GTK_PACK_END)
3443 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3447 switch (notebook->tab_pos)
3450 case GTK_POS_BOTTOM:
3453 page = children->data;
3454 if (GTK_WIDGET_VISIBLE (page->child))
3456 if (page->pack == pack)
3458 *tab_space -= page->requisition.width;
3459 if (*tab_space < 0 || children == *end)
3463 *tab_space = - (*tab_space +
3464 page->requisition.width);
3470 last_list = children;
3472 if (direction == STEP_NEXT)
3473 children = children->next;
3475 children = children->prev;
3482 page = children->data;
3483 if (GTK_WIDGET_VISIBLE (page->child))
3485 if (page->pack == pack)
3487 *tab_space -= page->requisition.height;
3488 if (*tab_space < 0 || children == *end)
3492 *tab_space = - (*tab_space +
3493 page->requisition.height);
3499 last_list = children;
3501 if (direction == STEP_NEXT)
3502 children = children->next;
3504 children = children->prev;
3508 if (direction == STEP_PREV)
3510 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3511 direction = STEP_PREV;
3512 children = last_list;
3516 /* Private GtkNotebook Page Switch Methods:
3518 * gtk_notebook_real_switch_page
3521 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3522 GtkNotebookPage *page,
3525 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3526 g_return_if_fail (page != NULL);
3528 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3531 if (notebook->cur_page)
3532 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3534 notebook->cur_page = page;
3536 if (!notebook->focus_tab ||
3537 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3538 notebook->focus_tab =
3539 g_list_find (notebook->children, notebook->cur_page);
3541 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3543 /* If the focus was on the previous page, move it to the first
3544 * element on the new page, if possible, or if not, to the
3547 if (notebook->child_has_focus)
3549 if (notebook->cur_page->last_focus_child &&
3550 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3551 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3553 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3554 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3557 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3558 g_object_notify (G_OBJECT (notebook), "page");
3561 /* Private GtkNotebook Page Switch Functions:
3563 * gtk_notebook_switch_page
3564 * gtk_notebook_page_select
3565 * gtk_notebook_switch_focus_tab
3566 * gtk_notebook_menu_switch_page
3569 gtk_notebook_switch_page (GtkNotebook *notebook,
3570 GtkNotebookPage *page,
3573 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3574 g_return_if_fail (page != NULL);
3576 if (notebook->cur_page == page)
3580 page_num = g_list_index (notebook->children, page);
3582 gtk_signal_emit (GTK_OBJECT (notebook),
3583 notebook_signals[SWITCH_PAGE],
3589 gtk_notebook_page_select (GtkNotebook *notebook,
3590 gboolean move_focus)
3592 GtkNotebookPage *page;
3593 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3595 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3597 if (!notebook->focus_tab)
3600 page = notebook->focus_tab->data;
3601 gtk_notebook_switch_page (notebook, page, -1);
3605 switch (notebook->tab_pos)
3610 case GTK_POS_BOTTOM:
3614 dir = GTK_DIR_RIGHT;
3621 if (gtk_widget_child_focus (page->child, dir))
3628 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3632 GtkNotebookPage *old_page = NULL;
3633 GtkNotebookPage *page;
3635 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3637 if (notebook->focus_tab == new_child)
3640 old_child = notebook->focus_tab;
3641 notebook->focus_tab = new_child;
3643 if (notebook->scrollable)
3644 gtk_notebook_redraw_arrows (notebook);
3646 if (!notebook->show_tabs || !notebook->focus_tab)
3650 old_page = old_child->data;
3652 page = notebook->focus_tab->data;
3653 if (GTK_WIDGET_MAPPED (page->tab_label))
3654 gtk_notebook_focus_changed (notebook, old_page);
3656 gtk_notebook_pages_allocate (notebook);
3660 gtk_notebook_menu_switch_page (GtkWidget *widget,
3661 GtkNotebookPage *page)
3663 GtkNotebook *notebook;
3667 g_return_if_fail (widget != NULL);
3668 g_return_if_fail (page != NULL);
3670 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3671 (GTK_MENU (widget->parent)));
3673 if (notebook->cur_page == page)
3677 children = notebook->children;
3678 while (children && children->data != page)
3680 children = children->next;
3684 gtk_signal_emit (GTK_OBJECT (notebook),
3685 notebook_signals[SWITCH_PAGE],
3690 /* Private GtkNotebook Menu Functions:
3692 * gtk_notebook_menu_item_create
3693 * gtk_notebook_menu_label_unparent
3694 * gtk_notebook_menu_detacher
3697 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3700 GtkNotebookPage *page;
3701 GtkWidget *menu_item;
3704 if (page->default_menu)
3706 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3707 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3709 page->menu_label = gtk_label_new ("");
3710 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3713 gtk_widget_show (page->menu_label);
3714 menu_item = gtk_menu_item_new ();
3715 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3716 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3717 gtk_notebook_real_page_position (notebook, list));
3718 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3719 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3720 if (GTK_WIDGET_VISIBLE (page->child))
3721 gtk_widget_show (menu_item);
3725 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3728 gtk_widget_unparent (GTK_BIN(widget)->child);
3729 GTK_BIN(widget)->child = NULL;
3733 gtk_notebook_menu_detacher (GtkWidget *widget,
3736 GtkNotebook *notebook;
3738 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3740 notebook = GTK_NOTEBOOK (widget);
3741 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3743 notebook->menu = NULL;
3746 /* Public GtkNotebook Page Insert/Remove Methods :
3748 * gtk_notebook_append_page
3749 * gtk_notebook_append_page_menu
3750 * gtk_notebook_prepend_page
3751 * gtk_notebook_prepend_page_menu
3752 * gtk_notebook_insert_page
3753 * gtk_notebook_insert_page_menu
3754 * gtk_notebook_remove_page
3757 * gtk_notebook_append_page:
3758 * @notebook: a #GtkNotebook
3759 * @child: the #GtkWidget to use as the contents of the page.
3760 * @tab_label: the #GtkWidget to be used as the label for the page,
3761 * or %NULL to use the default label, 'page N'.
3763 * Appends a page to @notebook.
3766 gtk_notebook_append_page (GtkNotebook *notebook,
3768 GtkWidget *tab_label)
3770 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3771 g_return_if_fail (GTK_IS_WIDGET (child));
3772 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3774 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3778 * gtk_notebook_append_page_menu:
3779 * @notebook: a #GtkNotebook
3780 * @child: the #GtkWidget to use as the contents of the page.
3781 * @tab_label: the #GtkWidget to be used as the label for the page,
3782 * or %NULL to use the default label, 'page N'.
3783 * @menu_label: the widget to use as a label for the page-switch
3784 * menu, if that is enabled. If %NULL, and @tab_label
3785 * is a #GtkLabel or %NULL, then the menu label will be
3786 * a newly created label with the same text as @tab_label;
3787 * If @tab_label is not a #GtkLabel, @menu_label must be
3788 * specified if the page-switch menu is to be used.
3790 * Appends a page to @notebook, specifying the widget to use as the
3791 * label in the popup menu.
3794 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3796 GtkWidget *tab_label,
3797 GtkWidget *menu_label)
3799 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3800 g_return_if_fail (GTK_IS_WIDGET (child));
3801 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3802 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3804 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3808 * gtk_notebook_prepend_page:
3809 * @notebook: a #GtkNotebook
3810 * @child: the #GtkWidget to use as the contents of the page.
3811 * @tab_label: the #GtkWidget to be used as the label for the page,
3812 * or %NULL to use the default label, 'page N'.
3814 * Prepends a page to @notebook.
3817 gtk_notebook_prepend_page (GtkNotebook *notebook,
3819 GtkWidget *tab_label)
3821 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3822 g_return_if_fail (GTK_IS_WIDGET (child));
3823 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3825 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3829 * gtk_notebook_prepend_page_menu:
3830 * @notebook: a #GtkNotebook
3831 * @child: the #GtkWidget to use as the contents of the page.
3832 * @tab_label: the #GtkWidget to be used as the label for the page,
3833 * or %NULL to use the default label, 'page N'.
3834 * @menu_label: the widget to use as a label for the page-switch
3835 * menu, if that is enabled. If %NULL, and @tab_label
3836 * is a #GtkLabel or %NULL, then the menu label will be
3837 * a newly created label with the same text as @tab_label;
3838 * If @tab_label is not a #GtkLabel, @menu_label must be
3839 * specified if the page-switch menu is to be used.
3841 * Prepends a page to @notebook, specifying the widget to use as the
3842 * label in the popup menu.
3845 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3847 GtkWidget *tab_label,
3848 GtkWidget *menu_label)
3850 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3851 g_return_if_fail (GTK_IS_WIDGET (child));
3852 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3853 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3855 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3859 * gtk_notebook_insert_page:
3860 * @notebook: a #GtkNotebook
3861 * @child: the #GtkWidget to use as the contents of the page.
3862 * @tab_label: the #GtkWidget to be used as the label for the page,
3863 * or %NULL to use the default label, 'page N'.
3864 * @position: the index (starting at 0) at which to insert the page,
3865 * or -1 to append the page after all other pages.
3867 * Insert a page into @notebook at the given position
3870 gtk_notebook_insert_page (GtkNotebook *notebook,
3872 GtkWidget *tab_label,
3875 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3876 g_return_if_fail (GTK_IS_WIDGET (child));
3877 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3879 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3884 gtk_notebook_page_compare_tab (gconstpointer a,
3887 return (((GtkNotebookPage *) a)->tab_label != b);
3891 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
3895 GtkNotebook *notebook = GTK_NOTEBOOK (data);
3898 list = g_list_find_custom (notebook->children, child,
3899 gtk_notebook_page_compare_tab);
3902 GtkNotebookPage *page = list->data;
3904 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
3905 gtk_notebook_switch_page (notebook, page, -1);
3906 focus_tabs_in (notebook);
3913 * gtk_notebook_insert_page_menu:
3914 * @notebook: a #GtkNotebook
3915 * @child: the #GtkWidget to use as the contents of the page.
3916 * @tab_label: the #GtkWidget to be used as the label for the page,
3917 * or %NULL to use the default label, 'page N'.
3918 * @menu_label: the widget to use as a label for the page-switch
3919 * menu, if that is enabled. If %NULL, and @tab_label
3920 * is a #GtkLabel or %NULL, then the menu label will be
3921 * a newly created label with the same text as @tab_label;
3922 * If @tab_label is not a #GtkLabel, @menu_label must be
3923 * specified if the page-switch menu is to be used.
3924 * @position: the index (starting at 0) at which to insert the page,
3925 * or -1 to append the page after all other pages.
3927 * Insert a page into @notebook at the given position, specifying
3928 * the widget to use as the label in the popup menu.
3931 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3933 GtkWidget *tab_label,
3934 GtkWidget *menu_label,
3937 GtkNotebookPage *page;
3940 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3941 g_return_if_fail (GTK_IS_WIDGET (child));
3942 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
3943 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
3945 gtk_widget_freeze_child_notify (child);
3947 page = g_new (GtkNotebookPage, 1);
3948 page->child = child;
3949 page->last_focus_child = NULL;
3950 page->requisition.width = 0;
3951 page->requisition.height = 0;
3952 page->allocation.x = 0;
3953 page->allocation.y = 0;
3954 page->allocation.width = 0;
3955 page->allocation.height = 0;
3956 page->default_menu = FALSE;
3957 page->default_tab = FALSE;
3958 page->mnemonic_activate_signal = 0;
3960 nchildren = g_list_length (notebook->children);
3961 if ((position < 0) || (position > nchildren))
3962 position = nchildren;
3964 notebook->children = g_list_insert (notebook->children, page, position);
3968 page->default_tab = TRUE;
3969 if (notebook->show_tabs)
3970 tab_label = gtk_label_new ("");
3972 page->tab_label = tab_label;
3973 page->menu_label = menu_label;
3974 page->expand = FALSE;
3976 page->pack = GTK_PACK_START;
3979 page->default_menu = TRUE;
3982 gtk_widget_ref (page->menu_label);
3983 gtk_object_sink (GTK_OBJECT (page->menu_label));
3987 gtk_notebook_menu_item_create (notebook,
3988 g_list_find (notebook->children, page));
3990 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3992 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3994 gtk_notebook_update_labels (notebook);
3996 if (!notebook->first_tab)
3997 notebook->first_tab = notebook->children;
3999 if (!notebook->cur_page)
4000 gtk_widget_set_child_visible (child, TRUE);
4002 gtk_widget_set_child_visible (child, FALSE);
4006 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4007 gtk_widget_show (tab_label);
4009 gtk_widget_hide (tab_label);
4012 if (!notebook->cur_page)
4014 gtk_notebook_switch_page (notebook, page, 0);
4015 gtk_notebook_switch_focus_tab (notebook, NULL);
4019 page->mnemonic_activate_signal =
4020 gtk_signal_connect (GTK_OBJECT (tab_label),
4021 "mnemonic_activate",
4022 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
4025 if (notebook->show_tabs && GTK_WIDGET_MAPPED (notebook))
4026 gdk_window_show_unraised (notebook->event_window);
4028 gtk_widget_child_notify (child, "tab_expand");
4029 gtk_widget_child_notify (child, "tab_fill");
4030 gtk_widget_child_notify (child, "tab_pack");
4031 gtk_widget_child_notify (child, "tab_label");
4032 gtk_widget_child_notify (child, "menu_label");
4033 gtk_widget_child_notify (child, "position");
4034 gtk_widget_thaw_child_notify (child);
4038 * gtk_notebook_remove_page:
4039 * @notebook: a #GtkNotebook.
4040 * @page_num: the index of a notebook page, starting
4041 * from 0. If -1, the last page will
4044 * Removes a page from the notebook given its index
4048 gtk_notebook_remove_page (GtkNotebook *notebook,
4053 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4057 list = g_list_nth (notebook->children, page_num);
4059 gtk_notebook_real_remove (notebook, list);
4063 list = g_list_last (notebook->children);
4065 gtk_notebook_real_remove (notebook, list);
4069 /* Public GtkNotebook Page Switch Methods :
4070 * gtk_notebook_get_current_page
4071 * gtk_notebook_page_num
4072 * gtk_notebook_set_current_page
4073 * gtk_notebook_next_page
4074 * gtk_notebook_prev_page
4077 * gtk_notebook_get_current_page:
4078 * @notebook: a #GtkNotebook
4080 * Returns the page number of the current page.
4082 * Return value: the index (starting from 0) of the current
4083 * page in the notebook. If the notebook has no pages, then
4084 * -1 will be returned.
4087 gtk_notebook_get_current_page (GtkNotebook *notebook)
4089 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4091 if (!notebook->cur_page)
4094 return g_list_index (notebook->children, notebook->cur_page);
4098 * gtk_notebook_get_nth_page:
4099 * @notebook: a #GtkNotebook
4100 * @page_num: the index of a page in the noteobok
4102 * Returns the child widget contained in page number @page_num.
4104 * Return value: the child widget, or %NULL if @page_num is
4108 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4111 GtkNotebookPage *page;
4113 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4115 page = g_list_nth_data (notebook->children, page_num);
4124 * gtk_notebook_page_num:
4125 * @notebook: a #GtkNotebook
4126 * @child: a #GtkWidget
4128 * Finds the index of the page which contains the given child
4131 * Return value: the index of the page containing @child, or
4132 * -1 if @child is not in the notebook.
4135 gtk_notebook_page_num (GtkNotebook *notebook,
4141 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4144 children = notebook->children;
4147 GtkNotebookPage *page = children->data;
4149 if (page->child == child)
4152 children = children->next;
4160 * gtk_notebook_set_current_page:
4161 * @notebook: a #GtkNotebook
4162 * @page_num: index of the page to switch to, starting from 0.
4163 * If negative, the last page will be used. If greater
4164 * than the number of pages in the notebook, nothing
4167 * Switches to the page number @page_num.
4170 gtk_notebook_set_current_page (GtkNotebook *notebook,
4175 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4178 list = g_list_nth (notebook->children, page_num);
4180 list = g_list_last (notebook->children);
4182 page_num = g_list_index (notebook->children, list);
4185 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4189 * gtk_notebook_next_page:
4190 * @notebook: a #GtkNotebook
4192 * Switches to the next page. Nothing happens if the current page is
4196 gtk_notebook_next_page (GtkNotebook *notebook)
4200 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4202 list = g_list_find (notebook->children, notebook->cur_page);
4206 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4210 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4214 * gtk_notebook_prev_page:
4215 * @notebook: a #GtkNotebook
4217 * Switches to the previous page. Nothing happens if the current page
4218 * is the first page.
4221 gtk_notebook_prev_page (GtkNotebook *notebook)
4225 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4227 list = g_list_find (notebook->children, notebook->cur_page);
4231 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4235 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4238 /* Public GtkNotebook/Tab Style Functions
4240 * gtk_notebook_set_show_border
4241 * gtk_notebook_set_show_tabs
4242 * gtk_notebook_set_tab_pos
4243 * gtk_notebook_set_homogeneous_tabs
4244 * gtk_notebook_set_tab_border
4245 * gtk_notebook_set_tab_hborder
4246 * gtk_notebook_set_tab_vborder
4247 * gtk_notebook_set_scrollable
4250 * gtk_notebook_set_show_border:
4251 * @notebook: a #GtkNotebook
4252 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4254 * Sets whether a bevel will be drawn around the notebook pages.
4255 * This is only has an effect when the tabs are not shown.
4256 * See gtk_notebook_set_show_tabs().
4259 gtk_notebook_set_show_border (GtkNotebook *notebook,
4260 gboolean show_border)
4262 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4264 if (notebook->show_border != show_border)
4266 notebook->show_border = show_border;
4268 if (GTK_WIDGET_VISIBLE (notebook))
4269 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4271 g_object_notify (G_OBJECT (notebook), "show_border");
4276 * gtk_notebook_get_show_border:
4277 * @notebook: a #GtkNotebook
4279 * Returns whether a bevel will be drawn around the notebook pages. See
4280 * gtk_notebook_set_show_border().
4282 * Return value: %TRUE if the bevel is drawn
4285 gtk_notebook_get_show_border (GtkNotebook *notebook)
4287 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4289 return notebook->show_border;
4293 * gtk_notebook_set_show_tabs:
4294 * @notebook: a #GtkNotebook
4295 * @show_tabs: %TRUE if the tabs should be shown.
4297 * Sets whether to show the tabs for the notebook or not.
4300 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4303 GtkNotebookPage *page;
4306 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4308 show_tabs = show_tabs != FALSE;
4310 if (notebook->show_tabs == show_tabs)
4313 notebook->show_tabs = show_tabs;
4314 children = notebook->children;
4318 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4322 page = children->data;
4323 children = children->next;
4324 if (page->default_tab)
4326 gtk_widget_destroy (page->tab_label);
4327 page->tab_label = NULL;
4330 gtk_widget_hide (page->tab_label);
4335 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4336 gtk_notebook_update_labels (notebook);
4338 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4340 g_object_notify (G_OBJECT (notebook), "show_tabs");
4344 * gtk_notebook_get_show_tabs:
4345 * @notebook: a #GtkNotebook
4347 * Returns whether the tabs of the notebook are shown. See
4348 * gtk_notebook_set_show_tabs().
4350 * Return value: %TRUE if the tabs are shown
4353 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4355 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4357 return notebook->show_tabs;
4361 * gtk_notebook_set_tab_pos:
4362 * @notebook: a #GtkNotebook.
4363 * @pos: the edge to draw the tabs at.
4365 * Sets the edge at which the tabs for switching pages in the
4366 * notebook are drawn.
4369 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4370 GtkPositionType pos)
4372 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4374 if (notebook->tab_pos != pos)
4376 notebook->tab_pos = pos;
4377 if (GTK_WIDGET_VISIBLE (notebook))
4378 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4381 g_object_notify (G_OBJECT (notebook), "tab_pos");
4385 * gtk_notebook_get_tab_pos:
4386 * @notebook: a #GtkNotebook
4388 * Gets the edge at which the tabs for switching pages in the
4389 * notebook are drawn.
4391 * Return value: the edge at which the tabs are drawn
4394 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4396 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4398 return notebook->tab_pos;
4402 * gtk_notebook_set_homogeneous_tabs:
4403 * @notebook: a #GtkNotebook
4404 * @homogeneous: %TRUE if all tabs should be the same size.
4406 * Sets whether the tabs must have all the same size or not.
4409 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4410 gboolean homogeneous)
4412 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4414 if (homogeneous == notebook->homogeneous)
4417 notebook->homogeneous = homogeneous;
4418 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4420 g_object_notify (G_OBJECT (notebook), "homogeneous");
4424 * gtk_notebook_set_tab_border:
4425 * @notebook: a #GtkNotebook
4426 * @border_width: width of the border around the tab labels.
4428 * Sets the width the border around the tab labels
4429 * in a notebook. This is equivalent to calling
4430 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4431 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4434 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4437 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4439 notebook->tab_hborder = border_width;
4440 notebook->tab_vborder = border_width;
4442 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4443 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4445 g_object_freeze_notify (G_OBJECT (notebook));
4446 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4447 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4448 g_object_thaw_notify (G_OBJECT (notebook));
4453 * gtk_notebook_set_tab_hborder:
4454 * @notebook: a #GtkNotebook
4455 * @tab_hborder: width of the horizontal border of tab labels.
4457 * Sets the width of the horizontal border of tab labels.
4460 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4463 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4465 if (notebook->tab_hborder == tab_hborder)
4468 notebook->tab_hborder = tab_hborder;
4470 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4471 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4473 g_object_notify (G_OBJECT (notebook), "tab_hborder");
4477 * gtk_notebook_set_tab_vborder:
4478 * @notebook: a #GtkNotebook
4479 * @tab_vborder: width of the vertical border of tab labels.
4481 * Sets the width of the vertical border of tab labels.
4484 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4487 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4489 if (notebook->tab_vborder == tab_vborder)
4492 notebook->tab_vborder = tab_vborder;
4494 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
4495 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4497 g_object_notify (G_OBJECT (notebook), "tab_vborder");
4501 * gtk_notebook_set_scrollable:
4502 * @notebook: a #GtkNotebook
4503 * @scrollable: %TRUE if scroll arrows should be added
4505 * Sets whether the tab label area will have arrows for scrolling if
4506 * there are too many tabs to fit in the area.
4509 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4510 gboolean scrollable)
4512 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4514 scrollable = (scrollable != FALSE);
4516 if (scrollable != notebook->scrollable)
4518 notebook->scrollable = scrollable;
4520 if (GTK_WIDGET_VISIBLE (notebook))
4521 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4523 g_object_notify (G_OBJECT (notebook), "scrollable");
4528 * gtk_notebook_get_scrollable:
4529 * @notebook: a #GtkNotebook
4531 * Returns whether the tab label area has arrows for scrolling. See
4532 * gtk_notebook_set_scrollable().
4534 * Return value: %TRUE if arrows for scrolling are present
4537 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4539 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4541 return notebook->scrollable;
4544 /* Public GtkNotebook Popup Menu Methods:
4546 * gtk_notebook_popup_enable
4547 * gtk_notebook_popup_disable
4552 * gtk_notebook_popup_enable:
4553 * @notebook: a #GtkNotebook
4555 * Enables the popup menu: if the user clicks with the right mouse button on
4556 * the bookmarks, a menu with all the pages will be popped up.
4559 gtk_notebook_popup_enable (GtkNotebook *notebook)
4563 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4568 notebook->menu = gtk_menu_new ();
4569 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4571 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4572 gtk_notebook_menu_item_create (notebook, list);
4574 gtk_notebook_update_labels (notebook);
4575 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4576 GTK_WIDGET (notebook),
4577 gtk_notebook_menu_detacher);
4579 g_object_notify (G_OBJECT (notebook), "enable_popup");
4583 * gtk_notebook_popup_disable:
4584 * @notebook: a #GtkNotebook
4586 * Disables the popup menu.
4589 gtk_notebook_popup_disable (GtkNotebook *notebook)
4591 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4593 if (!notebook->menu)
4596 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4597 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4598 gtk_widget_destroy (notebook->menu);
4600 g_object_notify (G_OBJECT (notebook), "enable_popup");
4603 /* Public GtkNotebook Page Properties Functions:
4605 * gtk_notebook_get_tab_label
4606 * gtk_notebook_set_tab_label
4607 * gtk_notebook_set_tab_label_text
4608 * gtk_notebook_get_menu_label
4609 * gtk_notebook_set_menu_label
4610 * gtk_notebook_set_menu_label_text
4611 * gtk_notebook_set_tab_label_packing
4612 * gtk_notebook_query_tab_label_packing
4616 * gtk_notebook_get_tab_label:
4617 * @notebook: a #GtkNotebook
4620 * Returns the tab label widget for the page @child. %NULL is returned
4621 * if @child is not in @notebook or if no tab label has specifically
4622 * been set for @child.
4624 * Return value: the tab label
4627 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4632 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4633 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4635 list = CHECK_FIND_CHILD (notebook, child);
4639 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4642 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4646 * gtk_notebook_set_tab_label:
4647 * @notebook: a #GtkNotebook
4649 * @tab_label: the tab label widget to use, or %NULL for default tab
4652 * Changes the tab label for @child. If %NULL is specified
4653 * for @tab_label, then the page will have the label 'page N'.
4656 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4658 GtkWidget *tab_label)
4660 GtkNotebookPage *page;
4663 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4664 g_return_if_fail (GTK_IS_WIDGET (child));
4666 list = CHECK_FIND_CHILD (notebook, child);
4670 /* a NULL pointer indicates a default_tab setting, otherwise
4671 * we need to set the associated label
4675 if (page->tab_label == tab_label)
4679 gtk_notebook_remove_tab_label (notebook, page);
4683 page->default_tab = FALSE;
4684 page->tab_label = tab_label;
4685 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4689 page->default_tab = TRUE;
4690 page->tab_label = NULL;
4692 if (notebook->show_tabs)
4696 g_snprintf (string, sizeof(string), _("Page %u"),
4697 gtk_notebook_real_page_position (notebook, list));
4698 page->tab_label = gtk_label_new (string);
4699 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4703 if (page->tab_label)
4704 page->mnemonic_activate_signal =
4705 gtk_signal_connect (GTK_OBJECT (page->tab_label),
4706 "mnemonic_activate",
4707 (GtkSignalFunc) gtk_notebook_mnemonic_activate_switch_page,
4710 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4712 gtk_widget_show (page->tab_label);
4713 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4715 gtk_widget_child_notify (child, "tab_label");
4719 * gtk_notebook_set_tab_label_text:
4720 * @notebook: a #GtkNotebook
4722 * @tab_text: the label text
4724 * Creates a new label and sets it as the tab label for the page
4725 * containing @child.
4728 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4730 const gchar *tab_text)
4732 GtkWidget *tab_label = NULL;
4734 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4737 tab_label = gtk_label_new (tab_text);
4738 gtk_notebook_set_tab_label (notebook, child, tab_label);
4739 gtk_widget_child_notify (child, "tab_label");
4743 * gtk_notebook_get_tab_label_text:
4744 * @notebook: a #GtkNotebook
4745 * @child: a widget contained in a page of @notebook
4747 * Retrieves the text of the tab label for the page containing
4750 * Returns value: the text of the tab label, or %NULL if the
4751 * tab label widget is not a #GtkLabel. The
4752 * string is owned by the widget and must not
4755 G_CONST_RETURN gchar *
4756 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4759 GtkWidget *tab_label;
4761 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4762 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4764 tab_label = gtk_notebook_get_tab_label (notebook, child);
4766 if (tab_label && GTK_IS_LABEL (tab_label))
4767 return gtk_label_get_text (GTK_LABEL (tab_label));
4773 * gtk_notebook_get_menu_label:
4774 * @notebook: a #GtkNotebook
4775 * @child: a widget contained in a page of @notebook
4777 * Retrieves the menu label widget of the page containing @child.
4779 * Return value: the menu label, or %NULL if the
4780 * notebook page does not have a menu label other
4781 * than the default (the tab label).
4784 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4789 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4790 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4792 list = CHECK_FIND_CHILD (notebook, child);
4796 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4799 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4803 * gtk_notebook_set_menu_label:
4804 * @notebook: a #GtkNotebook
4805 * @child: the child widget
4806 * @menu_label: the menu label, or NULL for default
4808 * Changes the menu label for the page containing @child.
4811 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4813 GtkWidget *menu_label)
4815 GtkNotebookPage *page;
4818 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4819 g_return_if_fail (GTK_IS_WIDGET (child));
4821 list = CHECK_FIND_CHILD (notebook, child);
4826 if (page->menu_label)
4829 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4830 page->menu_label->parent);
4832 if (!page->default_menu)
4833 gtk_widget_unref (page->menu_label);
4838 page->menu_label = menu_label;
4839 gtk_widget_ref (page->menu_label);
4840 gtk_object_sink (GTK_OBJECT(page->menu_label));
4841 page->default_menu = FALSE;
4844 page->default_menu = TRUE;
4847 gtk_notebook_menu_item_create (notebook, list);
4848 gtk_widget_child_notify (child, "menu_label");
4852 * gtk_notebook_set_menu_label_text:
4853 * @notebook: a #GtkNotebook
4854 * @child: the child widget
4855 * @menu_text: the label text
4857 * Creates a new label and sets it as the menu label of @child.
4860 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4862 const gchar *menu_text)
4864 GtkWidget *menu_label = NULL;
4866 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4869 menu_label = gtk_label_new (menu_text);
4870 gtk_notebook_set_menu_label (notebook, child, menu_label);
4871 gtk_widget_child_notify (child, "menu_label");
4875 * gtk_notebook_get_menu_label_text:
4876 * @notebook: a #GtkNotebook
4877 * @child: the child widget of a page of the notebook.
4879 * Retrieves the text of the menu label for the page containing
4882 * Returns value: the text of the tab label, or %NULL if the
4883 * widget does not have a menu label other than
4884 * the default menu label, or the menu label widget
4885 * is not a #GtkLabel. The string is owned by
4886 * the widget and must not be freed.
4888 G_CONST_RETURN gchar *
4889 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
4892 GtkWidget *menu_label;
4894 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4895 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4897 menu_label = gtk_notebook_get_menu_label (notebook, child);
4899 if (menu_label && GTK_IS_LABEL (menu_label))
4900 return gtk_label_get_text (GTK_LABEL (menu_label));
4905 /* Helper function called when pages are reordered
4908 gtk_notebook_child_reordered (GtkNotebook *notebook,
4909 GtkNotebookPage *page)
4913 GtkWidget *menu_item;
4915 menu_item = page->menu_label->parent;
4916 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4917 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4918 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
4921 gtk_notebook_update_labels (notebook);
4925 * gtk_notebook_set_tab_label_packing:
4926 * @notebook: a #GtkNotebook
4927 * @child: the child widget
4928 * @expand: whether to expand the bookmark or not
4929 * @fill: whether the bookmark should fill the allocated area or not
4930 * @pack_type: the position of the bookmark
4932 * Sets the packing parameters for the tab label of the page
4933 * containing @child. See gtk_box_pack_start() for the exact meaning
4934 * of the parameters.
4937 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4941 GtkPackType pack_type)
4943 GtkNotebookPage *page;
4946 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4947 g_return_if_fail (GTK_IS_WIDGET (child));
4949 list = CHECK_FIND_CHILD (notebook, child);
4954 expand = expand != FALSE;
4955 fill = fill != FALSE;
4956 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4959 gtk_widget_freeze_child_notify (child);
4960 page->expand = expand;
4961 gtk_widget_child_notify (child, "tab_expand");
4963 gtk_widget_child_notify (child, "tab_fill");
4964 if (page->pack != pack_type)
4966 page->pack = pack_type;
4967 gtk_notebook_child_reordered (notebook, page);
4969 gtk_widget_child_notify (child, "tab_pack");
4970 gtk_widget_child_notify (child, "position");
4971 if (notebook->show_tabs)
4972 gtk_notebook_pages_allocate (notebook);
4973 gtk_widget_thaw_child_notify (child);
4977 * gtk_notebook_query_tab_label_packing:
4978 * @notebook: a #GtkNotebook
4980 * @expand: location to store the expand value (or NULL)
4981 * @fill: location to store the fill value (or NULL)
4982 * @pack_type: location to store the pack_type (or NULL)
4984 * Query the packing attributes for the tab label of the page
4985 * containing @child.
4988 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4992 GtkPackType *pack_type)
4996 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4997 g_return_if_fail (GTK_IS_WIDGET (child));
4999 list = CHECK_FIND_CHILD (notebook, child);
5004 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5006 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5008 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5012 * gtk_notebook_reorder_child:
5013 * @notebook: a #GtkNotebook
5014 * @child: the child to move
5015 * @position: the new position, or -1 to move to the end
5017 * Reorders the page containing @child, so that it appears in position
5018 * @position. If @position is greater than or equal to the number of
5019 * children in the list or negative, @child will be moved to the end
5023 gtk_notebook_reorder_child (GtkNotebook *notebook,
5027 GList *list, *new_list;
5028 GtkNotebookPage *page;
5032 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5033 g_return_if_fail (GTK_IS_WIDGET (child));
5035 list = CHECK_FIND_CHILD (notebook, child);
5039 max_pos = g_list_length (notebook->children) - 1;
5040 if (position < 0 || position > max_pos)
5043 old_pos = g_list_position (notebook->children, list);
5045 if (old_pos == position)
5049 notebook->children = g_list_delete_link (notebook->children, list);
5051 notebook->children = g_list_insert (notebook->children, page, position);
5052 new_list = g_list_nth (notebook->children, position);
5054 /* Fix up GList references in GtkNotebook structure */
5055 if (notebook->first_tab == list)
5056 notebook->first_tab = new_list;
5057 if (notebook->focus_tab == list)
5058 notebook->focus_tab = new_list;
5060 gtk_widget_freeze_child_notify (child);
5062 /* Move around the menu items if necesary */
5063 gtk_notebook_child_reordered (notebook, page);
5064 gtk_widget_child_notify (child, "tab_pack");
5065 gtk_widget_child_notify (child, "position");
5067 if (notebook->show_tabs)
5068 gtk_notebook_pages_allocate (notebook);
5070 gtk_widget_thaw_child_notify (child);