1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtknotebook.h"
30 #include "gtkmenuitem.h"
32 #include <gdk/gdkkeysyms.h>
35 #include "gtkmarshalers.h"
36 #include "gtkbindings.h"
40 #define TAB_CURVATURE 1
42 #define ARROW_SPACING 0
43 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
44 #define NOTEBOOK_SCROLL_DELAY (100)
70 #define ARROW_IS_LEFT(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
71 #define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)
90 CHILD_PROP_MENU_LABEL,
92 CHILD_PROP_TAB_EXPAND,
97 #define GTK_NOTEBOOK_PAGE(_glist_) ((GtkNotebookPage *)((GList *)(_glist_))->data)
99 struct _GtkNotebookPage
102 GtkWidget *tab_label;
103 GtkWidget *menu_label;
104 GtkWidget *last_focus_child; /* Last descendant of the page that had focus */
106 guint default_menu : 1; /* If true, we create the menu label ourself */
107 guint default_tab : 1; /* If true, we create the tab label ourself */
112 GtkRequisition requisition;
113 GtkAllocation allocation;
115 guint mnemonic_activate_signal;
118 #ifdef G_DISABLE_CHECKS
119 #define CHECK_FIND_CHILD(notebook, child) \
120 gtk_notebook_find_child (notebook, child, G_STRLOC)
122 #define CHECK_FIND_CHILD(notebook, child) \
123 gtk_notebook_find_child (notebook, child, NULL)
126 /*** GtkNotebook Methods ***/
127 static void gtk_notebook_class_init (GtkNotebookClass *klass);
128 static void gtk_notebook_init (GtkNotebook *notebook);
130 static gboolean gtk_notebook_select_page (GtkNotebook *notebook,
131 gboolean move_focus);
132 static gboolean gtk_notebook_focus_tab (GtkNotebook *notebook,
133 GtkNotebookTab type);
134 static void gtk_notebook_change_current_page (GtkNotebook *notebook,
136 static void gtk_notebook_move_focus_out (GtkNotebook *notebook,
137 GtkDirectionType direction_type);
139 /*** GtkObject Methods ***/
140 static void gtk_notebook_destroy (GtkObject *object);
141 static void gtk_notebook_set_property (GObject *object,
145 static void gtk_notebook_get_property (GObject *object,
150 /*** GtkWidget Methods ***/
151 static void gtk_notebook_map (GtkWidget *widget);
152 static void gtk_notebook_unmap (GtkWidget *widget);
153 static void gtk_notebook_realize (GtkWidget *widget);
154 static void gtk_notebook_unrealize (GtkWidget *widget);
155 static void gtk_notebook_size_request (GtkWidget *widget,
156 GtkRequisition *requisition);
157 static void gtk_notebook_size_allocate (GtkWidget *widget,
158 GtkAllocation *allocation);
159 static gint gtk_notebook_expose (GtkWidget *widget,
160 GdkEventExpose *event);
161 static gint gtk_notebook_button_press (GtkWidget *widget,
162 GdkEventButton *event);
163 static gint gtk_notebook_button_release (GtkWidget *widget,
164 GdkEventButton *event);
165 static gint gtk_notebook_enter_notify (GtkWidget *widget,
166 GdkEventCrossing *event);
167 static gint gtk_notebook_leave_notify (GtkWidget *widget,
168 GdkEventCrossing *event);
169 static gint gtk_notebook_motion_notify (GtkWidget *widget,
170 GdkEventMotion *event);
171 static gint gtk_notebook_focus_in (GtkWidget *widget,
172 GdkEventFocus *event);
173 static void gtk_notebook_grab_notify (GtkWidget *widget,
174 gboolean was_grabbed);
175 static void gtk_notebook_state_changed (GtkWidget *widget,
176 GtkStateType previous_state);
177 static void gtk_notebook_draw_focus (GtkWidget *widget);
178 static gint gtk_notebook_focus (GtkWidget *widget,
179 GtkDirectionType direction);
180 static void gtk_notebook_style_set (GtkWidget *widget,
183 /*** GtkContainer Methods ***/
184 static void gtk_notebook_set_child_property (GtkContainer *container,
189 static void gtk_notebook_get_child_property (GtkContainer *container,
194 static void gtk_notebook_add (GtkContainer *container,
196 static void gtk_notebook_remove (GtkContainer *container,
198 static void gtk_notebook_set_focus_child (GtkContainer *container,
200 static GType gtk_notebook_child_type (GtkContainer *container);
201 static void gtk_notebook_forall (GtkContainer *container,
202 gboolean include_internals,
203 GtkCallback callback,
204 gpointer callback_data);
206 /*** GtkNotebook Private Functions ***/
207 static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
208 static void gtk_notebook_redraw_arrows (GtkNotebook *notebook);
209 static void gtk_notebook_real_remove (GtkNotebook *notebook,
211 gboolean destroying);
212 static void gtk_notebook_update_labels (GtkNotebook *notebook);
213 static gint gtk_notebook_timer (GtkNotebook *notebook);
214 static gint gtk_notebook_page_compare (gconstpointer a,
216 static GList* gtk_notebook_find_child (GtkNotebook *notebook,
218 const gchar *function);
219 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
221 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
224 gboolean find_visible);
226 /*** GtkNotebook Drawing Functions ***/
227 static void gtk_notebook_paint (GtkWidget *widget,
229 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
230 GtkNotebookPage *page,
232 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
233 GtkNotebookArrow arrow);
235 /*** GtkNotebook Size Allocate Functions ***/
236 static void gtk_notebook_pages_allocate (GtkNotebook *notebook);
237 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
238 GtkNotebookPage *page,
239 GtkAllocation *allocation);
240 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
246 /*** GtkNotebook Page Switch Methods ***/
247 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
248 GtkNotebookPage *page,
251 /*** GtkNotebook Page Switch Functions ***/
252 static void gtk_notebook_switch_page (GtkNotebook *notebook,
253 GtkNotebookPage *page,
255 static gint gtk_notebook_page_select (GtkNotebook *notebook,
256 gboolean move_focus);
257 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
259 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
260 GtkNotebookPage *page);
262 /*** GtkNotebook Menu Functions ***/
263 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
265 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
267 static void gtk_notebook_menu_detacher (GtkWidget *widget,
270 /*** GtkNotebook Private Setters ***/
271 static void gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
272 gboolean homogeneous);
273 static void gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
275 static void gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
277 static void gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
280 static gboolean focus_tabs_in (GtkNotebook *notebook);
281 static gboolean focus_child_in (GtkNotebook *notebook,
282 GtkDirectionType direction);
284 static GtkContainerClass *parent_class = NULL;
285 static guint notebook_signals[LAST_SIGNAL] = { 0 };
288 gtk_notebook_get_type (void)
290 static GType notebook_type = 0;
294 static const GTypeInfo notebook_info =
296 sizeof (GtkNotebookClass),
297 NULL, /* base_init */
298 NULL, /* base_finalize */
299 (GClassInitFunc) gtk_notebook_class_init,
300 NULL, /* class_finalize */
301 NULL, /* class_data */
302 sizeof (GtkNotebook),
304 (GInstanceInitFunc) gtk_notebook_init,
307 notebook_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkNotebook",
311 return notebook_type;
315 add_tab_bindings (GtkBindingSet *binding_set,
316 GdkModifierType modifiers,
317 GtkDirectionType direction)
319 gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
321 GTK_TYPE_DIRECTION_TYPE, direction);
322 gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
324 GTK_TYPE_DIRECTION_TYPE, direction);
328 add_arrow_bindings (GtkBindingSet *binding_set,
330 GtkDirectionType direction)
332 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
334 gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
336 GTK_TYPE_DIRECTION_TYPE, direction);
337 gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
339 GTK_TYPE_DIRECTION_TYPE, direction);
343 gtk_notebook_class_init (GtkNotebookClass *class)
345 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
346 GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
347 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
348 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
349 GtkBindingSet *binding_set;
351 parent_class = g_type_class_peek_parent (class);
353 gobject_class->set_property = gtk_notebook_set_property;
354 gobject_class->get_property = gtk_notebook_get_property;
355 object_class->destroy = gtk_notebook_destroy;
357 widget_class->map = gtk_notebook_map;
358 widget_class->unmap = gtk_notebook_unmap;
359 widget_class->realize = gtk_notebook_realize;
360 widget_class->unrealize = gtk_notebook_unrealize;
361 widget_class->size_request = gtk_notebook_size_request;
362 widget_class->size_allocate = gtk_notebook_size_allocate;
363 widget_class->expose_event = gtk_notebook_expose;
364 widget_class->button_press_event = gtk_notebook_button_press;
365 widget_class->button_release_event = gtk_notebook_button_release;
366 widget_class->enter_notify_event = gtk_notebook_enter_notify;
367 widget_class->leave_notify_event = gtk_notebook_leave_notify;
368 widget_class->motion_notify_event = gtk_notebook_motion_notify;
369 widget_class->grab_notify = gtk_notebook_grab_notify;
370 widget_class->state_changed = gtk_notebook_state_changed;
371 widget_class->focus_in_event = gtk_notebook_focus_in;
372 widget_class->focus = gtk_notebook_focus;
373 widget_class->style_set = gtk_notebook_style_set;
375 container_class->add = gtk_notebook_add;
376 container_class->remove = gtk_notebook_remove;
377 container_class->forall = gtk_notebook_forall;
378 container_class->set_focus_child = gtk_notebook_set_focus_child;
379 container_class->get_child_property = gtk_notebook_get_child_property;
380 container_class->set_child_property = gtk_notebook_set_child_property;
381 container_class->child_type = gtk_notebook_child_type;
383 class->switch_page = gtk_notebook_real_switch_page;
385 class->focus_tab = gtk_notebook_focus_tab;
386 class->select_page = gtk_notebook_select_page;
387 class->change_current_page = gtk_notebook_change_current_page;
388 class->move_focus_out = gtk_notebook_move_focus_out;
390 g_object_class_install_property (gobject_class,
392 g_param_spec_int ("page",
394 _("The index of the current page"),
399 g_object_class_install_property (gobject_class,
401 g_param_spec_enum ("tab_pos",
403 _("Which side of the notebook holds the tabs"),
404 GTK_TYPE_POSITION_TYPE,
407 g_object_class_install_property (gobject_class,
409 g_param_spec_uint ("tab_border",
411 _("Width of the border around the tab labels"),
416 g_object_class_install_property (gobject_class,
418 g_param_spec_uint ("tab_hborder",
419 _("Horizontal Tab Border"),
420 _("Width of the horizontal border of tab labels"),
425 g_object_class_install_property (gobject_class,
427 g_param_spec_uint ("tab_vborder",
428 _("Vertical Tab Border"),
429 _("Width of the vertical border of tab labels"),
434 g_object_class_install_property (gobject_class,
436 g_param_spec_boolean ("show_tabs",
438 _("Whether tabs should be shown or not"),
441 g_object_class_install_property (gobject_class,
443 g_param_spec_boolean ("show_border",
445 _("Whether the border should be shown or not"),
448 g_object_class_install_property (gobject_class,
450 g_param_spec_boolean ("scrollable",
452 _("If TRUE, scroll arrows are added if there are too many tabs to fit"),
455 g_object_class_install_property (gobject_class,
457 g_param_spec_boolean ("enable_popup",
459 _("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
462 g_object_class_install_property (gobject_class,
464 g_param_spec_boolean ("homogeneous",
466 _("Whether tabs should have homogeneous sizes"),
470 gtk_container_class_install_child_property (container_class,
471 CHILD_PROP_TAB_LABEL,
472 g_param_spec_string ("tab_label",
474 _("The string displayed on the childs tab label"),
477 gtk_container_class_install_child_property (container_class,
478 CHILD_PROP_MENU_LABEL,
479 g_param_spec_string ("menu_label",
481 _("The string displayed in the childs menu entry"),
484 gtk_container_class_install_child_property (container_class,
486 g_param_spec_int ("position",
488 _("The index of the child in the parent"),
491 gtk_container_class_install_child_property (container_class,
492 CHILD_PROP_TAB_EXPAND,
493 g_param_spec_boolean ("tab_expand",
495 _("Whether to expand the childs tab or not"),
498 gtk_container_class_install_child_property (container_class,
500 g_param_spec_boolean ("tab_fill",
502 _("Wheather the childs tab should fill the allocated area or not"),
505 gtk_container_class_install_child_property (container_class,
507 g_param_spec_enum ("tab_pack",
509 _("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
510 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
513 gtk_widget_class_install_style_property (widget_class,
514 g_param_spec_boolean ("has_secondary backward_stepper",
515 _("Secondary backward stepper"),
516 _("Display a second backward arrow button on the opposite end of the tab area"),
521 gtk_widget_class_install_style_property (widget_class,
522 g_param_spec_boolean ("has_secondary_forward_stepper",
523 _("Secondary forward stepper"),
524 _("Display a second forward arrow button on the opposite end of the tab area"),
529 gtk_widget_class_install_style_property (widget_class,
530 g_param_spec_boolean ("has_backward_stepper",
531 _("Backward stepper"),
532 _("Display the standard backward arrow button"),
537 gtk_widget_class_install_style_property (widget_class,
538 g_param_spec_boolean ("has_forward_stepper",
539 _("Forward stepper"),
540 _("Display the standard forward arrow button"),
545 notebook_signals[SWITCH_PAGE] =
546 g_signal_new ("switch_page",
547 G_TYPE_FROM_CLASS (gobject_class),
549 G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
551 _gtk_marshal_VOID__POINTER_UINT,
555 notebook_signals[FOCUS_TAB] =
556 g_signal_new ("focus_tab",
557 G_TYPE_FROM_CLASS (gobject_class),
558 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
559 G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
561 _gtk_marshal_BOOLEAN__ENUM,
563 GTK_TYPE_NOTEBOOK_TAB);
564 notebook_signals[SELECT_PAGE] =
565 g_signal_new ("select_page",
566 G_TYPE_FROM_CLASS (gobject_class),
567 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
568 G_STRUCT_OFFSET (GtkNotebookClass, select_page),
570 _gtk_marshal_BOOLEAN__BOOLEAN,
573 notebook_signals[CHANGE_CURRENT_PAGE] =
574 g_signal_new ("change_current_page",
575 G_TYPE_FROM_CLASS (gobject_class),
576 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
577 G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
579 _gtk_marshal_VOID__INT,
582 notebook_signals[MOVE_FOCUS_OUT] =
583 g_signal_new ("move_focus_out",
584 G_TYPE_FROM_CLASS (gobject_class),
585 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
586 G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
588 _gtk_marshal_VOID__ENUM,
590 GTK_TYPE_DIRECTION_TYPE);
593 binding_set = gtk_binding_set_by_class (class);
594 gtk_binding_entry_add_signal (binding_set,
597 G_TYPE_BOOLEAN, FALSE);
598 gtk_binding_entry_add_signal (binding_set,
601 G_TYPE_BOOLEAN, FALSE);
603 gtk_binding_entry_add_signal (binding_set,
606 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
607 gtk_binding_entry_add_signal (binding_set,
610 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
611 gtk_binding_entry_add_signal (binding_set,
614 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
615 gtk_binding_entry_add_signal (binding_set,
618 GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
620 gtk_binding_entry_add_signal (binding_set,
621 GDK_Page_Up, GDK_CONTROL_MASK,
622 "change_current_page", 1,
624 gtk_binding_entry_add_signal (binding_set,
625 GDK_Page_Down, GDK_CONTROL_MASK,
626 "change_current_page", 1,
629 gtk_binding_entry_add_signal (binding_set,
630 GDK_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
631 "change_current_page", 1,
633 gtk_binding_entry_add_signal (binding_set,
634 GDK_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
635 "change_current_page", 1,
638 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
639 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
640 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
641 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
643 add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
644 add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
648 gtk_notebook_init (GtkNotebook *notebook)
650 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
651 GTK_WIDGET_SET_FLAGS (notebook, GTK_NO_WINDOW);
653 notebook->cur_page = NULL;
654 notebook->children = NULL;
655 notebook->first_tab = NULL;
656 notebook->focus_tab = NULL;
657 notebook->event_window = NULL;
658 notebook->menu = NULL;
660 notebook->tab_hborder = 2;
661 notebook->tab_vborder = 2;
663 notebook->show_tabs = TRUE;
664 notebook->show_border = TRUE;
665 notebook->tab_pos = GTK_POS_TOP;
666 notebook->scrollable = FALSE;
667 notebook->in_child = 0;
668 notebook->click_child = 0;
669 notebook->button = 0;
670 notebook->need_timer = 0;
671 notebook->child_has_focus = FALSE;
672 notebook->have_visible_child = FALSE;
673 notebook->focus_out = FALSE;
675 notebook->has_before_previous = 1;
676 notebook->has_before_next = 0;
677 notebook->has_after_previous = 0;
678 notebook->has_after_next = 1;
682 gtk_notebook_select_page (GtkNotebook *notebook,
685 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
687 gtk_notebook_page_select (notebook, move_focus);
695 gtk_notebook_focus_tab (GtkNotebook *notebook,
700 if (gtk_widget_is_focus (GTK_WIDGET (notebook)))
704 case GTK_NOTEBOOK_TAB_FIRST:
705 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
707 gtk_notebook_switch_focus_tab (notebook, list);
709 case GTK_NOTEBOOK_TAB_LAST:
710 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
712 gtk_notebook_switch_focus_tab (notebook, list);
723 gtk_notebook_change_current_page (GtkNotebook *notebook,
726 GList *current = NULL;
728 if (notebook->cur_page)
729 current = g_list_find (notebook->children, notebook->cur_page);
733 current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
734 offset += offset < 0 ? 1 : -1;
738 gtk_notebook_switch_page (notebook, current->data, -1);
740 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
743 static GtkDirectionType
744 get_effective_direction (GtkNotebook *notebook,
745 GtkDirectionType direction)
747 /* Remap the directions into the effective direction it would be for a
748 * GTK_POS_TOP notebook
750 #define D(rest) GTK_DIR_##rest
752 static const GtkDirectionType translate_direction[4][6] = {
753 /* LEFT */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(LEFT), D(RIGHT), D(UP), D(DOWN) },
754 /* RIGHT */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(LEFT), D(RIGHT), D(DOWN), D(UP) },
755 /* TOP */ { D(TAB_FORWARD), D(TAB_BACKWARD), D(UP), D(DOWN), D(LEFT), D(RIGHT) },
756 /* BOTTOM */ { D(TAB_BACKWARD), D(TAB_FORWARD), D(DOWN), D(UP), D(LEFT), D(RIGHT) },
761 return translate_direction[notebook->tab_pos][direction];
765 gtk_notebook_move_focus_out (GtkNotebook *notebook,
766 GtkDirectionType direction_type)
768 GtkDirectionType effective_direction = get_effective_direction (notebook, direction_type);
771 if (GTK_CONTAINER (notebook)->focus_child && effective_direction == GTK_DIR_UP)
772 if (focus_tabs_in (notebook))
775 if (gtk_widget_is_focus (GTK_WIDGET (notebook)) && effective_direction == GTK_DIR_DOWN)
776 if (focus_child_in (notebook, GTK_DIR_TAB_FORWARD))
779 /* At this point, we know we should be focusing out of the notebook entirely. We
780 * do this by setting a flag, then propagating the focus motion to the notebook.
782 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (notebook));
783 if (!GTK_WIDGET_TOPLEVEL (toplevel))
786 g_object_ref (notebook);
788 notebook->focus_out = TRUE;
789 g_signal_emit_by_name (toplevel, "move_focus", direction_type);
790 notebook->focus_out = FALSE;
792 g_object_unref (notebook);
799 * Creates a new #GtkNotebook widget with no pages.
801 * Return value: the newly created #GtkNotebook
804 gtk_notebook_new (void)
806 return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
809 /* Private GtkObject Methods :
811 * gtk_notebook_destroy
812 * gtk_notebook_set_arg
813 * gtk_notebook_get_arg
816 gtk_notebook_destroy (GtkObject *object)
819 GtkNotebook *notebook = GTK_NOTEBOOK (object);
822 gtk_notebook_popup_disable (notebook);
824 children = notebook->children;
827 GList *child = children;
828 children = child->next;
830 gtk_notebook_real_remove (notebook, child, TRUE);
833 GTK_OBJECT_CLASS (parent_class)->destroy (object);
837 gtk_notebook_set_property (GObject *object,
842 GtkNotebook *notebook;
844 notebook = GTK_NOTEBOOK (object);
849 gtk_notebook_set_show_tabs (notebook, g_value_get_boolean (value));
851 case PROP_SHOW_BORDER:
852 gtk_notebook_set_show_border (notebook, g_value_get_boolean (value));
854 case PROP_SCROLLABLE:
855 gtk_notebook_set_scrollable (notebook, g_value_get_boolean (value));
857 case PROP_ENABLE_POPUP:
858 if (g_value_get_boolean (value))
859 gtk_notebook_popup_enable (notebook);
861 gtk_notebook_popup_disable (notebook);
863 case PROP_HOMOGENEOUS:
864 gtk_notebook_set_homogeneous_tabs_internal (notebook, g_value_get_boolean (value));
867 gtk_notebook_set_current_page (notebook, g_value_get_int (value));
870 gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
872 case PROP_TAB_BORDER:
873 gtk_notebook_set_tab_border_internal (notebook, g_value_get_uint (value));
875 case PROP_TAB_HBORDER:
876 gtk_notebook_set_tab_hborder_internal (notebook, g_value_get_uint (value));
878 case PROP_TAB_VBORDER:
879 gtk_notebook_set_tab_vborder_internal (notebook, g_value_get_uint (value));
887 gtk_notebook_get_property (GObject *object,
892 GtkNotebook *notebook;
894 notebook = GTK_NOTEBOOK (object);
899 g_value_set_boolean (value, notebook->show_tabs);
901 case PROP_SHOW_BORDER:
902 g_value_set_boolean (value, notebook->show_border);
904 case PROP_SCROLLABLE:
905 g_value_set_boolean (value, notebook->scrollable);
907 case PROP_ENABLE_POPUP:
908 g_value_set_boolean (value, notebook->menu != NULL);
910 case PROP_HOMOGENEOUS:
911 g_value_set_boolean (value, notebook->homogeneous);
914 g_value_set_int (value, gtk_notebook_get_current_page (notebook));
917 g_value_set_enum (value, notebook->tab_pos);
919 case PROP_TAB_HBORDER:
920 g_value_set_uint (value, notebook->tab_hborder);
922 case PROP_TAB_VBORDER:
923 g_value_set_uint (value, notebook->tab_vborder);
926 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
931 /* Private GtkWidget Methods :
935 * gtk_notebook_realize
936 * gtk_notebook_size_request
937 * gtk_notebook_size_allocate
938 * gtk_notebook_expose
939 * gtk_notebook_button_press
940 * gtk_notebook_button_release
941 * gtk_notebook_enter_notify
942 * gtk_notebook_leave_notify
943 * gtk_notebook_motion_notify
944 * gtk_notebook_focus_in
945 * gtk_notebook_focus_out
946 * gtk_notebook_draw_focus
947 * gtk_notebook_style_set
950 gtk_notebook_get_event_window_position (GtkNotebook *notebook,
951 GdkRectangle *rectangle)
953 GtkWidget *widget = GTK_WIDGET (notebook);
954 gint border_width = GTK_CONTAINER (notebook)->border_width;
955 GtkNotebookPage *visible_page = NULL;
958 for (tmp_list = notebook->children; tmp_list; tmp_list = tmp_list->next)
960 GtkNotebookPage *page = tmp_list->data;
961 if (GTK_WIDGET_VISIBLE (page->child))
968 if (notebook->show_tabs && visible_page)
972 rectangle->x = widget->allocation.x + border_width;
973 rectangle->y = widget->allocation.y + border_width;
975 switch (notebook->tab_pos)
979 rectangle->width = widget->allocation.width - 2 * border_width;
980 rectangle->height = visible_page->requisition.height;
981 if (notebook->tab_pos == GTK_POS_BOTTOM)
982 rectangle->y += widget->allocation.height - 2 * border_width - rectangle->height;
986 rectangle->width = visible_page->requisition.width;
987 rectangle->height = widget->allocation.height - 2 * border_width;
988 if (notebook->tab_pos == GTK_POS_RIGHT)
989 rectangle->x += widget->allocation.width - 2 * border_width - rectangle->width;
1000 rectangle->x = rectangle->y = 0;
1001 rectangle->width = rectangle->height = 10;
1009 gtk_notebook_map (GtkWidget *widget)
1011 GtkNotebook *notebook;
1012 GtkNotebookPage *page;
1015 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1017 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1019 notebook = GTK_NOTEBOOK (widget);
1021 if (notebook->cur_page &&
1022 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1023 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1024 gtk_widget_map (notebook->cur_page->child);
1026 if (notebook->scrollable)
1027 gtk_notebook_pages_allocate (notebook);
1030 children = notebook->children;
1034 page = children->data;
1035 children = children->next;
1037 if (page->tab_label &&
1038 GTK_WIDGET_VISIBLE (page->tab_label) &&
1039 !GTK_WIDGET_MAPPED (page->tab_label))
1040 gtk_widget_map (page->tab_label);
1044 if (gtk_notebook_get_event_window_position (notebook, NULL))
1045 gdk_window_show_unraised (notebook->event_window);
1049 gtk_notebook_unmap (GtkWidget *widget)
1051 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1053 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1055 gdk_window_hide (GTK_NOTEBOOK (widget)->event_window);
1057 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
1061 gtk_notebook_realize (GtkWidget *widget)
1063 GtkNotebook *notebook;
1064 GdkWindowAttr attributes;
1065 gint attributes_mask;
1066 GdkRectangle event_window_pos;
1068 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1070 notebook = GTK_NOTEBOOK (widget);
1071 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1073 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1075 widget->window = gtk_widget_get_parent_window (widget);
1076 g_object_ref (widget->window);
1078 attributes.window_type = GDK_WINDOW_CHILD;
1079 attributes.x = event_window_pos.x;
1080 attributes.y = event_window_pos.y;
1081 attributes.width = event_window_pos.width;
1082 attributes.height = event_window_pos.height;
1083 attributes.wclass = GDK_INPUT_ONLY;
1084 attributes.event_mask = gtk_widget_get_events (widget);
1085 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
1086 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
1088 attributes_mask = GDK_WA_X | GDK_WA_Y;
1090 notebook->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
1091 &attributes, attributes_mask);
1092 gdk_window_set_user_data (notebook->event_window, notebook);
1094 widget->style = gtk_style_attach (widget->style, widget->window);
1098 gtk_notebook_unrealize (GtkWidget *widget)
1100 GtkNotebook *notebook;
1102 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1104 notebook = GTK_NOTEBOOK (widget);
1106 gdk_window_set_user_data (notebook->event_window, NULL);
1107 gdk_window_destroy (notebook->event_window);
1108 notebook->event_window = NULL;
1110 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1111 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1115 gtk_notebook_size_request (GtkWidget *widget,
1116 GtkRequisition *requisition)
1118 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1119 GtkNotebookPage *page;
1121 GtkRequisition child_requisition;
1122 gboolean switch_page = FALSE;
1126 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1128 widget->requisition.width = 0;
1129 widget->requisition.height = 0;
1131 for (children = notebook->children, vis_pages = 0; children;
1132 children = children->next)
1134 page = children->data;
1136 if (GTK_WIDGET_VISIBLE (page->child))
1139 gtk_widget_size_request (page->child, &child_requisition);
1141 widget->requisition.width = MAX (widget->requisition.width,
1142 child_requisition.width);
1143 widget->requisition.height = MAX (widget->requisition.height,
1144 child_requisition.height);
1146 if (notebook->menu && page->menu_label->parent &&
1147 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
1148 gtk_widget_show (page->menu_label->parent);
1152 if (page == notebook->cur_page)
1154 if (notebook->menu && page->menu_label->parent &&
1155 GTK_WIDGET_VISIBLE (page->menu_label->parent))
1156 gtk_widget_hide (page->menu_label->parent);
1160 if (notebook->show_border || notebook->show_tabs)
1162 widget->requisition.width += widget->style->xthickness * 2;
1163 widget->requisition.height += widget->style->ythickness * 2;
1165 if (notebook->show_tabs)
1168 gint tab_height = 0;
1172 for (children = notebook->children; children;
1173 children = children->next)
1175 page = children->data;
1177 if (GTK_WIDGET_VISIBLE (page->child))
1179 if (!GTK_WIDGET_VISIBLE (page->tab_label))
1180 gtk_widget_show (page->tab_label);
1182 gtk_widget_size_request (page->tab_label,
1183 &child_requisition);
1185 page->requisition.width =
1186 child_requisition.width +
1187 2 * widget->style->xthickness;
1188 page->requisition.height =
1189 child_requisition.height +
1190 2 * widget->style->ythickness;
1192 switch (notebook->tab_pos)
1195 case GTK_POS_BOTTOM:
1196 page->requisition.height += 2 * (notebook->tab_vborder +
1198 tab_height = MAX (tab_height, page->requisition.height);
1199 tab_max = MAX (tab_max, page->requisition.width);
1203 page->requisition.width += 2 * (notebook->tab_hborder +
1205 tab_width = MAX (tab_width, page->requisition.width);
1206 tab_max = MAX (tab_max, page->requisition.height);
1210 else if (GTK_WIDGET_VISIBLE (page->tab_label))
1211 gtk_widget_hide (page->tab_label);
1214 children = notebook->children;
1218 switch (notebook->tab_pos)
1221 case GTK_POS_BOTTOM:
1222 if (tab_height == 0)
1225 if (notebook->scrollable && vis_pages > 1 &&
1226 widget->requisition.width < tab_width)
1227 tab_height = MAX (tab_height, ARROW_SIZE);
1229 padding = 2 * (TAB_CURVATURE + focus_width +
1230 notebook->tab_hborder) - TAB_OVERLAP;
1234 page = children->data;
1235 children = children->next;
1237 if (!GTK_WIDGET_VISIBLE (page->child))
1240 if (notebook->homogeneous)
1241 page->requisition.width = tab_max;
1243 page->requisition.width += padding;
1245 tab_width += page->requisition.width;
1246 page->requisition.height = tab_height;
1249 if (notebook->scrollable && vis_pages > 1 &&
1250 widget->requisition.width < tab_width)
1251 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1253 if (notebook->homogeneous && !notebook->scrollable)
1254 widget->requisition.width = MAX (widget->requisition.width,
1255 vis_pages * tab_max +
1258 widget->requisition.width = MAX (widget->requisition.width,
1259 tab_width + TAB_OVERLAP);
1261 widget->requisition.height += tab_height;
1268 if (notebook->scrollable && vis_pages > 1 &&
1269 widget->requisition.height < tab_height)
1270 tab_width = MAX (tab_width, ARROW_SPACING + 2 * ARROW_SIZE);
1272 padding = 2 * (TAB_CURVATURE + focus_width +
1273 notebook->tab_vborder) - TAB_OVERLAP;
1278 page = children->data;
1279 children = children->next;
1281 if (!GTK_WIDGET_VISIBLE (page->child))
1284 page->requisition.width = tab_width;
1286 if (notebook->homogeneous)
1287 page->requisition.height = tab_max;
1289 page->requisition.height += padding;
1291 tab_height += page->requisition.height;
1294 if (notebook->scrollable && vis_pages > 1 &&
1295 widget->requisition.height < tab_height)
1296 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1298 widget->requisition.width += tab_width;
1300 if (notebook->homogeneous && !notebook->scrollable)
1301 widget->requisition.height =
1302 MAX (widget->requisition.height,
1303 vis_pages * tab_max + TAB_OVERLAP);
1305 widget->requisition.height =
1306 MAX (widget->requisition.height,
1307 tab_height + TAB_OVERLAP);
1309 if (!notebook->homogeneous || notebook->scrollable)
1311 widget->requisition.height = MAX (widget->requisition.height,
1312 vis_pages * tab_max +
1320 for (children = notebook->children; children;
1321 children = children->next)
1323 page = children->data;
1325 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
1326 gtk_widget_hide (page->tab_label);
1331 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1332 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1338 for (children = notebook->children; children;
1339 children = children->next)
1341 page = children->data;
1342 if (GTK_WIDGET_VISIBLE (page->child))
1344 gtk_notebook_switch_page (notebook, page, -1);
1349 else if (GTK_WIDGET_VISIBLE (widget))
1351 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
1352 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
1355 if (vis_pages && !notebook->cur_page)
1357 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1360 notebook->first_tab = children;
1361 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
1367 gtk_notebook_size_allocate (GtkWidget *widget,
1368 GtkAllocation *allocation)
1370 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1373 widget->allocation = *allocation;
1374 if (GTK_WIDGET_REALIZED (widget))
1376 GdkRectangle position;
1378 if (gtk_notebook_get_event_window_position (notebook, &position))
1380 gdk_window_move_resize (notebook->event_window,
1381 position.x, position.y,
1382 position.width, position.height);
1383 if (GTK_WIDGET_MAPPED (notebook))
1384 gdk_window_show_unraised (notebook->event_window);
1387 gdk_window_hide (notebook->event_window);
1390 if (notebook->children)
1392 gint border_width = GTK_CONTAINER (widget)->border_width;
1393 GtkNotebookPage *page;
1394 GtkAllocation child_allocation;
1397 child_allocation.x = widget->allocation.x + border_width;
1398 child_allocation.y = widget->allocation.y + border_width;
1399 child_allocation.width = MAX (1, allocation->width - border_width * 2);
1400 child_allocation.height = MAX (1, allocation->height - border_width * 2);
1402 if (notebook->show_tabs || notebook->show_border)
1404 child_allocation.x += widget->style->xthickness;
1405 child_allocation.y += widget->style->ythickness;
1406 child_allocation.width = MAX (1, child_allocation.width -
1407 widget->style->xthickness * 2);
1408 child_allocation.height = MAX (1, child_allocation.height -
1409 widget->style->ythickness * 2);
1411 if (notebook->show_tabs && notebook->children && notebook->cur_page)
1413 switch (notebook->tab_pos)
1416 child_allocation.y += notebook->cur_page->requisition.height;
1417 case GTK_POS_BOTTOM:
1418 child_allocation.height =
1419 MAX (1, child_allocation.height -
1420 notebook->cur_page->requisition.height);
1423 child_allocation.x += notebook->cur_page->requisition.width;
1425 child_allocation.width =
1426 MAX (1, child_allocation.width -
1427 notebook->cur_page->requisition.width);
1433 children = notebook->children;
1436 page = children->data;
1437 children = children->next;
1439 if (GTK_WIDGET_VISIBLE (page->child))
1441 gtk_widget_size_allocate (page->child, &child_allocation);
1446 gtk_notebook_pages_allocate (notebook);
1449 if ((vis_pages != 0) != notebook->have_visible_child)
1451 notebook->have_visible_child = (vis_pages != 0);
1452 if (notebook->show_tabs)
1453 gtk_widget_queue_draw (widget);
1458 gtk_notebook_expose (GtkWidget *widget,
1459 GdkEventExpose *event)
1461 GtkNotebook *notebook;
1462 GdkRectangle child_area;
1464 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1465 g_return_val_if_fail (event != NULL, FALSE);
1467 if (GTK_WIDGET_DRAWABLE (widget))
1469 notebook = GTK_NOTEBOOK (widget);
1471 gtk_notebook_paint (widget, &event->area);
1472 if (notebook->show_tabs)
1474 if (notebook->cur_page &&
1475 gtk_widget_intersect (notebook->cur_page->tab_label,
1476 &event->area, &child_area))
1477 gtk_notebook_draw_focus (widget);
1481 if (notebook->cur_page)
1482 gtk_container_propagate_expose (GTK_CONTAINER (notebook),
1483 notebook->cur_page->child,
1491 gtk_notebook_show_arrows (GtkNotebook *notebook)
1493 gboolean show_arrow = FALSE;
1496 if (!notebook->scrollable)
1499 children = notebook->children;
1502 GtkNotebookPage *page = children->data;
1504 if (page->tab_label && !gtk_widget_get_child_visible (page->tab_label))
1507 children = children->next;
1514 gtk_notebook_get_arrow_rect (GtkNotebook *notebook,
1515 GdkRectangle *rectangle,
1516 GtkNotebookArrow arrow)
1518 GdkRectangle event_window_pos;
1519 gboolean before = ARROW_IS_BEFORE (arrow);
1520 gboolean left = ARROW_IS_LEFT (arrow);
1522 if (gtk_notebook_get_event_window_position (notebook, &event_window_pos))
1524 rectangle->width = ARROW_SIZE;
1525 rectangle->height = ARROW_SIZE;
1527 switch (notebook->tab_pos)
1531 if ((before && (notebook->has_before_previous != notebook->has_before_next)) ||
1532 (!before && (notebook->has_after_previous != notebook->has_after_next)))
1533 rectangle->x = event_window_pos.x + (event_window_pos.width - rectangle->width) / 2;
1535 rectangle->x = event_window_pos.x + event_window_pos.width / 2 - rectangle->width;
1537 rectangle->x = event_window_pos.x + event_window_pos.width / 2;
1538 rectangle->y = event_window_pos.y;
1540 rectangle->y += event_window_pos.height - rectangle->height;
1543 case GTK_POS_BOTTOM:
1546 if (left || !notebook->has_before_previous)
1547 rectangle->x = event_window_pos.x;
1549 rectangle->x = event_window_pos.x + rectangle->width;
1553 if (!left || !notebook->has_after_next)
1554 rectangle->x = event_window_pos.x + event_window_pos.width - rectangle->width;
1556 rectangle->x = event_window_pos.x + event_window_pos.width - 2 * rectangle->width;
1558 rectangle->y = event_window_pos.y + (event_window_pos.height - rectangle->height) / 2;
1564 static GtkNotebookArrow
1565 gtk_notebook_get_arrow (GtkNotebook *notebook,
1569 GdkRectangle arrow_rect;
1570 GdkRectangle event_window_pos;
1573 GtkNotebookArrow arrow[4];
1575 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
1576 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
1577 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
1578 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
1580 if (gtk_notebook_show_arrows (notebook))
1582 gtk_notebook_get_event_window_position (notebook, &event_window_pos);
1583 for (i = 0; i < 4; i++)
1585 if (arrow[i] == ARROW_NONE)
1588 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, arrow[i]);
1590 x0 = x - arrow_rect.x;
1591 y0 = y - arrow_rect.y;
1593 if (y0 >= 0 && y0 < arrow_rect.height &&
1594 x0 >= 0 && x0 < arrow_rect.width)
1603 gtk_notebook_do_arrow (GtkNotebook *notebook,
1604 GtkNotebookArrow arrow)
1606 GtkWidget *widget = GTK_WIDGET (notebook);
1607 GtkDirectionType dir;
1608 gboolean left = ARROW_IS_LEFT (arrow);
1610 if (!notebook->focus_tab ||
1611 gtk_notebook_search_page (notebook, notebook->focus_tab,
1612 left ? STEP_PREV : STEP_NEXT,
1615 if (notebook->tab_pos == GTK_POS_LEFT ||
1616 notebook->tab_pos == GTK_POS_RIGHT)
1617 dir = left ? GTK_DIR_UP : GTK_DIR_DOWN;
1619 dir = left ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1620 gtk_widget_child_focus (widget, dir);
1625 gtk_notebook_arrow_button_press (GtkNotebook *notebook,
1626 GtkNotebookArrow arrow,
1627 GdkEventButton *event)
1629 GtkWidget *widget = GTK_WIDGET (notebook);
1631 if (!GTK_WIDGET_HAS_FOCUS (widget))
1632 gtk_widget_grab_focus (widget);
1634 notebook->button = event->button;
1635 notebook->click_child = arrow;
1637 if (event->button == 1)
1639 gtk_notebook_do_arrow (notebook, arrow);
1641 if (!notebook->timer)
1643 notebook->timer = g_timeout_add (NOTEBOOK_INIT_SCROLL_DELAY,
1644 (GtkFunction) gtk_notebook_timer,
1645 (gpointer) notebook);
1646 notebook->need_timer = TRUE;
1649 else if (event->button == 2)
1650 gtk_notebook_page_select (notebook, TRUE);
1651 else if (event->button == 3)
1652 gtk_notebook_switch_focus_tab (notebook,
1653 gtk_notebook_search_page (notebook,
1655 ARROW_IS_LEFT (arrow) ? STEP_NEXT : STEP_PREV,
1657 gtk_notebook_redraw_arrows (notebook);
1663 get_widget_coordinates (GtkWidget *widget,
1668 GdkWindow *window = ((GdkEventAny *)event)->window;
1671 if (!gdk_event_get_coords (event, &tx, &ty))
1674 while (window && window != widget->window)
1676 gint window_x, window_y;
1678 gdk_window_get_position (window, &window_x, &window_y);
1682 window = gdk_window_get_parent (window);
1697 gtk_notebook_button_press (GtkWidget *widget,
1698 GdkEventButton *event)
1700 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1701 GtkNotebookPage *page;
1703 GtkNotebookArrow arrow;
1707 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1711 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1714 arrow = gtk_notebook_get_arrow (notebook, x, y);
1716 return gtk_notebook_arrow_button_press (notebook, arrow, event);
1718 if (event->button == 3 && notebook->menu)
1720 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1721 NULL, NULL, 3, event->time);
1725 if (event->button != 1)
1729 children = notebook->children;
1732 page = children->data;
1734 if (GTK_WIDGET_VISIBLE (page->child) &&
1735 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1736 (x >= page->allocation.x) &&
1737 (y >= page->allocation.y) &&
1738 (x <= (page->allocation.x + page->allocation.width)) &&
1739 (y <= (page->allocation.y + page->allocation.height)))
1741 gboolean page_changed = page != notebook->cur_page;
1742 gboolean was_focus = gtk_widget_is_focus (widget);
1744 gtk_notebook_switch_focus_tab (notebook, children);
1745 gtk_widget_grab_focus (widget);
1747 if (page_changed && !was_focus)
1748 gtk_widget_child_focus (page->child, GTK_DIR_TAB_FORWARD);
1752 children = children->next;
1760 stop_scrolling (GtkNotebook *notebook)
1762 if (notebook->timer)
1764 g_source_remove (notebook->timer);
1765 notebook->timer = 0;
1766 notebook->need_timer = FALSE;
1768 notebook->click_child = 0;
1769 notebook->button = 0;
1770 gtk_notebook_redraw_arrows (notebook);
1774 gtk_notebook_button_release (GtkWidget *widget,
1775 GdkEventButton *event)
1777 GtkNotebook *notebook;
1779 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1780 g_return_val_if_fail (event != NULL, FALSE);
1782 if (event->type != GDK_BUTTON_RELEASE)
1785 notebook = GTK_NOTEBOOK (widget);
1787 if (event->button == notebook->button)
1789 stop_scrolling (notebook);
1798 gtk_notebook_enter_notify (GtkWidget *widget,
1799 GdkEventCrossing *event)
1801 GtkNotebook *notebook;
1802 GtkNotebookArrow arrow;
1805 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1806 g_return_val_if_fail (event != NULL, FALSE);
1808 notebook = GTK_NOTEBOOK (widget);
1810 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1813 arrow = gtk_notebook_get_arrow (notebook, x, y);
1815 if (arrow != notebook->in_child)
1817 notebook->in_child = arrow;
1818 gtk_notebook_redraw_arrows (notebook);
1827 gtk_notebook_leave_notify (GtkWidget *widget,
1828 GdkEventCrossing *event)
1830 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1831 GtkNotebookArrow arrow;
1834 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1837 arrow = gtk_notebook_get_arrow (notebook, x, y);
1839 if (notebook->in_child)
1841 notebook->in_child = 0;
1842 gtk_notebook_redraw_arrows (notebook);
1849 gtk_notebook_motion_notify (GtkWidget *widget,
1850 GdkEventMotion *event)
1852 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1853 GtkNotebookArrow arrow;
1856 if (notebook->button)
1859 if (!get_widget_coordinates (widget, (GdkEvent *)event, &x, &y))
1862 arrow = gtk_notebook_get_arrow (notebook, x, y);
1864 if (arrow != notebook->in_child)
1866 notebook->in_child = arrow;
1867 gtk_notebook_redraw_arrows (notebook);
1874 gtk_notebook_grab_notify (GtkWidget *widget,
1875 gboolean was_grabbed)
1878 stop_scrolling (GTK_NOTEBOOK (widget));
1882 gtk_notebook_state_changed (GtkWidget *widget,
1883 GtkStateType previous_state)
1885 if (!GTK_WIDGET_IS_SENSITIVE (widget))
1886 stop_scrolling (GTK_NOTEBOOK (widget));
1890 gtk_notebook_focus_in (GtkWidget *widget,
1891 GdkEventFocus *event)
1893 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1895 return (* GTK_WIDGET_CLASS (parent_class)->focus_in_event) (widget, event);
1899 gtk_notebook_draw_focus (GtkWidget *widget)
1901 GtkNotebook *notebook = GTK_NOTEBOOK (widget);
1903 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1904 notebook->focus_tab)
1906 GtkNotebookPage *page;
1910 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
1912 page = notebook->focus_tab->data;
1914 area.x = page->tab_label->allocation.x - focus_width;
1915 area.y = page->tab_label->allocation.y - focus_width;
1916 area.width = page->tab_label->allocation.width + 2 * focus_width;
1917 area.height = page->tab_label->allocation.height + 2 * focus_width;
1919 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1924 gtk_notebook_style_set (GtkWidget *widget,
1927 GtkNotebook *notebook;
1929 gboolean has_before_previous;
1930 gboolean has_before_next;
1931 gboolean has_after_previous;
1932 gboolean has_after_next;
1934 notebook = GTK_NOTEBOOK (widget);
1936 gtk_widget_style_get (widget,
1937 "has_backward_stepper", &has_before_previous,
1938 "has_secondary_forward_stepper", &has_before_next,
1939 "has_secondary_backward_stepper", &has_after_previous,
1940 "has_forward_stepper", &has_after_next,
1943 notebook->has_before_previous = has_before_previous;
1944 notebook->has_before_next = has_before_next;
1945 notebook->has_after_previous = has_after_previous;
1946 notebook->has_after_next = has_after_next;
1948 (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
1951 /* Private GtkContainer Methods :
1953 * gtk_notebook_set_child_arg
1954 * gtk_notebook_get_child_arg
1956 * gtk_notebook_remove
1957 * gtk_notebook_focus
1958 * gtk_notebook_set_focus_child
1959 * gtk_notebook_child_type
1960 * gtk_notebook_forall
1963 gtk_notebook_set_child_property (GtkContainer *container,
1966 const GValue *value,
1971 GtkPackType pack_type;
1973 /* not finding child's page is valid for menus or labels */
1974 if (!gtk_notebook_find_child (GTK_NOTEBOOK (container), child, NULL))
1977 switch (property_id)
1979 case CHILD_PROP_TAB_LABEL:
1980 /* a NULL pointer indicates a default_tab setting, otherwise
1981 * we need to set the associated label
1983 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1984 g_value_get_string (value));
1986 case CHILD_PROP_MENU_LABEL:
1987 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1988 g_value_get_string (value));
1990 case CHILD_PROP_POSITION:
1991 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1992 g_value_get_int (value));
1994 case CHILD_PROP_TAB_EXPAND:
1995 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1996 &expand, &fill, &pack_type);
1997 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1998 g_value_get_boolean (value),
2001 case CHILD_PROP_TAB_FILL:
2002 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2003 &expand, &fill, &pack_type);
2004 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2006 g_value_get_boolean (value),
2009 case CHILD_PROP_TAB_PACK:
2010 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2011 &expand, &fill, &pack_type);
2012 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
2014 g_value_get_enum (value));
2017 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2023 gtk_notebook_get_child_property (GtkContainer *container,
2030 GtkNotebook *notebook;
2034 GtkPackType pack_type;
2036 notebook = GTK_NOTEBOOK (container);
2038 /* not finding child's page is valid for menus or labels */
2039 list = gtk_notebook_find_child (notebook, child, NULL);
2042 /* nothing to set on labels or menus */
2043 g_param_value_set_default (pspec, value);
2047 switch (property_id)
2049 case CHILD_PROP_TAB_LABEL:
2050 label = gtk_notebook_get_tab_label (notebook, child);
2052 if (label && GTK_IS_LABEL (label))
2053 g_value_set_string (value, GTK_LABEL (label)->label);
2055 g_value_set_string (value, NULL);
2057 case CHILD_PROP_MENU_LABEL:
2058 label = gtk_notebook_get_menu_label (notebook, child);
2060 if (label && GTK_IS_LABEL (label))
2061 g_value_set_string (value, GTK_LABEL (label)->label);
2063 g_value_set_string (value, NULL);
2065 case CHILD_PROP_POSITION:
2066 g_value_set_int (value, g_list_position (notebook->children, list));
2068 case CHILD_PROP_TAB_EXPAND:
2069 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2070 &expand, NULL, NULL);
2071 g_value_set_boolean (value, expand);
2073 case CHILD_PROP_TAB_FILL:
2074 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2076 g_value_set_boolean (value, fill);
2078 case CHILD_PROP_TAB_PACK:
2079 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
2080 NULL, NULL, &pack_type);
2081 g_value_set_enum (value, pack_type);
2084 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2090 gtk_notebook_add (GtkContainer *container,
2093 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2095 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
2100 gtk_notebook_remove (GtkContainer *container,
2103 GtkNotebook *notebook;
2104 GtkNotebookPage *page;
2108 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2109 g_return_if_fail (widget != NULL);
2111 notebook = GTK_NOTEBOOK (container);
2113 children = notebook->children;
2117 page = children->data;
2118 if (page->child == widget)
2120 gtk_notebook_real_remove (notebook, children, FALSE);
2124 children = children->next;
2129 focus_tabs_in (GtkNotebook *notebook)
2131 if (notebook->show_tabs && notebook->cur_page)
2133 gtk_widget_grab_focus (GTK_WIDGET (notebook));
2135 gtk_notebook_switch_focus_tab (notebook,
2136 g_list_find (notebook->children,
2137 notebook->cur_page));
2146 focus_tabs_move (GtkNotebook *notebook,
2147 GtkDirectionType direction,
2148 gint search_direction)
2152 new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
2153 search_direction, TRUE);
2155 gtk_notebook_switch_focus_tab (notebook, new_page);
2157 gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
2163 focus_child_in (GtkNotebook *notebook,
2164 GtkDirectionType direction)
2166 if (notebook->cur_page)
2167 return gtk_widget_child_focus (notebook->cur_page->child, direction);
2172 /* Focus in the notebook can either be on the pages, or on
2176 gtk_notebook_focus (GtkWidget *widget,
2177 GtkDirectionType direction)
2179 GtkWidget *old_focus_child;
2180 GtkNotebook *notebook;
2181 GtkDirectionType effective_direction;
2183 gboolean widget_is_focus;
2184 GtkContainer *container;
2186 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2188 container = GTK_CONTAINER (widget);
2189 notebook = GTK_NOTEBOOK (container);
2191 if (notebook->focus_out)
2193 notebook->focus_out = FALSE; /* Clear this to catch the wrap-around case */
2197 widget_is_focus = gtk_widget_is_focus (widget);
2198 old_focus_child = container->focus_child;
2200 effective_direction = get_effective_direction (notebook, direction);
2202 if (old_focus_child) /* Focus on page child */
2204 if (gtk_widget_child_focus (old_focus_child, direction))
2207 switch (effective_direction)
2209 case GTK_DIR_TAB_BACKWARD:
2211 /* Focus onto the tabs */
2212 return focus_tabs_in (notebook);
2214 case GTK_DIR_TAB_FORWARD:
2220 else if (widget_is_focus) /* Focus was on tabs */
2222 switch (effective_direction)
2224 case GTK_DIR_TAB_BACKWARD:
2227 case GTK_DIR_TAB_FORWARD:
2229 /* We use TAB_FORWARD rather than direction so that we focus a more
2230 * predictable widget for the user; users may be using arrow focusing
2231 * in this situation even if they don't usually use arrow focusing.
2233 return focus_child_in (notebook, GTK_DIR_TAB_FORWARD);
2235 return focus_tabs_move (notebook, direction, STEP_PREV);
2237 return focus_tabs_move (notebook, direction, STEP_NEXT);
2240 else /* Focus was not on widget */
2242 switch (effective_direction)
2244 case GTK_DIR_TAB_FORWARD:
2246 if (focus_tabs_in (notebook))
2248 if (focus_child_in (notebook, direction))
2251 case GTK_DIR_TAB_BACKWARD:
2253 if (focus_child_in (notebook, direction))
2255 if (focus_tabs_in (notebook))
2260 return focus_child_in (notebook, direction);
2264 g_assert_not_reached ();
2269 gtk_notebook_set_focus_child (GtkContainer *container,
2272 GtkNotebook *notebook = GTK_NOTEBOOK (container);
2273 GtkWidget *page_child;
2274 GtkWidget *toplevel;
2276 /* If the old focus widget was within a page of the notebook,
2277 * (child may either be NULL or not in this case), record it
2278 * for future use if we switch to the page with a mnemonic.
2281 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
2282 if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel))
2284 page_child = GTK_WINDOW (toplevel)->focus_widget;
2287 if (page_child->parent == GTK_WIDGET (container))
2289 GList *list = gtk_notebook_find_child (notebook, page_child, NULL);
2292 GtkNotebookPage *page = list->data;
2294 if (page->last_focus_child)
2295 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2297 page->last_focus_child = GTK_WINDOW (toplevel)->focus_widget;
2298 g_object_add_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2304 page_child = page_child->parent;
2310 g_return_if_fail (GTK_IS_WIDGET (child));
2312 notebook->child_has_focus = TRUE;
2313 if (!notebook->focus_tab)
2316 GtkNotebookPage *page;
2318 children = notebook->children;
2321 page = children->data;
2322 if (page->child == child || page->tab_label == child)
2323 gtk_notebook_switch_focus_tab (notebook, children);
2324 children = children->next;
2329 parent_class->set_focus_child (container, child);
2333 gtk_notebook_forall (GtkContainer *container,
2334 gboolean include_internals,
2335 GtkCallback callback,
2336 gpointer callback_data)
2338 GtkNotebook *notebook;
2341 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2342 g_return_if_fail (callback != NULL);
2344 notebook = GTK_NOTEBOOK (container);
2346 children = notebook->children;
2349 GtkNotebookPage *page;
2351 page = children->data;
2352 children = children->next;
2353 (* callback) (page->child, callback_data);
2354 if (include_internals)
2356 if (page->tab_label)
2357 (* callback) (page->tab_label, callback_data);
2358 if (page->menu_label)
2359 (* callback) (page->menu_label, callback_data);
2365 gtk_notebook_child_type (GtkContainer *container)
2367 return GTK_TYPE_WIDGET;
2370 /* Private GtkNotebook Functions:
2372 * gtk_notebook_redraw_tabs
2373 * gtk_notebook_real_remove
2374 * gtk_notebook_update_labels
2375 * gtk_notebook_timer
2376 * gtk_notebook_page_compare
2377 * gtk_notebook_real_page_position
2378 * gtk_notebook_search_page
2381 gtk_notebook_redraw_tabs (GtkNotebook *notebook)
2384 GtkNotebookPage *page;
2385 GdkRectangle redraw_rect;
2388 widget = GTK_WIDGET (notebook);
2389 border = GTK_CONTAINER (notebook)->border_width;
2391 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
2394 page = notebook->first_tab->data;
2396 redraw_rect.x = border;
2397 redraw_rect.y = border;
2399 switch (notebook->tab_pos)
2401 case GTK_POS_BOTTOM:
2402 redraw_rect.y = (widget->allocation.height - border -
2403 page->allocation.height -
2404 widget->style->ythickness);
2405 if (page != notebook->cur_page)
2406 redraw_rect.y -= widget->style->ythickness;
2409 redraw_rect.width = widget->allocation.width - 2 * border;
2410 redraw_rect.height = (page->allocation.height +
2411 widget->style->ythickness);
2412 if (page != notebook->cur_page)
2413 redraw_rect.height += widget->style->ythickness;
2416 redraw_rect.x = (widget->allocation.width - border -
2417 page->allocation.width -
2418 widget->style->xthickness);
2419 if (page != notebook->cur_page)
2420 redraw_rect.x -= widget->style->xthickness;
2423 redraw_rect.width = (page->allocation.width +
2424 widget->style->xthickness);
2425 redraw_rect.height = widget->allocation.height - 2 * border;
2426 if (page != notebook->cur_page)
2427 redraw_rect.width += widget->style->xthickness;
2431 redraw_rect.x += widget->allocation.x;
2432 redraw_rect.y += widget->allocation.y;
2434 gdk_window_invalidate_rect (widget->window, &redraw_rect, TRUE);
2438 gtk_notebook_redraw_arrows (GtkNotebook *notebook)
2440 if (GTK_WIDGET_MAPPED (notebook) && gtk_notebook_show_arrows (notebook))
2444 GtkNotebookArrow arrow[4];
2446 arrow[0] = notebook->has_before_previous ? ARROW_LEFT_BEFORE : ARROW_NONE;
2447 arrow[1] = notebook->has_before_next ? ARROW_RIGHT_BEFORE : ARROW_NONE;
2448 arrow[2] = notebook->has_after_previous ? ARROW_LEFT_AFTER : ARROW_NONE;
2449 arrow[3] = notebook->has_after_next ? ARROW_RIGHT_AFTER : ARROW_NONE;
2451 for (i = 0; i < 4; i++)
2453 if (arrow[i] == ARROW_NONE)
2456 gtk_notebook_get_arrow_rect (notebook, &rect, arrow[i]);
2457 gdk_window_invalidate_rect (GTK_WIDGET (notebook)->window,
2464 gtk_notebook_timer (GtkNotebook *notebook)
2466 gboolean retval = FALSE;
2468 GDK_THREADS_ENTER ();
2470 if (notebook->timer)
2472 gtk_notebook_do_arrow (notebook, notebook->click_child);
2474 if (notebook->need_timer)
2476 notebook->need_timer = FALSE;
2477 notebook->timer = g_timeout_add (NOTEBOOK_SCROLL_DELAY,
2478 (GtkFunction) gtk_notebook_timer,
2479 (gpointer) notebook);
2485 GDK_THREADS_LEAVE ();
2491 gtk_notebook_page_compare (gconstpointer a,
2494 return (((GtkNotebookPage *) a)->child != b);
2498 gtk_notebook_find_child (GtkNotebook *notebook,
2500 const gchar *function)
2502 GList *list = g_list_find_custom (notebook->children, child,
2503 gtk_notebook_page_compare);
2505 #ifndef G_DISABLE_CHECKS
2506 if (!list && function)
2507 g_warning ("%s: unable to find child %p in notebook %p",
2508 function, child, notebook);
2515 gtk_notebook_remove_tab_label (GtkNotebook *notebook,
2516 GtkNotebookPage *page)
2518 if (page->tab_label)
2520 if (page->mnemonic_activate_signal)
2521 g_signal_handler_disconnect (page->tab_label,
2522 page->mnemonic_activate_signal);
2523 page->mnemonic_activate_signal = 0;
2525 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
2526 gtk_widget_unparent (page->tab_label);
2531 gtk_notebook_real_remove (GtkNotebook *notebook,
2533 gboolean destroying)
2535 GtkNotebookPage *page;
2537 gint need_resize = FALSE;
2539 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2541 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2543 if (notebook->cur_page == list->data)
2545 notebook->cur_page = NULL;
2546 if (next_list && !destroying)
2547 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2550 if (list == notebook->first_tab)
2551 notebook->first_tab = next_list;
2552 if (list == notebook->focus_tab && !destroying)
2553 gtk_notebook_switch_focus_tab (notebook, next_list);
2557 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2560 gtk_widget_unparent (page->child);
2562 gtk_notebook_remove_tab_label (notebook, page);
2566 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2567 page->menu_label->parent);
2568 gtk_widget_queue_resize (notebook->menu);
2570 if (!page->default_menu)
2571 g_object_unref (page->menu_label);
2573 notebook->children = g_list_remove_link (notebook->children, list);
2576 if (page->last_focus_child)
2578 g_object_remove_weak_pointer (G_OBJECT (page->last_focus_child), (gpointer *)&page->last_focus_child);
2579 page->last_focus_child = NULL;
2584 gtk_notebook_update_labels (notebook);
2586 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2590 gtk_notebook_update_labels (GtkNotebook *notebook)
2592 GtkNotebookPage *page;
2597 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2599 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2602 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2603 if (notebook->show_tabs)
2605 if (page->default_tab)
2607 if (!page->tab_label)
2609 page->tab_label = gtk_label_new (string);
2610 gtk_widget_set_parent (page->tab_label,
2611 GTK_WIDGET (notebook));
2614 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2617 if (GTK_WIDGET_VISIBLE (page->child) &&
2618 !GTK_WIDGET_VISIBLE (page->tab_label))
2619 gtk_widget_show (page->tab_label);
2620 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2621 GTK_WIDGET_VISIBLE (page->tab_label))
2622 gtk_widget_hide (page->tab_label);
2624 if (notebook->menu && page->default_menu)
2626 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2627 gtk_label_set_text (GTK_LABEL (page->menu_label),
2628 GTK_LABEL (page->tab_label)->label);
2630 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2636 gtk_notebook_real_page_position (GtkNotebook *notebook,
2642 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2643 g_return_val_if_fail (list != NULL, -1);
2645 for (work = notebook->children, count_start = 0;
2646 work && work != list; work = work->next)
2647 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2653 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2656 return (count_start + g_list_length (list) - 1);
2660 gtk_notebook_search_page (GtkNotebook *notebook,
2663 gboolean find_visible)
2665 GtkNotebookPage *page = NULL;
2666 GList *old_list = NULL;
2669 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2674 flag = GTK_PACK_END;
2678 flag = GTK_PACK_START;
2685 if (!page || page->pack == flag)
2693 list = notebook->children;
2698 if (page->pack == flag &&
2699 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2714 if (page->pack != flag &&
2715 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2723 /* Private GtkNotebook Drawing Functions:
2725 * gtk_notebook_paint
2726 * gtk_notebook_draw_tab
2727 * gtk_notebook_draw_arrow
2730 gtk_notebook_paint (GtkWidget *widget,
2733 GtkNotebook *notebook;
2734 GtkNotebookPage *page;
2739 gint border_width = GTK_CONTAINER (widget)->border_width;
2740 gint gap_x = 0, gap_width = 0;
2742 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2743 g_return_if_fail (area != NULL);
2745 if (!GTK_WIDGET_DRAWABLE (widget))
2748 notebook = GTK_NOTEBOOK (widget);
2750 if ((!notebook->show_tabs && !notebook->show_border) ||
2751 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2754 x = widget->allocation.x + border_width;
2755 y = widget->allocation.y + border_width;
2756 width = widget->allocation.width - border_width * 2;
2757 height = widget->allocation.height - border_width * 2;
2759 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2761 gtk_paint_box (widget->style, widget->window,
2762 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2763 area, widget, "notebook",
2764 x, y, width, height);
2769 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2771 page = notebook->first_tab->data;
2773 switch (notebook->tab_pos)
2776 y += page->allocation.height + widget->style->ythickness;
2777 case GTK_POS_BOTTOM:
2778 height -= page->allocation.height + widget->style->ythickness;
2781 x += page->allocation.width + widget->style->xthickness;
2783 width -= page->allocation.width + widget->style->xthickness;
2786 gtk_paint_box (widget->style, widget->window,
2787 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2788 area, widget, "notebook",
2789 x, y, width, height);
2793 switch (notebook->tab_pos)
2796 y += notebook->cur_page->allocation.height;
2797 case GTK_POS_BOTTOM:
2798 height -= notebook->cur_page->allocation.height;
2801 x += notebook->cur_page->allocation.width;
2803 width -= notebook->cur_page->allocation.width;
2807 switch (notebook->tab_pos)
2810 case GTK_POS_BOTTOM:
2811 gap_x = (notebook->cur_page->allocation.x - widget->allocation.x - border_width);
2812 gap_width = notebook->cur_page->allocation.width;
2816 gap_x = (notebook->cur_page->allocation.y - widget->allocation.y - border_width);
2817 gap_width = notebook->cur_page->allocation.height;
2820 gtk_paint_box_gap(widget->style, widget->window,
2821 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2822 area, widget, "notebook",
2823 x, y, width, height,
2824 notebook->tab_pos, gap_x, gap_width);
2828 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2831 page = children->data;
2832 children = gtk_notebook_search_page (notebook, children,
2834 if (!GTK_WIDGET_VISIBLE (page->child))
2836 if (!GTK_WIDGET_MAPPED (page->tab_label))
2838 else if (page != notebook->cur_page)
2839 gtk_notebook_draw_tab (notebook, page, area);
2842 if (showarrow && notebook->scrollable)
2844 if (notebook->has_before_previous)
2845 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
2846 if (notebook->has_before_next)
2847 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
2848 if (notebook->has_after_previous)
2849 gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
2850 if (notebook->has_after_next)
2851 gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
2853 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2857 gtk_notebook_draw_tab (GtkNotebook *notebook,
2858 GtkNotebookPage *page,
2861 GdkRectangle child_area;
2862 GdkRectangle page_area;
2863 GtkStateType state_type;
2864 GtkPositionType gap_side;
2866 g_return_if_fail (notebook != NULL);
2867 g_return_if_fail (page != NULL);
2868 g_return_if_fail (area != NULL);
2870 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2871 (page->allocation.width == 0) || (page->allocation.height == 0))
2874 page_area.x = page->allocation.x;
2875 page_area.y = page->allocation.y;
2876 page_area.width = page->allocation.width;
2877 page_area.height = page->allocation.height;
2879 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2883 widget = GTK_WIDGET (notebook);
2885 switch (notebook->tab_pos)
2888 gap_side = GTK_POS_BOTTOM;
2890 case GTK_POS_BOTTOM:
2891 gap_side = GTK_POS_TOP;
2894 gap_side = GTK_POS_RIGHT;
2897 gap_side = GTK_POS_LEFT;
2901 if (notebook->cur_page == page)
2902 state_type = GTK_STATE_NORMAL;
2904 state_type = GTK_STATE_ACTIVE;
2905 gtk_paint_extension(widget->style, widget->window,
2906 state_type, GTK_SHADOW_OUT,
2907 area, widget, "tab",
2908 page_area.x, page_area.y,
2909 page_area.width, page_area.height,
2911 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2912 notebook->focus_tab && (notebook->focus_tab->data == page))
2916 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
2918 gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2919 area, widget, "tab",
2920 page->tab_label->allocation.x - focus_width,
2921 page->tab_label->allocation.y - focus_width,
2922 page->tab_label->allocation.width + 2 * focus_width,
2923 page->tab_label->allocation.height + 2 * focus_width);
2925 if (gtk_widget_intersect (page->tab_label, area, &child_area) &&
2926 GTK_WIDGET_DRAWABLE (page->tab_label))
2928 GdkEvent *expose_event = gdk_event_new (GDK_EXPOSE);
2930 /* This is a lame hack since all this code needs rewriting anyhow */
2932 expose_event->expose.window = g_object_ref (page->tab_label->window);
2933 expose_event->expose.area = child_area;
2934 expose_event->expose.region = gdk_region_rectangle (&child_area);
2935 expose_event->expose.send_event = TRUE;
2936 expose_event->expose.count = 0;
2938 gtk_container_propagate_expose (GTK_CONTAINER (notebook), page->tab_label, (GdkEventExpose *)expose_event);
2940 gdk_event_free (expose_event);
2946 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2947 GtkNotebookArrow nbarrow)
2949 GtkStateType state_type;
2950 GtkShadowType shadow_type;
2952 GdkRectangle arrow_rect;
2955 gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
2957 widget = GTK_WIDGET (notebook);
2959 if (GTK_WIDGET_DRAWABLE (notebook))
2961 if (notebook->in_child == nbarrow)
2963 if (notebook->click_child == nbarrow)
2964 state_type = GTK_STATE_ACTIVE;
2966 state_type = GTK_STATE_PRELIGHT;
2969 state_type = GTK_WIDGET_STATE (widget);
2971 if (notebook->click_child == nbarrow)
2972 shadow_type = GTK_SHADOW_IN;
2974 shadow_type = GTK_SHADOW_OUT;
2976 if (notebook->focus_tab &&
2977 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2978 ARROW_IS_LEFT (nbarrow) ? STEP_PREV : STEP_NEXT, TRUE))
2980 shadow_type = GTK_SHADOW_ETCHED_IN;
2981 state_type = GTK_STATE_INSENSITIVE;
2984 if (notebook->tab_pos == GTK_POS_LEFT ||
2985 notebook->tab_pos == GTK_POS_RIGHT)
2986 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
2988 arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
2990 gtk_paint_arrow (widget->style, widget->window, state_type,
2991 shadow_type, NULL, widget, "notebook",
2992 arrow, TRUE, arrow_rect.x, arrow_rect.y,
2993 ARROW_SIZE, ARROW_SIZE);
2997 /* Private GtkNotebook Size Allocate Functions:
2999 * gtk_notebook_pages_allocate
3000 * gtk_notebook_page_allocate
3001 * gtk_notebook_calc_tabs
3004 gtk_notebook_pages_allocate (GtkNotebook *notebook)
3006 GtkWidget *widget = GTK_WIDGET (notebook);
3007 GtkContainer *container = GTK_CONTAINER (notebook);
3008 GtkNotebookPage *page = NULL;
3009 GtkAllocation *allocation = &widget->allocation;
3010 GtkAllocation child_allocation;
3011 GList *children = NULL;
3012 GList *last_child = NULL;
3013 gboolean showarrow = FALSE;
3021 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
3024 child_allocation.x = widget->allocation.x + container->border_width;
3025 child_allocation.y = widget->allocation.y + container->border_width;
3027 switch (notebook->tab_pos)
3029 case GTK_POS_BOTTOM:
3030 child_allocation.y = (widget->allocation.y +
3031 allocation->height -
3032 notebook->cur_page->requisition.height -
3033 container->border_width);
3036 child_allocation.height = notebook->cur_page->requisition.height;
3040 child_allocation.x = (widget->allocation.x +
3042 notebook->cur_page->requisition.width -
3043 container->border_width);
3046 child_allocation.width = notebook->cur_page->requisition.width;
3050 if (notebook->scrollable)
3054 children = notebook->children;
3056 if (notebook->focus_tab)
3057 focus_tab = notebook->focus_tab;
3058 else if (notebook->first_tab)
3059 focus_tab = notebook->first_tab;
3061 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
3063 switch (notebook->tab_pos)
3066 case GTK_POS_BOTTOM:
3069 page = children->data;
3070 children = children->next;
3072 if (GTK_WIDGET_VISIBLE (page->child))
3073 tab_space += page->requisition.width;
3076 allocation->width - 2 * container->border_width - TAB_OVERLAP)
3079 page = focus_tab->data;
3081 tab_space = allocation->width - TAB_OVERLAP -
3082 page->requisition.width - 2 * container->border_width;
3083 if (notebook->has_after_previous)
3084 tab_space -= ARROW_SPACING + ARROW_SIZE;
3085 if (notebook->has_after_next)
3086 tab_space -= ARROW_SPACING + ARROW_SIZE;
3087 if (notebook->has_before_previous)
3089 tab_space -= ARROW_SPACING + ARROW_SIZE;
3090 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3092 if (notebook->has_before_next)
3094 tab_space -= ARROW_SPACING + ARROW_SIZE;
3095 child_allocation.x += ARROW_SPACING + ARROW_SIZE;
3103 page = children->data;
3104 children = children->next;
3106 if (GTK_WIDGET_VISIBLE (page->child))
3107 tab_space += page->requisition.height;
3110 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
3113 page = focus_tab->data;
3114 tab_space = allocation->height
3115 - TAB_OVERLAP - 2 * container->border_width
3116 - page->requisition.height;
3117 if (notebook->has_after_previous || notebook->has_after_next)
3118 tab_space -= ARROW_SPACING + ARROW_SIZE;
3119 if (notebook->has_before_previous || notebook->has_before_next)
3121 tab_space -= ARROW_SPACING + ARROW_SIZE;
3122 child_allocation.y += ARROW_SPACING + ARROW_SIZE;
3127 if (showarrow) /* first_tab <- focus_tab */
3131 notebook->first_tab = focus_tab;
3132 last_child = gtk_notebook_search_page (notebook, focus_tab,
3138 if (notebook->first_tab && notebook->first_tab != focus_tab)
3140 /* Is first_tab really predecessor of focus_tab ? */
3141 page = notebook->first_tab->data;
3142 if (GTK_WIDGET_VISIBLE (page->child))
3143 for (children = focus_tab;
3144 children && children != notebook->first_tab;
3145 children = gtk_notebook_search_page (notebook,
3151 notebook->first_tab = focus_tab;
3153 gtk_notebook_calc_tabs (notebook,
3154 gtk_notebook_search_page (notebook,
3158 &(notebook->first_tab), &tab_space,
3163 notebook->first_tab =
3164 gtk_notebook_search_page (notebook, notebook->first_tab,
3166 if (!notebook->first_tab)
3167 notebook->first_tab = focus_tab;
3168 last_child = gtk_notebook_search_page (notebook, focus_tab,
3171 else /* focus_tab -> end */
3173 if (!notebook->first_tab)
3174 notebook->first_tab = gtk_notebook_search_page (notebook,
3179 gtk_notebook_calc_tabs (notebook,
3180 gtk_notebook_search_page (notebook,
3184 &children, &tab_space, STEP_NEXT);
3187 last_child = children;
3188 else /* start <- first_tab */
3192 gtk_notebook_calc_tabs
3194 gtk_notebook_search_page (notebook,
3195 notebook->first_tab,
3198 &children, &tab_space, STEP_PREV);
3199 notebook->first_tab = gtk_notebook_search_page(notebook,
3209 tab_space = -tab_space;
3211 for (children = notebook->first_tab;
3212 children && children != last_child;
3213 children = gtk_notebook_search_page (notebook, children,
3220 /*unmap all non-visible tabs*/
3221 for (children = gtk_notebook_search_page (notebook, NULL,
3223 children && children != notebook->first_tab;
3224 children = gtk_notebook_search_page (notebook, children,
3227 page = children->data;
3228 if (page->tab_label)
3229 gtk_widget_set_child_visible (page->tab_label, FALSE);
3231 for (children = last_child; children;
3232 children = gtk_notebook_search_page (notebook, children,
3235 page = children->data;
3236 if (page->tab_label)
3237 gtk_widget_set_child_visible (page->tab_label, FALSE);
3240 else /* !showarrow */
3242 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3253 children = notebook->children;
3254 switch (notebook->tab_pos)
3257 case GTK_POS_BOTTOM:
3260 page = children->data;
3261 children = children->next;
3263 if (GTK_WIDGET_VISIBLE (page->child))
3266 tab_space += page->requisition.width;
3271 tab_space -= allocation->width;
3277 page = children->data;
3278 children = children->next;
3280 if (GTK_WIDGET_VISIBLE (page->child))
3283 tab_space += page->requisition.height;
3288 tab_space -= allocation->height;
3290 tab_space += 2 * container->border_width + TAB_OVERLAP;
3292 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
3294 if (notebook->homogeneous && n)
3298 children = notebook->first_tab;
3302 if (children == last_child)
3304 /* FIXME double check */
3308 page = children->data;
3309 if (!showarrow && page->pack != GTK_PACK_START)
3311 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
3314 if (n && (showarrow || page->expand || notebook->homogeneous))
3316 new_fill = (tab_space * i++) / n;
3317 delta = new_fill - old_fill;
3318 old_fill = new_fill;
3321 switch (notebook->tab_pos)
3324 case GTK_POS_BOTTOM:
3325 child_allocation.width = (page->requisition.width +
3326 TAB_OVERLAP + delta);
3330 child_allocation.height = (page->requisition.height +
3331 TAB_OVERLAP + delta);
3335 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3337 switch (notebook->tab_pos)
3340 case GTK_POS_BOTTOM:
3341 child_allocation.x += child_allocation.width - TAB_OVERLAP;
3345 child_allocation.y += child_allocation.height - TAB_OVERLAP;
3349 if (page->tab_label)
3350 gtk_widget_set_child_visible (page->tab_label, TRUE);
3355 children = notebook->children;
3356 switch (notebook->tab_pos)
3359 case GTK_POS_BOTTOM:
3360 child_allocation.x = (allocation->x + allocation->width -
3361 container->border_width);
3365 child_allocation.y = (allocation->y + allocation->height -
3366 container->border_width);
3370 while (children != last_child)
3372 page = children->data;
3373 children = children->next;
3375 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
3379 if (n && (page->expand || notebook->homogeneous))
3381 new_fill = (tab_space * i++) / n;
3382 delta = new_fill - old_fill;
3383 old_fill = new_fill;
3386 switch (notebook->tab_pos)
3389 case GTK_POS_BOTTOM:
3390 child_allocation.width = (page->requisition.width +
3391 TAB_OVERLAP + delta);
3392 child_allocation.x -= child_allocation.width;
3396 child_allocation.height = (page->requisition.height +
3397 TAB_OVERLAP + delta);
3398 child_allocation.y -= child_allocation.height;
3402 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3404 switch (notebook->tab_pos)
3407 case GTK_POS_BOTTOM:
3408 child_allocation.x += TAB_OVERLAP;
3412 child_allocation.y += TAB_OVERLAP;
3416 if (page->tab_label)
3417 gtk_widget_set_child_visible (page->tab_label, TRUE);
3422 gtk_notebook_redraw_tabs (notebook);
3426 gtk_notebook_page_allocate (GtkNotebook *notebook,
3427 GtkNotebookPage *page,
3428 GtkAllocation *allocation)
3430 GtkWidget *widget = GTK_WIDGET (notebook);
3431 GtkAllocation child_allocation;
3432 GtkRequisition tab_requisition;
3438 gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
3440 xthickness = widget->style->xthickness;
3441 ythickness = widget->style->ythickness;
3443 /* If the size of the notebook tabs change, we need to queue
3444 * a redraw on the tab area
3446 if ((allocation->width != page->allocation.width) ||
3447 (allocation->height != page->allocation.height))
3449 gint x, y, width, height, border_width;
3451 border_width = GTK_CONTAINER (notebook)->border_width;
3453 switch (notebook->tab_pos)
3456 width = widget->allocation.width;
3457 height = MAX (page->allocation.height, allocation->height) + ythickness;
3462 case GTK_POS_BOTTOM:
3463 width = widget->allocation.width + xthickness;
3464 height = MAX (page->allocation.height, allocation->height) + ythickness;
3466 y = widget->allocation.height - height - border_width;
3470 width = MAX (page->allocation.width, allocation->width) + xthickness;
3471 height = widget->allocation.height;
3477 default: /* quiet gcc */
3478 width = MAX (page->allocation.width, allocation->width) + xthickness;
3479 height = widget->allocation.height;
3480 x = widget->allocation.width - width - border_width;
3485 gtk_widget_queue_draw_area (widget, x, y, width, height);
3488 page->allocation = *allocation;
3489 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3491 if (notebook->cur_page != page)
3493 switch (notebook->tab_pos)
3496 page->allocation.y += ythickness;
3497 case GTK_POS_BOTTOM:
3498 if (page->allocation.height > ythickness)
3499 page->allocation.height -= ythickness;
3502 page->allocation.x += xthickness;
3504 if (page->allocation.width > xthickness)
3505 page->allocation.width -= xthickness;
3510 switch (notebook->tab_pos)
3513 case GTK_POS_BOTTOM:
3514 padding = TAB_CURVATURE + focus_width + notebook->tab_hborder;
3517 child_allocation.x = (xthickness + focus_width +
3518 notebook->tab_hborder);
3519 child_allocation.width = MAX (1, (page->allocation.width -
3520 2 * child_allocation.x));
3521 child_allocation.x += page->allocation.x;
3525 child_allocation.x = (page->allocation.x +
3526 (page->allocation.width -
3527 tab_requisition.width) / 2);
3528 child_allocation.width = tab_requisition.width;
3530 child_allocation.y = (notebook->tab_vborder + focus_width +
3531 page->allocation.y);
3532 if (notebook->tab_pos == GTK_POS_TOP)
3533 child_allocation.y += ythickness;
3534 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3535 2 * (notebook->tab_vborder + focus_width)));
3539 padding = TAB_CURVATURE + focus_width + notebook->tab_vborder;
3542 child_allocation.y = ythickness + padding;
3543 child_allocation.height = MAX (1, (page->allocation.height -
3544 2 * child_allocation.y));
3545 child_allocation.y += page->allocation.y;
3549 child_allocation.y = (page->allocation.y + (page->allocation.height -
3550 tab_requisition.height) / 2);
3551 child_allocation.height = tab_requisition.height;
3553 child_allocation.x = page->allocation.x + notebook->tab_hborder + focus_width;
3554 if (notebook->tab_pos == GTK_POS_LEFT)
3555 child_allocation.x += xthickness;
3556 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3557 2 * (notebook->tab_hborder + focus_width)));
3561 if (page->tab_label)
3562 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3566 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3572 GtkNotebookPage *page = NULL;
3574 GList *last_list = NULL;
3581 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3582 if (pack == GTK_PACK_END)
3583 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3587 switch (notebook->tab_pos)
3590 case GTK_POS_BOTTOM:
3593 page = children->data;
3594 if (GTK_WIDGET_VISIBLE (page->child))
3596 if (page->pack == pack)
3598 *tab_space -= page->requisition.width;
3599 if (*tab_space < 0 || children == *end)
3603 *tab_space = - (*tab_space +
3604 page->requisition.width);
3610 last_list = children;
3612 if (direction == STEP_NEXT)
3613 children = children->next;
3615 children = children->prev;
3622 page = children->data;
3623 if (GTK_WIDGET_VISIBLE (page->child))
3625 if (page->pack == pack)
3627 *tab_space -= page->requisition.height;
3628 if (*tab_space < 0 || children == *end)
3632 *tab_space = - (*tab_space +
3633 page->requisition.height);
3639 last_list = children;
3641 if (direction == STEP_NEXT)
3642 children = children->next;
3644 children = children->prev;
3648 if (direction == STEP_PREV)
3650 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3651 direction = STEP_PREV;
3652 children = last_list;
3657 gtk_notebook_update_tab_states (GtkNotebook *notebook)
3661 for (list = notebook->children; list != NULL; list = list->next)
3663 GtkNotebookPage *page = list->data;
3665 if (page->tab_label)
3667 if (page == notebook->cur_page)
3668 gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
3670 gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
3675 /* Private GtkNotebook Page Switch Methods:
3677 * gtk_notebook_real_switch_page
3680 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3681 GtkNotebookPage *page,
3684 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3685 g_return_if_fail (page != NULL);
3687 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3690 if (notebook->cur_page)
3691 gtk_widget_set_child_visible (notebook->cur_page->child, FALSE);
3693 notebook->cur_page = page;
3695 if (!notebook->focus_tab ||
3696 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3697 notebook->focus_tab =
3698 g_list_find (notebook->children, notebook->cur_page);
3700 gtk_widget_set_child_visible (notebook->cur_page->child, TRUE);
3702 /* If the focus was on the previous page, move it to the first
3703 * element on the new page, if possible, or if not, to the
3706 if (notebook->child_has_focus)
3708 if (notebook->cur_page->last_focus_child &&
3709 gtk_widget_is_ancestor (notebook->cur_page->last_focus_child, notebook->cur_page->child))
3710 gtk_widget_grab_focus (notebook->cur_page->last_focus_child);
3712 if (!gtk_widget_child_focus (notebook->cur_page->child, GTK_DIR_TAB_FORWARD))
3713 gtk_widget_grab_focus (GTK_WIDGET (notebook));
3716 gtk_notebook_update_tab_states (notebook);
3717 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3718 g_object_notify (G_OBJECT (notebook), "page");
3721 /* Private GtkNotebook Page Switch Functions:
3723 * gtk_notebook_switch_page
3724 * gtk_notebook_page_select
3725 * gtk_notebook_switch_focus_tab
3726 * gtk_notebook_menu_switch_page
3729 gtk_notebook_switch_page (GtkNotebook *notebook,
3730 GtkNotebookPage *page,
3733 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3734 g_return_if_fail (page != NULL);
3736 if (notebook->cur_page == page)
3740 page_num = g_list_index (notebook->children, page);
3742 g_signal_emit (notebook,
3743 notebook_signals[SWITCH_PAGE],
3750 gtk_notebook_page_select (GtkNotebook *notebook,
3751 gboolean move_focus)
3753 GtkNotebookPage *page;
3754 GtkDirectionType dir = GTK_DIR_DOWN; /* Quiet GCC */
3756 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3758 if (!notebook->focus_tab)
3761 page = notebook->focus_tab->data;
3762 gtk_notebook_switch_page (notebook, page, -1);
3766 switch (notebook->tab_pos)
3771 case GTK_POS_BOTTOM:
3775 dir = GTK_DIR_RIGHT;
3782 if (gtk_widget_child_focus (page->child, dir))
3789 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3793 GtkNotebookPage *old_page = NULL;
3794 GtkNotebookPage *page;
3796 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3798 if (notebook->focus_tab == new_child)
3801 old_child = notebook->focus_tab;
3802 notebook->focus_tab = new_child;
3804 if (notebook->scrollable)
3805 gtk_notebook_redraw_arrows (notebook);
3807 if (!notebook->show_tabs || !notebook->focus_tab)
3811 old_page = old_child->data;
3813 page = notebook->focus_tab->data;
3814 if (GTK_WIDGET_MAPPED (page->tab_label))
3815 gtk_notebook_redraw_tabs (notebook);
3817 gtk_notebook_pages_allocate (notebook);
3819 gtk_notebook_switch_page (notebook, page,
3820 g_list_index (notebook->children, page));
3824 gtk_notebook_menu_switch_page (GtkWidget *widget,
3825 GtkNotebookPage *page)
3827 GtkNotebook *notebook;
3831 g_return_if_fail (widget != NULL);
3832 g_return_if_fail (page != NULL);
3834 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3835 (GTK_MENU (widget->parent)));
3837 if (notebook->cur_page == page)
3841 children = notebook->children;
3842 while (children && children->data != page)
3844 children = children->next;
3848 g_signal_emit (notebook,
3849 notebook_signals[SWITCH_PAGE],
3855 /* Private GtkNotebook Menu Functions:
3857 * gtk_notebook_menu_item_create
3858 * gtk_notebook_menu_label_unparent
3859 * gtk_notebook_menu_detacher
3862 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3865 GtkNotebookPage *page;
3866 GtkWidget *menu_item;
3869 if (page->default_menu)
3871 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3872 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3874 page->menu_label = gtk_label_new ("");
3875 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3878 gtk_widget_show (page->menu_label);
3879 menu_item = gtk_menu_item_new ();
3880 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3881 gtk_menu_shell_insert (GTK_MENU_SHELL (notebook->menu), menu_item,
3882 gtk_notebook_real_page_position (notebook, list));
3883 g_signal_connect (menu_item, "activate",
3884 G_CALLBACK (gtk_notebook_menu_switch_page), page);
3885 if (GTK_WIDGET_VISIBLE (page->child))
3886 gtk_widget_show (menu_item);
3890 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3893 gtk_widget_unparent (GTK_BIN(widget)->child);
3894 GTK_BIN(widget)->child = NULL;
3898 gtk_notebook_menu_detacher (GtkWidget *widget,
3901 GtkNotebook *notebook;
3903 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3905 notebook = GTK_NOTEBOOK (widget);
3906 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3908 notebook->menu = NULL;
3911 /* Private GtkNotebook Setter Functions:
3913 * gtk_notebook_set_homogeneous_tabs_internal
3914 * gtk_notebook_set_tab_border_internal
3915 * gtk_notebook_set_tab_hborder_internal
3916 * gtk_notebook_set_tab_vborder_internal
3919 gtk_notebook_set_homogeneous_tabs_internal (GtkNotebook *notebook,
3920 gboolean homogeneous)
3922 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3924 if (homogeneous == notebook->homogeneous)
3927 notebook->homogeneous = homogeneous;
3928 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3930 g_object_notify (G_OBJECT (notebook), "homogeneous");
3934 gtk_notebook_set_tab_border_internal (GtkNotebook *notebook,
3937 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3939 notebook->tab_hborder = border_width;
3940 notebook->tab_vborder = border_width;
3942 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3943 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3945 g_object_freeze_notify (G_OBJECT (notebook));
3946 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3947 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3948 g_object_thaw_notify (G_OBJECT (notebook));
3952 gtk_notebook_set_tab_hborder_internal (GtkNotebook *notebook,
3955 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3957 if (notebook->tab_hborder == tab_hborder)
3960 notebook->tab_hborder = tab_hborder;
3962 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3963 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3965 g_object_notify (G_OBJECT (notebook), "tab_hborder");
3969 gtk_notebook_set_tab_vborder_internal (GtkNotebook *notebook,
3972 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3974 if (notebook->tab_vborder == tab_vborder)
3977 notebook->tab_vborder = tab_vborder;
3979 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3980 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3982 g_object_notify (G_OBJECT (notebook), "tab_vborder");
3985 /* Public GtkNotebook Page Insert/Remove Methods :
3987 * gtk_notebook_append_page
3988 * gtk_notebook_append_page_menu
3989 * gtk_notebook_prepend_page
3990 * gtk_notebook_prepend_page_menu
3991 * gtk_notebook_insert_page
3992 * gtk_notebook_insert_page_menu
3993 * gtk_notebook_remove_page
3996 * gtk_notebook_append_page:
3997 * @notebook: a #GtkNotebook
3998 * @child: the #GtkWidget to use as the contents of the page.
3999 * @tab_label: the #GtkWidget to be used as the label for the page,
4000 * or %NULL to use the default label, 'page N'.
4002 * Appends a page to @notebook.
4005 gtk_notebook_append_page (GtkNotebook *notebook,
4007 GtkWidget *tab_label)
4009 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4010 g_return_if_fail (GTK_IS_WIDGET (child));
4011 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4013 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
4017 * gtk_notebook_append_page_menu:
4018 * @notebook: a #GtkNotebook
4019 * @child: the #GtkWidget to use as the contents of the page.
4020 * @tab_label: the #GtkWidget to be used as the label for the page,
4021 * or %NULL to use the default label, 'page N'.
4022 * @menu_label: the widget to use as a label for the page-switch
4023 * menu, if that is enabled. If %NULL, and @tab_label
4024 * is a #GtkLabel or %NULL, then the menu label will be
4025 * a newly created label with the same text as @tab_label;
4026 * If @tab_label is not a #GtkLabel, @menu_label must be
4027 * specified if the page-switch menu is to be used.
4029 * Appends a page to @notebook, specifying the widget to use as the
4030 * label in the popup menu.
4033 gtk_notebook_append_page_menu (GtkNotebook *notebook,
4035 GtkWidget *tab_label,
4036 GtkWidget *menu_label)
4038 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4039 g_return_if_fail (GTK_IS_WIDGET (child));
4040 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4041 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4043 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
4047 * gtk_notebook_prepend_page:
4048 * @notebook: a #GtkNotebook
4049 * @child: the #GtkWidget to use as the contents of the page.
4050 * @tab_label: the #GtkWidget to be used as the label for the page,
4051 * or %NULL to use the default label, 'page N'.
4053 * Prepends a page to @notebook.
4056 gtk_notebook_prepend_page (GtkNotebook *notebook,
4058 GtkWidget *tab_label)
4060 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4061 g_return_if_fail (GTK_IS_WIDGET (child));
4062 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4064 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
4068 * gtk_notebook_prepend_page_menu:
4069 * @notebook: a #GtkNotebook
4070 * @child: the #GtkWidget to use as the contents of the page.
4071 * @tab_label: the #GtkWidget to be used as the label for the page,
4072 * or %NULL to use the default label, 'page N'.
4073 * @menu_label: the widget to use as a label for the page-switch
4074 * menu, if that is enabled. If %NULL, and @tab_label
4075 * is a #GtkLabel or %NULL, then the menu label will be
4076 * a newly created label with the same text as @tab_label;
4077 * If @tab_label is not a #GtkLabel, @menu_label must be
4078 * specified if the page-switch menu is to be used.
4080 * Prepends a page to @notebook, specifying the widget to use as the
4081 * label in the popup menu.
4084 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
4086 GtkWidget *tab_label,
4087 GtkWidget *menu_label)
4089 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4090 g_return_if_fail (GTK_IS_WIDGET (child));
4091 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4092 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4094 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
4098 * gtk_notebook_insert_page:
4099 * @notebook: a #GtkNotebook
4100 * @child: the #GtkWidget to use as the contents of the page.
4101 * @tab_label: the #GtkWidget to be used as the label for the page,
4102 * or %NULL to use the default label, 'page N'.
4103 * @position: the index (starting at 0) at which to insert the page,
4104 * or -1 to append the page after all other pages.
4106 * Insert a page into @notebook at the given position
4109 gtk_notebook_insert_page (GtkNotebook *notebook,
4111 GtkWidget *tab_label,
4114 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4115 g_return_if_fail (GTK_IS_WIDGET (child));
4116 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4118 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
4123 gtk_notebook_page_compare_tab (gconstpointer a,
4126 return (((GtkNotebookPage *) a)->tab_label != b);
4130 gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
4134 GtkNotebook *notebook = GTK_NOTEBOOK (data);
4137 list = g_list_find_custom (notebook->children, child,
4138 gtk_notebook_page_compare_tab);
4141 GtkNotebookPage *page = list->data;
4143 gtk_widget_grab_focus (GTK_WIDGET (notebook)); /* Do this first to avoid focusing new page */
4144 gtk_notebook_switch_page (notebook, page, -1);
4145 focus_tabs_in (notebook);
4152 * gtk_notebook_insert_page_menu:
4153 * @notebook: a #GtkNotebook
4154 * @child: the #GtkWidget to use as the contents of the page.
4155 * @tab_label: the #GtkWidget to be used as the label for the page,
4156 * or %NULL to use the default label, 'page N'.
4157 * @menu_label: the widget to use as a label for the page-switch
4158 * menu, if that is enabled. If %NULL, and @tab_label
4159 * is a #GtkLabel or %NULL, then the menu label will be
4160 * a newly created label with the same text as @tab_label;
4161 * If @tab_label is not a #GtkLabel, @menu_label must be
4162 * specified if the page-switch menu is to be used.
4163 * @position: the index (starting at 0) at which to insert the page,
4164 * or -1 to append the page after all other pages.
4166 * Insert a page into @notebook at the given position, specifying
4167 * the widget to use as the label in the popup menu.
4170 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
4172 GtkWidget *tab_label,
4173 GtkWidget *menu_label,
4176 GtkNotebookPage *page;
4179 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4180 g_return_if_fail (GTK_IS_WIDGET (child));
4181 g_return_if_fail (tab_label == NULL || GTK_IS_WIDGET (tab_label));
4182 g_return_if_fail (menu_label == NULL || GTK_IS_WIDGET (menu_label));
4184 gtk_widget_freeze_child_notify (child);
4186 page = g_new (GtkNotebookPage, 1);
4187 page->child = child;
4188 page->last_focus_child = NULL;
4189 page->requisition.width = 0;
4190 page->requisition.height = 0;
4191 page->allocation.x = 0;
4192 page->allocation.y = 0;
4193 page->allocation.width = 0;
4194 page->allocation.height = 0;
4195 page->default_menu = FALSE;
4196 page->default_tab = FALSE;
4197 page->mnemonic_activate_signal = 0;
4199 nchildren = g_list_length (notebook->children);
4200 if ((position < 0) || (position > nchildren))
4201 position = nchildren;
4203 notebook->children = g_list_insert (notebook->children, page, position);
4207 page->default_tab = TRUE;
4208 if (notebook->show_tabs)
4209 tab_label = gtk_label_new ("");
4211 page->tab_label = tab_label;
4212 page->menu_label = menu_label;
4213 page->expand = FALSE;
4215 page->pack = GTK_PACK_START;
4218 page->default_menu = TRUE;
4221 g_object_ref (page->menu_label);
4222 gtk_object_sink (GTK_OBJECT (page->menu_label));
4226 gtk_notebook_menu_item_create (notebook,
4227 g_list_find (notebook->children, page));
4229 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
4231 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
4233 gtk_notebook_update_labels (notebook);
4235 if (!notebook->first_tab)
4236 notebook->first_tab = notebook->children;
4238 if (!notebook->cur_page)
4239 gtk_widget_set_child_visible (child, TRUE);
4241 gtk_widget_set_child_visible (child, FALSE);
4245 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4246 gtk_widget_show (tab_label);
4248 gtk_widget_hide (tab_label);
4251 if (!notebook->cur_page)
4253 gtk_notebook_switch_page (notebook, page, 0);
4254 gtk_notebook_switch_focus_tab (notebook, NULL);
4257 gtk_notebook_update_tab_states (notebook);
4260 page->mnemonic_activate_signal =
4261 g_signal_connect (tab_label,
4262 "mnemonic_activate",
4263 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4266 gtk_widget_child_notify (child, "tab_expand");
4267 gtk_widget_child_notify (child, "tab_fill");
4268 gtk_widget_child_notify (child, "tab_pack");
4269 gtk_widget_child_notify (child, "tab_label");
4270 gtk_widget_child_notify (child, "menu_label");
4271 gtk_widget_child_notify (child, "position");
4272 gtk_widget_thaw_child_notify (child);
4276 * gtk_notebook_remove_page:
4277 * @notebook: a #GtkNotebook.
4278 * @page_num: the index of a notebook page, starting
4279 * from 0. If -1, the last page will
4282 * Removes a page from the notebook given its index
4286 gtk_notebook_remove_page (GtkNotebook *notebook,
4291 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4295 list = g_list_nth (notebook->children, page_num);
4297 gtk_notebook_real_remove (notebook, list, FALSE);
4301 list = g_list_last (notebook->children);
4303 gtk_notebook_real_remove (notebook, list, FALSE);
4307 /* Public GtkNotebook Page Switch Methods :
4308 * gtk_notebook_get_current_page
4309 * gtk_notebook_page_num
4310 * gtk_notebook_set_current_page
4311 * gtk_notebook_next_page
4312 * gtk_notebook_prev_page
4315 * gtk_notebook_get_current_page:
4316 * @notebook: a #GtkNotebook
4318 * Returns the page number of the current page.
4320 * Return value: the index (starting from 0) of the current
4321 * page in the notebook. If the notebook has no pages, then
4322 * -1 will be returned.
4325 gtk_notebook_get_current_page (GtkNotebook *notebook)
4327 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4329 if (!notebook->cur_page)
4332 return g_list_index (notebook->children, notebook->cur_page);
4336 * gtk_notebook_get_nth_page:
4337 * @notebook: a #GtkNotebook
4338 * @page_num: the index of a page in the noteobok, or -1
4339 * to get the last page.
4341 * Returns the child widget contained in page number @page_num.
4343 * Return value: the child widget, or %NULL if @page_num is
4347 gtk_notebook_get_nth_page (GtkNotebook *notebook,
4350 GtkNotebookPage *page;
4353 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4356 list = g_list_nth (notebook->children, page_num);
4358 list = g_list_last (notebook->children);
4370 * gtk_notebook_get_n_pages:
4371 * @notebook: a #GtkNotebook
4373 * Gets the number of pages in a notebook.
4375 * Return value: the number of pages in the notebook.
4380 gtk_notebook_get_n_pages (GtkNotebook *notebook)
4382 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), 0);
4384 return g_list_length (notebook->children);
4388 * gtk_notebook_page_num:
4389 * @notebook: a #GtkNotebook
4390 * @child: a #GtkWidget
4392 * Finds the index of the page which contains the given child
4395 * Return value: the index of the page containing @child, or
4396 * -1 if @child is not in the notebook.
4399 gtk_notebook_page_num (GtkNotebook *notebook,
4405 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
4408 children = notebook->children;
4411 GtkNotebookPage *page = children->data;
4413 if (page->child == child)
4416 children = children->next;
4424 * gtk_notebook_set_current_page:
4425 * @notebook: a #GtkNotebook
4426 * @page_num: index of the page to switch to, starting from 0.
4427 * If negative, the last page will be used. If greater
4428 * than the number of pages in the notebook, nothing
4431 * Switches to the page number @page_num.
4434 gtk_notebook_set_current_page (GtkNotebook *notebook,
4439 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4442 list = g_list_nth (notebook->children, page_num);
4444 list = g_list_last (notebook->children);
4446 page_num = g_list_index (notebook->children, list);
4449 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
4453 * gtk_notebook_next_page:
4454 * @notebook: a #GtkNotebook
4456 * Switches to the next page. Nothing happens if the current page is
4460 gtk_notebook_next_page (GtkNotebook *notebook)
4464 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4466 list = g_list_find (notebook->children, notebook->cur_page);
4470 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
4474 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4478 * gtk_notebook_prev_page:
4479 * @notebook: a #GtkNotebook
4481 * Switches to the previous page. Nothing happens if the current page
4482 * is the first page.
4485 gtk_notebook_prev_page (GtkNotebook *notebook)
4489 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4491 list = g_list_find (notebook->children, notebook->cur_page);
4495 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
4499 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
4502 /* Public GtkNotebook/Tab Style Functions
4504 * gtk_notebook_set_show_border
4505 * gtk_notebook_set_show_tabs
4506 * gtk_notebook_set_tab_pos
4507 * gtk_notebook_set_homogeneous_tabs
4508 * gtk_notebook_set_tab_border
4509 * gtk_notebook_set_tab_hborder
4510 * gtk_notebook_set_tab_vborder
4511 * gtk_notebook_set_scrollable
4514 * gtk_notebook_set_show_border:
4515 * @notebook: a #GtkNotebook
4516 * @show_border: %TRUE if a bevel should be drawn around the notebook.
4518 * Sets whether a bevel will be drawn around the notebook pages.
4519 * This only has a visual effect when the tabs are not shown.
4520 * See gtk_notebook_set_show_tabs().
4523 gtk_notebook_set_show_border (GtkNotebook *notebook,
4524 gboolean show_border)
4526 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4528 if (notebook->show_border != show_border)
4530 notebook->show_border = show_border;
4532 if (GTK_WIDGET_VISIBLE (notebook))
4533 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4535 g_object_notify (G_OBJECT (notebook), "show_border");
4540 * gtk_notebook_get_show_border:
4541 * @notebook: a #GtkNotebook
4543 * Returns whether a bevel will be drawn around the notebook pages. See
4544 * gtk_notebook_set_show_border().
4546 * Return value: %TRUE if the bevel is drawn
4549 gtk_notebook_get_show_border (GtkNotebook *notebook)
4551 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4553 return notebook->show_border;
4557 * gtk_notebook_set_show_tabs:
4558 * @notebook: a #GtkNotebook
4559 * @show_tabs: %TRUE if the tabs should be shown.
4561 * Sets whether to show the tabs for the notebook or not.
4564 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
4567 GtkNotebookPage *page;
4570 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4572 show_tabs = show_tabs != FALSE;
4574 if (notebook->show_tabs == show_tabs)
4577 notebook->show_tabs = show_tabs;
4578 children = notebook->children;
4582 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
4586 page = children->data;
4587 children = children->next;
4588 if (page->default_tab)
4590 gtk_widget_destroy (page->tab_label);
4591 page->tab_label = NULL;
4594 gtk_widget_hide (page->tab_label);
4599 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
4600 gtk_notebook_update_labels (notebook);
4602 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4604 g_object_notify (G_OBJECT (notebook), "show_tabs");
4608 * gtk_notebook_get_show_tabs:
4609 * @notebook: a #GtkNotebook
4611 * Returns whether the tabs of the notebook are shown. See
4612 * gtk_notebook_set_show_tabs().
4614 * Return value: %TRUE if the tabs are shown
4617 gtk_notebook_get_show_tabs (GtkNotebook *notebook)
4619 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4621 return notebook->show_tabs;
4625 * gtk_notebook_set_tab_pos:
4626 * @notebook: a #GtkNotebook.
4627 * @pos: the edge to draw the tabs at.
4629 * Sets the edge at which the tabs for switching pages in the
4630 * notebook are drawn.
4633 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
4634 GtkPositionType pos)
4636 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4638 if (notebook->tab_pos != pos)
4640 notebook->tab_pos = pos;
4641 if (GTK_WIDGET_VISIBLE (notebook))
4642 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4645 g_object_notify (G_OBJECT (notebook), "tab_pos");
4649 * gtk_notebook_get_tab_pos:
4650 * @notebook: a #GtkNotebook
4652 * Gets the edge at which the tabs for switching pages in the
4653 * notebook are drawn.
4655 * Return value: the edge at which the tabs are drawn
4658 gtk_notebook_get_tab_pos (GtkNotebook *notebook)
4660 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), GTK_POS_TOP);
4662 return notebook->tab_pos;
4666 * gtk_notebook_set_homogeneous_tabs:
4667 * @notebook: a #GtkNotebook
4668 * @homogeneous: %TRUE if all tabs should be the same size.
4670 * Sets whether the tabs must have all the same size or not.
4673 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
4674 gboolean homogeneous)
4676 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4678 gtk_notebook_set_homogeneous_tabs_internal (notebook, homogeneous);
4682 * gtk_notebook_set_tab_border:
4683 * @notebook: a #GtkNotebook
4684 * @border_width: width of the border around the tab labels.
4686 * Sets the width the border around the tab labels
4687 * in a notebook. This is equivalent to calling
4688 * gtk_notebook_set_tab_hborder (@notebook, @border_width) followed
4689 * by gtk_notebook_set_tab_vborder (@notebook, @border_width).
4692 gtk_notebook_set_tab_border (GtkNotebook *notebook,
4695 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4697 gtk_notebook_set_tab_border_internal (notebook, border_width);
4701 * gtk_notebook_set_tab_hborder:
4702 * @notebook: a #GtkNotebook
4703 * @tab_hborder: width of the horizontal border of tab labels.
4705 * Sets the width of the horizontal border of tab labels.
4708 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
4711 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4713 gtk_notebook_set_tab_hborder_internal (notebook, tab_hborder);
4717 * gtk_notebook_set_tab_vborder:
4718 * @notebook: a #GtkNotebook
4719 * @tab_vborder: width of the vertical border of tab labels.
4721 * Sets the width of the vertical border of tab labels.
4724 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
4727 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4729 gtk_notebook_set_tab_vborder_internal (notebook, tab_vborder);
4733 * gtk_notebook_set_scrollable:
4734 * @notebook: a #GtkNotebook
4735 * @scrollable: %TRUE if scroll arrows should be added
4737 * Sets whether the tab label area will have arrows for scrolling if
4738 * there are too many tabs to fit in the area.
4741 gtk_notebook_set_scrollable (GtkNotebook *notebook,
4742 gboolean scrollable)
4744 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4746 scrollable = (scrollable != FALSE);
4748 if (scrollable != notebook->scrollable)
4750 notebook->scrollable = scrollable;
4752 if (GTK_WIDGET_VISIBLE (notebook))
4753 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4755 g_object_notify (G_OBJECT (notebook), "scrollable");
4760 * gtk_notebook_get_scrollable:
4761 * @notebook: a #GtkNotebook
4763 * Returns whether the tab label area has arrows for scrolling. See
4764 * gtk_notebook_set_scrollable().
4766 * Return value: %TRUE if arrows for scrolling are present
4769 gtk_notebook_get_scrollable (GtkNotebook *notebook)
4771 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
4773 return notebook->scrollable;
4776 /* Public GtkNotebook Popup Menu Methods:
4778 * gtk_notebook_popup_enable
4779 * gtk_notebook_popup_disable
4784 * gtk_notebook_popup_enable:
4785 * @notebook: a #GtkNotebook
4787 * Enables the popup menu: if the user clicks with the right mouse button on
4788 * the bookmarks, a menu with all the pages will be popped up.
4791 gtk_notebook_popup_enable (GtkNotebook *notebook)
4795 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4800 notebook->menu = gtk_menu_new ();
4801 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4803 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4804 gtk_notebook_menu_item_create (notebook, list);
4806 gtk_notebook_update_labels (notebook);
4807 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4808 GTK_WIDGET (notebook),
4809 gtk_notebook_menu_detacher);
4811 g_object_notify (G_OBJECT (notebook), "enable_popup");
4815 * gtk_notebook_popup_disable:
4816 * @notebook: a #GtkNotebook
4818 * Disables the popup menu.
4821 gtk_notebook_popup_disable (GtkNotebook *notebook)
4823 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4825 if (!notebook->menu)
4828 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4829 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4830 gtk_widget_destroy (notebook->menu);
4832 g_object_notify (G_OBJECT (notebook), "enable_popup");
4835 /* Public GtkNotebook Page Properties Functions:
4837 * gtk_notebook_get_tab_label
4838 * gtk_notebook_set_tab_label
4839 * gtk_notebook_set_tab_label_text
4840 * gtk_notebook_get_menu_label
4841 * gtk_notebook_set_menu_label
4842 * gtk_notebook_set_menu_label_text
4843 * gtk_notebook_set_tab_label_packing
4844 * gtk_notebook_query_tab_label_packing
4848 * gtk_notebook_get_tab_label:
4849 * @notebook: a #GtkNotebook
4852 * Returns the tab label widget for the page @child. %NULL is returned
4853 * if @child is not in @notebook or if no tab label has specifically
4854 * been set for @child.
4856 * Return value: the tab label
4859 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4864 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4865 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4867 list = CHECK_FIND_CHILD (notebook, child);
4871 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4874 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4878 * gtk_notebook_set_tab_label:
4879 * @notebook: a #GtkNotebook
4881 * @tab_label: the tab label widget to use, or %NULL for default tab
4884 * Changes the tab label for @child. If %NULL is specified
4885 * for @tab_label, then the page will have the label 'page N'.
4888 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4890 GtkWidget *tab_label)
4892 GtkNotebookPage *page;
4895 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4896 g_return_if_fail (GTK_IS_WIDGET (child));
4898 list = CHECK_FIND_CHILD (notebook, child);
4902 /* a NULL pointer indicates a default_tab setting, otherwise
4903 * we need to set the associated label
4907 if (page->tab_label == tab_label)
4911 gtk_notebook_remove_tab_label (notebook, page);
4915 page->default_tab = FALSE;
4916 page->tab_label = tab_label;
4917 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4921 page->default_tab = TRUE;
4922 page->tab_label = NULL;
4924 if (notebook->show_tabs)
4928 g_snprintf (string, sizeof(string), _("Page %u"),
4929 gtk_notebook_real_page_position (notebook, list));
4930 page->tab_label = gtk_label_new (string);
4931 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4935 if (page->tab_label)
4936 page->mnemonic_activate_signal =
4937 g_signal_connect (page->tab_label,
4938 "mnemonic_activate",
4939 G_CALLBACK (gtk_notebook_mnemonic_activate_switch_page),
4942 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4944 gtk_widget_show (page->tab_label);
4945 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4948 gtk_notebook_update_tab_states (notebook);
4949 gtk_widget_child_notify (child, "tab_label");
4953 * gtk_notebook_set_tab_label_text:
4954 * @notebook: a #GtkNotebook
4956 * @tab_text: the label text
4958 * Creates a new label and sets it as the tab label for the page
4959 * containing @child.
4962 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4964 const gchar *tab_text)
4966 GtkWidget *tab_label = NULL;
4968 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4971 tab_label = gtk_label_new (tab_text);
4972 gtk_notebook_set_tab_label (notebook, child, tab_label);
4973 gtk_widget_child_notify (child, "tab_label");
4977 * gtk_notebook_get_tab_label_text:
4978 * @notebook: a #GtkNotebook
4979 * @child: a widget contained in a page of @notebook
4981 * Retrieves the text of the tab label for the page containing
4984 * Returns value: the text of the tab label, or %NULL if the
4985 * tab label widget is not a #GtkLabel. The
4986 * string is owned by the widget and must not
4989 G_CONST_RETURN gchar *
4990 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
4993 GtkWidget *tab_label;
4995 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4996 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
4998 tab_label = gtk_notebook_get_tab_label (notebook, child);
5000 if (tab_label && GTK_IS_LABEL (tab_label))
5001 return gtk_label_get_text (GTK_LABEL (tab_label));
5007 * gtk_notebook_get_menu_label:
5008 * @notebook: a #GtkNotebook
5009 * @child: a widget contained in a page of @notebook
5011 * Retrieves the menu label widget of the page containing @child.
5013 * Return value: the menu label, or %NULL if the
5014 * notebook page does not have a menu label other
5015 * than the default (the tab label).
5018 gtk_notebook_get_menu_label (GtkNotebook *notebook,
5023 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5024 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5026 list = CHECK_FIND_CHILD (notebook, child);
5030 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
5033 return GTK_NOTEBOOK_PAGE (list)->menu_label;
5037 * gtk_notebook_set_menu_label:
5038 * @notebook: a #GtkNotebook
5039 * @child: the child widget
5040 * @menu_label: the menu label, or NULL for default
5042 * Changes the menu label for the page containing @child.
5045 gtk_notebook_set_menu_label (GtkNotebook *notebook,
5047 GtkWidget *menu_label)
5049 GtkNotebookPage *page;
5052 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5053 g_return_if_fail (GTK_IS_WIDGET (child));
5055 list = CHECK_FIND_CHILD (notebook, child);
5060 if (page->menu_label)
5063 gtk_container_remove (GTK_CONTAINER (notebook->menu),
5064 page->menu_label->parent);
5066 if (!page->default_menu)
5067 g_object_unref (page->menu_label);
5072 page->menu_label = menu_label;
5073 g_object_ref (page->menu_label);
5074 gtk_object_sink (GTK_OBJECT(page->menu_label));
5075 page->default_menu = FALSE;
5078 page->default_menu = TRUE;
5081 gtk_notebook_menu_item_create (notebook, list);
5082 gtk_widget_child_notify (child, "menu_label");
5086 * gtk_notebook_set_menu_label_text:
5087 * @notebook: a #GtkNotebook
5088 * @child: the child widget
5089 * @menu_text: the label text
5091 * Creates a new label and sets it as the menu label of @child.
5094 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
5096 const gchar *menu_text)
5098 GtkWidget *menu_label = NULL;
5100 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5103 menu_label = gtk_label_new (menu_text);
5104 gtk_notebook_set_menu_label (notebook, child, menu_label);
5105 gtk_widget_child_notify (child, "menu_label");
5109 * gtk_notebook_get_menu_label_text:
5110 * @notebook: a #GtkNotebook
5111 * @child: the child widget of a page of the notebook.
5113 * Retrieves the text of the menu label for the page containing
5116 * Returns value: the text of the tab label, or %NULL if the
5117 * widget does not have a menu label other than
5118 * the default menu label, or the menu label widget
5119 * is not a #GtkLabel. The string is owned by
5120 * the widget and must not be freed.
5122 G_CONST_RETURN gchar *
5123 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
5126 GtkWidget *menu_label;
5128 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
5129 g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
5131 menu_label = gtk_notebook_get_menu_label (notebook, child);
5133 if (menu_label && GTK_IS_LABEL (menu_label))
5134 return gtk_label_get_text (GTK_LABEL (menu_label));
5139 /* Helper function called when pages are reordered
5142 gtk_notebook_child_reordered (GtkNotebook *notebook,
5143 GtkNotebookPage *page)
5147 GtkWidget *menu_item;
5149 menu_item = page->menu_label->parent;
5150 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
5151 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
5152 gtk_notebook_menu_item_create (notebook, g_list_find (notebook->children, page));
5155 gtk_notebook_update_tab_states (notebook);
5156 gtk_notebook_update_labels (notebook);
5160 * gtk_notebook_set_tab_label_packing:
5161 * @notebook: a #GtkNotebook
5162 * @child: the child widget
5163 * @expand: whether to expand the bookmark or not
5164 * @fill: whether the bookmark should fill the allocated area or not
5165 * @pack_type: the position of the bookmark
5167 * Sets the packing parameters for the tab label of the page
5168 * containing @child. See gtk_box_pack_start() for the exact meaning
5169 * of the parameters.
5172 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
5176 GtkPackType pack_type)
5178 GtkNotebookPage *page;
5181 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5182 g_return_if_fail (GTK_IS_WIDGET (child));
5184 list = CHECK_FIND_CHILD (notebook, child);
5189 expand = expand != FALSE;
5190 fill = fill != FALSE;
5191 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
5194 gtk_widget_freeze_child_notify (child);
5195 page->expand = expand;
5196 gtk_widget_child_notify (child, "tab_expand");
5198 gtk_widget_child_notify (child, "tab_fill");
5199 if (page->pack != pack_type)
5201 page->pack = pack_type;
5202 gtk_notebook_child_reordered (notebook, page);
5204 gtk_widget_child_notify (child, "tab_pack");
5205 gtk_widget_child_notify (child, "position");
5206 if (notebook->show_tabs)
5207 gtk_notebook_pages_allocate (notebook);
5208 gtk_widget_thaw_child_notify (child);
5212 * gtk_notebook_query_tab_label_packing:
5213 * @notebook: a #GtkNotebook
5215 * @expand: location to store the expand value (or NULL)
5216 * @fill: location to store the fill value (or NULL)
5217 * @pack_type: location to store the pack_type (or NULL)
5219 * Query the packing attributes for the tab label of the page
5220 * containing @child.
5223 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
5227 GtkPackType *pack_type)
5231 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5232 g_return_if_fail (GTK_IS_WIDGET (child));
5234 list = CHECK_FIND_CHILD (notebook, child);
5239 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
5241 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
5243 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
5247 * gtk_notebook_reorder_child:
5248 * @notebook: a #GtkNotebook
5249 * @child: the child to move
5250 * @position: the new position, or -1 to move to the end
5252 * Reorders the page containing @child, so that it appears in position
5253 * @position. If @position is greater than or equal to the number of
5254 * children in the list or negative, @child will be moved to the end
5258 gtk_notebook_reorder_child (GtkNotebook *notebook,
5262 GList *list, *new_list;
5263 GtkNotebookPage *page;
5267 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
5268 g_return_if_fail (GTK_IS_WIDGET (child));
5270 list = CHECK_FIND_CHILD (notebook, child);
5274 max_pos = g_list_length (notebook->children) - 1;
5275 if (position < 0 || position > max_pos)
5278 old_pos = g_list_position (notebook->children, list);
5280 if (old_pos == position)
5284 notebook->children = g_list_delete_link (notebook->children, list);
5286 notebook->children = g_list_insert (notebook->children, page, position);
5287 new_list = g_list_nth (notebook->children, position);
5289 /* Fix up GList references in GtkNotebook structure */
5290 if (notebook->first_tab == list)
5291 notebook->first_tab = new_list;
5292 if (notebook->focus_tab == list)
5293 notebook->focus_tab = new_list;
5295 gtk_widget_freeze_child_notify (child);
5297 /* Move around the menu items if necesary */
5298 gtk_notebook_child_reordered (notebook, page);
5299 gtk_widget_child_notify (child, "tab_pack");
5300 gtk_widget_child_notify (child, "position");
5302 if (notebook->show_tabs)
5303 gtk_notebook_pages_allocate (notebook);
5305 gtk_widget_thaw_child_notify (child);