typedef struct { int x; int y; int width; int height; } GdkRectangle; enum { GTK_POS_LEFT, GTK_POS_RIGHT, GTK_POS_TOP, GTK_POS_BOTTOM }; typedef struct { void *parent; }GtkWidget ; typedef struct { GtkWidget *tab_label; int pack; GdkRectangle requisition, allocation; } GtkNotebookPage ; typedef struct { GtkNotebookPage *cur_page; int homogeneous:1; } GtkNotebook; enum { DRAG_OPERATION_NONE, DRAG_OPERATION_REORDER, DRAG_OPERATION_DETACH } ; typedef struct { int operation; int x; int y; GtkNotebookPage *detached_tab; }GtkNotebookPrivate; gtk_notebook_calculate_tabs_allocation() { GtkNotebook * notebook; void ** children; void* last_child; int showarrow; int *remaining_space; int *expanded_tabs; int min; int max; GtkNotebookPrivate *priv; GtkNotebookPage *page; int allocate_at_bottom; int tab_overlap; int tab_pos; int tab_extra_space; int left_x; int right_x; int top_y; int anchor; int xthickness; int ythickness; int gap_left; int packing_changed; GdkRectangle child_allocation; while (*children && *children != last_child) { if (page->tab_label->parent != notebook) continue; if (*expanded_tabs && notebook->homogeneous) { tab_extra_space = *remaining_space / *expanded_tabs; *remaining_space -= tab_extra_space; } switch (tab_pos) { case GTK_POS_TOP: case GTK_POS_BOTTOM: child_allocation.width = page->requisition.width + tab_overlap + tab_extra_space; if (gap_left && packing_changed) { if (allocate_at_bottom) { left_x = priv->x = anchor; anchor += notebook->cur_page->allocation. width - tab_overlap; if (notebook->cur_page->pack && right_x > anchor) { anchor -= notebook->cur_page-> allocation.width; priv->x = anchor; } } } else { if (allocate_at_bottom) anchor -= child_allocation.width; if (priv->operation == DRAG_OPERATION_REORDER && page->pack == notebook->cur_page->pack) { if (!allocate_at_bottom && left_x >= anchor && left_x <= anchor + child_allocation.width / 2) anchor += notebook->cur_page-> allocation.width - tab_overlap; else if (allocate_at_bottom && right_x >= anchor + child_allocation.width / 2 && right_x <= anchor + child_allocation.width) anchor -= notebook->cur_page-> allocation.width - tab_overlap; } child_allocation.x = anchor; } break; case GTK_POS_LEFT: case GTK_POS_RIGHT: child_allocation.height = page->requisition.height + tab_overlap + tab_extra_space; if (packing_changed) { priv->x = child_allocation.x; priv->y = top_y; if (priv->operation == DRAG_OPERATION_REORDER && page->pack == notebook->cur_page->pack) { if (!allocate_at_bottom && top_y >= anchor && top_y <= anchor + child_allocation.height / 2) anchor += notebook->cur_page-> allocation.height - tab_overlap; } } } if ((page == priv->detached_tab && priv->operation == DRAG_OPERATION_DETACH) || (page == notebook->cur_page && priv->operation == DRAG_OPERATION_REORDER)) { page->allocation.x = 0; } if (page != notebook->cur_page) { switch (tab_pos) { case GTK_POS_TOP: page->allocation.y += ythickness; case GTK_POS_BOTTOM: page->allocation.height = 1 > page->allocation.height - ythickness ? 1 : page->allocation.height - ythickness; break; case GTK_POS_LEFT: page->allocation.x += xthickness; case GTK_POS_RIGHT: page->allocation.width = 1 > page->allocation.width - xthickness ? 1 : page->allocation.width - xthickness; } } switch (tab_pos) { case GTK_POS_TOP: case GTK_POS_BOTTOM: if (priv->operation != DRAG_OPERATION_REORDER || priv->operation == DRAG_OPERATION_REORDER && page != notebook->cur_page) if (!allocate_at_bottom) anchor += child_allocation.width - tab_overlap; case GTK_POS_LEFT: case GTK_POS_RIGHT: if (priv->operation != DRAG_OPERATION_REORDER || priv->operation == DRAG_OPERATION_REORDER && page != notebook->cur_page) if (priv->operation == DRAG_OPERATION_REORDER) if (page->pack == notebook->cur_page->pack && !allocate_at_bottom && top_y >= anchor + child_allocation.height / 2 && top_y <= anchor + child_allocation.height) anchor += notebook->cur_page-> allocation.height - tab_overlap; } if (page->tab_label) IA__gtk_widget_set_child_visible(page->tab_label, 1); } }