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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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.
19 #include "gtknotebook.h"
20 #include "gtksignal.h"
23 #include "gtkmenuitem.h"
25 #include <gdk/gdkkeysyms.h>
30 #define TAB_CURVATURE 1
32 #define ARROW_SPACING 3
33 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
34 #define NOTEBOOK_SCROLL_DELAY (100)
65 typedef void (*GtkNotebookSignal) (GtkObject *object,
66 GtkNotebookPage *arg1,
70 static void gtk_notebook_class_init (GtkNotebookClass *klass);
71 static void gtk_notebook_init (GtkNotebook *notebook);
72 static void gtk_notebook_set_arg (GtkObject *object,
75 static void gtk_notebook_get_arg (GtkObject *object,
78 static void gtk_notebook_set_child_arg (GtkContainer *container,
82 static void gtk_notebook_get_child_arg (GtkContainer *container,
86 static void gtk_notebook_destroy (GtkObject *object);
87 static void gtk_notebook_map (GtkWidget *widget);
88 static void gtk_notebook_unmap (GtkWidget *widget);
89 static void gtk_notebook_realize (GtkWidget *widget);
90 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
91 static void gtk_notebook_size_request (GtkWidget *widget,
92 GtkRequisition *requisition);
93 static void gtk_notebook_size_allocate (GtkWidget *widget,
94 GtkAllocation *allocation);
95 static void gtk_notebook_paint (GtkWidget *widget,
97 static void gtk_notebook_draw (GtkWidget *widget,
99 static gint gtk_notebook_expose (GtkWidget *widget,
100 GdkEventExpose *event);
101 static gint gtk_notebook_button_press (GtkWidget *widget,
102 GdkEventButton *event);
103 static gint gtk_notebook_button_release (GtkWidget *widget,
104 GdkEventButton *event);
105 static gint gtk_notebook_enter_notify (GtkWidget *widget,
106 GdkEventCrossing *event);
107 static gint gtk_notebook_leave_notify (GtkWidget *widget,
108 GdkEventCrossing *event);
109 static gint gtk_notebook_motion_notify (GtkWidget *widget,
110 GdkEventMotion *event);
111 static gint gtk_notebook_key_press (GtkWidget *widget,
113 static void gtk_notebook_add (GtkContainer *container,
115 static void gtk_notebook_remove (GtkContainer *container,
117 static void gtk_notebook_real_remove (GtkNotebook *notebook,
120 static void gtk_notebook_foreach (GtkContainer *container,
121 GtkCallback callback,
122 gpointer callback_data);
123 static void gtk_notebook_switch_page (GtkNotebook *notebook,
124 GtkNotebookPage *page,
126 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
127 GtkNotebookPage *page,
129 static void gtk_notebook_set_focus_child (GtkContainer *container,
131 static gint gtk_notebook_focus_in (GtkWidget *widget,
132 GdkEventFocus *event);
133 static gint gtk_notebook_focus_out (GtkWidget *widget,
134 GdkEventFocus *event);
135 static void gtk_notebook_draw_focus (GtkWidget *widget);
136 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
137 GtkNotebookPage *old_page);
138 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
139 GtkAllocation *allocation);
140 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
141 GtkNotebookPage *page,
142 GtkAllocation *allocation);
143 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
145 static gint gtk_notebook_timer (GtkNotebook *notebook);
146 static gint gtk_notebook_focus (GtkContainer *container,
147 GtkDirectionType direction);
148 static gint gtk_notebook_page_select (GtkNotebook *notebook);
149 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
154 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
155 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
157 static void gtk_real_notebook_switch_page (GtkNotebook *notebook,
158 GtkNotebookPage *page,
160 static void gtk_notebook_marshal_signal (GtkObject *object,
164 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
165 GtkNotebookPage *page);
166 static void gtk_notebook_update_labels (GtkNotebook *notebook,
169 static void gtk_notebook_menu_detacher (GtkWidget *widget,
171 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
173 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
174 GtkNotebookPage *page,
176 static GtkType gtk_notebook_child_type (GtkContainer *container);
177 static gint gtk_notebook_find_page (gconstpointer a,
181 static GtkContainerClass *parent_class = NULL;
182 static guint notebook_signals[LAST_SIGNAL] = { 0 };
185 gtk_notebook_get_type (void)
187 static GtkType notebook_type = 0;
191 GtkTypeInfo notebook_info =
194 sizeof (GtkNotebook),
195 sizeof (GtkNotebookClass),
196 (GtkClassInitFunc) gtk_notebook_class_init,
197 (GtkObjectInitFunc) gtk_notebook_init,
198 /* reserved_1 */ NULL,
199 /* reserved_2 */ NULL,
200 (GtkClassInitFunc) NULL,
203 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
206 return notebook_type;
210 gtk_notebook_class_init (GtkNotebookClass *class)
212 GtkObjectClass *object_class;
213 GtkWidgetClass *widget_class;
214 GtkContainerClass *container_class;
216 object_class = (GtkObjectClass*) class;
217 widget_class = (GtkWidgetClass*) class;
218 container_class = (GtkContainerClass*) class;
219 parent_class = gtk_type_class (gtk_container_get_type ());
221 gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
222 gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
223 gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_BORDER);
224 gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
225 gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
226 gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
227 gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
229 gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
230 gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
231 gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
233 notebook_signals[SWITCH_PAGE] =
234 gtk_signal_new ("switch_page",
237 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
238 gtk_notebook_marshal_signal,
243 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
245 object_class->set_arg = gtk_notebook_set_arg;
246 object_class->get_arg = gtk_notebook_get_arg;
247 object_class->destroy = gtk_notebook_destroy;
249 widget_class->map = gtk_notebook_map;
250 widget_class->unmap = gtk_notebook_unmap;
251 widget_class->realize = gtk_notebook_realize;
252 widget_class->size_request = gtk_notebook_size_request;
253 widget_class->size_allocate = gtk_notebook_size_allocate;
254 widget_class->draw = gtk_notebook_draw;
255 widget_class->expose_event = gtk_notebook_expose;
256 widget_class->button_press_event = gtk_notebook_button_press;
257 widget_class->button_release_event = gtk_notebook_button_release;
258 widget_class->enter_notify_event = gtk_notebook_enter_notify;
259 widget_class->leave_notify_event = gtk_notebook_leave_notify;
260 widget_class->motion_notify_event = gtk_notebook_motion_notify;
261 widget_class->key_press_event = gtk_notebook_key_press;
262 widget_class->focus_in_event = gtk_notebook_focus_in;
263 widget_class->focus_out_event = gtk_notebook_focus_out;
264 widget_class->draw_focus = gtk_notebook_draw_focus;
266 container_class->add = gtk_notebook_add;
267 container_class->remove = gtk_notebook_remove;
268 container_class->foreach = gtk_notebook_foreach;
269 container_class->focus = gtk_notebook_focus;
270 container_class->set_focus_child = gtk_notebook_set_focus_child;
271 container_class->get_child_arg = gtk_notebook_get_child_arg;
272 container_class->set_child_arg = gtk_notebook_set_child_arg;
273 container_class->child_type = gtk_notebook_child_type;
275 class->switch_page = gtk_real_notebook_switch_page;
279 gtk_notebook_set_arg (GtkObject *object,
283 GtkNotebook *notebook;
285 notebook = GTK_NOTEBOOK (object);
290 gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
292 case ARG_SHOW_BORDER:
293 gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
296 gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
298 case ARG_ENABLE_POPUP:
299 if (GTK_VALUE_BOOL (*arg))
300 gtk_notebook_popup_enable (notebook);
302 gtk_notebook_popup_disable (notebook);
305 gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
308 gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
311 gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
319 gtk_notebook_get_arg (GtkObject *object,
323 GtkNotebook *notebook;
325 notebook = GTK_NOTEBOOK (object);
330 GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
332 case ARG_SHOW_BORDER:
333 GTK_VALUE_BOOL (*arg) = notebook->show_border;
336 GTK_VALUE_BOOL (*arg) = notebook->scrollable;
338 case ARG_ENABLE_POPUP:
339 GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
342 GTK_VALUE_INT (*arg) = gtk_notebook_current_page (notebook);
345 GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
348 GTK_VALUE_UINT (*arg) = notebook->tab_border;
351 arg->type = GTK_TYPE_INVALID;
357 gtk_notebook_set_child_arg (GtkContainer *container,
362 GtkNotebook *notebook;
363 GtkNotebookPage *page = NULL;
367 notebook = GTK_NOTEBOOK (container);
371 case CHILD_ARG_TAB_LABEL:
372 /* a NULL pointer indicates a default_tab setting, otherwise
373 * we need to set the associated label
376 if (!(list = g_list_find_custom (notebook->children, child,
377 gtk_notebook_find_page)))
382 if (GTK_VALUE_STRING (*arg))
384 page->default_tab = FALSE;
386 gtk_widget_unparent (page->tab_label);
387 page->tab_label = gtk_label_new (GTK_VALUE_STRING (*arg));
388 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
389 if (notebook->show_tabs)
391 gtk_widget_show (page->tab_label);
392 gtk_notebook_pages_allocate
393 (notebook, &(GTK_WIDGET (notebook)->allocation));
394 gtk_notebook_expose_tabs (notebook);
399 page->default_tab = TRUE;
401 gtk_widget_unparent (page->tab_label);
402 if (!notebook->show_tabs)
403 page->tab_label = NULL;
408 sprintf (string, "Page %u", g_list_index (notebook->children, page) + 1);
409 page->tab_label = gtk_label_new (string);
410 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
411 gtk_widget_show (page->tab_label);
412 gtk_notebook_pages_allocate
413 (notebook, &(GTK_WIDGET (notebook)->allocation));
414 gtk_notebook_expose_tabs (notebook);
418 case CHILD_ARG_MENU_LABEL:
420 for (position = 0, list = notebook->children; list;
421 list = list->next, position++)
424 if (page->child == child)
428 if (page->menu_label)
432 gtk_container_remove (GTK_CONTAINER (notebook->menu),
433 page->menu_label->parent);
434 gtk_widget_queue_resize (notebook->menu);
436 if (!page->default_menu)
437 gtk_widget_unref (page->menu_label);
439 if (GTK_VALUE_STRING (*arg))
441 page->menu_label = gtk_label_new (GTK_VALUE_STRING (*arg));
442 gtk_widget_ref (page->menu_label);
443 gtk_object_sink (GTK_OBJECT(page->menu_label));
444 page->default_menu = FALSE;
447 page->default_menu = TRUE;
450 gtk_notebook_menu_item_create (notebook, page, position);
453 case CHILD_ARG_POSITION:
454 gtk_notebook_reorder_child (notebook, child, GTK_VALUE_INT (*arg));
462 gtk_notebook_get_child_arg (GtkContainer *container,
467 GtkNotebook *notebook;
468 GtkNotebookPage *page = NULL;
471 notebook = GTK_NOTEBOOK (container);
473 if (!(list = g_list_find_custom (notebook->children, child,
474 gtk_notebook_find_page)))
476 arg->type = GTK_TYPE_INVALID;
484 case CHILD_ARG_TAB_LABEL:
485 if (page->default_tab)
486 GTK_VALUE_STRING (*arg) = NULL;
489 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
490 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->tab_label)->label);
492 GTK_VALUE_STRING (*arg) = NULL;
495 case CHILD_ARG_MENU_LABEL:
496 if (page->default_menu)
497 GTK_VALUE_STRING (*arg) = NULL;
500 if (page->menu_label && GTK_IS_LABEL (page->menu_label))
501 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->menu_label)->label);
503 GTK_VALUE_STRING (*arg) = NULL;
506 case CHILD_ARG_POSITION:
507 GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
510 arg->type = GTK_TYPE_INVALID;
516 gtk_notebook_child_type (GtkContainer *container)
518 return GTK_TYPE_WIDGET;
522 gtk_notebook_init (GtkNotebook *notebook)
524 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
526 notebook->cur_page = NULL;
527 notebook->children = NULL;
528 notebook->first_tab = NULL;
529 notebook->focus_tab = NULL;
530 notebook->panel = NULL;
531 notebook->menu = NULL;
533 notebook->tab_border = 3;
534 notebook->show_tabs = TRUE;
535 notebook->show_border = TRUE;
536 notebook->tab_pos = GTK_POS_TOP;
537 notebook->scrollable = FALSE;
538 notebook->in_child = 0;
539 notebook->click_child = 0;
540 notebook->button = 0;
541 notebook->need_timer = 0;
542 notebook->child_has_focus = FALSE;
546 gtk_notebook_new (void)
548 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
552 gtk_notebook_destroy (GtkObject *object)
554 GtkNotebook *notebook;
556 g_return_if_fail (object != NULL);
557 g_return_if_fail (GTK_IS_NOTEBOOK (object));
559 notebook = GTK_NOTEBOOK (object);
562 gtk_notebook_popup_disable (notebook);
564 GTK_OBJECT_CLASS (parent_class)->destroy (object);
568 gtk_notebook_append_page (GtkNotebook *notebook,
570 GtkWidget *tab_label)
572 g_return_if_fail (notebook != NULL);
573 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
574 g_return_if_fail (child != NULL);
576 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
580 gtk_notebook_append_page_menu (GtkNotebook *notebook,
582 GtkWidget *tab_label,
583 GtkWidget *menu_label)
585 g_return_if_fail (notebook != NULL);
586 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
587 g_return_if_fail (child != NULL);
589 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
593 gtk_notebook_prepend_page (GtkNotebook *notebook,
595 GtkWidget *tab_label)
597 g_return_if_fail (notebook != NULL);
598 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
599 g_return_if_fail (child != NULL);
601 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
605 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
607 GtkWidget *tab_label,
608 GtkWidget *menu_label)
610 g_return_if_fail (notebook != NULL);
611 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
612 g_return_if_fail (child != NULL);
614 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
618 gtk_notebook_insert_page (GtkNotebook *notebook,
620 GtkWidget *tab_label,
623 g_return_if_fail (notebook != NULL);
624 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
625 g_return_if_fail (child != NULL);
627 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
631 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
633 GtkWidget *tab_label,
634 GtkWidget *menu_label,
637 GtkNotebookPage *page;
640 g_return_if_fail (notebook != NULL);
641 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
642 g_return_if_fail (child != NULL);
644 page = g_new (GtkNotebookPage, 1);
646 page->requisition.width = 0;
647 page->requisition.height = 0;
648 page->allocation.x = 0;
649 page->allocation.y = 0;
650 page->allocation.width = 0;
651 page->allocation.height = 0;
652 page->default_menu = FALSE;
653 page->default_tab = FALSE;
655 nchildren = g_list_length (notebook->children);
656 if ((position < 0) || (position > nchildren))
657 position = nchildren;
659 notebook->children = g_list_insert (notebook->children, page, position);
663 page->default_tab = TRUE;
664 if (notebook->show_tabs)
665 tab_label = gtk_label_new ("");
667 page->tab_label = tab_label;
668 page->menu_label = menu_label;
671 page->default_menu = TRUE;
674 gtk_widget_ref (page->menu_label);
675 gtk_object_sink (GTK_OBJECT(page->menu_label));
679 gtk_notebook_menu_item_create (notebook, page, position);
681 gtk_notebook_update_labels
682 (notebook, g_list_nth (notebook->children, position), position + 1);
684 if (!notebook->first_tab)
685 notebook->first_tab = notebook->children;
687 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
690 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
691 gtk_widget_show (tab_label);
694 if (!notebook->cur_page)
696 gtk_notebook_switch_page (notebook, page, 0);
697 gtk_notebook_switch_focus_tab (notebook, NULL);
700 if (GTK_WIDGET_VISIBLE (notebook))
702 if (GTK_WIDGET_REALIZED (notebook) &&
703 !GTK_WIDGET_REALIZED (child))
704 gtk_widget_realize (child);
706 if (GTK_WIDGET_MAPPED (notebook) &&
707 !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
708 gtk_widget_map (child);
712 if (GTK_WIDGET_REALIZED (notebook) &&
713 !GTK_WIDGET_REALIZED (tab_label))
714 gtk_widget_realize (tab_label);
716 if (GTK_WIDGET_MAPPED (notebook) &&
717 !GTK_WIDGET_MAPPED (tab_label))
718 gtk_widget_map (tab_label);
722 if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
723 gtk_widget_queue_resize (child);
727 gtk_notebook_remove_page (GtkNotebook *notebook,
732 g_return_if_fail (notebook != NULL);
733 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
737 list = g_list_nth (notebook->children, page_num);
739 gtk_notebook_real_remove (notebook, list, page_num);
743 list = g_list_last (notebook->children);
745 gtk_notebook_real_remove
746 (notebook, list, g_list_index (notebook->children, list->data));
751 gtk_notebook_add (GtkContainer *container,
754 g_return_if_fail (container != NULL);
755 g_return_if_fail (GTK_IS_NOTEBOOK (container));
756 g_return_if_fail (widget != NULL);
758 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
763 gtk_notebook_remove (GtkContainer *container,
766 GtkNotebook *notebook;
767 GtkNotebookPage *page;
771 g_return_if_fail (container != NULL);
772 g_return_if_fail (GTK_IS_NOTEBOOK (container));
773 g_return_if_fail (widget != NULL);
775 notebook = GTK_NOTEBOOK (container);
777 children = notebook->children;
781 page = children->data;
782 if (page->child == widget)
784 gtk_notebook_real_remove (notebook, children, page_num);
788 children = children->next;
793 gtk_notebook_real_remove (GtkNotebook *notebook,
797 GtkNotebookPage *page;
799 gint need_resize = FALSE;
803 next_list = list->prev;
808 next_list = list->next;
814 if (notebook->cur_page == list->data)
816 notebook->cur_page = NULL;
819 page = next_list->data;
820 gtk_notebook_switch_page (notebook, page, page_num);
824 if (list == notebook->first_tab)
825 notebook->first_tab = next_list;
826 if (list == notebook->focus_tab)
827 gtk_notebook_switch_focus_tab (notebook, next_list);
831 if ((GTK_WIDGET_VISIBLE (page->child) ||
832 (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label)))
833 && GTK_WIDGET_VISIBLE (notebook))
836 gtk_widget_unparent (page->child);
839 gtk_widget_unparent (page->tab_label);
843 gtk_container_remove (GTK_CONTAINER (notebook->menu),
844 page->menu_label->parent);
845 gtk_widget_queue_resize (notebook->menu);
847 if (!page->default_menu)
848 gtk_widget_unref (page->menu_label);
850 gtk_notebook_update_labels (notebook, list->next, page_num + 1);
852 notebook->children = g_list_remove_link (notebook->children, list);
857 gtk_widget_queue_resize (GTK_WIDGET (notebook));
862 gtk_notebook_current_page (GtkNotebook *notebook)
867 g_return_val_if_fail (notebook != NULL, -1);
868 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
870 if (notebook->cur_page)
873 children = notebook->children;
877 if (children->data == notebook->cur_page)
879 children = children->next;
895 gtk_notebook_set_page (GtkNotebook *notebook,
900 g_return_if_fail (notebook != NULL);
901 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
905 list = g_list_nth (notebook->children, page_num);
907 gtk_notebook_switch_page (notebook, list->data, page_num);
911 list = g_list_last (notebook->children);
913 gtk_notebook_switch_page (notebook, list->data,
914 g_list_index (notebook->children, list->data));
919 gtk_notebook_next_page (GtkNotebook *notebook)
921 GtkNotebookPage *page;
925 g_return_if_fail (notebook != NULL);
926 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
928 children = notebook->children;
932 if (notebook->cur_page == children->data)
934 children = children->next;
943 children = children->next;
948 children = notebook->children;
952 page = children->data;
953 gtk_notebook_switch_page (notebook, page, num);
957 gtk_notebook_prev_page (GtkNotebook *notebook)
959 GtkNotebookPage *page;
963 g_return_if_fail (notebook != NULL);
964 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
966 children = notebook->children;
970 if (notebook->cur_page == children->data)
972 children = children->next;
981 children = children->prev;
986 while (children->next)
988 children = children->next;
993 page = children->data;
994 gtk_notebook_switch_page (notebook, page, num);
998 gtk_notebook_reorder_child (GtkNotebook *notebook,
1003 GtkNotebookPage *page;
1006 g_return_if_fail (notebook != NULL);
1007 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1008 g_return_if_fail (child != NULL);
1009 g_return_if_fail (GTK_IS_WIDGET (child));
1011 for (old_pos = 0, list = notebook->children; list;
1012 list = list->next, old_pos++)
1015 if (page->child == child)
1019 if (!list || old_pos == position)
1022 notebook->children = g_list_remove_link (notebook->children, list);
1024 if (position <= 0 || !notebook->children)
1026 list->next = notebook->children;
1028 list->next->prev = list;
1029 notebook->children = list;
1035 if ((work = g_list_nth (notebook->children, position)))
1037 list->prev = work->prev;
1039 list->prev->next = list;
1045 work = g_list_last (notebook->children);
1053 GtkWidget *menu_item;
1055 menu_item = page->menu_label->parent;
1056 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
1057 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
1058 gtk_notebook_menu_item_create (notebook, page, position);
1059 gtk_widget_queue_resize (notebook->menu);
1062 gtk_notebook_update_labels (notebook, notebook->children, 1);
1064 if (notebook->show_tabs)
1066 gtk_notebook_pages_allocate (notebook,
1067 &(GTK_WIDGET (notebook)->allocation));
1068 gtk_notebook_expose_tabs (notebook);
1073 gtk_notebook_foreach (GtkContainer *container,
1074 GtkCallback callback,
1075 gpointer callback_data)
1077 GtkNotebook *notebook;
1078 GtkNotebookPage *page;
1081 g_return_if_fail (container != NULL);
1082 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1083 g_return_if_fail (callback != NULL);
1085 notebook = GTK_NOTEBOOK (container);
1087 children = notebook->children;
1090 page = children->data;
1091 children = children->next;
1092 (* callback) (page->child, callback_data);
1097 gtk_notebook_expose_tabs (GtkNotebook *notebook)
1100 GtkNotebookPage *page;
1101 GdkEventExpose event;
1104 widget = GTK_WIDGET (notebook);
1105 border = GTK_CONTAINER (notebook)->border_width;
1107 page = notebook->first_tab->data;
1109 event.type = GDK_EXPOSE;
1110 event.window = widget->window;
1112 event.area.x = border;
1113 event.area.y = border;
1115 switch (notebook->tab_pos)
1117 case GTK_POS_BOTTOM:
1118 event.area.y = widget->allocation.height - border
1119 - page->allocation.height - widget->style->klass->ythickness;
1120 if (notebook->first_tab->data != notebook->cur_page)
1121 event.area.y -= widget->style->klass->ythickness;
1123 event.area.width = widget->allocation.width - 2 * border;
1124 event.area.height = page->allocation.height
1125 + widget->style->klass->ythickness;
1126 if (notebook->first_tab->data != notebook->cur_page)
1127 event.area.height += widget->style->klass->ythickness;
1130 event.area.x = widget->allocation.width - border
1131 - page->allocation.width - widget->style->klass->xthickness;
1132 if (notebook->first_tab->data != notebook->cur_page)
1133 event.area.x -= widget->style->klass->xthickness;
1135 event.area.width = page->allocation.width
1136 + widget->style->klass->xthickness;
1137 event.area.height = widget->allocation.height - 2 * border;
1138 if (notebook->first_tab->data != notebook->cur_page)
1139 event.area.width += widget->style->klass->xthickness;
1142 gtk_widget_event (widget, (GdkEvent *) &event);
1146 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
1147 GtkPositionType pos)
1149 g_return_if_fail (notebook != NULL);
1150 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1152 if (notebook->tab_pos != pos)
1154 notebook->tab_pos = pos;
1156 if (GTK_WIDGET_VISIBLE (notebook))
1158 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1159 if (notebook->panel)
1160 gdk_window_clear (notebook->panel);
1166 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
1169 GtkNotebookPage *page;
1172 g_return_if_fail (notebook != NULL);
1173 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1175 if (notebook->show_tabs == show_tabs)
1178 notebook->show_tabs = show_tabs;
1179 children = notebook->children;
1183 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
1187 page = children->data;
1188 children = children->next;
1189 if (page->default_tab)
1191 gtk_widget_destroy (page->tab_label);
1192 page->tab_label = NULL;
1195 gtk_widget_hide (page->tab_label);
1198 if (notebook->panel)
1199 gdk_window_hide (notebook->panel);
1206 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
1210 page = children->data;
1211 children = children->next;
1212 if (page->default_tab)
1214 sprintf (string, "Page %d", i);
1215 page->tab_label = gtk_label_new (string);
1216 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
1218 gtk_widget_show (page->tab_label);
1222 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1226 gtk_notebook_set_show_border (GtkNotebook *notebook,
1229 g_return_if_fail (notebook != NULL);
1230 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1232 if (notebook->show_border != show_border)
1234 notebook->show_border = show_border;
1236 if (GTK_WIDGET_VISIBLE (notebook))
1237 gtk_widget_queue_resize (GTK_WIDGET (notebook));
1242 gtk_notebook_set_scrollable (GtkNotebook *notebook,
1245 g_return_if_fail (notebook != NULL);
1246 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1248 if (scrollable != notebook->scrollable)
1250 if ( (notebook->scrollable = (scrollable != 0)) )
1251 gtk_notebook_panel_realize (notebook);
1252 else if (notebook->panel)
1254 gdk_window_destroy (notebook->panel);
1255 notebook->panel = NULL;
1257 gtk_widget_queue_resize (GTK_WIDGET(notebook));
1262 gtk_notebook_map (GtkWidget *widget)
1264 GtkNotebook *notebook;
1265 GtkNotebookPage *page;
1268 g_return_if_fail (widget != NULL);
1269 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1271 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1272 gdk_window_show (widget->window);
1274 notebook = GTK_NOTEBOOK (widget);
1276 if (notebook->cur_page &&
1277 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1278 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1279 gtk_widget_map (notebook->cur_page->child);
1281 if (notebook->scrollable)
1282 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
1285 children = notebook->children;
1289 page = children->data;
1290 children = children->next;
1292 if (page->tab_label &&
1293 GTK_WIDGET_VISIBLE (page->child) &&
1294 !GTK_WIDGET_MAPPED (page->tab_label))
1295 gtk_widget_map (page->tab_label);
1301 gtk_notebook_unmap (GtkWidget *widget)
1303 g_return_if_fail (widget != NULL);
1304 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1306 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1307 gdk_window_hide (widget->window);
1308 if (GTK_NOTEBOOK (widget)->panel)
1309 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
1313 gtk_notebook_realize (GtkWidget *widget)
1315 GtkNotebook *notebook;
1316 GdkWindowAttr attributes;
1317 gint attributes_mask;
1319 g_return_if_fail (widget != NULL);
1320 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1322 notebook = GTK_NOTEBOOK (widget);
1323 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1325 attributes.window_type = GDK_WINDOW_CHILD;
1326 attributes.x = widget->allocation.x;
1327 attributes.y = widget->allocation.y;
1328 attributes.width = widget->allocation.width;
1329 attributes.height = widget->allocation.height;
1330 attributes.wclass = GDK_INPUT_OUTPUT;
1331 attributes.visual = gtk_widget_get_visual (widget);
1332 attributes.colormap = gtk_widget_get_colormap (widget);
1333 attributes.event_mask = gtk_widget_get_events (widget);
1334 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1335 | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
1337 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1339 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1340 gdk_window_set_user_data (widget->window, notebook);
1342 widget->style = gtk_style_attach (widget->style, widget->window);
1343 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1345 if (notebook->scrollable)
1346 gtk_notebook_panel_realize (notebook);
1350 gtk_notebook_panel_realize (GtkNotebook *notebook)
1353 GdkWindowAttr attributes;
1354 gint attributes_mask;
1356 g_return_if_fail (notebook != NULL);
1357 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1359 widget = GTK_WIDGET (notebook);
1361 attributes.window_type = GDK_WINDOW_CHILD;
1362 attributes.wclass = GDK_INPUT_OUTPUT;
1363 attributes.visual = gtk_widget_get_visual (widget);
1364 attributes.colormap = gtk_widget_get_colormap (widget);
1365 attributes.event_mask = gtk_widget_get_events (widget);
1366 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1367 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1368 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1370 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1372 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1373 attributes.height = ARROW_SIZE;
1375 attributes.x = widget->allocation.width - attributes.width -
1376 GTK_CONTAINER (notebook)->border_width;
1377 attributes.y = widget->allocation.height - ARROW_SIZE -
1378 GTK_CONTAINER (notebook)->border_width;
1379 if (notebook->tab_pos == GTK_POS_TOP)
1380 attributes.y = GTK_CONTAINER (notebook)->border_width;
1381 else if (notebook->tab_pos == GTK_POS_LEFT)
1382 attributes.x = widget->allocation.x
1383 + GTK_CONTAINER (notebook)->border_width;
1386 notebook->panel = gdk_window_new (widget->window, &attributes,
1388 gtk_style_set_background (widget->style, notebook->panel,
1390 gdk_window_set_user_data (notebook->panel, widget);
1394 gtk_notebook_size_request (GtkWidget *widget,
1395 GtkRequisition *requisition)
1397 GtkNotebook *notebook;
1398 GtkNotebookPage *page;
1401 g_return_if_fail (widget != NULL);
1402 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1403 g_return_if_fail (requisition != NULL);
1405 notebook = GTK_NOTEBOOK (widget);
1406 widget->requisition.width = 0;
1407 widget->requisition.height = 0;
1409 children = notebook->children;
1412 page = children->data;
1413 children = children->next;
1415 if (GTK_WIDGET_VISIBLE (page->child))
1417 gtk_widget_size_request (page->child, &page->child->requisition);
1419 widget->requisition.width = MAX (widget->requisition.width,
1420 page->child->requisition.width);
1421 widget->requisition.height = MAX (widget->requisition.height,
1422 page->child->requisition.height);
1426 if (notebook->show_border || notebook->show_tabs)
1428 widget->requisition.width += widget->style->klass->xthickness * 2;
1429 widget->requisition.height += widget->style->klass->ythickness * 2;
1431 if (notebook->show_tabs)
1434 gint tab_height = 0;
1437 children = notebook->children;
1440 page = children->data;
1441 children = children->next;
1443 if (GTK_WIDGET_VISIBLE (page->child))
1445 gtk_widget_size_request (page->tab_label,
1446 &page->tab_label->requisition);
1448 page->requisition.width =
1449 (page->tab_label->requisition.width +
1450 (widget->style->klass->xthickness + notebook->tab_border)
1452 page->requisition.height =
1453 (page->tab_label->requisition.height +
1454 (widget->style->klass->ythickness + notebook->tab_border)
1457 switch (notebook->tab_pos)
1460 case GTK_POS_BOTTOM:
1461 page->requisition.width -= TAB_OVERLAP;
1463 tab_width += page->requisition.width;
1464 tab_height = MAX (tab_height, page->requisition.height);
1465 tab_max = MAX (tab_max, page->requisition.width);
1469 page->requisition.height -= TAB_OVERLAP;
1471 tab_width = MAX (tab_width, page->requisition.width);
1472 tab_height += page->requisition.height;
1473 tab_max = MAX (tab_max, page->requisition.height);
1479 children = notebook->children;
1481 if (children && children->next && notebook->scrollable)
1483 if ((notebook->tab_pos == GTK_POS_TOP) ||
1484 (notebook->tab_pos == GTK_POS_BOTTOM))
1486 if (widget->requisition.width < tab_width)
1488 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1489 tab_height = MAX (tab_height, ARROW_SIZE);
1494 if (widget->requisition.height < tab_height)
1496 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1497 tab_width = MAX (tab_width,
1498 ARROW_SPACING + 2 * ARROW_SIZE);
1505 page = children->data;
1506 children = children->next;
1508 if (GTK_WIDGET_VISIBLE (page->child))
1510 if ((notebook->tab_pos == GTK_POS_TOP) ||
1511 (notebook->tab_pos == GTK_POS_BOTTOM))
1512 page->requisition.height = tab_height;
1514 page->requisition.width = tab_width;
1518 switch (notebook->tab_pos)
1521 case GTK_POS_BOTTOM:
1522 tab_width += widget->style->klass->xthickness;
1523 widget->requisition.width = MAX (widget->requisition.width,
1525 widget->requisition.height += tab_height;
1529 tab_height += widget->style->klass->ythickness;
1530 widget->requisition.width += tab_width;
1531 widget->requisition.height = MAX (widget->requisition.height,
1537 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1538 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1542 gtk_notebook_size_allocate (GtkWidget *widget,
1543 GtkAllocation *allocation)
1545 GtkNotebook *notebook;
1546 GtkNotebookPage *page;
1547 GtkAllocation child_allocation;
1550 g_return_if_fail (widget != NULL);
1551 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1552 g_return_if_fail (allocation != NULL);
1554 widget->allocation = *allocation;
1555 if (GTK_WIDGET_REALIZED (widget))
1556 gdk_window_move_resize (widget->window,
1557 allocation->x, allocation->y,
1558 allocation->width, allocation->height);
1560 notebook = GTK_NOTEBOOK (widget);
1561 if (notebook->children)
1563 child_allocation.x = GTK_CONTAINER (widget)->border_width;
1564 child_allocation.y = GTK_CONTAINER (widget)->border_width;
1565 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1566 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1568 if (notebook->show_tabs || notebook->show_border)
1570 child_allocation.x += widget->style->klass->xthickness;
1571 child_allocation.y += widget->style->klass->ythickness;
1572 child_allocation.width = MAX (1,
1573 child_allocation.width - widget->style->klass->xthickness * 2);
1574 child_allocation.height = MAX (1,
1575 child_allocation.height - widget->style->klass->ythickness * 2);
1577 if (notebook->show_tabs && notebook->children)
1579 switch (notebook->tab_pos)
1582 child_allocation.y += notebook->cur_page->requisition.height;
1583 case GTK_POS_BOTTOM:
1584 child_allocation.height = MAX (1,
1585 child_allocation.height - notebook->cur_page->requisition.height);
1588 child_allocation.x += notebook->cur_page->requisition.width;
1590 child_allocation.width = MAX (1,
1591 child_allocation.width - notebook->cur_page->requisition.width);
1597 children = notebook->children;
1600 page = children->data;
1601 children = children->next;
1603 if (GTK_WIDGET_VISIBLE (page->child))
1604 gtk_widget_size_allocate (page->child, &child_allocation);
1607 gtk_notebook_pages_allocate (notebook, allocation);
1612 gtk_notebook_paint (GtkWidget *widget,
1615 GtkNotebook *notebook;
1616 GtkNotebookPage *page;
1623 g_return_if_fail (widget != NULL);
1624 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1625 g_return_if_fail (area != NULL);
1627 if (GTK_WIDGET_DRAWABLE (widget))
1629 notebook = GTK_NOTEBOOK (widget);
1631 gdk_window_clear_area (widget->window,
1633 area->width, area->height);
1635 if (notebook->show_tabs || notebook->show_border)
1637 x = GTK_CONTAINER (widget)->border_width;
1638 y = GTK_CONTAINER (widget)->border_width;
1639 width = widget->allocation.width - x * 2;
1640 height = widget->allocation.height - y * 2;
1642 if (notebook->show_tabs && notebook->children)
1645 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1647 GtkNotebookPage *page;
1649 page = notebook->first_tab->data;
1651 switch (notebook->tab_pos)
1654 y += page->allocation.height +
1655 widget->style->klass->ythickness;
1656 case GTK_POS_BOTTOM:
1657 height -= page->allocation.height +
1658 widget->style->klass->ythickness;
1661 x += page->allocation.width +
1662 widget->style->klass->xthickness;
1664 width -= page->allocation.width +
1665 widget->style->klass->xthickness;
1668 gtk_draw_shadow (widget->style, widget->window,
1669 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1670 x, y, width, height);
1674 switch (notebook->tab_pos)
1677 y += notebook->cur_page->allocation.height;
1678 case GTK_POS_BOTTOM:
1679 height -= notebook->cur_page->allocation.height;
1682 x += notebook->cur_page->allocation.width;
1684 width -= notebook->cur_page->allocation.width;
1688 switch (notebook->tab_pos)
1691 points[0].x = notebook->cur_page->allocation.x;
1696 points[2].y = y + height - 1;
1697 points[3].x = x + width - 1;
1698 points[3].y = y + height - 1;
1699 points[4].x = x + width - 1;
1701 points[5].x = (notebook->cur_page->allocation.x +
1702 notebook->cur_page->allocation.width -
1703 widget->style->klass->xthickness);
1706 if (points[5].x == (x + width))
1709 case GTK_POS_BOTTOM:
1710 points[0].x = (notebook->cur_page->allocation.x +
1711 notebook->cur_page->allocation.width -
1712 widget->style->klass->xthickness);
1713 points[0].y = y + height - 1;
1714 points[1].x = x + width - 1;
1715 points[1].y = y + height - 1;
1716 points[2].x = x + width - 1;
1721 points[4].y = y + height - 1;
1722 points[5].x = notebook->cur_page->allocation.x;
1723 points[5].y = y + height - 1;
1725 if (points[0].x == (x + width))
1730 points[0].y = (notebook->cur_page->allocation.y +
1731 notebook->cur_page->allocation.height -
1732 widget->style->klass->ythickness);
1734 points[1].y = y + height - 1;
1735 points[2].x = x + width - 1;
1736 points[2].y = y + height - 1;
1737 points[3].x = x + width - 1;
1742 points[5].y = notebook->cur_page->allocation.y;
1744 if (points[0].y == (y + height))
1748 points[0].x = x + width - 1;
1749 points[0].y = notebook->cur_page->allocation.y;
1750 points[1].x = x + width - 1;
1755 points[3].y = y + height - 1;
1756 points[4].x = x + width - 1;
1757 points[4].y = y + height - 1;
1758 points[5].x = x + width - 1;
1759 points[5].y = (notebook->cur_page->allocation.y +
1760 notebook->cur_page->allocation.height -
1761 widget->style->klass->ythickness);
1763 if (points[5].y == (y + height))
1768 gtk_draw_polygon (widget->style, widget->window,
1769 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1772 children = g_list_last (notebook->children);
1777 page = children->data;
1778 children = children->prev;
1780 if (!GTK_WIDGET_MAPPED (page->tab_label))
1782 else if (notebook->cur_page != page)
1783 gtk_notebook_draw_tab (notebook, page, area);
1786 if (showarrow && notebook->scrollable && notebook->show_tabs)
1788 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1789 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1791 if (notebook->cur_page &&
1792 GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1793 (notebook->cur_page))->tab_label))
1794 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1796 else if (notebook->show_border)
1798 gtk_draw_shadow (widget->style, widget->window,
1799 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1800 x, y, width, height);
1807 gtk_notebook_draw (GtkWidget *widget,
1810 GtkNotebook *notebook;
1811 GdkRectangle child_area;
1813 g_return_if_fail (widget != NULL);
1814 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1815 g_return_if_fail (area != NULL);
1817 if (GTK_WIDGET_DRAWABLE (widget))
1819 notebook = GTK_NOTEBOOK (widget);
1821 gtk_notebook_paint (widget, area);
1822 gtk_widget_draw_focus (widget);
1824 if (notebook->cur_page &&
1825 gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1826 gtk_widget_draw (notebook->cur_page->child, &child_area);
1831 gtk_notebook_expose (GtkWidget *widget,
1832 GdkEventExpose *event)
1834 GtkNotebook *notebook;
1835 GdkEventExpose child_event;
1837 g_return_val_if_fail (widget != NULL, FALSE);
1838 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1839 g_return_val_if_fail (event != NULL, FALSE);
1841 if (GTK_WIDGET_DRAWABLE (widget))
1843 notebook = GTK_NOTEBOOK (widget);
1845 gtk_notebook_paint (widget, &event->area);
1846 gtk_widget_draw_focus (widget);
1848 child_event = *event;
1849 if (notebook->cur_page &&
1850 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1851 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1853 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1860 gtk_notebook_button_press (GtkWidget *widget,
1861 GdkEventButton *event)
1863 GtkNotebook *notebook;
1864 GtkNotebookPage *page;
1868 g_return_val_if_fail (widget != NULL, FALSE);
1869 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1870 g_return_val_if_fail (event != NULL, FALSE);
1872 notebook = GTK_NOTEBOOK (widget);
1874 if (event->type != GDK_BUTTON_PRESS || !notebook->children
1875 || notebook->button)
1878 if (event->window == notebook->panel)
1880 if (!GTK_WIDGET_HAS_FOCUS (widget))
1881 gtk_widget_grab_focus (widget);
1883 gtk_grab_add (widget);
1884 notebook->button = event->button;
1886 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1888 notebook->click_child = GTK_ARROW_LEFT;
1889 if (event->button == 1)
1891 if (!notebook->focus_tab || notebook->focus_tab->prev)
1892 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1894 if (!notebook->timer)
1896 notebook->timer = gtk_timeout_add
1897 (NOTEBOOK_INIT_SCROLL_DELAY,
1898 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1899 notebook->need_timer = TRUE;
1902 else if (event->button == 2)
1903 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1904 else if (event->button == 3)
1905 gtk_notebook_switch_focus_tab (notebook, notebook->children);
1906 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1910 notebook->click_child = GTK_ARROW_RIGHT;
1911 if (event->button == 1)
1913 if (!notebook->focus_tab || notebook->focus_tab->next)
1914 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1915 if (!notebook->timer)
1917 notebook->timer = gtk_timeout_add
1918 (NOTEBOOK_INIT_SCROLL_DELAY,
1919 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1920 notebook->need_timer = TRUE;
1923 else if (event->button == 2)
1924 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1925 else if (event->button == 3)
1926 gtk_notebook_switch_focus_tab (notebook,
1927 g_list_last (notebook->children));
1928 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1931 else if (event->window == widget->window)
1933 if (event->button == 3 && notebook->menu)
1935 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1936 NULL, NULL, 3, event->time);
1941 children = notebook->children;
1944 page = children->data;
1946 if (GTK_WIDGET_VISIBLE (page->child) &&
1947 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1948 (event->x >= page->allocation.x) &&
1949 (event->y >= page->allocation.y) &&
1950 (event->x <= (page->allocation.x + page->allocation.width)) &&
1951 (event->y <= (page->allocation.y + page->allocation.height)))
1953 if (page == notebook->cur_page && notebook->focus_tab &&
1954 notebook->focus_tab != children &&
1955 GTK_WIDGET_HAS_FOCUS (notebook))
1957 GtkNotebookPage *old_page;
1959 notebook->child_has_focus = FALSE;
1960 old_page = (GtkNotebookPage *)
1961 (notebook->focus_tab->data);
1962 gtk_notebook_switch_focus_tab (notebook, children);
1963 gtk_notebook_focus_changed (notebook, old_page);
1967 gtk_notebook_switch_focus_tab (notebook, children);
1968 gtk_notebook_switch_page (notebook, page, num);
1969 gtk_widget_grab_focus (widget);
1973 children = children->next;
1976 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1977 gtk_widget_grab_focus (widget);
1983 gtk_notebook_button_release (GtkWidget *widget,
1984 GdkEventButton *event)
1986 GtkNotebook *notebook;
1988 g_return_val_if_fail (widget != NULL, FALSE);
1989 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1990 g_return_val_if_fail (event != NULL, FALSE);
1992 if (event->type != GDK_BUTTON_RELEASE)
1995 notebook = GTK_NOTEBOOK (widget);
1997 if (event->button == notebook->button)
2001 if (notebook->timer)
2003 gtk_timeout_remove (notebook->timer);
2004 notebook->timer = 0;
2005 notebook->need_timer = FALSE;
2007 gtk_grab_remove (widget);
2008 click_child = notebook->click_child;
2009 notebook->click_child = 0;
2010 notebook->button = 0;
2011 gtk_notebook_draw_arrow (notebook, click_child);
2018 gtk_notebook_enter_notify (GtkWidget *widget,
2019 GdkEventCrossing *event)
2021 GtkNotebook *notebook;
2023 g_return_val_if_fail (widget != NULL, FALSE);
2024 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2025 g_return_val_if_fail (event != NULL, FALSE);
2027 notebook = GTK_NOTEBOOK (widget);
2029 if (event->window == notebook->panel)
2034 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
2036 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
2038 notebook->in_child = GTK_ARROW_LEFT;
2040 if (notebook->click_child == 0)
2041 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2045 notebook->in_child = GTK_ARROW_RIGHT;
2047 if (notebook->click_child == 0)
2048 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2056 gtk_notebook_leave_notify (GtkWidget *widget,
2057 GdkEventCrossing *event)
2059 GtkNotebook *notebook;
2061 g_return_val_if_fail (widget != NULL, FALSE);
2062 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2063 g_return_val_if_fail (event != NULL, FALSE);
2065 notebook = GTK_NOTEBOOK (widget);
2067 if (event->window == notebook->panel && !notebook->click_child)
2069 if (notebook->in_child == GTK_ARROW_LEFT)
2071 notebook->in_child = 0;
2072 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
2076 notebook->in_child = 0;
2077 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
2084 gtk_notebook_motion_notify (GtkWidget *widget,
2085 GdkEventMotion *event)
2087 GtkNotebook *notebook;
2089 g_return_val_if_fail (widget != NULL, FALSE);
2090 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2091 g_return_val_if_fail (event != NULL, FALSE);
2093 notebook = GTK_NOTEBOOK (widget);
2095 if (notebook->button)
2098 if (event->window == notebook->panel)
2104 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
2106 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
2107 notebook->in_child == GTK_ARROW_RIGHT)
2109 notebook->in_child = GTK_ARROW_LEFT;
2110 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2111 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2113 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
2114 notebook->in_child == GTK_ARROW_LEFT)
2116 notebook->in_child = GTK_ARROW_RIGHT;
2117 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2118 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2126 gtk_notebook_timer (GtkNotebook *notebook)
2128 g_return_val_if_fail (notebook != NULL, FALSE);
2129 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2131 if (notebook->timer)
2133 if (notebook->click_child == GTK_ARROW_LEFT)
2135 if (!notebook->focus_tab || notebook->focus_tab->prev)
2136 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
2138 else if (notebook->click_child == GTK_ARROW_RIGHT)
2140 if (!notebook->focus_tab || notebook->focus_tab->next)
2141 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
2144 if (notebook->need_timer)
2146 notebook->need_timer = FALSE;
2147 notebook->timer = gtk_timeout_add
2148 (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer,
2149 (gpointer) notebook);
2158 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
2160 GtkStateType state_type;
2161 GtkShadowType shadow_type;
2164 g_return_if_fail (notebook != NULL);
2165 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2167 widget = GTK_WIDGET(notebook);
2169 if (GTK_WIDGET_DRAWABLE (notebook))
2171 if (notebook->in_child == arrow)
2173 if (notebook->click_child == arrow)
2174 state_type = GTK_STATE_ACTIVE;
2176 state_type = GTK_STATE_PRELIGHT;
2179 state_type = GTK_STATE_NORMAL;
2181 if (notebook->click_child == arrow)
2182 shadow_type = GTK_SHADOW_IN;
2184 shadow_type = GTK_SHADOW_OUT;
2186 if (arrow == GTK_ARROW_LEFT)
2188 if (notebook->focus_tab && !notebook->focus_tab->prev)
2190 shadow_type = GTK_SHADOW_ETCHED_IN;
2191 state_type = GTK_STATE_NORMAL;
2194 if (notebook->tab_pos == GTK_POS_LEFT ||
2195 notebook->tab_pos == GTK_POS_RIGHT)
2196 arrow = GTK_ARROW_UP;
2197 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2198 shadow_type, arrow, TRUE,
2199 0, 0, ARROW_SIZE, ARROW_SIZE);
2203 if (notebook->focus_tab && !notebook->focus_tab->next)
2205 shadow_type = GTK_SHADOW_ETCHED_IN;
2206 state_type = GTK_STATE_NORMAL;
2209 if (notebook->tab_pos == GTK_POS_LEFT ||
2210 notebook->tab_pos == GTK_POS_RIGHT)
2211 arrow = GTK_ARROW_DOWN;
2212 gtk_draw_arrow (widget->style, notebook->panel, state_type,
2213 shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2214 0, ARROW_SIZE, ARROW_SIZE);
2220 gtk_real_notebook_switch_page (GtkNotebook *notebook,
2221 GtkNotebookPage *page,
2224 g_return_if_fail (notebook != NULL);
2225 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2226 g_return_if_fail (page != NULL);
2228 if (notebook->cur_page == page)
2231 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
2232 gtk_widget_unmap (notebook->cur_page->child);
2234 notebook->cur_page = page;
2236 if (!notebook->focus_tab ||
2237 notebook->focus_tab->data != (gpointer) notebook->cur_page)
2238 notebook->focus_tab =
2239 g_list_find (notebook->children, notebook->cur_page);
2241 gtk_notebook_pages_allocate (notebook, >K_WIDGET (notebook)->allocation);
2243 if (GTK_WIDGET_MAPPED (notebook))
2245 if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
2246 gtk_widget_map (notebook->cur_page->child);
2249 gtk_widget_map (notebook->cur_page->child);
2250 gtk_widget_size_allocate (GTK_WIDGET (notebook),
2251 >K_WIDGET (notebook)->allocation);
2255 if (GTK_WIDGET_DRAWABLE (notebook))
2256 gtk_widget_queue_draw (GTK_WIDGET (notebook));
2260 gtk_notebook_draw_tab (GtkNotebook *notebook,
2261 GtkNotebookPage *page,
2264 GdkRectangle child_area;
2265 GdkRectangle page_area;
2266 GtkStateType state_type;
2270 g_return_if_fail (notebook != NULL);
2271 g_return_if_fail (page != NULL);
2272 g_return_if_fail (area != NULL);
2274 if (!GTK_WIDGET_MAPPED (page->tab_label))
2277 page_area.x = page->allocation.x;
2278 page_area.y = page->allocation.y;
2279 page_area.width = page->allocation.width;
2280 page_area.height = page->allocation.height;
2282 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2286 switch (notebook->tab_pos)
2289 if (child_area.x + child_area.width >
2290 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2292 points[0].x = page->allocation.x + page->allocation.width - 1;
2293 points[0].y = page->allocation.y + page->allocation.height - 1;
2295 points[1].x = page->allocation.x + page->allocation.width - 1;
2296 points[1].y = page->allocation.y + TAB_CURVATURE;
2298 points[2].x = page->allocation.x + page->allocation.width
2299 - TAB_CURVATURE - 1;
2300 points[2].y = page->allocation.y;
2305 points[0].x = page->allocation.x + page->allocation.width
2307 points[0].y = page->allocation.y;
2311 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2312 (page == notebook->cur_page ||
2313 page == (GtkNotebookPage *)(notebook->children->data) ||
2314 (notebook->scrollable &&
2315 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2317 points[n].x = page->allocation.x + TAB_CURVATURE;
2318 points[n++].y = page->allocation.y;
2320 points[n].x = page->allocation.x;
2321 points[n++].y = page->allocation.y + TAB_CURVATURE;
2323 points[n].x = page->allocation.x;
2324 points[n++].y = page->allocation.y + page->allocation.height - 1;
2328 points[n].x = page->allocation.x + TAB_OVERLAP;
2329 points[n++].y = page->allocation.y;
2332 case GTK_POS_BOTTOM:
2333 if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2334 (page == notebook->cur_page ||
2335 page == (GtkNotebookPage *)(notebook->children->data) ||
2336 (notebook->scrollable &&
2337 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2339 points[0].x = page->allocation.x;
2340 points[0].y = page->allocation.y;
2342 points[1].x = page->allocation.x;
2343 points[1].y = page->allocation.y + page->allocation.height
2344 - TAB_CURVATURE - 1;
2346 points[2].x = page->allocation.x + TAB_CURVATURE;
2347 points[2].y = page->allocation.y + page->allocation.height - 1;
2352 points[0].x = page->allocation.x + TAB_OVERLAP;
2353 points[0].y = page->allocation.y + page->allocation.height - 1;
2357 if (child_area.x + child_area.width >
2358 page->allocation.x + page->allocation.width - TAB_OVERLAP)
2360 points[n].x = page->allocation.x + page->allocation.width
2361 - TAB_CURVATURE - 1;
2362 points[n++].y = page->allocation.y + page->allocation.height - 1;
2364 points[n].x = page->allocation.x + page->allocation.width - 1;
2365 points[n++].y = page->allocation.y + page->allocation.height
2366 - TAB_CURVATURE - 1;
2368 points[n].x = page->allocation.x + page->allocation.width - 1;
2369 points[n++].y = page->allocation.y;
2373 points[n].x = page->allocation.x + page->allocation.width
2375 points[n++].y = page->allocation.y + page->allocation.height - 1;
2379 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2380 (page == notebook->cur_page ||
2381 page == (GtkNotebookPage *)(notebook->children->data) ||
2382 (notebook->scrollable &&
2383 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2385 points[0].x = page->allocation.x + page->allocation.width - 1;
2386 points[0].y = page->allocation.y;
2388 points[1].x = page->allocation.x + TAB_CURVATURE;
2389 points[1].y = page->allocation.y;
2391 points[2].x = page->allocation.x;
2392 points[2].y = page->allocation.y + TAB_CURVATURE;
2397 points[0].x = page->allocation.x;
2398 points[0].y = page->allocation.y + TAB_OVERLAP;
2402 if (child_area.y + child_area.height >
2403 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2405 points[n].x = page->allocation.x;
2406 points[n++].y = page->allocation.y + page->allocation.height
2407 - TAB_CURVATURE - 1;
2409 points[n].x = page->allocation.x + TAB_CURVATURE;
2410 points[n++].y = page->allocation.y + page->allocation.height - 1;
2412 points[n].x = page->allocation.x + page->allocation.width - 1;
2413 points[n++].y = page->allocation.y + page->allocation.height - 1;
2417 points[n].x = page->allocation.x;
2418 points[n++].y = page->allocation.y + page->allocation.height
2423 if (child_area.y + child_area.height >
2424 page->allocation.y + page->allocation.height - TAB_OVERLAP)
2426 points[0].x = page->allocation.x;
2427 points[0].y = page->allocation.y + page->allocation.height - 1;
2429 points[1].x = page->allocation.x + page->allocation.width
2430 - TAB_CURVATURE - 1;
2431 points[1].y = page->allocation.y + page->allocation.height - 1;
2433 points[2].x = page->allocation.x + page->allocation.width - 1;
2434 points[2].y = page->allocation.y + page->allocation.height
2435 - TAB_CURVATURE - 1;
2440 points[0].x = page->allocation.x + page->allocation.width - 1;
2441 points[0].y = page->allocation.y + page->allocation.height
2446 if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2447 (page == notebook->cur_page ||
2448 page == (GtkNotebookPage *)(notebook->children->data) ||
2449 (notebook->scrollable &&
2450 page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2452 points[n].x = page->allocation.x + page->allocation.width - 1;
2453 points[n++].y = page->allocation.y + TAB_CURVATURE;
2455 points[n].x = page->allocation.x + page->allocation.width
2456 - TAB_CURVATURE - 1;
2457 points[n++].y = page->allocation.y;
2459 points[n].x = page->allocation.x;
2460 points[n++].y = page->allocation.y;
2464 points[n].x = page->allocation.x + page->allocation.width - 1;
2465 points[n++].y = page->allocation.y + TAB_OVERLAP;
2470 widget = GTK_WIDGET(notebook);
2472 if (notebook->cur_page == page)
2474 state_type = GTK_STATE_NORMAL;
2478 state_type = GTK_STATE_ACTIVE;
2479 gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2480 TRUE, child_area.x, child_area.y,
2481 child_area.width, child_area.height);
2484 gtk_draw_polygon (widget->style, widget->window, state_type,
2485 GTK_SHADOW_OUT, points, n, FALSE);
2487 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2488 gtk_widget_draw (page->tab_label, &child_area);
2493 gtk_notebook_set_focus_child (GtkContainer *container,
2496 GtkNotebook *notebook;
2498 g_return_if_fail (container != NULL);
2499 g_return_if_fail (GTK_IS_NOTEBOOK (container));
2503 g_return_if_fail (GTK_IS_WIDGET (child));
2505 notebook = GTK_NOTEBOOK (container);
2507 notebook->child_has_focus = TRUE;
2508 if (!notebook->focus_tab)
2511 GtkNotebookPage *page;
2513 children = notebook->children;
2516 page = children->data;
2517 if (page->child == child || page->tab_label == child)
2518 gtk_notebook_switch_focus_tab (notebook, children);
2519 children = children->next;
2523 parent_class->set_focus_child (container, child);
2527 gtk_notebook_focus_in (GtkWidget *widget,
2528 GdkEventFocus *event)
2530 g_return_val_if_fail (widget != NULL, FALSE);
2531 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2532 g_return_val_if_fail (event != NULL, FALSE);
2534 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2535 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2536 gtk_widget_draw_focus (widget);
2542 gtk_notebook_focus_out (GtkWidget *widget,
2543 GdkEventFocus *event)
2545 g_return_val_if_fail (widget != NULL, FALSE);
2546 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2547 g_return_val_if_fail (event != NULL, FALSE);
2549 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2550 gtk_widget_draw_focus (widget);
2556 gtk_notebook_draw_focus (GtkWidget *widget)
2558 GtkNotebook *notebook;
2560 g_return_if_fail (widget != NULL);
2561 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2563 notebook = GTK_NOTEBOOK (widget);
2565 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2566 notebook->focus_tab)
2568 GtkNotebookPage *page;
2571 page = notebook->focus_tab->data;
2573 if (GTK_WIDGET_HAS_FOCUS (widget))
2574 gc = widget->style->black_gc;
2575 else if (page == notebook->cur_page)
2576 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2578 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2580 gdk_draw_rectangle (widget->window,
2582 page->tab_label->allocation.x - 1,
2583 page->tab_label->allocation.y - 1,
2584 page->tab_label->allocation.width + 1,
2585 page->tab_label->allocation.height + 1);
2590 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2594 g_return_if_fail (notebook != NULL);
2595 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2597 widget = GTK_WIDGET (notebook);
2599 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs)
2603 if (notebook->focus_tab)
2605 GtkNotebookPage *page;
2607 page = notebook->focus_tab->data;
2609 if (GTK_WIDGET_HAS_FOCUS (widget))
2610 gc = widget->style->black_gc;
2611 else if (page == notebook->cur_page)
2612 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2614 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2616 gdk_draw_rectangle (widget->window,
2618 page->tab_label->allocation.x - 1,
2619 page->tab_label->allocation.y - 1,
2620 page->tab_label->allocation.width + 1,
2621 page->tab_label->allocation.height + 1);
2626 if (old_page == notebook->cur_page)
2627 gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2629 gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2631 gdk_draw_rectangle (widget->window,
2633 old_page->tab_label->allocation.x - 1,
2634 old_page->tab_label->allocation.y - 1,
2635 old_page->tab_label->allocation.width + 1,
2636 old_page->tab_label->allocation.height + 1);
2642 gtk_notebook_calc_tabs (GtkNotebook *notebook,
2648 GtkNotebookPage *page = NULL;
2652 switch (notebook->tab_pos)
2655 case GTK_POS_BOTTOM:
2658 page = children->data;
2659 *tab_space -= page->requisition.width;
2660 if (*tab_space < 0 || children == *end)
2664 *tab_space = - (*tab_space + page->requisition.width);
2669 if (direction == STEP_NEXT)
2670 children = children->next;
2672 children = children->prev;
2679 page = children->data;
2680 *tab_space -= page->requisition.height;
2681 if (*tab_space < 0 || children == *end)
2685 *tab_space = - (*tab_space + page->requisition.height);
2690 if (direction == STEP_NEXT)
2691 children = children->next;
2693 children = children->prev;
2700 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2701 GtkAllocation *allocation)
2704 GtkContainer *container;
2705 GtkNotebookPage *page = NULL;
2706 GtkAllocation child_allocation;
2708 GList *last_child = NULL;
2709 gint showarrow = FALSE;
2718 if (!notebook->show_tabs || !notebook->children)
2721 widget = GTK_WIDGET (notebook);
2722 container = GTK_CONTAINER (notebook);
2724 child_allocation.x = container->border_width;
2725 child_allocation.y = container->border_width;
2727 switch (notebook->tab_pos)
2729 case GTK_POS_BOTTOM:
2730 child_allocation.y = (allocation->height -
2731 notebook->cur_page->requisition.height -
2732 container->border_width);
2734 child_allocation.height = notebook->cur_page->requisition.height;
2737 child_allocation.x = (allocation->width -
2738 notebook->cur_page->requisition.width -
2739 container->border_width);
2741 child_allocation.width = notebook->cur_page->requisition.width;
2745 if (notebook->scrollable)
2749 children = notebook->children;
2751 if (notebook->focus_tab)
2752 focus_tab = notebook->focus_tab;
2753 else if (notebook->first_tab)
2754 focus_tab = notebook->first_tab;
2756 focus_tab = notebook->children;
2758 switch (notebook->tab_pos)
2761 case GTK_POS_BOTTOM:
2764 page = children->data;
2765 children = children->next;
2766 tab_space += page->requisition.width;
2768 if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP)
2771 page = focus_tab->data;
2773 tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2774 2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2775 x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2777 page = notebook->children->data;
2778 if (notebook->tab_pos == GTK_POS_TOP)
2779 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2781 y = (allocation->height - container->border_width -
2782 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2789 page = children->data;
2790 children = children->next;
2791 tab_space += page->requisition.height;
2793 if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2796 page = focus_tab->data;
2797 tab_space = (allocation->height -
2798 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2799 2 * container->border_width - page->requisition.height);
2800 y = allocation->height - container->border_width - ARROW_SIZE;
2802 page = notebook->children->data;
2803 if (notebook->tab_pos == GTK_POS_LEFT)
2804 x = (container->border_width +
2805 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2807 x = (allocation->width - container->border_width -
2808 (2 * ARROW_SIZE - ARROW_SPACING) -
2809 (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2813 if (showarrow) /* first_tab <- focus_tab */
2815 children = focus_tab->prev;
2818 if (notebook->first_tab == children)
2820 children = children->prev;
2824 notebook->first_tab = focus_tab;
2826 gtk_notebook_calc_tabs (notebook, focus_tab->prev,
2827 &(notebook->first_tab), &tab_space,
2831 notebook->first_tab = notebook->first_tab->next;
2832 if (!notebook->first_tab)
2833 notebook->first_tab = focus_tab;
2834 last_child = focus_tab->next;
2836 else /* focus_tab -> end */
2838 if (!notebook->first_tab)
2839 notebook->first_tab = notebook->children;
2842 gtk_notebook_calc_tabs (notebook, focus_tab->next,
2843 &children, &tab_space, STEP_NEXT);
2846 last_child = children;
2847 else /* start <- first_tab */
2851 gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2852 &children, &tab_space, STEP_PREV);
2854 notebook->first_tab = children->next;
2856 notebook->first_tab = notebook->children;
2860 if (GTK_WIDGET_REALIZED (notebook))
2862 gdk_window_move (notebook->panel, x, y);
2863 gdk_window_show (notebook->panel);
2868 tab_space = -tab_space;
2870 children = notebook->first_tab;
2871 while (children != last_child)
2873 children = children->next;
2880 children = notebook->children;
2881 while (children != notebook->first_tab)
2883 page = children->data;
2884 children = children->next;
2886 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2887 gtk_widget_unmap (page->tab_label);
2890 children = last_child;
2893 page = children->data;
2894 children = children->next;
2896 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2897 gtk_widget_unmap (page->tab_label);
2900 else /* !showarrow */
2902 notebook->first_tab = notebook->children;
2904 if (GTK_WIDGET_REALIZED (notebook))
2905 gdk_window_hide (notebook->panel);
2907 children = notebook->first_tab;
2910 children = notebook->children;
2913 while (children != last_child)
2915 page = children->data;
2916 children = children->next;
2918 if (GTK_WIDGET_VISIBLE (page->child))
2920 new_fill = (tab_space * i++) / n;
2921 switch (notebook->tab_pos)
2924 case GTK_POS_BOTTOM:
2925 child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2929 child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2932 old_fill = new_fill;
2933 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2935 switch (notebook->tab_pos)
2938 case GTK_POS_BOTTOM:
2939 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2943 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2947 if (GTK_WIDGET_REALIZED (notebook) &&
2948 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2949 gtk_widget_map (page->tab_label);
2955 gtk_notebook_page_allocate (GtkNotebook *notebook,
2956 GtkNotebookPage *page,
2957 GtkAllocation *allocation)
2959 GtkAllocation child_allocation;
2960 gint xthickness, ythickness;
2962 g_return_if_fail (notebook != NULL);
2963 g_return_if_fail (page != NULL);
2964 g_return_if_fail (allocation != NULL);
2966 page->allocation = *allocation;
2968 xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2969 ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2971 if (notebook->cur_page != page)
2973 switch (notebook->tab_pos)
2976 page->allocation.y += ythickness;
2977 case GTK_POS_BOTTOM:
2978 page->allocation.height -= ythickness;
2981 page->allocation.x += xthickness;
2983 page->allocation.width -= xthickness;
2988 switch (notebook->tab_pos)
2991 child_allocation.x = xthickness + notebook->tab_border;
2992 child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2993 child_allocation.width = page->allocation.width - child_allocation.x * 2;
2994 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2995 child_allocation.x += page->allocation.x;
2997 case GTK_POS_BOTTOM:
2998 child_allocation.x = xthickness + notebook->tab_border;
2999 child_allocation.width = page->allocation.width - child_allocation.x * 2;
3000 child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
3001 child_allocation.x += page->allocation.x;
3002 child_allocation.y = page->allocation.y + notebook->tab_border;
3005 child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
3006 child_allocation.y = ythickness + notebook->tab_border;
3007 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3008 child_allocation.height = page->allocation.height - child_allocation.y * 2;
3009 child_allocation.y += page->allocation.y;
3012 child_allocation.y = ythickness + notebook->tab_border;
3013 child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3014 child_allocation.height = page->allocation.height - child_allocation.y * 2;
3015 child_allocation.x = page->allocation.x + notebook->tab_border;
3016 child_allocation.y += page->allocation.y;
3020 if (page->tab_label)
3021 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3025 gtk_notebook_menu_switch_page (GtkWidget *widget,
3026 GtkNotebookPage *page)
3028 GtkNotebook *notebook;
3032 g_return_if_fail (widget != NULL);
3033 g_return_if_fail (page != NULL);
3035 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3036 (GTK_MENU (widget->parent)));
3038 if (notebook->cur_page == page)
3042 children = notebook->children;
3043 while (children && children->data != page)
3045 children = children->next;
3049 gtk_signal_emit (GTK_OBJECT (notebook),
3050 notebook_signals[SWITCH_PAGE],
3056 gtk_notebook_switch_page (GtkNotebook *notebook,
3057 GtkNotebookPage *page,
3060 g_return_if_fail (notebook != NULL);
3061 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3062 g_return_if_fail (page != NULL);
3064 if (notebook->cur_page == page)
3067 gtk_signal_emit (GTK_OBJECT (notebook),
3068 notebook_signals[SWITCH_PAGE],
3074 gtk_notebook_marshal_signal (GtkObject *object,
3079 GtkNotebookSignal rfunc;
3081 rfunc = (GtkNotebookSignal) func;
3083 (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
3088 gtk_notebook_focus (GtkContainer *container,
3089 GtkDirectionType direction)
3091 GtkNotebook *notebook;
3092 GtkWidget *focus_child;
3093 GtkNotebookPage *page = NULL;
3094 GtkNotebookPage *old_page = NULL;
3097 g_return_val_if_fail (container != NULL, FALSE);
3098 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
3100 notebook = GTK_NOTEBOOK (container);
3102 if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
3105 focus_child = container->focus_child;
3106 gtk_container_set_focus_child (container, NULL);
3108 if (!notebook->show_tabs)
3110 if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
3112 if (GTK_IS_CONTAINER (notebook->cur_page->child))
3114 if (gtk_container_focus
3115 (GTK_CONTAINER (notebook->cur_page->child), direction))
3118 else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
3122 gtk_widget_grab_focus (notebook->cur_page->child);
3130 if (notebook->focus_tab)
3131 old_page = notebook->focus_tab->data;
3135 if (focus_child && old_page && focus_child == old_page->child &&
3136 notebook->child_has_focus)
3138 if (GTK_WIDGET_VISIBLE (old_page->child))
3140 if (GTK_IS_CONTAINER (old_page->child) &&
3141 !GTK_WIDGET_HAS_FOCUS (old_page->child))
3143 if (gtk_container_focus (GTK_CONTAINER (old_page->child),
3147 gtk_widget_grab_focus (GTK_WIDGET(notebook));
3155 case GTK_DIR_TAB_FORWARD:
3158 if (!notebook->focus_tab)
3159 gtk_notebook_switch_focus_tab (notebook, notebook->children);
3161 gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->next);
3163 if (!notebook->focus_tab)
3165 gtk_notebook_focus_changed (notebook, old_page);
3169 page = notebook->focus_tab->data;
3173 case GTK_DIR_TAB_BACKWARD:
3176 if (!notebook->focus_tab)
3177 gtk_notebook_switch_focus_tab
3178 (notebook, g_list_last (notebook->children));
3180 gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->prev);
3182 if (!notebook->focus_tab)
3184 gtk_notebook_focus_changed (notebook, old_page);
3188 page = notebook->focus_tab->data;
3195 if (!GTK_WIDGET_HAS_FOCUS (container) )
3196 gtk_widget_grab_focus (GTK_WIDGET (container));
3198 if (GTK_WIDGET_MAPPED (page->tab_label))
3199 gtk_notebook_focus_changed (notebook, old_page);
3202 gtk_notebook_pages_allocate (notebook,
3203 &(GTK_WIDGET (notebook)->allocation));
3204 gtk_notebook_expose_tabs (notebook);
3212 gtk_notebook_page_select (GtkNotebook *notebook)
3214 g_return_val_if_fail (notebook != NULL, FALSE);
3215 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3217 if (notebook->focus_tab)
3219 GtkNotebookPage *page;
3223 page = notebook->focus_tab->data;
3225 children = notebook->children;
3227 while (children != notebook->focus_tab)
3229 children = children->next;
3233 gtk_notebook_switch_page (notebook, page, num);
3235 if (GTK_WIDGET_VISIBLE (page->child))
3237 if (GTK_IS_CONTAINER (page->child))
3239 if (gtk_container_focus (GTK_CONTAINER (page->child),
3240 GTK_DIR_TAB_FORWARD))
3243 else if (GTK_WIDGET_CAN_FOCUS (page->child))
3245 gtk_widget_grab_focus (page->child);
3254 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3258 GtkNotebookPage *old_page = NULL;
3259 GtkNotebookPage *page;
3261 g_return_if_fail (notebook != NULL);
3262 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3264 if (notebook->focus_tab == new_child)
3267 old_tab = notebook->focus_tab;
3268 notebook->focus_tab = new_child;
3270 if (notebook->scrollable)
3272 if ((new_child == NULL) != (old_tab == NULL))
3274 gdk_window_clear (notebook->panel);
3275 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3276 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3281 if ((old_tab->prev == NULL) != (new_child->prev == NULL))
3283 gdk_window_clear_area (notebook->panel, 0, 0,
3284 ARROW_SIZE, ARROW_SIZE);
3285 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3287 if ((old_tab->next == NULL) != (new_child->next == NULL))
3289 gdk_window_clear_area (notebook->panel,
3290 ARROW_SIZE + ARROW_SPACING, 0,
3291 ARROW_SIZE, ARROW_SIZE);
3292 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3297 if (!notebook->focus_tab)
3301 old_page = old_tab->data;
3303 page = notebook->focus_tab->data;
3304 if (GTK_WIDGET_MAPPED (page->tab_label))
3305 gtk_notebook_focus_changed (notebook, old_page);
3308 gtk_notebook_pages_allocate (notebook,
3309 &(GTK_WIDGET (notebook)->allocation));
3310 gtk_notebook_expose_tabs (notebook);
3315 gtk_notebook_key_press (GtkWidget *widget,
3318 GtkNotebook *notebook;
3319 GtkDirectionType direction = 0;
3322 g_return_val_if_fail (widget != NULL, FALSE);
3323 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3324 g_return_val_if_fail (event != NULL, FALSE);
3326 notebook = GTK_NOTEBOOK (widget);
3329 if (!notebook->children || !notebook->show_tabs)
3332 switch (event->keyval)
3335 direction = GTK_DIR_UP;
3338 direction = GTK_DIR_LEFT;
3341 direction = GTK_DIR_DOWN;
3344 direction = GTK_DIR_RIGHT;
3347 case GDK_ISO_Left_Tab:
3348 if (event->state & GDK_SHIFT_MASK)
3349 direction = GTK_DIR_TAB_BACKWARD;
3351 direction = GTK_DIR_TAB_FORWARD;
3354 gtk_notebook_switch_focus_tab (notebook, notebook->children);
3357 gtk_notebook_switch_focus_tab (notebook,
3358 g_list_last (notebook->children));
3362 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
3368 return gtk_container_focus (GTK_CONTAINER (widget), direction);
3373 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3376 g_return_if_fail (notebook != NULL);
3377 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3379 if (notebook->tab_border != tab_border)
3381 notebook->tab_border = tab_border;
3383 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3384 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3389 gtk_notebook_update_labels (GtkNotebook *notebook,
3393 GtkNotebookPage *page;
3400 sprintf (string, "Page %u", page_num);
3401 if (notebook->show_tabs && page->default_tab)
3402 gtk_label_set (GTK_LABEL (page->tab_label), string);
3403 if (notebook->menu && page->default_menu)
3405 if (GTK_IS_LABEL (page->tab_label))
3406 gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
3408 gtk_label_set (GTK_LABEL (page->menu_label), string);
3415 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3416 GtkNotebookPage *page,
3419 GtkWidget *menu_item;
3421 if (page->default_menu)
3423 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3424 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3426 page->menu_label = gtk_label_new ("");
3427 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3430 gtk_widget_show (page->menu_label);
3431 menu_item = gtk_menu_item_new ();
3432 gtk_widget_freeze_accelerators (menu_item);
3433 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3434 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
3435 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3436 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3437 gtk_widget_show (menu_item);
3441 gtk_notebook_popup_enable (GtkNotebook *notebook)
3443 GtkNotebookPage *page;
3446 g_return_if_fail (notebook != NULL);
3447 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3452 notebook->menu = gtk_menu_new ();
3454 children = notebook->children;
3457 page = children->data;
3458 children = children->next;
3459 gtk_notebook_menu_item_create (notebook, page, -1);
3461 gtk_notebook_update_labels (notebook, notebook->children,1);
3463 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
3464 gtk_notebook_menu_detacher);
3468 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3471 gtk_widget_unparent (GTK_BIN(widget)->child);
3472 GTK_BIN(widget)->child = NULL;
3476 gtk_notebook_popup_disable (GtkNotebook *notebook)
3478 g_return_if_fail (notebook != NULL);
3479 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3481 if (!notebook->menu)
3484 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
3485 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
3486 gtk_widget_destroy (notebook->menu);
3490 gtk_notebook_menu_detacher (GtkWidget *widget,
3493 GtkNotebook *notebook;
3495 g_return_if_fail (widget != NULL);
3496 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3498 notebook = GTK_NOTEBOOK (widget);
3499 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3501 notebook->menu = NULL;
3505 gtk_notebook_find_page (gconstpointer a,
3508 return (((GtkNotebookPage *) a)->child != b);