X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkoverlay.c;h=a66ede8dc67cba6622b01f628f03528b35763a00;hb=935d458fa1b72b8f1b0a36566b7c40c06870bb9f;hp=66fc9ee90f8af29b87492abe70ebc70ca7272b99;hpb=9d0febc9a64a5bfb0fcfc3a88de4757f6c1ff090;p=~andy%2Fgtk diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c index 66fc9ee90..a66ede8dc 100644 --- a/gtk/gtkoverlay.c +++ b/gtk/gtkoverlay.c @@ -113,6 +113,129 @@ gtk_overlay_create_child_window (GtkOverlay *overlay, return window; } +static GtkAlign +effective_align (GtkAlign align, + GtkTextDirection direction) +{ + switch (align) + { + case GTK_ALIGN_START: + return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START; + case GTK_ALIGN_END: + return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END; + default: + return align; + } +} + +static void +gtk_overlay_get_main_widget_allocation (GtkOverlay *overlay, + GtkAllocation *main_alloc_out) +{ + GtkWidget *main_widget; + GtkAllocation main_alloc; + + main_widget = gtk_bin_get_child (GTK_BIN (overlay)); + + /* special-case scrolled windows */ + if (GTK_IS_SCROLLED_WINDOW (main_widget)) + { + GtkWidget *grandchild; + gint x, y; + gboolean res; + + grandchild = gtk_bin_get_child (GTK_BIN (main_widget)); + res = gtk_widget_translate_coordinates (grandchild, main_widget, 0, 0, &x, &y); + + if (res) + { + main_alloc.x = x; + main_alloc.y = y; + } + else + { + main_alloc.x = 0; + main_alloc.y = 0; + } + + main_alloc.width = gtk_widget_get_allocated_width (grandchild); + main_alloc.height = gtk_widget_get_allocated_height (grandchild); + } + else + { + main_alloc.x = 0; + main_alloc.y = 0; + main_alloc.width = gtk_widget_get_allocated_width (main_widget); + main_alloc.height = gtk_widget_get_allocated_height (main_widget); + } + + if (main_alloc_out) + *main_alloc_out = main_alloc; +} + +static void +gtk_overlay_child_update_style_classes (GtkOverlay *overlay, + GtkWidget *child, + GtkAllocation *child_allocation) +{ + GtkAllocation overlay_allocation, main_allocation; + GtkAlign valign, halign; + gboolean is_left, is_right, is_top, is_bottom; + gboolean has_left, has_right, has_top, has_bottom; + GtkStyleContext *context; + + context = gtk_widget_get_style_context (child); + has_left = gtk_style_context_has_class (context, GTK_STYLE_CLASS_LEFT); + has_right = gtk_style_context_has_class (context, GTK_STYLE_CLASS_RIGHT); + has_top = gtk_style_context_has_class (context, GTK_STYLE_CLASS_TOP); + has_bottom = gtk_style_context_has_class (context, GTK_STYLE_CLASS_BOTTOM); + + is_left = is_right = is_top = is_bottom = FALSE; + + gtk_overlay_get_main_widget_allocation (overlay, &main_allocation); + gtk_widget_get_allocation (GTK_WIDGET (overlay), &overlay_allocation); + + main_allocation.x += overlay_allocation.x; + main_allocation.y += overlay_allocation.y; + + halign = effective_align (gtk_widget_get_halign (child), + gtk_widget_get_direction (child)); + + if (halign == GTK_ALIGN_START) + is_left = (child_allocation->x == main_allocation.x); + else if (halign == GTK_ALIGN_END) + is_right = (child_allocation->x + child_allocation->width == + main_allocation.x + main_allocation.width); + + valign = gtk_widget_get_valign (child); + + if (valign == GTK_ALIGN_START) + is_top = (child_allocation->y == main_allocation.y); + else if (valign == GTK_ALIGN_END) + is_bottom = (child_allocation->y + child_allocation->height == + main_allocation.y + main_allocation.height); + + if (has_left && !is_left) + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_LEFT); + else if (!has_left && is_left) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT); + + if (has_right && !is_right) + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_RIGHT); + else if (!has_right && is_right) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT); + + if (has_top && !is_top) + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOP); + else if (!has_top && is_top) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP); + + if (has_bottom && !is_bottom) + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BOTTOM); + else if (!has_bottom && is_bottom) + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM); +} + static void gtk_overlay_child_allocate (GtkOverlay *overlay, GtkOverlayChild *child) @@ -163,6 +286,7 @@ gtk_overlay_child_allocate (GtkOverlay *overlay, allocation.x, allocation.y, allocation.width, allocation.height); + gtk_overlay_child_update_style_classes (overlay, child->widget, &allocation); gtk_widget_size_allocate (child->widget, &child_allocation); } @@ -227,56 +351,17 @@ gtk_overlay_size_allocate (GtkWidget *widget, } } -static GtkAlign -effective_align (GtkAlign align, - GtkTextDirection direction) -{ - switch (align) - { - case GTK_ALIGN_START: - return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START; - case GTK_ALIGN_END: - return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END; - default: - return align; - } -} - static gboolean gtk_overlay_get_child_position (GtkOverlay *overlay, GtkWidget *widget, GtkAllocation *alloc) { - GtkWidget *main_widget; GtkAllocation main_alloc; GtkRequisition req; GtkAlign halign; GtkTextDirection direction; - main_widget = gtk_bin_get_child (GTK_BIN (overlay)); - - /* special-case scrolled windows */ - if (GTK_IS_SCROLLED_WINDOW (main_widget)) - { - GtkWidget *grandchild; - gint x, y; - - grandchild = gtk_bin_get_child (GTK_BIN (main_widget)); - gtk_widget_translate_coordinates (grandchild, main_widget, 0, 0, &x, &y); - - main_alloc.x = x; - main_alloc.y = y; - main_alloc.width = gtk_widget_get_allocated_width (grandchild); - main_alloc.height = gtk_widget_get_allocated_height (grandchild); - } - else - { - main_alloc.x = 0; - main_alloc.y = 0; - main_alloc.width = gtk_widget_get_allocated_width (main_widget); - main_alloc.height = gtk_widget_get_allocated_height (main_widget); - } - + gtk_overlay_get_main_widget_allocation (overlay, &main_alloc); gtk_widget_get_preferred_size (widget, NULL, &req); alloc->x = main_alloc.x; @@ -338,7 +423,10 @@ gtk_overlay_realize (GtkWidget *widget) child = children->data; if (child->window == NULL) - child->window = gtk_overlay_create_child_window (overlay, child->widget); + { + child->window = gtk_overlay_create_child_window (overlay, child->widget); + gtk_overlay_child_allocate (overlay, child); + } } } @@ -517,7 +605,7 @@ gtk_overlay_class_init (GtkOverlayClass *klass) * GtkOverlay::get-child-position: * @overlay: the #GtkOverlay * @widget: the child widget to position - * @allocation: (out): return location for the allocation + * @allocation: (out caller-allocates): return location for the allocation * * The ::get-child-position signal is emitted to determine * the position and size of any overlay child widgets. A