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.
21 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gtknotebook.h"
28 #include "gtksignal.h"
31 #include "gtkmenuitem.h"
33 #include <gdk/gdkkeysyms.h>
39 #define TAB_CURVATURE 1
41 #define ARROW_SPACING 0
43 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
44 #define NOTEBOOK_SCROLL_DELAY (100)
81 /** GtkNotebook Methods **/
82 static void gtk_notebook_class_init (GtkNotebookClass *klass);
83 static void gtk_notebook_init (GtkNotebook *notebook);
85 /** GtkObject Methods **/
86 static void gtk_notebook_destroy (GtkObject *object);
87 static void gtk_notebook_set_arg (GtkObject *object,
90 static void gtk_notebook_get_arg (GtkObject *object,
94 /** GtkWidget Methods **/
95 static void gtk_notebook_map (GtkWidget *widget);
96 static void gtk_notebook_unmap (GtkWidget *widget);
97 static void gtk_notebook_realize (GtkWidget *widget);
98 static void gtk_notebook_unrealize (GtkWidget *widget);
99 static void gtk_notebook_size_request (GtkWidget *widget,
100 GtkRequisition *requisition);
101 static void gtk_notebook_size_allocate (GtkWidget *widget,
102 GtkAllocation *allocation);
103 static void gtk_notebook_draw (GtkWidget *widget,
105 static gint gtk_notebook_expose (GtkWidget *widget,
106 GdkEventExpose *event);
107 static gint gtk_notebook_button_press (GtkWidget *widget,
108 GdkEventButton *event);
109 static gint gtk_notebook_button_release (GtkWidget *widget,
110 GdkEventButton *event);
111 static gint gtk_notebook_enter_notify (GtkWidget *widget,
112 GdkEventCrossing *event);
113 static gint gtk_notebook_leave_notify (GtkWidget *widget,
114 GdkEventCrossing *event);
115 static gint gtk_notebook_motion_notify (GtkWidget *widget,
116 GdkEventMotion *event);
117 static gint gtk_notebook_key_press (GtkWidget *widget,
119 static gint gtk_notebook_focus_in (GtkWidget *widget,
120 GdkEventFocus *event);
121 static gint gtk_notebook_focus_out (GtkWidget *widget,
122 GdkEventFocus *event);
123 static void gtk_notebook_draw_focus (GtkWidget *widget);
124 static void gtk_notebook_style_set (GtkWidget *widget,
125 GtkStyle *previous_style);
127 /** GtkContainer Methods **/
128 static void gtk_notebook_set_child_arg (GtkContainer *container,
132 static void gtk_notebook_get_child_arg (GtkContainer *container,
136 static void gtk_notebook_add (GtkContainer *container,
138 static void gtk_notebook_remove (GtkContainer *container,
140 static gint gtk_notebook_focus (GtkContainer *container,
141 GtkDirectionType direction);
142 static void gtk_notebook_set_focus_child (GtkContainer *container,
144 static GtkType gtk_notebook_child_type (GtkContainer *container);
145 static void gtk_notebook_forall (GtkContainer *container,
146 gboolean include_internals,
147 GtkCallback callback,
148 gpointer callback_data);
150 /** GtkNotebook Private Functions **/
151 static void gtk_notebook_panel_realize (GtkNotebook *notebook);
152 static void gtk_notebook_expose_tabs (GtkNotebook *notebook);
153 static void gtk_notebook_focus_changed (GtkNotebook *notebook,
154 GtkNotebookPage *old_page);
155 static void gtk_notebook_real_remove (GtkNotebook *notebook,
157 static void gtk_notebook_update_labels (GtkNotebook *notebook);
158 static gint gtk_notebook_timer (GtkNotebook *notebook);
159 static gint gtk_notebook_page_compare (gconstpointer a,
161 static gint gtk_notebook_real_page_position (GtkNotebook *notebook,
163 static GList * gtk_notebook_search_page (GtkNotebook *notebook,
166 gboolean find_visible);
168 /** GtkNotebook Drawing Functions **/
169 static void gtk_notebook_paint (GtkWidget *widget,
171 static void gtk_notebook_draw_tab (GtkNotebook *notebook,
172 GtkNotebookPage *page,
174 static void gtk_notebook_draw_arrow (GtkNotebook *notebook,
176 static void gtk_notebook_set_shape (GtkNotebook *notebook);
178 /** GtkNotebook Size Allocate Functions **/
179 static void gtk_notebook_pages_allocate (GtkNotebook *notebook,
180 GtkAllocation *allocation);
181 static void gtk_notebook_page_allocate (GtkNotebook *notebook,
182 GtkNotebookPage *page,
183 GtkAllocation *allocation);
184 static void gtk_notebook_calc_tabs (GtkNotebook *notebook,
190 /** GtkNotebook Page Switch Methods **/
191 static void gtk_notebook_real_switch_page (GtkNotebook *notebook,
192 GtkNotebookPage *page,
195 /** GtkNotebook Page Switch Functions **/
196 static void gtk_notebook_switch_page (GtkNotebook *notebook,
197 GtkNotebookPage *page,
199 static gint gtk_notebook_page_select (GtkNotebook *notebook);
200 static void gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
202 static void gtk_notebook_menu_switch_page (GtkWidget *widget,
203 GtkNotebookPage *page);
205 /** GtkNotebook Menu Functions **/
206 static void gtk_notebook_menu_item_create (GtkNotebook *notebook,
208 static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
210 static void gtk_notebook_menu_detacher (GtkWidget *widget,
214 static GtkContainerClass *parent_class = NULL;
215 static guint notebook_signals[LAST_SIGNAL] = { 0 };
218 gtk_notebook_get_type (void)
220 static GtkType notebook_type = 0;
224 static const GtkTypeInfo notebook_info =
227 sizeof (GtkNotebook),
228 sizeof (GtkNotebookClass),
229 (GtkClassInitFunc) gtk_notebook_class_init,
230 (GtkObjectInitFunc) gtk_notebook_init,
231 /* reserved_1 */ NULL,
232 /* reserved_2 */ NULL,
233 (GtkClassInitFunc) NULL,
236 notebook_type = gtk_type_unique (gtk_container_get_type (), ¬ebook_info);
239 return notebook_type;
243 gtk_notebook_class_init (GtkNotebookClass *class)
245 GtkObjectClass *object_class;
246 GtkWidgetClass *widget_class;
247 GtkContainerClass *container_class;
249 object_class = (GtkObjectClass*) class;
250 widget_class = (GtkWidgetClass*) class;
251 container_class = (GtkContainerClass*) class;
252 parent_class = gtk_type_class (gtk_container_get_type ());
254 gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
255 gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
256 gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_WRITABLE, ARG_TAB_BORDER);
257 gtk_object_add_arg_type ("GtkNotebook::tab_hborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_HBORDER);
258 gtk_object_add_arg_type ("GtkNotebook::tab_vborder", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_VBORDER);
259 gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
260 gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
261 gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
262 gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
263 gtk_object_add_arg_type ("GtkNotebook::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
265 gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
266 gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
267 gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
268 gtk_container_add_child_arg_type ("GtkNotebook::tab_fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_FILL);
269 gtk_container_add_child_arg_type ("GtkNotebook::tab_pack", GTK_TYPE_BOOL, GTK_ARG_READWRITE, CHILD_ARG_TAB_PACK);
271 notebook_signals[SWITCH_PAGE] =
272 gtk_signal_new ("switch_page",
275 GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
276 gtk_marshal_NONE__POINTER_UINT,
281 gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
283 object_class->set_arg = gtk_notebook_set_arg;
284 object_class->get_arg = gtk_notebook_get_arg;
285 object_class->destroy = gtk_notebook_destroy;
287 widget_class->map = gtk_notebook_map;
288 widget_class->unmap = gtk_notebook_unmap;
289 widget_class->realize = gtk_notebook_realize;
290 widget_class->unrealize = gtk_notebook_unrealize;
291 widget_class->size_request = gtk_notebook_size_request;
292 widget_class->size_allocate = gtk_notebook_size_allocate;
293 widget_class->draw = gtk_notebook_draw;
294 widget_class->expose_event = gtk_notebook_expose;
295 widget_class->button_press_event = gtk_notebook_button_press;
296 widget_class->button_release_event = gtk_notebook_button_release;
297 widget_class->enter_notify_event = gtk_notebook_enter_notify;
298 widget_class->leave_notify_event = gtk_notebook_leave_notify;
299 widget_class->motion_notify_event = gtk_notebook_motion_notify;
300 widget_class->key_press_event = gtk_notebook_key_press;
301 widget_class->focus_in_event = gtk_notebook_focus_in;
302 widget_class->focus_out_event = gtk_notebook_focus_out;
303 widget_class->draw_focus = gtk_notebook_draw_focus;
304 widget_class->style_set = gtk_notebook_style_set;
306 container_class->add = gtk_notebook_add;
307 container_class->remove = gtk_notebook_remove;
308 container_class->forall = gtk_notebook_forall;
309 container_class->focus = gtk_notebook_focus;
310 container_class->set_focus_child = gtk_notebook_set_focus_child;
311 container_class->get_child_arg = gtk_notebook_get_child_arg;
312 container_class->set_child_arg = gtk_notebook_set_child_arg;
313 container_class->child_type = gtk_notebook_child_type;
315 class->switch_page = gtk_notebook_real_switch_page;
319 gtk_notebook_init (GtkNotebook *notebook)
321 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
322 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_NO_WINDOW);
324 notebook->cur_page = NULL;
325 notebook->children = NULL;
326 notebook->first_tab = NULL;
327 notebook->focus_tab = NULL;
328 notebook->panel = NULL;
329 notebook->menu = NULL;
331 notebook->tab_hborder = 2;
332 notebook->tab_vborder = 2;
334 notebook->show_tabs = TRUE;
335 notebook->show_border = TRUE;
336 notebook->tab_pos = GTK_POS_TOP;
337 notebook->scrollable = FALSE;
338 notebook->in_child = 0;
339 notebook->click_child = 0;
340 notebook->button = 0;
341 notebook->need_timer = 0;
342 notebook->child_has_focus = FALSE;
343 notebook->have_visible_child = FALSE;
347 gtk_notebook_new (void)
349 return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
352 /* Private GtkObject Methods :
354 * gtk_notebook_destroy
355 * gtk_notebook_set_arg
356 * gtk_notebook_get_arg
359 gtk_notebook_destroy (GtkObject *object)
361 GtkNotebook *notebook;
363 g_return_if_fail (object != NULL);
364 g_return_if_fail (GTK_IS_NOTEBOOK (object));
366 notebook = GTK_NOTEBOOK (object);
369 gtk_notebook_popup_disable (notebook);
371 GTK_OBJECT_CLASS (parent_class)->destroy (object);
375 gtk_notebook_set_arg (GtkObject *object,
379 GtkNotebook *notebook;
381 notebook = GTK_NOTEBOOK (object);
386 gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
388 case ARG_SHOW_BORDER:
389 gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
392 gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
394 case ARG_ENABLE_POPUP:
395 if (GTK_VALUE_BOOL (*arg))
396 gtk_notebook_popup_enable (notebook);
398 gtk_notebook_popup_disable (notebook);
400 case ARG_HOMOGENEOUS:
401 gtk_notebook_set_homogeneous_tabs (notebook, GTK_VALUE_BOOL (*arg));
404 gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
407 gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
410 gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
412 case ARG_TAB_HBORDER:
413 gtk_notebook_set_tab_hborder (notebook, GTK_VALUE_UINT (*arg));
415 case ARG_TAB_VBORDER:
416 gtk_notebook_set_tab_vborder (notebook, GTK_VALUE_UINT (*arg));
424 gtk_notebook_get_arg (GtkObject *object,
428 GtkNotebook *notebook;
430 notebook = GTK_NOTEBOOK (object);
435 GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
437 case ARG_SHOW_BORDER:
438 GTK_VALUE_BOOL (*arg) = notebook->show_border;
441 GTK_VALUE_BOOL (*arg) = notebook->scrollable;
443 case ARG_ENABLE_POPUP:
444 GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
446 case ARG_HOMOGENEOUS:
447 GTK_VALUE_BOOL (*arg) = notebook->homogeneous;
450 GTK_VALUE_INT (*arg) = gtk_notebook_get_current_page (notebook);
453 GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
455 case ARG_TAB_HBORDER:
456 GTK_VALUE_UINT (*arg) = notebook->tab_hborder;
458 case ARG_TAB_VBORDER:
459 GTK_VALUE_UINT (*arg) = notebook->tab_vborder;
462 arg->type = GTK_TYPE_INVALID;
467 /* Private GtkWidget Methods :
471 * gtk_notebook_realize
472 * gtk_notebook_size_request
473 * gtk_notebook_size_allocate
475 * gtk_notebook_expose
476 * gtk_notebook_button_press
477 * gtk_notebook_button_release
478 * gtk_notebook_enter_notify
479 * gtk_notebook_leave_notify
480 * gtk_notebook_motion_notify
481 * gtk_notebook_key_press
482 * gtk_notebook_focus_in
483 * gtk_notebook_focus_out
484 * gtk_notebook_draw_focus
485 * gtk_notebook_style_set
488 gtk_notebook_map (GtkWidget *widget)
490 GtkNotebook *notebook;
491 GtkNotebookPage *page;
494 g_return_if_fail (widget != NULL);
495 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
497 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
499 notebook = GTK_NOTEBOOK (widget);
501 if (notebook->cur_page &&
502 GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
503 !GTK_WIDGET_MAPPED (notebook->cur_page->child))
504 gtk_widget_map (notebook->cur_page->child);
506 if (notebook->scrollable)
507 gtk_notebook_pages_allocate (notebook, &(widget->allocation));
510 children = notebook->children;
514 page = children->data;
515 children = children->next;
517 if (page->tab_label &&
518 GTK_WIDGET_VISIBLE (page->tab_label) &&
519 !GTK_WIDGET_MAPPED (page->tab_label))
520 gtk_widget_map (page->tab_label);
524 gdk_window_show (widget->window);
528 gtk_notebook_unmap (GtkWidget *widget)
530 g_return_if_fail (widget != NULL);
531 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
533 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
534 gdk_window_hide (widget->window);
535 if (GTK_NOTEBOOK (widget)->panel)
536 gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
540 gtk_notebook_realize (GtkWidget *widget)
542 GtkNotebook *notebook;
543 GdkWindowAttr attributes;
544 gint attributes_mask;
546 g_return_if_fail (widget != NULL);
547 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
549 notebook = GTK_NOTEBOOK (widget);
550 GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
552 attributes.window_type = GDK_WINDOW_CHILD;
553 attributes.x = widget->allocation.x;
554 attributes.y = widget->allocation.y;
555 attributes.width = widget->allocation.width;
556 attributes.height = widget->allocation.height;
557 attributes.wclass = GDK_INPUT_OUTPUT;
558 attributes.visual = gtk_widget_get_visual (widget);
559 attributes.colormap = gtk_widget_get_colormap (widget);
560 attributes.event_mask = gtk_widget_get_events (widget);
561 attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
562 GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
564 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
566 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
567 gdk_window_set_user_data (widget->window, notebook);
569 widget->style = gtk_style_attach (widget->style, widget->window);
570 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
572 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
573 if (notebook->scrollable)
574 gtk_notebook_panel_realize (notebook);
578 gtk_notebook_unrealize (GtkWidget *widget)
580 GtkNotebook *notebook;
582 g_return_if_fail (widget != NULL);
583 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
585 notebook = GTK_NOTEBOOK (widget);
589 gdk_window_set_user_data (notebook->panel, NULL);
590 gdk_window_destroy (notebook->panel);
591 notebook->panel = NULL;
594 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
595 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
599 gtk_notebook_size_request (GtkWidget *widget,
600 GtkRequisition *requisition)
602 GtkNotebook *notebook;
603 GtkNotebookPage *page;
605 GtkRequisition child_requisition;
606 gboolean switch_page = FALSE;
609 g_return_if_fail (widget != NULL);
610 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
611 g_return_if_fail (requisition != NULL);
613 notebook = GTK_NOTEBOOK (widget);
614 widget->requisition.width = 0;
615 widget->requisition.height = 0;
617 for (children = notebook->children, vis_pages = 0; children;
618 children = children->next)
620 page = children->data;
622 if (GTK_WIDGET_VISIBLE (page->child))
625 gtk_widget_size_request (page->child, &child_requisition);
627 widget->requisition.width = MAX (widget->requisition.width,
628 child_requisition.width);
629 widget->requisition.height = MAX (widget->requisition.height,
630 child_requisition.height);
632 if (GTK_WIDGET_MAPPED (page->child) && page != notebook->cur_page)
633 gtk_widget_unmap (page->child);
634 if (notebook->menu && page->menu_label->parent &&
635 !GTK_WIDGET_VISIBLE (page->menu_label->parent))
636 gtk_widget_show (page->menu_label->parent);
640 if (page == notebook->cur_page)
642 if (notebook->menu && page->menu_label->parent &&
643 GTK_WIDGET_VISIBLE (page->menu_label->parent))
644 gtk_widget_hide (page->menu_label->parent);
648 if (notebook->show_border || notebook->show_tabs)
650 widget->requisition.width += widget->style->klass->xthickness * 2;
651 widget->requisition.height += widget->style->klass->ythickness * 2;
653 if (notebook->show_tabs)
660 for (children = notebook->children; children;
661 children = children->next)
663 page = children->data;
665 if (GTK_WIDGET_VISIBLE (page->child))
667 if (!GTK_WIDGET_VISIBLE (page->tab_label))
668 gtk_widget_show (page->tab_label);
670 gtk_widget_size_request (page->tab_label,
673 page->requisition.width =
674 child_requisition.width +
675 2 * widget->style->klass->xthickness;
676 page->requisition.height =
677 child_requisition.height +
678 2 * widget->style->klass->ythickness;
680 switch (notebook->tab_pos)
684 page->requisition.height += 2 * (notebook->tab_vborder +
686 tab_height = MAX (tab_height, page->requisition.height);
687 tab_max = MAX (tab_max, page->requisition.width);
691 page->requisition.width += 2 * (notebook->tab_hborder +
693 tab_width = MAX (tab_width, page->requisition.width);
694 tab_max = MAX (tab_max, page->requisition.height);
698 else if (GTK_WIDGET_VISIBLE (page->tab_label))
699 gtk_widget_hide (page->tab_label);
702 children = notebook->children;
706 switch (notebook->tab_pos)
713 if (notebook->scrollable && vis_pages > 1 &&
714 widget->requisition.width < tab_width)
715 tab_height = MAX (tab_height, ARROW_SIZE);
717 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
718 notebook->tab_hborder) - TAB_OVERLAP;
722 page = children->data;
723 children = children->next;
725 if (!GTK_WIDGET_VISIBLE (page->child))
728 if (notebook->homogeneous)
729 page->requisition.width = tab_max;
731 page->requisition.width += padding;
733 tab_width += page->requisition.width;
734 page->requisition.height = tab_height;
737 if (notebook->scrollable && vis_pages > 1 &&
738 widget->requisition.width < tab_width)
739 tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
741 if (notebook->homogeneous && !notebook->scrollable)
742 widget->requisition.width = MAX (widget->requisition.width,
743 vis_pages * tab_max +
746 widget->requisition.width = MAX (widget->requisition.width,
747 tab_width + TAB_OVERLAP);
749 widget->requisition.height += tab_height;
756 if (notebook->scrollable && vis_pages > 1 &&
757 widget->requisition.height < tab_height)
758 tab_width = MAX (tab_width, ARROW_SPACING +2 * ARROW_SIZE);
760 padding = 2 * (TAB_CURVATURE + FOCUS_WIDTH +
761 notebook->tab_vborder) - TAB_OVERLAP;
766 page = children->data;
767 children = children->next;
769 if (!GTK_WIDGET_VISIBLE (page->child))
772 page->requisition.width = tab_width;
774 if (notebook->homogeneous)
775 page->requisition.height = tab_max;
777 page->requisition.height += padding;
779 tab_height += page->requisition.height;
782 if (notebook->scrollable && vis_pages > 1 &&
783 widget->requisition.height < tab_height)
784 tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
786 widget->requisition.width += tab_width;
788 if (notebook->homogeneous && !notebook->scrollable)
789 widget->requisition.height =
790 MAX (widget->requisition.height,
791 vis_pages * tab_max + TAB_OVERLAP);
793 widget->requisition.height =
794 MAX (widget->requisition.height,
795 tab_height + TAB_OVERLAP);
797 if (!notebook->homogeneous || notebook->scrollable)
799 widget->requisition.height = MAX (widget->requisition.height,
800 vis_pages * tab_max +
808 for (children = notebook->children; children;
809 children = children->next)
811 page = children->data;
813 if (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))
814 gtk_widget_hide (page->tab_label);
819 widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
820 widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
826 for (children = notebook->children; children;
827 children = children->next)
829 page = children->data;
830 if (GTK_WIDGET_VISIBLE (page->child))
832 gtk_notebook_switch_page (notebook, page, -1);
837 else if (GTK_WIDGET_VISIBLE (widget))
839 widget->requisition.width = GTK_CONTAINER (widget)->border_width * 2;
840 widget->requisition.height= GTK_CONTAINER (widget)->border_width * 2;
843 if (vis_pages && !notebook->cur_page)
845 children = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
848 notebook->first_tab = children;
849 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (children),-1);
855 gtk_notebook_size_allocate (GtkWidget *widget,
856 GtkAllocation *allocation)
858 GtkNotebook *notebook;
859 GtkNotebookPage *page;
860 GtkAllocation child_allocation;
863 g_return_if_fail (widget != NULL);
864 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
865 g_return_if_fail (allocation != NULL);
867 widget->allocation = *allocation;
868 if (GTK_WIDGET_REALIZED (widget))
869 gdk_window_move_resize (widget->window,
870 allocation->x, allocation->y,
871 allocation->width, allocation->height);
873 notebook = GTK_NOTEBOOK (widget);
874 if (notebook->children)
876 child_allocation.x = GTK_CONTAINER (widget)->border_width;
877 child_allocation.y = GTK_CONTAINER (widget)->border_width;
878 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
879 child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
881 if (notebook->show_tabs || notebook->show_border)
883 child_allocation.x += widget->style->klass->xthickness;
884 child_allocation.y += widget->style->klass->ythickness;
885 child_allocation.width = MAX (1, (gint)child_allocation.width -
886 (gint) widget->style->klass->xthickness * 2);
887 child_allocation.height = MAX (1, (gint)child_allocation.height -
888 (gint) widget->style->klass->ythickness * 2);
890 if (notebook->show_tabs && notebook->children && notebook->cur_page)
892 switch (notebook->tab_pos)
895 child_allocation.y += notebook->cur_page->requisition.height;
897 child_allocation.height =
898 MAX (1, (gint)child_allocation.height -
899 (gint)notebook->cur_page->requisition.height);
902 child_allocation.x += notebook->cur_page->requisition.width;
904 child_allocation.width =
905 MAX (1, (gint)child_allocation.width -
906 (gint)notebook->cur_page->requisition.width);
912 children = notebook->children;
915 page = children->data;
916 children = children->next;
918 if (GTK_WIDGET_VISIBLE (page->child))
919 gtk_widget_size_allocate (page->child, &child_allocation);
922 gtk_notebook_pages_allocate (notebook, allocation);
924 gtk_notebook_set_shape (notebook);
928 gtk_notebook_draw (GtkWidget *widget,
931 GtkNotebook *notebook;
932 GdkRectangle child_area;
933 GdkRectangle draw_area;
935 g_return_if_fail (widget != NULL);
936 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
937 g_return_if_fail (area != NULL);
939 notebook = GTK_NOTEBOOK (widget);
943 if (GTK_WIDGET_DRAWABLE (widget))
945 gboolean have_visible_child;
947 have_visible_child = notebook->cur_page && GTK_WIDGET_VISIBLE (notebook->cur_page->child);
949 if (have_visible_child != notebook->have_visible_child)
951 notebook->have_visible_child = have_visible_child;
954 draw_area.width = widget->allocation.width;
955 draw_area.height = widget->allocation.height;
958 gtk_notebook_paint (widget, &draw_area);
960 gtk_widget_draw_focus (widget);
962 if (notebook->cur_page && GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
963 gtk_widget_intersect (notebook->cur_page->child, &draw_area, &child_area))
964 gtk_widget_draw (notebook->cur_page->child, &child_area);
967 notebook->have_visible_child = FALSE;
971 gtk_notebook_expose (GtkWidget *widget,
972 GdkEventExpose *event)
974 GtkNotebook *notebook;
975 GdkEventExpose child_event;
976 GdkRectangle child_area;
978 g_return_val_if_fail (widget != NULL, FALSE);
979 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
980 g_return_val_if_fail (event != NULL, FALSE);
982 if (GTK_WIDGET_DRAWABLE (widget))
984 notebook = GTK_NOTEBOOK (widget);
986 gtk_notebook_paint (widget, &event->area);
987 if (notebook->show_tabs)
989 if (notebook->cur_page &&
990 gtk_widget_intersect (notebook->cur_page->tab_label,
991 &event->area, &child_area))
992 gtk_widget_draw_focus (widget);
995 child_event = *event;
996 if (notebook->cur_page &&
997 GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
998 gtk_widget_intersect (notebook->cur_page->child, &event->area,
1000 gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1007 gtk_notebook_button_press (GtkWidget *widget,
1008 GdkEventButton *event)
1010 GtkNotebook *notebook;
1011 GtkNotebookPage *page;
1015 g_return_val_if_fail (widget != NULL, FALSE);
1016 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1017 g_return_val_if_fail (event != NULL, FALSE);
1019 notebook = GTK_NOTEBOOK (widget);
1021 if (event->type != GDK_BUTTON_PRESS || !notebook->children ||
1025 if (event->window == notebook->panel)
1027 if (!GTK_WIDGET_HAS_FOCUS (widget))
1028 gtk_widget_grab_focus (widget);
1030 gtk_grab_add (widget);
1031 notebook->button = event->button;
1033 if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1035 notebook->click_child = GTK_ARROW_LEFT;
1036 if (event->button == 1)
1038 if (!notebook->focus_tab ||
1039 gtk_notebook_search_page (notebook, notebook->focus_tab,
1041 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1043 if (!notebook->timer)
1045 notebook->timer = gtk_timeout_add
1046 (NOTEBOOK_INIT_SCROLL_DELAY,
1047 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1048 notebook->need_timer = TRUE;
1051 else if (event->button == 2)
1052 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1053 else if (event->button == 3)
1054 gtk_notebook_switch_focus_tab (notebook,
1055 gtk_notebook_search_page (notebook,
1059 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1063 notebook->click_child = GTK_ARROW_RIGHT;
1064 if (event->button == 1)
1066 if (!notebook->focus_tab ||
1067 gtk_notebook_search_page (notebook, notebook->focus_tab,
1069 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1071 if (!notebook->timer)
1073 notebook->timer = gtk_timeout_add
1074 (NOTEBOOK_INIT_SCROLL_DELAY,
1075 (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1076 notebook->need_timer = TRUE;
1079 else if (event->button == 2)
1080 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1081 else if (event->button == 3)
1082 gtk_notebook_switch_focus_tab
1083 (notebook, gtk_notebook_search_page (notebook, NULL,
1085 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1088 else if (event->window == widget->window)
1090 if (event->button == 3 && notebook->menu)
1092 gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL,
1093 NULL, NULL, 3, event->time);
1098 children = notebook->children;
1101 page = children->data;
1103 if (GTK_WIDGET_VISIBLE (page->child) &&
1104 page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1105 (event->x >= page->allocation.x) &&
1106 (event->y >= page->allocation.y) &&
1107 (event->x <= (page->allocation.x + page->allocation.width)) &&
1108 (event->y <= (page->allocation.y + page->allocation.height)))
1110 if (page == notebook->cur_page && notebook->focus_tab &&
1111 notebook->focus_tab != children &&
1112 GTK_WIDGET_HAS_FOCUS (notebook))
1114 GtkNotebookPage *old_page;
1116 notebook->child_has_focus = FALSE;
1117 old_page = (GtkNotebookPage *)
1118 (notebook->focus_tab->data);
1119 gtk_notebook_switch_focus_tab (notebook, children);
1120 gtk_notebook_focus_changed (notebook, old_page);
1124 gtk_notebook_switch_focus_tab (notebook, children);
1125 gtk_widget_grab_focus (widget);
1126 gtk_notebook_switch_page (notebook, page, num);
1130 children = children->next;
1133 if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1134 gtk_widget_grab_focus (widget);
1136 gtk_notebook_set_shape (notebook);
1141 gtk_notebook_button_release (GtkWidget *widget,
1142 GdkEventButton *event)
1144 GtkNotebook *notebook;
1146 g_return_val_if_fail (widget != NULL, FALSE);
1147 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1148 g_return_val_if_fail (event != NULL, FALSE);
1150 if (event->type != GDK_BUTTON_RELEASE)
1153 notebook = GTK_NOTEBOOK (widget);
1155 if (event->button == notebook->button)
1159 if (notebook->timer)
1161 gtk_timeout_remove (notebook->timer);
1162 notebook->timer = 0;
1163 notebook->need_timer = FALSE;
1165 gtk_grab_remove (widget);
1166 click_child = notebook->click_child;
1167 notebook->click_child = 0;
1168 notebook->button = 0;
1169 gtk_notebook_draw_arrow (notebook, click_child);
1176 gtk_notebook_enter_notify (GtkWidget *widget,
1177 GdkEventCrossing *event)
1179 GtkNotebook *notebook;
1181 g_return_val_if_fail (widget != NULL, FALSE);
1182 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1183 g_return_val_if_fail (event != NULL, FALSE);
1185 notebook = GTK_NOTEBOOK (widget);
1187 if (event->window == notebook->panel)
1192 gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
1194 if (x <= ARROW_SIZE + ARROW_SPACING / 2)
1196 notebook->in_child = GTK_ARROW_LEFT;
1198 if (notebook->click_child == 0)
1199 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1203 notebook->in_child = GTK_ARROW_RIGHT;
1205 if (notebook->click_child == 0)
1206 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1214 gtk_notebook_leave_notify (GtkWidget *widget,
1215 GdkEventCrossing *event)
1217 GtkNotebook *notebook;
1219 g_return_val_if_fail (widget != NULL, FALSE);
1220 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1221 g_return_val_if_fail (event != NULL, FALSE);
1223 notebook = GTK_NOTEBOOK (widget);
1225 if (event->window == notebook->panel && !notebook->click_child)
1227 if (notebook->in_child == GTK_ARROW_LEFT)
1229 notebook->in_child = 0;
1230 gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
1234 notebook->in_child = 0;
1235 gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
1242 gtk_notebook_motion_notify (GtkWidget *widget,
1243 GdkEventMotion *event)
1245 GtkNotebook *notebook;
1247 g_return_val_if_fail (widget != NULL, FALSE);
1248 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1249 g_return_val_if_fail (event != NULL, FALSE);
1251 notebook = GTK_NOTEBOOK (widget);
1253 if (notebook->button)
1256 if (event->window == notebook->panel)
1262 gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
1264 if (x <= ARROW_SIZE + ARROW_SPACING / 2 &&
1265 notebook->in_child == GTK_ARROW_RIGHT)
1267 notebook->in_child = GTK_ARROW_LEFT;
1268 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1269 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1271 else if (x > ARROW_SIZE + ARROW_SPACING / 2 &&
1272 notebook->in_child == GTK_ARROW_LEFT)
1274 notebook->in_child = GTK_ARROW_RIGHT;
1275 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1276 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1284 gtk_notebook_key_press (GtkWidget *widget,
1287 GtkNotebook *notebook;
1288 GtkDirectionType direction = 0;
1291 g_return_val_if_fail (widget != NULL, FALSE);
1292 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1293 g_return_val_if_fail (event != NULL, FALSE);
1295 notebook = GTK_NOTEBOOK (widget);
1297 if (!notebook->children || !notebook->show_tabs)
1300 switch (event->keyval)
1303 switch (notebook->tab_pos)
1305 case GTK_POS_BOTTOM:
1306 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1311 direction = GTK_DIR_UP;
1316 switch (notebook->tab_pos)
1319 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1324 direction = GTK_DIR_LEFT;
1329 switch (notebook->tab_pos)
1332 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1334 case GTK_POS_BOTTOM:
1337 direction = GTK_DIR_DOWN;
1342 switch (notebook->tab_pos)
1345 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1350 direction = GTK_DIR_RIGHT;
1355 case GDK_ISO_Left_Tab:
1356 if (event->state & GDK_SHIFT_MASK)
1357 direction = GTK_DIR_TAB_BACKWARD;
1359 direction = GTK_DIR_TAB_FORWARD;
1362 list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
1364 gtk_notebook_switch_focus_tab (notebook, list);
1367 list = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
1369 gtk_notebook_switch_focus_tab (notebook, list);
1373 gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1378 return gtk_container_focus (GTK_CONTAINER (widget), direction);
1382 gtk_notebook_focus_in (GtkWidget *widget,
1383 GdkEventFocus *event)
1385 g_return_val_if_fail (widget != NULL, FALSE);
1386 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1387 g_return_val_if_fail (event != NULL, FALSE);
1389 GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
1390 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1391 gtk_widget_draw_focus (widget);
1397 gtk_notebook_focus_out (GtkWidget *widget,
1398 GdkEventFocus *event)
1400 g_return_val_if_fail (widget != NULL, FALSE);
1401 g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1402 g_return_val_if_fail (event != NULL, FALSE);
1404 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1405 gtk_widget_draw_focus (widget);
1411 gtk_notebook_draw_focus (GtkWidget *widget)
1413 GtkNotebook *notebook;
1415 g_return_if_fail (widget != NULL);
1416 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1418 notebook = GTK_NOTEBOOK (widget);
1420 if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
1421 notebook->focus_tab)
1423 GtkNotebookPage *page;
1426 page = notebook->focus_tab->data;
1428 area.x = page->tab_label->allocation.x - 1;
1429 area.y = page->tab_label->allocation.y - 1;
1430 area.width = page->tab_label->allocation.width + 2;
1431 area.height = page->tab_label->allocation.height + 2;
1433 gtk_notebook_draw_tab (GTK_NOTEBOOK (widget), page, &area);
1438 gtk_notebook_style_set (GtkWidget *widget,
1439 GtkStyle *previous_style)
1441 if (GTK_WIDGET_REALIZED (widget) &&
1442 !GTK_WIDGET_NO_WINDOW (widget))
1444 gtk_style_set_background (widget->style, widget->window, widget->state);
1445 if (GTK_WIDGET_DRAWABLE (widget))
1446 gdk_window_clear (widget->window);
1449 gtk_notebook_set_shape (GTK_NOTEBOOK(widget));
1452 /* Private GtkContainer Methods :
1454 * gtk_notebook_set_child_arg
1455 * gtk_notebook_get_child_arg
1457 * gtk_notebook_remove
1458 * gtk_notebook_focus
1459 * gtk_notebook_set_focus_child
1460 * gtk_notebook_child_type
1461 * gtk_notebook_forall
1464 gtk_notebook_set_child_arg (GtkContainer *container,
1471 GtkPackType pack_type;
1475 case CHILD_ARG_TAB_LABEL:
1476 /* a NULL pointer indicates a default_tab setting, otherwise
1477 * we need to set the associated label
1479 gtk_notebook_set_tab_label_text (GTK_NOTEBOOK (container), child,
1480 GTK_VALUE_STRING(*arg));
1482 case CHILD_ARG_MENU_LABEL:
1483 gtk_notebook_set_menu_label_text (GTK_NOTEBOOK (container), child,
1484 GTK_VALUE_STRING (*arg));
1486 case CHILD_ARG_POSITION:
1487 gtk_notebook_reorder_child (GTK_NOTEBOOK (container), child,
1488 GTK_VALUE_INT (*arg));
1490 case CHILD_ARG_TAB_EXPAND:
1491 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1492 &expand, &fill, &pack_type);
1493 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1494 GTK_VALUE_BOOL (*arg),
1497 case CHILD_ARG_TAB_FILL:
1498 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1499 &expand, &fill, &pack_type);
1500 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1502 GTK_VALUE_BOOL (*arg),
1505 case CHILD_ARG_TAB_PACK:
1506 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1507 &expand, &fill, &pack_type);
1508 gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (container), child,
1510 GTK_VALUE_BOOL (*arg));
1518 gtk_notebook_get_child_arg (GtkContainer *container,
1524 GtkNotebook *notebook;
1528 GtkPackType pack_type;
1530 notebook = GTK_NOTEBOOK (container);
1532 if (!(list = g_list_find_custom (notebook->children, child,
1533 gtk_notebook_page_compare)))
1535 arg->type = GTK_TYPE_INVALID;
1541 case CHILD_ARG_TAB_LABEL:
1542 label = gtk_notebook_get_tab_label (notebook, child);
1544 if (label && GTK_IS_LABEL (label))
1545 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
1547 GTK_VALUE_STRING (*arg) = NULL;
1549 case CHILD_ARG_MENU_LABEL:
1550 label = gtk_notebook_get_menu_label (notebook, child);
1552 if (label && GTK_IS_LABEL (label))
1553 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (label)->label);
1555 GTK_VALUE_STRING (*arg) = NULL;
1557 case CHILD_ARG_POSITION:
1558 GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
1560 case CHILD_ARG_TAB_EXPAND:
1561 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1562 &expand, NULL, NULL);
1563 GTK_VALUE_BOOL (*arg) = expand;
1565 case CHILD_ARG_TAB_FILL:
1566 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1568 GTK_VALUE_BOOL (*arg) = fill;
1570 case CHILD_ARG_TAB_PACK:
1571 gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (container), child,
1572 NULL, NULL, &pack_type);
1573 GTK_VALUE_BOOL (*arg) = pack_type;
1576 arg->type = GTK_TYPE_INVALID;
1582 gtk_notebook_add (GtkContainer *container,
1585 g_return_if_fail (container != NULL);
1586 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1588 gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget,
1593 gtk_notebook_remove (GtkContainer *container,
1596 GtkNotebook *notebook;
1597 GtkNotebookPage *page;
1601 g_return_if_fail (container != NULL);
1602 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1603 g_return_if_fail (widget != NULL);
1605 notebook = GTK_NOTEBOOK (container);
1607 children = notebook->children;
1611 page = children->data;
1612 if (page->child == widget)
1614 gtk_notebook_real_remove (notebook, children);
1618 children = children->next;
1623 gtk_notebook_focus (GtkContainer *container,
1624 GtkDirectionType direction)
1626 GtkNotebook *notebook;
1627 GtkNotebookPage *page = NULL;
1628 GtkNotebookPage *old_page = NULL;
1630 g_return_val_if_fail (container != NULL, FALSE);
1631 g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
1633 notebook = GTK_NOTEBOOK (container);
1635 if (!GTK_WIDGET_DRAWABLE (notebook) ||
1636 !GTK_WIDGET_IS_SENSITIVE (container) ||
1637 !notebook->children ||
1638 !notebook->cur_page)
1641 if (!notebook->show_tabs)
1643 if (GTK_WIDGET_DRAWABLE (notebook->cur_page->child) &&
1644 GTK_WIDGET_IS_SENSITIVE (notebook->cur_page->child))
1646 if (GTK_IS_CONTAINER (notebook->cur_page->child))
1648 if (gtk_container_focus
1649 (GTK_CONTAINER (notebook->cur_page->child), direction))
1652 else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
1654 if (!container->focus_child)
1656 gtk_widget_grab_focus (notebook->cur_page->child);
1664 if (notebook->focus_tab)
1665 old_page = notebook->focus_tab->data;
1667 if (container->focus_child && old_page &&
1668 container->focus_child == old_page->child && notebook->child_has_focus)
1670 if (GTK_WIDGET_DRAWABLE (container->focus_child))
1672 if (GTK_IS_CONTAINER (container->focus_child) &&
1673 !GTK_WIDGET_HAS_FOCUS (container->focus_child))
1675 if (gtk_container_focus (GTK_CONTAINER (container->focus_child),
1679 gtk_widget_grab_focus (GTK_WIDGET(notebook));
1682 notebook->focus_tab = NULL;
1686 if (!GTK_WIDGET_HAS_FOCUS (container))
1687 notebook->focus_tab = NULL;
1691 case GTK_DIR_TAB_FORWARD:
1694 gtk_notebook_switch_focus_tab
1695 (notebook, gtk_notebook_search_page (notebook, notebook->focus_tab,
1698 case GTK_DIR_TAB_BACKWARD:
1701 gtk_notebook_switch_focus_tab
1702 (notebook, gtk_notebook_search_page (notebook, notebook->focus_tab,
1707 if (notebook->focus_tab)
1709 if (!GTK_WIDGET_HAS_FOCUS (container))
1710 gtk_widget_grab_focus (GTK_WIDGET (container));
1712 page = notebook->focus_tab->data;
1713 if (GTK_WIDGET_MAPPED (page->tab_label))
1714 gtk_notebook_focus_changed (notebook, old_page);
1717 gtk_notebook_pages_allocate (notebook,
1718 &(GTK_WIDGET (notebook)->allocation));
1719 gtk_notebook_expose_tabs (notebook);
1724 gtk_notebook_focus_changed (notebook, old_page);
1729 gtk_notebook_set_focus_child (GtkContainer *container,
1732 GtkNotebook *notebook;
1734 g_return_if_fail (container != NULL);
1735 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1739 g_return_if_fail (GTK_IS_WIDGET (child));
1741 notebook = GTK_NOTEBOOK (container);
1743 notebook->child_has_focus = TRUE;
1744 if (!notebook->focus_tab)
1747 GtkNotebookPage *page;
1749 children = notebook->children;
1752 page = children->data;
1753 if (page->child == child || page->tab_label == child)
1754 gtk_notebook_switch_focus_tab (notebook, children);
1755 children = children->next;
1759 parent_class->set_focus_child (container, child);
1763 gtk_notebook_forall (GtkContainer *container,
1764 gboolean include_internals,
1765 GtkCallback callback,
1766 gpointer callback_data)
1768 GtkNotebook *notebook;
1771 g_return_if_fail (container != NULL);
1772 g_return_if_fail (GTK_IS_NOTEBOOK (container));
1773 g_return_if_fail (callback != NULL);
1775 notebook = GTK_NOTEBOOK (container);
1777 children = notebook->children;
1780 GtkNotebookPage *page;
1782 page = children->data;
1783 children = children->next;
1784 (* callback) (page->child, callback_data);
1785 if (include_internals)
1787 if (page->tab_label)
1788 (* callback) (page->tab_label, callback_data);
1789 if (page->menu_label)
1790 (* callback) (page->menu_label, callback_data);
1796 gtk_notebook_child_type (GtkContainer *container)
1798 return GTK_TYPE_WIDGET;
1801 /* Private GtkNotebook Functions:
1803 * gtk_notebook_panel_realize
1804 * gtk_notebook_expose_tabs
1805 * gtk_notebook_focus_changed
1806 * gtk_notebook_real_remove
1807 * gtk_notebook_update_labels
1808 * gtk_notebook_timer
1809 * gtk_notebook_page_compare
1810 * gtk_notebook_real_page_position
1811 * gtk_notebook_search_page
1814 gtk_notebook_panel_realize (GtkNotebook *notebook)
1817 GdkWindowAttr attributes;
1818 gint attributes_mask;
1820 g_return_if_fail (notebook != NULL);
1821 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1823 widget = GTK_WIDGET (notebook);
1825 attributes.window_type = GDK_WINDOW_CHILD;
1826 attributes.wclass = GDK_INPUT_OUTPUT;
1827 attributes.visual = gtk_widget_get_visual (widget);
1828 attributes.colormap = gtk_widget_get_colormap (widget);
1829 attributes.event_mask = gtk_widget_get_events (widget);
1830 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1831 | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1832 | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1834 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1836 attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1837 attributes.height = ARROW_SIZE;
1839 attributes.x = (widget->allocation.width - attributes.width -
1840 GTK_CONTAINER (notebook)->border_width);
1841 attributes.y = (widget->allocation.height - ARROW_SIZE -
1842 GTK_CONTAINER (notebook)->border_width);
1843 if (notebook->tab_pos == GTK_POS_TOP)
1844 attributes.y = GTK_CONTAINER (notebook)->border_width;
1845 else if (notebook->tab_pos == GTK_POS_LEFT)
1846 attributes.x = (widget->allocation.x +
1847 GTK_CONTAINER (notebook)->border_width);
1849 notebook->panel = gdk_window_new (widget->window, &attributes,
1851 gtk_style_set_background (widget->style, notebook->panel,
1853 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
1854 gdk_window_set_user_data (notebook->panel, widget);
1858 gtk_notebook_expose_tabs (GtkNotebook *notebook)
1861 GtkNotebookPage *page;
1862 GdkEventExpose event;
1865 widget = GTK_WIDGET (notebook);
1866 border = GTK_CONTAINER (notebook)->border_width;
1868 if (!GTK_WIDGET_MAPPED (notebook) || !notebook->first_tab)
1871 page = notebook->first_tab->data;
1873 event.type = GDK_EXPOSE;
1874 event.window = widget->window;
1876 event.area.x = border;
1877 event.area.y = border;
1879 switch (notebook->tab_pos)
1881 case GTK_POS_BOTTOM:
1882 event.area.y = (widget->allocation.height - border -
1883 page->allocation.height -
1884 widget->style->klass->ythickness);
1885 if (page != notebook->cur_page)
1886 event.area.y -= widget->style->klass->ythickness;
1888 event.area.width = widget->allocation.width - 2 * border;
1889 event.area.height = (page->allocation.height +
1890 widget->style->klass->ythickness);
1891 if (page != notebook->cur_page)
1892 event.area.height += widget->style->klass->ythickness;
1895 event.area.x = (widget->allocation.width - border -
1896 page->allocation.width -
1897 widget->style->klass->xthickness);
1898 if (page != notebook->cur_page)
1899 event.area.x -= widget->style->klass->xthickness;
1901 event.area.width = (page->allocation.width +
1902 widget->style->klass->xthickness);
1903 event.area.height = widget->allocation.height - 2 * border;
1904 if (page != notebook->cur_page)
1905 event.area.width += widget->style->klass->xthickness;
1908 gtk_widget_event (widget, (GdkEvent *) &event);
1912 gtk_notebook_focus_changed (GtkNotebook *notebook,
1913 GtkNotebookPage *old_page)
1915 g_return_if_fail (notebook != NULL);
1916 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1918 if (GTK_WIDGET_DRAWABLE (notebook) && notebook->show_tabs)
1922 if (notebook->focus_tab)
1924 GtkNotebookPage *page;
1926 page = notebook->focus_tab->data;
1928 area.x = page->tab_label->allocation.x - 1;
1929 area.y = page->tab_label->allocation.y - 1;
1930 area.width = page->tab_label->allocation.width + 2;
1931 area.height = page->tab_label->allocation.height + 2;
1933 gtk_notebook_draw_tab (notebook, page, &area);
1938 area.x = old_page->tab_label->allocation.x - 1;
1939 area.y = old_page->tab_label->allocation.y - 1;
1940 area.width = old_page->tab_label->allocation.width + 2;
1941 area.height = old_page->tab_label->allocation.height + 2;
1943 gtk_notebook_draw_tab (notebook, old_page, &area);
1949 gtk_notebook_timer (GtkNotebook *notebook)
1951 gboolean retval = FALSE;
1953 GDK_THREADS_ENTER ();
1955 if (notebook->timer)
1957 if (notebook->click_child == GTK_ARROW_LEFT)
1959 if (!notebook->focus_tab ||
1960 gtk_notebook_search_page (notebook, notebook->focus_tab,
1962 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1964 else if (notebook->click_child == GTK_ARROW_RIGHT)
1966 if (!notebook->focus_tab ||
1967 gtk_notebook_search_page (notebook, notebook->focus_tab,
1969 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1971 if (notebook->need_timer)
1973 notebook->need_timer = FALSE;
1974 notebook->timer = gtk_timeout_add (NOTEBOOK_SCROLL_DELAY,
1975 (GtkFunction) gtk_notebook_timer,
1976 (gpointer) notebook);
1982 GDK_THREADS_LEAVE ();
1988 gtk_notebook_page_compare (gconstpointer a,
1991 return (((GtkNotebookPage *) a)->child != b);
1995 gtk_notebook_real_remove (GtkNotebook *notebook,
1998 GtkNotebookPage *page;
2000 gint need_resize = FALSE;
2002 next_list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
2004 next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
2006 if (notebook->cur_page == list->data)
2008 notebook->cur_page = NULL;
2010 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next_list), -1);
2013 if (list == notebook->first_tab)
2014 notebook->first_tab = next_list;
2015 if (list == notebook->focus_tab)
2016 gtk_notebook_switch_focus_tab (notebook, next_list);
2020 if (GTK_WIDGET_VISIBLE (page->child) && GTK_WIDGET_VISIBLE (notebook))
2023 gtk_widget_unparent (page->child);
2025 if (page->tab_label)
2026 gtk_widget_unparent (page->tab_label);
2030 gtk_container_remove (GTK_CONTAINER (notebook->menu),
2031 page->menu_label->parent);
2032 gtk_widget_queue_resize (notebook->menu);
2034 if (!page->default_menu)
2035 gtk_widget_unref (page->menu_label);
2037 notebook->children = g_list_remove_link (notebook->children, list);
2041 gtk_notebook_update_labels (notebook);
2043 gtk_widget_queue_resize (GTK_WIDGET (notebook));
2047 gtk_notebook_update_labels (GtkNotebook *notebook)
2049 GtkNotebookPage *page;
2054 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
2056 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
2059 g_snprintf (string, sizeof(string), _("Page %u"), page_num++);
2060 if (notebook->show_tabs)
2062 if (page->default_tab)
2064 if (!page->tab_label)
2066 page->tab_label = gtk_label_new (string);
2067 gtk_widget_set_parent (page->tab_label,
2068 GTK_WIDGET (notebook));
2071 gtk_label_set_text (GTK_LABEL (page->tab_label), string);
2074 if (GTK_WIDGET_VISIBLE (page->child) &&
2075 !GTK_WIDGET_VISIBLE (page->tab_label))
2076 gtk_widget_show (page->tab_label);
2077 else if (!GTK_WIDGET_VISIBLE (page->child) &&
2078 GTK_WIDGET_VISIBLE (page->tab_label))
2079 gtk_widget_hide (page->tab_label);
2081 if (notebook->menu && page->default_menu)
2083 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
2084 gtk_label_set_text (GTK_LABEL (page->menu_label),
2085 GTK_LABEL (page->tab_label)->label);
2087 gtk_label_set_text (GTK_LABEL (page->menu_label), string);
2093 gtk_notebook_real_page_position (GtkNotebook *notebook,
2099 g_return_val_if_fail (notebook != NULL, -1);
2100 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
2101 g_return_val_if_fail (list != NULL, -1);
2103 for (work = notebook->children, count_start = 0;
2104 work && work != list; work = work->next)
2105 if (GTK_NOTEBOOK_PAGE (work)->pack == GTK_PACK_START)
2111 if (GTK_NOTEBOOK_PAGE (list)->pack == GTK_PACK_START)
2114 return (count_start + g_list_length (list) - 1);
2118 gtk_notebook_search_page (GtkNotebook *notebook,
2121 gboolean find_visible)
2123 GtkNotebookPage *page = NULL;
2124 GList *old_list = NULL;
2127 g_return_val_if_fail (notebook != NULL, NULL);
2128 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
2133 flag = GTK_PACK_END;
2137 flag = GTK_PACK_START;
2144 if (!page || page->pack == flag)
2152 list = notebook->children;
2157 if (page->pack == flag &&
2158 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2173 if (page->pack != flag &&
2174 (!find_visible || GTK_WIDGET_VISIBLE (page->child)))
2182 /* Private GtkNotebook Drawing Functions:
2184 * gtk_notebook_paint
2185 * gtk_notebook_draw_tab
2186 * gtk_notebook_draw_arrow
2187 * gtk_notebook_set_shape
2190 gtk_notebook_paint (GtkWidget *widget,
2193 GtkNotebook *notebook;
2194 GtkNotebookPage *page;
2199 gint gap_x = 0, gap_width = 0;
2201 g_return_if_fail (widget != NULL);
2202 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2203 g_return_if_fail (area != NULL);
2205 if (!GTK_WIDGET_DRAWABLE (widget))
2208 notebook = GTK_NOTEBOOK (widget);
2210 if ((!notebook->show_tabs && !notebook->show_border) ||
2211 !notebook->cur_page || !GTK_WIDGET_VISIBLE (notebook->cur_page->child))
2213 gdk_window_clear_area (widget->window,
2215 area->width, area->height);
2219 x = GTK_CONTAINER (widget)->border_width;
2220 y = GTK_CONTAINER (widget)->border_width;
2221 width = widget->allocation.width - x * 2;
2222 height = widget->allocation.height - y * 2;
2224 if (notebook->show_border && (!notebook->show_tabs || !notebook->children))
2226 gtk_paint_box (widget->style, widget->window,
2227 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2228 area, widget, "notebook",
2229 x, y, width, height);
2234 if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
2236 page = notebook->first_tab->data;
2238 switch (notebook->tab_pos)
2241 y += page->allocation.height + widget->style->klass->ythickness;
2242 case GTK_POS_BOTTOM:
2243 height -= page->allocation.height + widget->style->klass->ythickness;
2246 x += page->allocation.width + widget->style->klass->xthickness;
2248 width -= page->allocation.width + widget->style->klass->xthickness;
2251 gtk_paint_box (widget->style, widget->window,
2252 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2253 area, widget, "notebook",
2254 x, y, width, height);
2258 switch (notebook->tab_pos)
2261 y += notebook->cur_page->allocation.height;
2262 case GTK_POS_BOTTOM:
2263 height -= notebook->cur_page->allocation.height;
2266 x += notebook->cur_page->allocation.width;
2268 width -= notebook->cur_page->allocation.width;
2272 switch (notebook->tab_pos)
2275 gap_x = (notebook->cur_page->allocation.x -
2276 GTK_CONTAINER(notebook)->border_width);
2277 gap_width = notebook->cur_page->allocation.width;
2279 case GTK_POS_BOTTOM:
2280 gap_x = (notebook->cur_page->allocation.x -
2281 GTK_CONTAINER(notebook)->border_width);
2282 gap_width = notebook->cur_page->allocation.width;
2285 gap_x = (notebook->cur_page->allocation.y -
2286 GTK_CONTAINER(notebook)->border_width);
2287 gap_width = notebook->cur_page->allocation.height;
2290 gap_x = (notebook->cur_page->allocation.y -
2291 GTK_CONTAINER(notebook)->border_width);
2292 gap_width = notebook->cur_page->allocation.height;
2295 gtk_paint_box_gap(widget->style, widget->window,
2296 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
2297 area, widget, "notebook",
2298 x, y, width, height,
2299 notebook->tab_pos, gap_x, gap_width);
2303 children = gtk_notebook_search_page (notebook, NULL, STEP_PREV, TRUE);
2306 page = children->data;
2307 children = gtk_notebook_search_page (notebook, children,
2309 if (!GTK_WIDGET_VISIBLE (page->child))
2311 if (!GTK_WIDGET_MAPPED (page->tab_label))
2313 else if (page != notebook->cur_page)
2314 gtk_notebook_draw_tab (notebook, page, area);
2317 if (showarrow && notebook->scrollable)
2319 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2320 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2322 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
2326 gtk_notebook_draw_tab (GtkNotebook *notebook,
2327 GtkNotebookPage *page,
2330 GdkRectangle child_area;
2331 GdkRectangle page_area;
2332 GtkStateType state_type;
2333 GtkPositionType gap_side;
2335 g_return_if_fail (notebook != NULL);
2336 g_return_if_fail (page != NULL);
2337 g_return_if_fail (area != NULL);
2339 if (!GTK_WIDGET_MAPPED (page->tab_label) ||
2340 (page->allocation.width == 0) || (page->allocation.height == 0))
2343 page_area.x = page->allocation.x;
2344 page_area.y = page->allocation.y;
2345 page_area.width = page->allocation.width;
2346 page_area.height = page->allocation.height;
2348 if (gdk_rectangle_intersect (&page_area, area, &child_area))
2352 widget = GTK_WIDGET (notebook);
2354 switch (notebook->tab_pos)
2357 gap_side = GTK_POS_BOTTOM;
2359 case GTK_POS_BOTTOM:
2360 gap_side = GTK_POS_TOP;
2363 gap_side = GTK_POS_RIGHT;
2366 gap_side = GTK_POS_LEFT;
2370 if (notebook->cur_page == page)
2371 state_type = GTK_STATE_NORMAL;
2373 state_type = GTK_STATE_ACTIVE;
2374 gtk_paint_extension(widget->style, widget->window,
2375 state_type, GTK_SHADOW_OUT,
2376 area, widget, "tab",
2377 page_area.x, page_area.y,
2378 page_area.width, page_area.height,
2380 if ((GTK_WIDGET_HAS_FOCUS (widget)) &&
2381 notebook->focus_tab && (notebook->focus_tab->data == page))
2383 gtk_paint_focus (widget->style, widget->window,
2384 area, widget, "tab",
2385 page->tab_label->allocation.x - 1,
2386 page->tab_label->allocation.y - 1,
2387 page->tab_label->allocation.width + 1,
2388 page->tab_label->allocation.height + 1);
2390 if (gtk_widget_intersect (page->tab_label, area, &child_area))
2391 gtk_widget_draw (page->tab_label, &child_area);
2396 gtk_notebook_draw_arrow (GtkNotebook *notebook,
2399 GtkStateType state_type;
2400 GtkShadowType shadow_type;
2403 g_return_if_fail (notebook != NULL);
2404 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2406 widget = GTK_WIDGET(notebook);
2408 if (GTK_WIDGET_DRAWABLE (notebook))
2410 if (notebook->in_child == arrow)
2412 if (notebook->click_child == arrow)
2413 state_type = GTK_STATE_ACTIVE;
2415 state_type = GTK_STATE_PRELIGHT;
2418 state_type = GTK_STATE_NORMAL;
2420 if (notebook->click_child == arrow)
2421 shadow_type = GTK_SHADOW_IN;
2423 shadow_type = GTK_SHADOW_OUT;
2425 if (arrow == GTK_ARROW_LEFT)
2427 if (notebook->focus_tab &&
2428 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2431 shadow_type = GTK_SHADOW_ETCHED_IN;
2432 state_type = GTK_STATE_NORMAL;
2435 if (notebook->tab_pos == GTK_POS_LEFT ||
2436 notebook->tab_pos == GTK_POS_RIGHT)
2437 arrow = GTK_ARROW_UP;
2439 gdk_window_clear_area (notebook->panel, 0, 0, ARROW_SIZE, ARROW_SIZE);
2440 gtk_paint_arrow (widget->style, notebook->panel, state_type,
2441 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2443 0, 0, ARROW_SIZE, ARROW_SIZE);
2447 if (notebook->focus_tab &&
2448 !gtk_notebook_search_page (notebook, notebook->focus_tab,
2451 shadow_type = GTK_SHADOW_ETCHED_IN;
2452 state_type = GTK_STATE_NORMAL;
2455 if (notebook->tab_pos == GTK_POS_LEFT ||
2456 notebook->tab_pos == GTK_POS_RIGHT)
2457 arrow = GTK_ARROW_DOWN;
2459 gdk_window_clear_area(notebook->panel, ARROW_SIZE + ARROW_SPACING,
2460 0, ARROW_SIZE, ARROW_SIZE);
2461 gtk_paint_arrow (widget->style, notebook->panel, state_type,
2462 shadow_type, NULL, GTK_WIDGET(notebook), "notebook",
2463 arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2464 0, ARROW_SIZE, ARROW_SIZE);
2470 gtk_notebook_set_shape (GtkNotebook *notebook)
2472 GtkWidget *widget = NULL;
2473 GdkPixmap *pm = NULL;
2476 gint x, y, width, height, w, h, depth;
2477 GtkNotebookPage *page;
2480 if (!GTK_WIDGET(notebook)->window)
2483 widget = GTK_WIDGET(notebook);
2485 w = widget->allocation.width;
2486 h = widget->allocation.height;
2488 pm = gdk_pixmap_new (widget->window, w, h, 1);
2489 pmgc = gdk_gc_new (pm);
2491 /* clear the shape mask */
2493 gdk_gc_set_foreground(pmgc, &col);
2494 gdk_draw_rectangle(pm, pmgc, TRUE, 0, 0, w, h);
2497 gdk_gc_set_foreground(pmgc, &col);
2499 /* draw the shape for the notebook page itself */
2500 x = GTK_CONTAINER(notebook)->border_width;
2501 y = GTK_CONTAINER(notebook)->border_width;
2502 width = widget->allocation.width - x * 2;
2503 height = widget->allocation.height - y * 2;
2505 if (notebook->show_tabs && notebook->children)
2507 if (!(notebook->show_tabs))
2509 page = notebook->first_tab->data;
2510 switch (notebook->tab_pos)
2513 y += page->allocation.height +
2514 widget->style->klass->ythickness;
2515 case GTK_POS_BOTTOM:
2516 height -= page->allocation.height +
2517 widget->style->klass->ythickness;
2520 x += page->allocation.width +
2521 widget->style->klass->xthickness;
2523 width -= page->allocation.width +
2524 widget->style->klass->xthickness;
2530 if (notebook->cur_page)
2531 page = notebook->cur_page;
2533 page = notebook->children->data;
2535 if (!GTK_WIDGET_MAPPED (page->tab_label))
2537 if (notebook->tab_pos == GTK_POS_LEFT)
2539 x -= widget->style->klass->xthickness * 2;
2540 width += widget->style->klass->xthickness * 2;
2542 else if (notebook->tab_pos == GTK_POS_RIGHT)
2543 width += widget->style->klass->xthickness * 2;
2545 switch (notebook->tab_pos)
2548 y += page->allocation.height;
2549 case GTK_POS_BOTTOM:
2550 height -= page->allocation.height;
2553 x += page->allocation.width;
2555 width -= page->allocation.width;
2560 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2562 /* if theres an area for scrollign arrows draw the shape for them */
2563 if (notebook->panel)
2565 gdk_window_get_geometry(notebook->panel, &x, &y, &width, &height, &depth);
2566 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2569 /* draw the shapes of all the children */
2570 if (notebook->show_tabs)
2572 children = notebook->children;
2575 page = children->data;
2576 if (GTK_WIDGET_MAPPED (page->tab_label))
2578 x = page->allocation.x;
2579 y = page->allocation.y;
2580 width = page->allocation.width;
2581 height = page->allocation.height;
2582 gdk_draw_rectangle(pm, pmgc, TRUE, x, y, width, height);
2584 children = children->next;
2589 gdk_window_shape_combine_mask(widget->window, pm, 0, 0);
2590 gdk_pixmap_unref(pm);
2591 gdk_gc_destroy(pmgc);
2594 /* Private GtkNotebook Size Allocate Functions:
2596 * gtk_notebook_pages_allocate
2597 * gtk_notebook_page_allocate
2598 * gtk_notebook_calc_tabs
2601 gtk_notebook_pages_allocate (GtkNotebook *notebook,
2602 GtkAllocation *allocation)
2605 GtkContainer *container;
2606 GtkNotebookPage *page = NULL;
2607 GtkAllocation child_allocation;
2608 GList *children = NULL;
2609 GList *last_child = NULL;
2610 gboolean showarrow = FALSE;
2620 if (!notebook->show_tabs || !notebook->children || !notebook->cur_page)
2623 widget = GTK_WIDGET (notebook);
2624 container = GTK_CONTAINER (notebook);
2626 child_allocation.x = container->border_width;
2627 child_allocation.y = container->border_width;
2629 switch (notebook->tab_pos)
2631 case GTK_POS_BOTTOM:
2632 child_allocation.y = (allocation->height -
2633 notebook->cur_page->requisition.height -
2634 container->border_width);
2636 child_allocation.height = notebook->cur_page->requisition.height;
2639 child_allocation.x = (allocation->width -
2640 notebook->cur_page->requisition.width -
2641 container->border_width);
2643 child_allocation.width = notebook->cur_page->requisition.width;
2647 if (notebook->scrollable)
2651 children = notebook->children;
2653 if (notebook->focus_tab)
2654 focus_tab = notebook->focus_tab;
2655 else if (notebook->first_tab)
2656 focus_tab = notebook->first_tab;
2658 focus_tab = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, TRUE);
2660 switch (notebook->tab_pos)
2663 case GTK_POS_BOTTOM:
2666 page = children->data;
2667 children = children->next;
2669 if (GTK_WIDGET_VISIBLE (page->child))
2670 tab_space += page->requisition.width;
2673 allocation->width - 2 * container->border_width - TAB_OVERLAP)
2676 page = focus_tab->data;
2678 tab_space = (allocation->width - TAB_OVERLAP -
2679 page->requisition.width -
2680 2 * (container->border_width + ARROW_SPACING +
2682 x = (allocation->width - 2 * ARROW_SIZE - ARROW_SPACING -
2683 container->border_width);
2685 page = notebook->children->data;
2686 if (notebook->tab_pos == GTK_POS_TOP)
2687 y = (container->border_width +
2688 (page->requisition.height - ARROW_SIZE) / 2);
2690 y = (allocation->height - container->border_width -
2691 ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2698 page = children->data;
2699 children = children->next;
2701 if (GTK_WIDGET_VISIBLE (page->child))
2702 tab_space += page->requisition.height;
2705 (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2708 page = focus_tab->data;
2709 tab_space = (allocation->height -
2710 ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2711 2 * container->border_width -
2712 page->requisition.height);
2713 y = allocation->height - container->border_width - ARROW_SIZE;
2715 page = notebook->children->data;
2716 if (notebook->tab_pos == GTK_POS_LEFT)
2717 x = (container->border_width +
2718 (page->requisition.width -
2719 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2721 x = (allocation->width - container->border_width -
2722 (2 * ARROW_SIZE - ARROW_SPACING) -
2723 (page->requisition.width -
2724 (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2728 if (showarrow) /* first_tab <- focus_tab */
2732 notebook->first_tab = focus_tab;
2733 last_child = gtk_notebook_search_page (notebook, focus_tab,
2739 if (notebook->first_tab && notebook->first_tab != focus_tab)
2741 /* Is first_tab really predecessor of focus_tab ? */
2742 page = notebook->first_tab->data;
2743 if (GTK_WIDGET_VISIBLE (page->child))
2744 for (children = focus_tab;
2745 children && children != notebook->first_tab;
2746 children = gtk_notebook_search_page (notebook,
2752 notebook->first_tab = focus_tab;
2754 gtk_notebook_calc_tabs (notebook,
2755 gtk_notebook_search_page (notebook,
2759 &(notebook->first_tab), &tab_space,
2764 notebook->first_tab =
2765 gtk_notebook_search_page (notebook, notebook->first_tab,
2767 if (!notebook->first_tab)
2768 notebook->first_tab = focus_tab;
2769 last_child = gtk_notebook_search_page (notebook, focus_tab,
2772 else /* focus_tab -> end */
2774 if (!notebook->first_tab)
2775 notebook->first_tab = gtk_notebook_search_page (notebook,
2780 gtk_notebook_calc_tabs (notebook,
2781 gtk_notebook_search_page (notebook,
2785 &children, &tab_space, STEP_NEXT);
2788 last_child = children;
2789 else /* start <- first_tab */
2793 gtk_notebook_calc_tabs
2795 gtk_notebook_search_page (notebook,
2796 notebook->first_tab,
2799 &children, &tab_space, STEP_PREV);
2800 notebook->first_tab = gtk_notebook_search_page(notebook,
2808 if (GTK_WIDGET_REALIZED (notebook))
2810 gdk_window_move (notebook->panel, x, y);
2811 gdk_window_show (notebook->panel);
2816 tab_space = -tab_space;
2818 for (children = notebook->first_tab;
2819 children && children != last_child;
2820 children = gtk_notebook_search_page (notebook, children,
2827 /*unmap all non-visible tabs*/
2828 for (children = gtk_notebook_search_page (notebook, NULL,
2830 children && children != notebook->first_tab;
2831 children = gtk_notebook_search_page (notebook, children,
2834 page = children->data;
2835 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2836 gtk_widget_unmap (page->tab_label);
2838 for (children = last_child; children;
2839 children = gtk_notebook_search_page (notebook, children,
2842 page = children->data;
2843 if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2844 gtk_widget_unmap (page->tab_label);
2847 else /* !showarrow */
2849 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2852 if (GTK_WIDGET_REALIZED (notebook))
2853 gdk_window_hide (notebook->panel);
2862 children = notebook->children;
2863 switch (notebook->tab_pos)
2866 case GTK_POS_BOTTOM:
2869 page = children->data;
2870 children = children->next;
2872 if (GTK_WIDGET_VISIBLE (page->child))
2875 tab_space += page->requisition.width;
2880 tab_space -= allocation->width;
2886 page = children->data;
2887 children = children->next;
2889 if (GTK_WIDGET_VISIBLE (page->child))
2892 tab_space += page->requisition.height;
2897 tab_space -= allocation->height;
2899 tab_space += 2 * container->border_width + TAB_OVERLAP;
2901 notebook->first_tab = gtk_notebook_search_page (notebook, NULL,
2903 if (notebook->homogeneous && n)
2907 children = notebook->first_tab;
2911 if (children == last_child)
2913 gtk_notebook_set_shape (notebook);
2919 page = children->data;
2920 if (!showarrow && page->pack != GTK_PACK_START)
2922 children = gtk_notebook_search_page (notebook, children, STEP_NEXT,TRUE);
2925 if (n && (showarrow || page->expand || notebook->homogeneous))
2927 new_fill = (tab_space * i++) / n;
2928 delta = new_fill - old_fill;
2929 old_fill = new_fill;
2932 switch (notebook->tab_pos)
2935 case GTK_POS_BOTTOM:
2936 child_allocation.width = (page->requisition.width +
2937 TAB_OVERLAP + delta);
2941 child_allocation.height = (page->requisition.height +
2942 TAB_OVERLAP + delta);
2946 gtk_notebook_page_allocate (notebook, page, &child_allocation);
2948 switch (notebook->tab_pos)
2951 case GTK_POS_BOTTOM:
2952 child_allocation.x += child_allocation.width - TAB_OVERLAP;
2956 child_allocation.y += child_allocation.height - TAB_OVERLAP;
2960 if (GTK_WIDGET_REALIZED (notebook) &&
2961 page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2963 if (GTK_WIDGET_VISIBLE (page->tab_label))
2964 gtk_widget_map (page->tab_label);
2966 gtk_widget_show (page->tab_label);
2972 children = notebook->children;
2973 switch (notebook->tab_pos)
2976 case GTK_POS_BOTTOM:
2977 child_allocation.x = (allocation->x + allocation->width -
2978 container->border_width);
2982 child_allocation.y = (allocation->y + allocation->height -
2983 container->border_width);
2987 while (children != last_child)
2989 page = children->data;
2990 children = children->next;
2992 if (page->pack != GTK_PACK_END || !GTK_WIDGET_VISIBLE (page->child))
2996 if (n && (page->expand || notebook->homogeneous))
2998 new_fill = (tab_space * i++) / n;
2999 delta = new_fill - old_fill;
3000 old_fill = new_fill;
3003 switch (notebook->tab_pos)
3006 case GTK_POS_BOTTOM:
3007 child_allocation.width = (page->requisition.width +
3008 TAB_OVERLAP + delta);
3009 child_allocation.x -= child_allocation.width;
3013 child_allocation.height = (page->requisition.height +
3014 TAB_OVERLAP + delta);
3015 child_allocation.y -= child_allocation.height;
3019 gtk_notebook_page_allocate (notebook, page, &child_allocation);
3021 switch (notebook->tab_pos)
3024 case GTK_POS_BOTTOM:
3025 child_allocation.x += TAB_OVERLAP;
3029 child_allocation.y += TAB_OVERLAP;
3033 if (GTK_WIDGET_REALIZED (notebook) && page->tab_label &&
3034 !GTK_WIDGET_MAPPED (page->tab_label))
3036 if (GTK_WIDGET_VISIBLE (page->tab_label))
3037 gtk_widget_map (page->tab_label);
3039 gtk_widget_show (page->tab_label);
3043 gtk_notebook_set_shape (notebook);
3047 gtk_notebook_page_allocate (GtkNotebook *notebook,
3048 GtkNotebookPage *page,
3049 GtkAllocation *allocation)
3052 GtkAllocation child_allocation;
3053 GtkRequisition tab_requisition;
3058 g_return_if_fail (notebook != NULL);
3059 g_return_if_fail (page != NULL);
3060 g_return_if_fail (allocation != NULL);
3062 widget = GTK_WIDGET (notebook);
3064 xthickness = widget->style->klass->xthickness;
3065 ythickness = widget->style->klass->ythickness;
3067 /* If the size of the notebook tabs change, we need to queue
3068 * a redraw on the tab area
3070 if ((allocation->width != page->allocation.width) ||
3071 (allocation->height != page->allocation.height))
3073 gint x, y, width, height, border_width;
3075 border_width = GTK_CONTAINER (notebook)->border_width;
3077 switch (notebook->tab_pos)
3080 width = widget->allocation.width;
3081 height = MAX (page->allocation.height, allocation->height) + ythickness;
3086 case GTK_POS_BOTTOM:
3087 width = widget->allocation.width + xthickness;
3088 height = MAX (page->allocation.height, allocation->height) + ythickness;
3090 y = widget->allocation.height - height - border_width;
3094 width = MAX (page->allocation.width, allocation->width) + xthickness;
3095 height = widget->allocation.height;
3101 default: /* quiet gcc */
3102 width = MAX (page->allocation.width, allocation->width) + xthickness;
3103 height = widget->allocation.height;
3104 x = widget->allocation.width - width - border_width;
3109 gtk_widget_queue_clear_area (widget, x, y, width, height);
3112 page->allocation = *allocation;
3113 gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
3115 if (notebook->cur_page != page)
3117 switch (notebook->tab_pos)
3120 page->allocation.y += ythickness;
3121 case GTK_POS_BOTTOM:
3122 if (page->allocation.height > ythickness)
3123 page->allocation.height -= ythickness;
3126 page->allocation.x += xthickness;
3128 if (page->allocation.width > xthickness)
3129 page->allocation.width -= xthickness;
3134 switch (notebook->tab_pos)
3137 case GTK_POS_BOTTOM:
3138 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_hborder;
3141 child_allocation.x = (xthickness + FOCUS_WIDTH +
3142 notebook->tab_hborder);
3143 child_allocation.width = MAX (1, (((gint) page->allocation.width) -
3144 2 * child_allocation.x));
3145 child_allocation.x += page->allocation.x;
3149 child_allocation.x = (page->allocation.x +
3150 (page->allocation.width -
3151 tab_requisition.width) / 2);
3152 child_allocation.width = tab_requisition.width;
3154 child_allocation.y = (notebook->tab_vborder + FOCUS_WIDTH +
3155 page->allocation.y);
3156 if (notebook->tab_pos == GTK_POS_TOP)
3157 child_allocation.y += ythickness;
3158 child_allocation.height = MAX (1, (((gint) page->allocation.height) - ythickness -
3159 2 * (notebook->tab_vborder + FOCUS_WIDTH)));
3163 padding = TAB_CURVATURE + FOCUS_WIDTH + notebook->tab_vborder;
3166 child_allocation.y = ythickness + padding;
3167 child_allocation.height = MAX (1, (((gint) page->allocation.height) -
3168 2 * child_allocation.y));
3169 child_allocation.y += page->allocation.y;
3173 child_allocation.y = (page->allocation.y + (page->allocation.height -
3174 tab_requisition.height) / 2);
3175 child_allocation.height = tab_requisition.height;
3177 child_allocation.x = page->allocation.x + notebook->tab_hborder + FOCUS_WIDTH;
3178 if (notebook->tab_pos == GTK_POS_LEFT)
3179 child_allocation.x += xthickness;
3180 child_allocation.width = MAX (1, (((gint) page->allocation.width) - xthickness -
3181 2 * (notebook->tab_hborder + FOCUS_WIDTH)));
3185 if (page->tab_label)
3186 gtk_widget_size_allocate (page->tab_label, &child_allocation);
3190 gtk_notebook_calc_tabs (GtkNotebook *notebook,
3196 GtkNotebookPage *page = NULL;
3198 GList *last_list = NULL;
3205 pack = GTK_NOTEBOOK_PAGE (start)->pack;
3206 if (pack == GTK_PACK_END)
3207 direction = (direction == STEP_PREV) ? STEP_NEXT : STEP_PREV;
3211 switch (notebook->tab_pos)
3214 case GTK_POS_BOTTOM:
3217 page = children->data;
3218 if (GTK_WIDGET_VISIBLE (page->child))
3220 if (page->pack == pack)
3222 *tab_space -= page->requisition.width;
3223 if (*tab_space < 0 || children == *end)
3227 *tab_space = - (*tab_space +
3228 page->requisition.width);
3234 last_list = children;
3236 if (direction == STEP_NEXT)
3237 children = children->next;
3239 children = children->prev;
3246 page = children->data;
3247 if (GTK_WIDGET_VISIBLE (page->child))
3249 if (page->pack == pack)
3251 *tab_space -= page->requisition.height;
3252 if (*tab_space < 0 || children == *end)
3256 *tab_space = - (*tab_space +
3257 page->requisition.height);
3263 last_list = children;
3265 if (direction == STEP_NEXT)
3266 children = children->next;
3268 children = children->prev;
3272 if (direction == STEP_PREV)
3274 pack = (pack == GTK_PACK_END) ? GTK_PACK_START : GTK_PACK_END;
3275 direction = STEP_PREV;
3276 children = last_list;
3280 /* Private GtkNotebook Page Switch Methods:
3282 * gtk_notebook_real_switch_page
3285 gtk_notebook_real_switch_page (GtkNotebook *notebook,
3286 GtkNotebookPage *page,
3289 g_return_if_fail (notebook != NULL);
3290 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3291 g_return_if_fail (page != NULL);
3293 if (notebook->cur_page == page || !GTK_WIDGET_VISIBLE (page->child))
3296 if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
3297 gtk_widget_unmap (notebook->cur_page->child);
3299 notebook->cur_page = page;
3301 if (!notebook->focus_tab ||
3302 notebook->focus_tab->data != (gpointer) notebook->cur_page)
3303 notebook->focus_tab =
3304 g_list_find (notebook->children, notebook->cur_page);
3306 if (GTK_WIDGET_MAPPED (notebook))
3307 gtk_widget_map (notebook->cur_page->child);
3309 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3312 /* Private GtkNotebook Page Switch Functions:
3314 * gtk_notebook_switch_page
3315 * gtk_notebook_page_select
3316 * gtk_notebook_switch_focus_tab
3317 * gtk_notebook_menu_switch_page
3320 gtk_notebook_switch_page (GtkNotebook *notebook,
3321 GtkNotebookPage *page,
3324 g_return_if_fail (notebook != NULL);
3325 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3326 g_return_if_fail (page != NULL);
3328 if (notebook->cur_page == page)
3332 page_num = g_list_index (notebook->children, page);
3334 gtk_signal_emit (GTK_OBJECT (notebook),
3335 notebook_signals[SWITCH_PAGE],
3341 gtk_notebook_page_select (GtkNotebook *notebook)
3343 GtkNotebookPage *page;
3345 g_return_val_if_fail (notebook != NULL, FALSE);
3346 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3348 if (!notebook->focus_tab)
3351 page = notebook->focus_tab->data;
3352 gtk_notebook_switch_page (notebook, page, -1);
3354 if (GTK_WIDGET_VISIBLE (page->child))
3356 if (GTK_IS_CONTAINER (page->child))
3358 if (gtk_container_focus (GTK_CONTAINER (page->child),
3359 GTK_DIR_TAB_FORWARD))
3362 else if (GTK_WIDGET_CAN_FOCUS (page->child))
3364 gtk_widget_grab_focus (page->child);
3372 gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
3376 GtkNotebookPage *old_page = NULL;
3377 GtkNotebookPage *page;
3379 g_return_if_fail (notebook != NULL);
3380 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3382 if (notebook->focus_tab == new_child)
3385 old_child = notebook->focus_tab;
3386 notebook->focus_tab = new_child;
3388 if (notebook->scrollable && GTK_WIDGET_DRAWABLE (notebook))
3390 if ((new_child == NULL) != (old_child == NULL))
3392 gdk_window_clear (notebook->panel);
3393 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3394 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3401 olist = gtk_notebook_search_page (notebook, old_child,
3403 nlist = gtk_notebook_search_page (notebook, new_child,
3406 if ((olist == NULL) != (nlist == NULL))
3408 gdk_window_clear_area (notebook->panel, 0, 0,
3409 ARROW_SIZE, ARROW_SIZE);
3410 gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3413 olist = gtk_notebook_search_page (notebook, old_child,
3415 nlist = gtk_notebook_search_page (notebook, new_child,
3418 if ((olist == NULL) != (nlist == NULL))
3420 gdk_window_clear_area (notebook->panel,
3421 ARROW_SIZE + ARROW_SPACING, 0,
3422 ARROW_SIZE, ARROW_SIZE);
3423 gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3428 if (!notebook->show_tabs || !notebook->focus_tab)
3432 old_page = old_child->data;
3434 page = notebook->focus_tab->data;
3435 if (GTK_WIDGET_MAPPED (page->tab_label))
3436 gtk_notebook_focus_changed (notebook, old_page);
3439 gtk_notebook_pages_allocate (notebook,
3440 &(GTK_WIDGET (notebook)->allocation));
3441 gtk_notebook_expose_tabs (notebook);
3444 gtk_notebook_set_shape (notebook);
3448 gtk_notebook_menu_switch_page (GtkWidget *widget,
3449 GtkNotebookPage *page)
3451 GtkNotebook *notebook;
3455 g_return_if_fail (widget != NULL);
3456 g_return_if_fail (page != NULL);
3458 notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget
3459 (GTK_MENU (widget->parent)));
3461 if (notebook->cur_page == page)
3465 children = notebook->children;
3466 while (children && children->data != page)
3468 children = children->next;
3472 gtk_signal_emit (GTK_OBJECT (notebook),
3473 notebook_signals[SWITCH_PAGE],
3478 /* Private GtkNotebook Menu Functions:
3480 * gtk_notebook_menu_item_create
3481 * gtk_notebook_menu_label_unparent
3482 * gtk_notebook_menu_detacher
3485 gtk_notebook_menu_item_create (GtkNotebook *notebook,
3488 GtkNotebookPage *page;
3489 GtkWidget *menu_item;
3492 if (page->default_menu)
3494 if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3495 page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3497 page->menu_label = gtk_label_new ("");
3498 gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3501 gtk_widget_show (page->menu_label);
3502 menu_item = gtk_menu_item_new ();
3503 gtk_widget_lock_accelerators (menu_item);
3504 gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3505 gtk_menu_insert (GTK_MENU (notebook->menu), menu_item,
3506 gtk_notebook_real_page_position (notebook, list));
3507 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3508 GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3509 if (GTK_WIDGET_VISIBLE (page->child))
3510 gtk_widget_show (menu_item);
3514 gtk_notebook_menu_label_unparent (GtkWidget *widget,
3517 gtk_widget_unparent (GTK_BIN(widget)->child);
3518 GTK_BIN(widget)->child = NULL;
3522 gtk_notebook_menu_detacher (GtkWidget *widget,
3525 GtkNotebook *notebook;
3527 g_return_if_fail (widget != NULL);
3528 g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3530 notebook = GTK_NOTEBOOK (widget);
3531 g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3533 notebook->menu = NULL;
3536 /* Public GtkNotebook Page Insert/Remove Methods :
3538 * gtk_notebook_append_page
3539 * gtk_notebook_append_page_menu
3540 * gtk_notebook_prepend_page
3541 * gtk_notebook_prepend_page_menu
3542 * gtk_notebook_insert_page
3543 * gtk_notebook_insert_page_menu
3544 * gtk_notebook_remove_page
3547 gtk_notebook_append_page (GtkNotebook *notebook,
3549 GtkWidget *tab_label)
3551 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
3555 gtk_notebook_append_page_menu (GtkNotebook *notebook,
3557 GtkWidget *tab_label,
3558 GtkWidget *menu_label)
3560 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
3564 gtk_notebook_prepend_page (GtkNotebook *notebook,
3566 GtkWidget *tab_label)
3568 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
3572 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
3574 GtkWidget *tab_label,
3575 GtkWidget *menu_label)
3577 gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
3581 gtk_notebook_insert_page (GtkNotebook *notebook,
3583 GtkWidget *tab_label,
3586 gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
3590 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
3592 GtkWidget *tab_label,
3593 GtkWidget *menu_label,
3596 GtkNotebookPage *page;
3599 g_return_if_fail (notebook != NULL);
3600 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3601 g_return_if_fail (child != NULL);
3603 page = g_new (GtkNotebookPage, 1);
3604 page->child = child;
3605 page->requisition.width = 0;
3606 page->requisition.height = 0;
3607 page->allocation.x = 0;
3608 page->allocation.y = 0;
3609 page->allocation.width = 0;
3610 page->allocation.height = 0;
3611 page->default_menu = FALSE;
3612 page->default_tab = FALSE;
3614 nchildren = g_list_length (notebook->children);
3615 if ((position < 0) || (position > nchildren))
3616 position = nchildren;
3618 notebook->children = g_list_insert (notebook->children, page, position);
3622 page->default_tab = TRUE;
3623 if (notebook->show_tabs)
3624 tab_label = gtk_label_new ("");
3626 page->tab_label = tab_label;
3627 page->menu_label = menu_label;
3628 page->expand = FALSE;
3630 page->pack = GTK_PACK_START;
3633 page->default_menu = TRUE;
3636 gtk_widget_ref (page->menu_label);
3637 gtk_object_sink (GTK_OBJECT(page->menu_label));
3641 gtk_notebook_menu_item_create (notebook,
3642 g_list_find (notebook->children, page));
3644 gtk_notebook_update_labels (notebook);
3646 if (!notebook->first_tab)
3647 notebook->first_tab = notebook->children;
3649 gtk_widget_set_parent (child, GTK_WIDGET (notebook));
3651 gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
3653 if (!notebook->cur_page)
3655 gtk_notebook_switch_page (notebook, page, 0);
3656 gtk_notebook_switch_focus_tab (notebook, NULL);
3659 if (GTK_WIDGET_REALIZED (child->parent))
3660 gtk_widget_realize (child);
3662 if (GTK_WIDGET_VISIBLE (notebook))
3664 if (GTK_WIDGET_VISIBLE (child))
3666 if (GTK_WIDGET_MAPPED (notebook) &&
3667 !GTK_WIDGET_MAPPED (child) &&
3668 notebook->cur_page == page)
3669 gtk_widget_map (child);
3671 gtk_widget_queue_resize (child);
3676 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
3678 if (!GTK_WIDGET_VISIBLE (tab_label))
3679 gtk_widget_show (tab_label);
3681 if (GTK_WIDGET_REALIZED (notebook) &&
3682 !GTK_WIDGET_REALIZED (tab_label))
3683 gtk_widget_realize (tab_label);
3685 if (GTK_WIDGET_MAPPED (notebook) &&
3686 !GTK_WIDGET_MAPPED (tab_label))
3687 gtk_widget_map (tab_label);
3689 else if (GTK_WIDGET_VISIBLE (tab_label))
3690 gtk_widget_hide (tab_label);
3696 gtk_notebook_remove_page (GtkNotebook *notebook,
3701 g_return_if_fail (notebook != NULL);
3702 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3706 list = g_list_nth (notebook->children, page_num);
3708 gtk_notebook_real_remove (notebook, list);
3712 list = g_list_last (notebook->children);
3714 gtk_notebook_real_remove (notebook, list);
3718 /* Public GtkNotebook Page Switch Methods :
3719 * gtk_notebook_get_current_page
3720 * gtk_notebook_page_num
3721 * gtk_notebook_set_page
3722 * gtk_notebook_next_page
3723 * gtk_notebook_prev_page
3726 gtk_notebook_get_current_page (GtkNotebook *notebook)
3728 g_return_val_if_fail (notebook != NULL, -1);
3729 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3731 if (!notebook->cur_page)
3734 return g_list_index (notebook->children, notebook->cur_page);
3738 gtk_notebook_get_nth_page (GtkNotebook *notebook,
3741 GtkNotebookPage *page;
3743 g_return_val_if_fail (notebook != NULL, NULL);
3744 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
3746 page = g_list_nth_data (notebook->children, page_num);
3755 gtk_notebook_page_num (GtkNotebook *notebook,
3761 g_return_val_if_fail (notebook != NULL, -1);
3762 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
3765 children = notebook->children;
3768 GtkNotebookPage *page;
3770 page = children->data;
3771 if (page->child == child)
3774 children = children->next;
3782 gtk_notebook_set_page (GtkNotebook *notebook,
3787 g_return_if_fail (notebook != NULL);
3788 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3791 list = g_list_nth (notebook->children, page_num);
3794 list = g_list_last (notebook->children);
3795 page_num = g_list_length (notebook->children) - 1;
3798 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), page_num);
3802 gtk_notebook_next_page (GtkNotebook *notebook)
3806 g_return_if_fail (notebook != NULL);
3807 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3809 list = g_list_find (notebook->children, notebook->cur_page);
3813 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
3817 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
3821 gtk_notebook_prev_page (GtkNotebook *notebook)
3825 g_return_if_fail (notebook != NULL);
3826 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3828 list = g_list_find (notebook->children, notebook->cur_page);
3832 list = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
3836 gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (list), -1);
3839 /* Public GtkNotebook/Tab Style Functions
3841 * gtk_notebook_set_show_border
3842 * gtk_notebook_set_show_tabs
3843 * gtk_notebook_set_tab_pos
3844 * gtk_notebook_set_homogeneous_tabs
3845 * gtk_notebook_set_tab_border
3846 * gtk_notebook_set_tab_hborder
3847 * gtk_notebook_set_tab_vborder
3848 * gtk_notebook_set_scrollable
3851 gtk_notebook_set_show_border (GtkNotebook *notebook,
3852 gboolean show_border)
3854 g_return_if_fail (notebook != NULL);
3855 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3857 if (notebook->show_border != show_border)
3859 notebook->show_border = show_border;
3861 if (GTK_WIDGET_VISIBLE (notebook))
3862 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3867 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
3870 GtkNotebookPage *page;
3873 g_return_if_fail (notebook != NULL);
3874 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3876 show_tabs = show_tabs != FALSE;
3878 if (notebook->show_tabs == show_tabs)
3881 notebook->show_tabs = show_tabs;
3882 children = notebook->children;
3886 GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
3890 page = children->data;
3891 children = children->next;
3892 if (page->default_tab)
3894 gtk_widget_destroy (page->tab_label);
3895 page->tab_label = NULL;
3898 gtk_widget_hide (page->tab_label);
3901 if (notebook->panel)
3902 gdk_window_hide (notebook->panel);
3906 GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
3907 gtk_notebook_update_labels (notebook);
3909 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3913 gtk_notebook_set_tab_pos (GtkNotebook *notebook,
3914 GtkPositionType pos)
3916 g_return_if_fail (notebook != NULL);
3917 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3919 if (notebook->tab_pos != pos)
3921 notebook->tab_pos = pos;
3922 if (GTK_WIDGET_VISIBLE (notebook))
3923 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3928 gtk_notebook_set_homogeneous_tabs (GtkNotebook *notebook,
3929 gboolean homogeneous)
3931 g_return_if_fail (notebook != NULL);
3932 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3934 if (homogeneous == notebook->homogeneous)
3937 notebook->homogeneous = homogeneous;
3938 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3942 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3945 g_return_if_fail (notebook != NULL);
3946 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3948 notebook->tab_hborder = tab_border;
3949 notebook->tab_vborder = tab_border;
3951 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3952 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3956 gtk_notebook_set_tab_hborder (GtkNotebook *notebook,
3959 g_return_if_fail (notebook != NULL);
3960 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3962 if (notebook->tab_hborder == tab_hborder)
3965 notebook->tab_hborder = tab_hborder;
3967 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3968 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3972 gtk_notebook_set_tab_vborder (GtkNotebook *notebook,
3975 g_return_if_fail (notebook != NULL);
3976 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3978 if (notebook->tab_vborder == tab_vborder)
3981 notebook->tab_vborder = tab_vborder;
3983 if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3984 gtk_widget_queue_resize (GTK_WIDGET (notebook));
3988 gtk_notebook_set_scrollable (GtkNotebook *notebook,
3989 gboolean scrollable)
3991 g_return_if_fail (notebook != NULL);
3992 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3994 scrollable = (scrollable != FALSE);
3996 if (scrollable != notebook->scrollable)
3998 notebook->scrollable = scrollable;
4000 if (GTK_WIDGET_REALIZED (notebook))
4004 gtk_notebook_panel_realize (notebook);
4006 else if (notebook->panel)
4008 gdk_window_set_user_data (notebook->panel, NULL);
4009 gdk_window_destroy (notebook->panel);
4010 notebook->panel = NULL;
4014 if (GTK_WIDGET_VISIBLE (notebook))
4015 gtk_widget_queue_resize (GTK_WIDGET(notebook));
4019 /* Public GtkNotebook Popup Menu Methods:
4021 * gtk_notebook_popup_enable
4022 * gtk_notebook_popup_disable
4025 gtk_notebook_popup_enable (GtkNotebook *notebook)
4029 g_return_if_fail (notebook != NULL);
4030 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4035 notebook->menu = gtk_menu_new ();
4036 for (list = gtk_notebook_search_page (notebook, NULL, STEP_NEXT, FALSE);
4038 list = gtk_notebook_search_page (notebook, list, STEP_NEXT, FALSE))
4039 gtk_notebook_menu_item_create (notebook, list);
4041 gtk_notebook_update_labels (notebook);
4042 gtk_menu_attach_to_widget (GTK_MENU (notebook->menu),
4043 GTK_WIDGET (notebook),
4044 gtk_notebook_menu_detacher);
4048 gtk_notebook_popup_disable (GtkNotebook *notebook)
4050 g_return_if_fail (notebook != NULL);
4051 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4053 if (!notebook->menu)
4056 gtk_container_foreach (GTK_CONTAINER (notebook->menu),
4057 (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
4058 gtk_widget_destroy (notebook->menu);
4061 /* Public GtkNotebook Page Properties Functions:
4063 * gtk_notebook_get_tab_label
4064 * gtk_notebook_set_tab_label
4065 * gtk_notebook_set_tab_label_text
4066 * gtk_notebook_get_menu_label
4067 * gtk_notebook_set_menu_label
4068 * gtk_notebook_set_menu_label_text
4069 * gtk_notebook_set_tab_label_packing
4070 * gtk_notebook_query_tab_label_packing
4073 gtk_notebook_get_tab_label (GtkNotebook *notebook,
4078 g_return_val_if_fail (notebook != NULL, NULL);
4079 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4080 g_return_val_if_fail (child != NULL, NULL);
4082 if (!(list = g_list_find_custom (notebook->children, child,
4083 gtk_notebook_page_compare)))
4086 if (GTK_NOTEBOOK_PAGE (list)->default_tab)
4089 return GTK_NOTEBOOK_PAGE (list)->tab_label;
4093 gtk_notebook_set_tab_label (GtkNotebook *notebook,
4095 GtkWidget *tab_label)
4097 GtkNotebookPage *page;
4100 g_return_if_fail (notebook != NULL);
4101 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4102 g_return_if_fail (child != NULL);
4104 if (!(list = g_list_find_custom (notebook->children, child,
4105 gtk_notebook_page_compare)))
4108 /* a NULL pointer indicates a default_tab setting, otherwise
4109 * we need to set the associated label
4113 if (page->tab_label)
4114 gtk_widget_unparent (page->tab_label);
4118 page->default_tab = FALSE;
4119 page->tab_label = tab_label;
4120 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4124 page->default_tab = TRUE;
4125 page->tab_label = NULL;
4127 if (notebook->show_tabs)
4131 g_snprintf (string, sizeof(string), _("Page %u"),
4132 gtk_notebook_real_page_position (notebook, list));
4133 page->tab_label = gtk_label_new (string);
4134 gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
4138 if (notebook->show_tabs && GTK_WIDGET_VISIBLE (child))
4140 gtk_widget_show (page->tab_label);
4141 gtk_widget_queue_resize (GTK_WIDGET (notebook));
4146 gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
4148 const gchar *tab_text)
4150 GtkWidget *tab_label = NULL;
4153 tab_label = gtk_label_new (tab_text);
4154 gtk_notebook_set_tab_label (notebook, child, tab_label);
4158 gtk_notebook_get_menu_label (GtkNotebook *notebook,
4163 g_return_val_if_fail (notebook != NULL, NULL);
4164 g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
4165 g_return_val_if_fail (child != NULL, NULL);
4167 if (!(list = g_list_find_custom (notebook->children, child,
4168 gtk_notebook_page_compare)))
4171 if (GTK_NOTEBOOK_PAGE (list)->default_menu)
4174 return GTK_NOTEBOOK_PAGE (list)->menu_label;
4178 gtk_notebook_set_menu_label (GtkNotebook *notebook,
4180 GtkWidget *menu_label)
4182 GtkNotebookPage *page;
4185 g_return_if_fail (notebook != NULL);
4186 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4187 g_return_if_fail (child != NULL);
4189 if (!(list = g_list_find_custom (notebook->children, child,
4190 gtk_notebook_page_compare)))
4194 if (page->menu_label)
4198 gtk_container_remove (GTK_CONTAINER (notebook->menu),
4199 page->menu_label->parent);
4200 gtk_widget_queue_resize (notebook->menu);
4202 if (!page->default_menu)
4203 gtk_widget_unref (page->menu_label);
4208 page->menu_label = menu_label;
4209 gtk_widget_ref (page->menu_label);
4210 gtk_object_sink (GTK_OBJECT(page->menu_label));
4211 page->default_menu = FALSE;
4214 page->default_menu = TRUE;
4217 gtk_notebook_menu_item_create (notebook, list);
4221 gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
4223 const gchar *menu_text)
4225 GtkWidget *menu_label = NULL;
4228 menu_label = gtk_label_new (menu_text);
4229 gtk_notebook_set_menu_label (notebook, child, menu_label);
4233 gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
4237 GtkPackType pack_type)
4239 GtkNotebookPage *page;
4242 g_return_if_fail (notebook != NULL);
4243 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4244 g_return_if_fail (child != NULL);
4246 if (!(list = g_list_find_custom (notebook->children, child,
4247 gtk_notebook_page_compare)))
4251 if (page->pack == pack_type && page->expand == expand && page->fill == fill)
4254 page->expand = expand;
4257 if (page->pack != pack_type)
4259 page->pack = pack_type;
4262 GtkWidget *menu_item;
4264 menu_item = page->menu_label->parent;
4265 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4266 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4267 gtk_notebook_menu_item_create (notebook, list);
4268 gtk_widget_queue_resize (notebook->menu);
4270 gtk_notebook_update_labels (notebook);
4273 if (!notebook->show_tabs)
4276 gtk_notebook_pages_allocate (notebook, &(GTK_WIDGET (notebook)->allocation));
4277 gtk_notebook_expose_tabs (notebook);
4281 gtk_notebook_query_tab_label_packing (GtkNotebook *notebook,
4285 GtkPackType *pack_type)
4289 g_return_if_fail (notebook != NULL);
4290 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4291 g_return_if_fail (child != NULL);
4293 if (!(list = g_list_find_custom (notebook->children, child,
4294 gtk_notebook_page_compare)))
4298 *expand = GTK_NOTEBOOK_PAGE (list)->expand;
4300 *fill = GTK_NOTEBOOK_PAGE (list)->fill;
4302 *pack_type = GTK_NOTEBOOK_PAGE (list)->pack;
4306 gtk_notebook_reorder_child (GtkNotebook *notebook,
4312 GtkNotebookPage *page = NULL;
4315 g_return_if_fail (notebook != NULL);
4316 g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
4317 g_return_if_fail (child != NULL);
4318 g_return_if_fail (GTK_IS_WIDGET (child));
4320 for (old_pos = 0, list = notebook->children; list;
4321 list = list->next, old_pos++)
4324 if (page->child == child)
4328 if (!list || old_pos == position)
4331 notebook->children = g_list_remove_link (notebook->children, list);
4333 if (position <= 0 || !notebook->children)
4335 list->next = notebook->children;
4337 list->next->prev = list;
4338 notebook->children = list;
4340 else if (position > 0 && (work = g_list_nth (notebook->children, position)))
4342 list->prev = work->prev;
4344 list->prev->next = list;
4350 work = g_list_last (notebook->children);
4357 GtkWidget *menu_item;
4359 g_assert(page != NULL);
4361 menu_item = page->menu_label->parent;
4362 gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
4363 gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
4364 gtk_notebook_menu_item_create (notebook, list);
4365 gtk_widget_queue_resize (notebook->menu);
4368 gtk_notebook_update_labels (notebook);
4370 if (notebook->show_tabs)
4372 gtk_notebook_pages_allocate (notebook,
4373 &(GTK_WIDGET (notebook)->allocation));
4374 gtk_notebook_expose_tabs (notebook);