X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktoolbar.c;h=e4dbfa45eb2aa79e5cf54a8f223a9e3161b264ef;hb=e09957a47da9425cc26d1b33cb4e9cc3e92e9ac7;hp=e3f207e80530bbebd6281a6f85b2c8c9e9d9f70d;hpb=913cdf3be750a1e74c09b20edf55a57f9a919fcc;p=~andy%2Fgtk diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c index e3f207e80..e4dbfa45e 100644 --- a/gtk/gtktoolbar.c +++ b/gtk/gtktoolbar.c @@ -17,9 +17,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* @@ -35,32 +33,56 @@ #include #include -#include +#include "gtktoolbar.h" #include "gtkarrow.h" #include "gtkbindings.h" -#include "gtkhbox.h" +#include "gtkcontainerprivate.h" #include "gtkimage.h" #include "gtklabel.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkmenu.h" #include "gtkorientable.h" +#include "gtkorientableprivate.h" #include "gtkradiobutton.h" #include "gtkradiotoolbutton.h" #include "gtkseparatormenuitem.h" #include "gtkseparatortoolitem.h" #include "gtkstock.h" -#include "gtktoolbar.h" #include "gtktoolshell.h" -#include "gtkvbox.h" +#include "gtkbox.h" #include "gtkprivate.h" #include "gtkintl.h" +#include "gtktypebuiltins.h" +#include "gtkwidgetpath.h" +#include "gtkwidgetprivate.h" -typedef struct _ToolbarContent ToolbarContent; +/** + * SECTION:gtktoolbar + * @Short_description: Create bars of buttons and other widgets + * @Title: GtkToolbar + * @See_also: #GtkToolItem + * + * A toolbar is created with a call to gtk_toolbar_new(). + * + * A toolbar can contain instances of a subclass of #GtkToolItem. To add + * a #GtkToolItem to the a toolbar, use gtk_toolbar_insert(). To remove + * an item from the toolbar use gtk_container_remove(). To add a button + * to the toolbar, add an instance of #GtkToolButton. + * + * Toolbar items can be visually grouped by adding instances of + * #GtkSeparatorToolItem to the toolbar. If the GtkToolbar child property + * "expand" is #TRUE and the property #GtkSeparatorToolItem:draw is set to + * #FALSE, the effect is to force all following items to the end of the toolbar. + * + * Creating a context menu for the toolbar can be done by connecting to + * the #GtkToolbar::popup-context-menu signal. + */ + -#define DEFAULT_IPADDING 0 +typedef struct _ToolbarContent ToolbarContent; #define DEFAULT_SPACE_SIZE 12 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE @@ -82,29 +104,31 @@ typedef struct _ToolbarContent ToolbarContent; struct _GtkToolbarPrivate { - GtkIconSize icon_size; GtkMenu *menu; - GtkOrientation orientation; GtkSettings *settings; + + GtkIconSize icon_size; GtkToolbarStyle style; + GtkToolItem *highlight_tool_item; GtkWidget *arrow; GtkWidget *arrow_button; GdkWindow *event_window; - GList *children; GList *content; GTimer *timer; + gulong settings_connection; + gint idle_id; gint button_maxw; /* maximum width of homogeneous children */ gint button_maxh; /* maximum height of homogeneous children */ gint max_homogeneous_pixels; gint num_children; - gulong settings_connection; + GtkOrientation orientation; guint animation : 1; guint icon_size_set : 1; @@ -158,16 +182,20 @@ static void gtk_toolbar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static gint gtk_toolbar_expose (GtkWidget *widget, - GdkEventExpose *event); +static gint gtk_toolbar_draw (GtkWidget *widget, + cairo_t *cr); static void gtk_toolbar_realize (GtkWidget *widget); static void gtk_toolbar_unrealize (GtkWidget *widget); -static void gtk_toolbar_size_request (GtkWidget *widget, - GtkRequisition *requisition); +static void gtk_toolbar_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void gtk_toolbar_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); + static void gtk_toolbar_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static void gtk_toolbar_style_set (GtkWidget *widget, - GtkStyle *prev_style); +static void gtk_toolbar_style_updated (GtkWidget *widget); static gboolean gtk_toolbar_focus (GtkWidget *widget, GtkDirectionType dir); static void gtk_toolbar_move_focus (GtkWidget *widget, @@ -187,8 +215,8 @@ static void gtk_toolbar_get_child_property (GtkContainer *contain GValue *value, GParamSpec *pspec); static void gtk_toolbar_finalize (GObject *object); +static void gtk_toolbar_dispose (GObject *object); static void gtk_toolbar_show_all (GtkWidget *widget); -static void gtk_toolbar_hide_all (GtkWidget *widget); static void gtk_toolbar_add (GtkContainer *container, GtkWidget *widget); static void gtk_toolbar_remove (GtkContainer *container, @@ -198,6 +226,13 @@ static void gtk_toolbar_forall (GtkContainer *contain GtkCallback callback, gpointer callback_data); static GType gtk_toolbar_child_type (GtkContainer *container); +static GtkWidgetPath * gtk_toolbar_get_path_for_child + (GtkContainer *container, + GtkWidget *child); +static void gtk_toolbar_invalidate_order (GtkToolbar *toolbar); + +static void gtk_toolbar_direction_changed (GtkWidget *widget, + GtkTextDirection previous_direction); static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar, GtkOrientation orientation); static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar, @@ -216,9 +251,7 @@ static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar static void gtk_toolbar_reconfigured (GtkToolbar *toolbar); static GtkReliefStyle get_button_relief (GtkToolbar *toolbar); -static gint get_internal_padding (GtkToolbar *toolbar); static gint get_max_child_expand (GtkToolbar *toolbar); -static GtkShadowType get_shadow_type (GtkToolbar *toolbar); /* methods on ToolbarContent 'class' */ static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar *toolbar, @@ -228,9 +261,9 @@ static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar static void toolbar_content_remove (ToolbarContent *content, GtkToolbar *toolbar); static void toolbar_content_free (ToolbarContent *content); -static void toolbar_content_expose (ToolbarContent *content, +static void toolbar_content_draw (ToolbarContent *content, GtkContainer *container, - GdkEventExpose *expose); + cairo_t *cr); static gboolean toolbar_content_visible (ToolbarContent *content, GtkToolbar *toolbar); static void toolbar_content_size_request (ToolbarContent *content, @@ -272,7 +305,6 @@ static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content); static gboolean toolbar_content_is_separator (ToolbarContent *content); static void toolbar_content_show_all (ToolbarContent *content); -static void toolbar_content_hide_all (ToolbarContent *content); static void toolbar_content_set_expand (ToolbarContent *content, gboolean expand); @@ -338,14 +370,18 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) gobject_class->set_property = gtk_toolbar_set_property; gobject_class->get_property = gtk_toolbar_get_property; gobject_class->finalize = gtk_toolbar_finalize; + gobject_class->dispose = gtk_toolbar_dispose; widget_class->button_press_event = gtk_toolbar_button_press; - widget_class->expose_event = gtk_toolbar_expose; - widget_class->size_request = gtk_toolbar_size_request; + widget_class->draw = gtk_toolbar_draw; + widget_class->get_preferred_width = gtk_toolbar_get_preferred_width; + widget_class->get_preferred_height = gtk_toolbar_get_preferred_height; widget_class->size_allocate = gtk_toolbar_size_allocate; - widget_class->style_set = gtk_toolbar_style_set; + widget_class->style_updated = gtk_toolbar_style_updated; widget_class->focus = gtk_toolbar_focus; + gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_TOOL_BAR); + /* need to override the base class function via override_class_handler, * because the signal slot is not available in GtkWidgetClass */ @@ -360,7 +396,7 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) widget_class->unmap = gtk_toolbar_unmap; widget_class->popup_menu = gtk_toolbar_popup_menu; widget_class->show_all = gtk_toolbar_show_all; - widget_class->hide_all = gtk_toolbar_hide_all; + widget_class->direction_changed = gtk_toolbar_direction_changed; container_class->add = gtk_toolbar_add; container_class->remove = gtk_toolbar_remove; @@ -368,7 +404,8 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) container_class->child_type = gtk_toolbar_child_type; container_class->get_child_property = gtk_toolbar_get_child_property; container_class->set_child_property = gtk_toolbar_set_child_property; - + container_class->get_path_for_child = gtk_toolbar_get_path_for_child; + klass->orientation_changed = gtk_toolbar_orientation_changed; klass->style_changed = gtk_toolbar_real_style_changed; @@ -538,13 +575,22 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) DEFAULT_SPACE_SIZE, GTK_PARAM_READABLE)); + /** + * GtkToolbar:internal-padding: + * + * Amount of border space between the toolbar shadow and the buttons. + * + * Deprecated: 3.6: Use the standard padding CSS property + * (through objects like #GtkStyleContext and #GtkCssProvider); the value + * of this style property is ignored. + */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("internal-padding", P_("Internal padding"), P_("Amount of border space between the toolbar shadow and the buttons"), 0, G_MAXINT, - DEFAULT_IPADDING, + 0, GTK_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, @@ -571,6 +617,15 @@ gtk_toolbar_class_init (GtkToolbarClass *klass) GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NONE, GTK_PARAM_READABLE)); + /** + * GtkToolbar:shadow-type: + * + * Style of bevel around the toolbar. + * + * Deprecated: 3.6: Use the standard border CSS property + * (through objects like #GtkStyleContext and #GtkCssProvider); the value + * of this style property is ignored. + */ gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("shadow-type", P_("Shadow type"), @@ -619,6 +674,7 @@ static void gtk_toolbar_init (GtkToolbar *toolbar) { GtkToolbarPrivate *priv; + GtkStyleContext *context; toolbar->priv = G_TYPE_INSTANCE_GET_PRIVATE (toolbar, GTK_TYPE_TOOLBAR, @@ -658,6 +714,9 @@ gtk_toolbar_init (GtkToolbar *toolbar) priv->max_homogeneous_pixels = -1; priv->timer = g_timer_new (); + + context = gtk_widget_get_style_context (GTK_WIDGET (toolbar)); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLBAR); } static void @@ -786,11 +845,9 @@ gtk_toolbar_realize (GtkWidget *widget) gtk_widget_set_window (widget, window); g_object_ref (window); - gtk_widget_style_attach (widget); - priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); - gdk_window_set_user_data (priv->event_window, toolbar); + gtk_widget_register_window (widget, priv->event_window); } static void @@ -801,7 +858,7 @@ gtk_toolbar_unrealize (GtkWidget *widget) if (priv->event_window) { - gdk_window_set_user_data (priv->event_window, NULL); + gtk_widget_unregister_window (widget, priv->event_window); gdk_window_destroy (priv->event_window); priv->event_window = NULL; } @@ -810,45 +867,59 @@ gtk_toolbar_unrealize (GtkWidget *widget) } static gint -gtk_toolbar_expose (GtkWidget *widget, - GdkEventExpose *event) +gtk_toolbar_draw (GtkWidget *widget, + cairo_t *cr) { - GtkAllocation allocation; GtkToolbar *toolbar = GTK_TOOLBAR (widget); GtkToolbarPrivate *priv = toolbar->priv; + GtkStyleContext *context; GList *list; guint border_width; border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); + context = gtk_widget_get_style_context (widget); + + gtk_render_background (context, cr, border_width, border_width, + gtk_widget_get_allocated_width (widget) - 2 * border_width, + gtk_widget_get_allocated_height (widget) - 2 * border_width); + gtk_render_frame (context, cr, border_width, border_width, + gtk_widget_get_allocated_width (widget) - 2 * border_width, + gtk_widget_get_allocated_height (widget) - 2 * border_width); - if (gtk_widget_is_drawable (widget)) - { - gtk_widget_get_allocation (widget, &allocation); - gtk_paint_box (gtk_widget_get_style (widget), - gtk_widget_get_window (widget), - gtk_widget_get_state (widget), - get_shadow_type (toolbar), - &event->area, widget, "toolbar", - border_width + allocation.x, - border_width + allocation.y, - allocation.width - 2 * border_width, - allocation.height - 2 * border_width); - } - for (list = priv->content; list != NULL; list = list->next) { ToolbarContent *content = list->data; - toolbar_content_expose (content, GTK_CONTAINER (widget), event); + toolbar_content_draw (content, GTK_CONTAINER (widget), cr); } - gtk_container_propagate_expose (GTK_CONTAINER (widget), - priv->arrow_button, - event); - + gtk_container_propagate_draw (GTK_CONTAINER (widget), + priv->arrow_button, + cr); + return FALSE; } +static void +get_widget_padding_and_border (GtkWidget *widget, + GtkBorder *padding) +{ + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder tmp; + + context = gtk_widget_get_style_context (widget); + state = gtk_style_context_get_state (context); + + gtk_style_context_get_padding (context, state, padding); + gtk_style_context_get_border (context, state, &tmp); + + padding->top += tmp.top; + padding->right += tmp.right; + padding->bottom += tmp.bottom; + padding->left += tmp.left; +} + static void gtk_toolbar_size_request (GtkWidget *widget, GtkRequisition *requisition) @@ -863,7 +934,7 @@ gtk_toolbar_size_request (GtkWidget *widget, gint homogeneous_size; gint long_req; gint pack_front_size; - gint ipadding; + GtkBorder padding; guint border_width; GtkRequisition arrow_requisition; @@ -926,8 +997,9 @@ gtk_toolbar_size_request (GtkWidget *widget, if (priv->show_arrow) { - gtk_widget_size_request (priv->arrow_button, &arrow_requisition); - + gtk_widget_get_preferred_size (priv->arrow_button, + &arrow_requisition, NULL); + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) long_req = arrow_requisition.width; else @@ -956,27 +1028,42 @@ gtk_toolbar_size_request (GtkWidget *widget, requisition->height = long_req; requisition->width = MAX (max_child_width, arrow_requisition.width); } - - /* Extra spacing */ - ipadding = get_internal_padding (toolbar); + /* Extra spacing */ border_width = gtk_container_get_border_width (GTK_CONTAINER (toolbar)); - requisition->width += 2 * (ipadding + border_width); - requisition->height += 2 * (ipadding + border_width); - - if (get_shadow_type (toolbar) != GTK_SHADOW_NONE) - { - GtkStyle *style; + get_widget_padding_and_border (widget, &padding); - style = gtk_widget_get_style (widget); - requisition->width += 2 * style->xthickness; - requisition->height += 2 * style->ythickness; - } + requisition->width += 2 * border_width + padding.left + padding.right; + requisition->height += 2 * border_width + padding.top + padding.bottom; priv->button_maxw = max_homogeneous_child_width; priv->button_maxh = max_homogeneous_child_height; } +static void +gtk_toolbar_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + GtkRequisition requisition; + + gtk_toolbar_size_request (widget, &requisition); + + *minimum = *natural = requisition.width; +} + +static void +gtk_toolbar_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + GtkRequisition requisition; + + gtk_toolbar_size_request (widget, &requisition); + + *minimum = *natural = requisition.height; +} + static gint position (GtkToolbar *toolbar, gint from, @@ -1175,11 +1262,11 @@ gtk_toolbar_begin_sliding (GtkToolbar *toolbar) GtkAllocation allocation; GtkWidget *widget = GTK_WIDGET (toolbar); GtkToolbarPrivate *priv = toolbar->priv; - GtkStyle *style; GList *list; gint cur_x; gint cur_y; gint border_width; + GtkBorder padding; gboolean rtl; gboolean vertical; @@ -1197,21 +1284,22 @@ gtk_toolbar_begin_sliding (GtkToolbar *toolbar) priv->idle_id = gdk_threads_add_idle (slide_idle_handler, toolbar); gtk_widget_get_allocation (widget, &allocation); - style = gtk_widget_get_style (widget); rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); vertical = (priv->orientation == GTK_ORIENTATION_VERTICAL); - border_width = get_internal_padding (toolbar) + gtk_container_get_border_width (GTK_CONTAINER (toolbar)); - + + border_width = gtk_container_get_border_width (GTK_CONTAINER (toolbar)); + get_widget_padding_and_border (GTK_WIDGET (toolbar), &padding); + if (rtl) { - cur_x = allocation.width - border_width - style->xthickness; - cur_y = allocation.height - border_width - style->ythickness; + cur_x = allocation.width - border_width - padding.right; + cur_y = allocation.height - border_width - padding.top; } else { - cur_x = border_width + style->xthickness; - cur_y = border_width + style->ythickness; + cur_x = border_width + padding.left; + cur_y = border_width + padding.top; } cur_x += allocation.x; @@ -1241,14 +1329,16 @@ gtk_toolbar_begin_sliding (GtkToolbar *toolbar) if (vertical) { new_start_allocation.width = allocation.width - - 2 * border_width - 2 * style->xthickness; + 2 * border_width - + padding.left - padding.right; new_start_allocation.height = 0; } else { new_start_allocation.width = 0; new_start_allocation.height = allocation.height - - 2 * border_width - 2 * style->ythickness; + 2 * border_width - + padding.top - padding.bottom; } } @@ -1407,7 +1497,7 @@ gtk_toolbar_size_allocate (GtkWidget *widget, GtkAllocation *allocations; ItemState *new_states; GtkAllocation arrow_allocation; - GtkStyle *style; + GtkBorder padding; gint arrow_size; gint size, pos, short_size; GList *list; @@ -1421,22 +1511,18 @@ gtk_toolbar_size_allocate (GtkWidget *widget, GtkRequisition arrow_requisition; gboolean overflowing; gboolean size_changed; - gdouble elapsed; GtkAllocation item_area; - GtkShadowType shadow_type; - - style = gtk_widget_get_style (widget); gtk_widget_get_allocation (widget, &widget_allocation); size_changed = FALSE; - if (widget_allocation.x != allocation->x || - widget_allocation.y != allocation->y || - widget_allocation.width != allocation->width || + if (widget_allocation.x != allocation->x || + widget_allocation.y != allocation->y || + widget_allocation.width != allocation->width || widget_allocation.height != allocation->height) { size_changed = TRUE; } - + if (size_changed) gtk_toolbar_stop_sliding (toolbar); @@ -1445,183 +1531,167 @@ gtk_toolbar_size_allocate (GtkWidget *widget, border_width = gtk_container_get_border_width (GTK_CONTAINER (toolbar)); if (gtk_widget_get_realized (widget)) - { - gdk_window_move_resize (priv->event_window, - allocation->x + border_width, - allocation->y + border_width, - allocation->width - border_width * 2, - allocation->height - border_width * 2); - } - - border_width += get_internal_padding (toolbar); - - gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button), - &arrow_requisition); - - shadow_type = get_shadow_type (toolbar); + gdk_window_move_resize (priv->event_window, + allocation->x + border_width, + allocation->y + border_width, + allocation->width - border_width * 2, + allocation->height - border_width * 2); + + + gtk_widget_get_preferred_size (priv->arrow_button, + &arrow_requisition, NULL); + get_widget_padding_and_border (widget, &padding); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { - available_size = size = allocation->width - 2 * border_width; - short_size = allocation->height - 2 * border_width; + available_size = size = allocation->width - 2 * border_width - padding.left - padding.right; + short_size = allocation->height - 2 * border_width - padding.top - padding.bottom; arrow_size = arrow_requisition.width; - - if (shadow_type != GTK_SHADOW_NONE) - { - available_size -= 2 * style->xthickness; - short_size -= 2 * style->ythickness; - } } else { - available_size = size = allocation->height - 2 * border_width; - short_size = allocation->width - 2 * border_width; + available_size = size = allocation->height - 2 * border_width - padding.top - padding.bottom; + short_size = allocation->width - 2 * border_width - padding.left - padding.right; arrow_size = arrow_requisition.height; - - if (shadow_type != GTK_SHADOW_NONE) - { - available_size -= 2 * style->ythickness; - short_size -= 2 * style->xthickness; - } } - + n_items = g_list_length (priv->content); allocations = g_new0 (GtkAllocation, n_items); new_states = g_new0 (ItemState, n_items); - + needed_size = 0; need_arrow = FALSE; for (list = priv->content; list != NULL; list = list->next) { ToolbarContent *content = list->data; - - if (toolbar_content_visible (content, toolbar)) - { - needed_size += get_item_size (toolbar, content); - /* Do we need an arrow? - * - * Assume we don't, and see if any non-separator item with a - * proxy menu item is then going to overflow. - */ - if (needed_size > available_size && - !need_arrow && - priv->show_arrow && - toolbar_content_has_proxy_menu_item (content) && - !toolbar_content_is_separator (content)) - { - need_arrow = TRUE; - } - } + if (toolbar_content_visible (content, toolbar)) + { + needed_size += get_item_size (toolbar, content); + + /* Do we need an arrow? + * + * Assume we don't, and see if any non-separator item + * with a proxy menu item is then going to overflow. + */ + if (needed_size > available_size && + !need_arrow && + priv->show_arrow && + toolbar_content_has_proxy_menu_item (content) && + !toolbar_content_is_separator (content)) + { + need_arrow = TRUE; + } + } } - + if (need_arrow) size = available_size - arrow_size; else size = available_size; - + /* calculate widths and states of items */ overflowing = FALSE; for (list = priv->content, i = 0; list != NULL; list = list->next, ++i) { ToolbarContent *content = list->data; gint item_size; - + if (!toolbar_content_visible (content, toolbar)) - { - new_states[i] = HIDDEN; - continue; - } - + { + new_states[i] = HIDDEN; + continue; + } + item_size = get_item_size (toolbar, content); if (item_size <= size && !overflowing) - { - size -= item_size; - allocations[i].width = item_size; - new_states[i] = NORMAL; - } + { + size -= item_size; + allocations[i].width = item_size; + new_states[i] = NORMAL; + } else - { - overflowing = TRUE; - new_states[i] = OVERFLOWN; - allocations[i].width = item_size; - } + { + overflowing = TRUE; + new_states[i] = OVERFLOWN; + allocations[i].width = item_size; + } } - - /* calculate width of arrow */ + + /* calculate width of arrow */ if (need_arrow) { arrow_allocation.width = arrow_size; arrow_allocation.height = MAX (short_size, 1); } - + /* expand expandable items */ - - /* We don't expand when there is an overflow menu, because that leads to - * weird jumps when items get moved to the overflow menu and the expanding + + /* We don't expand when there is an overflow menu, + * because that leads to weird jumps when items get + * moved to the overflow menu and the expanding * items suddenly get a lot of extra space */ if (!overflowing) { gint max_child_expand; n_expand_items = 0; - + for (i = 0, list = priv->content; list != NULL; list = list->next, ++i) - { - ToolbarContent *content = list->data; - - if (toolbar_content_get_expand (content) && new_states[i] == NORMAL) - n_expand_items++; - } - + { + ToolbarContent *content = list->data; + + if (toolbar_content_get_expand (content) && new_states[i] == NORMAL) + n_expand_items++; + } + max_child_expand = get_max_child_expand (toolbar); for (list = priv->content, i = 0; list != NULL; list = list->next, ++i) - { - ToolbarContent *content = list->data; - - if (toolbar_content_get_expand (content) && new_states[i] == NORMAL) - { - gint extra = size / n_expand_items; - if (size % n_expand_items != 0) - extra++; + { + ToolbarContent *content = list->data; + + if (toolbar_content_get_expand (content) && new_states[i] == NORMAL) + { + gint extra = size / n_expand_items; + if (size % n_expand_items != 0) + extra++; if (extra > max_child_expand) extra = max_child_expand; - allocations[i].width += extra; - size -= extra; - n_expand_items--; - } - } - + allocations[i].width += extra; + size -= extra; + n_expand_items--; + } + } + g_assert (n_expand_items == 0); } - + /* position items */ pos = border_width; for (list = priv->content, i = 0; list != NULL; list = list->next, ++i) { - /* both NORMAL and OVERFLOWN items get a position. This ensures - * that sliding will work for OVERFLOWN items too + /* Both NORMAL and OVERFLOWN items get a position. + * This ensures that sliding will work for OVERFLOWN items too. */ - if (new_states[i] == NORMAL || - new_states[i] == OVERFLOWN) - { - allocations[i].x = pos; - allocations[i].y = border_width; - allocations[i].height = short_size; - - pos += allocations[i].width; - } + if (new_states[i] == NORMAL || new_states[i] == OVERFLOWN) + { + allocations[i].x = pos; + allocations[i].y = border_width; + allocations[i].height = short_size; + + pos += allocations[i].width; + } } - + /* position arrow */ if (need_arrow) { arrow_allocation.x = available_size - border_width - arrow_allocation.width; arrow_allocation.y = border_width; } - + item_area.x = border_width; item_area.y = border_width; item_area.width = available_size - (need_arrow? arrow_size : 0); @@ -1631,144 +1701,125 @@ gtk_toolbar_size_allocate (GtkWidget *widget, if (priv->orientation == GTK_ORIENTATION_VERTICAL) { for (i = 0; i < n_items; ++i) - fixup_allocation_for_vertical (&(allocations[i])); - + fixup_allocation_for_vertical (&(allocations[i])); + if (need_arrow) - fixup_allocation_for_vertical (&arrow_allocation); + fixup_allocation_for_vertical (&arrow_allocation); fixup_allocation_for_vertical (&item_area); } else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL) { for (i = 0; i < n_items; ++i) - fixup_allocation_for_rtl (available_size, &(allocations[i])); - + fixup_allocation_for_rtl (available_size, &(allocations[i])); + if (need_arrow) - fixup_allocation_for_rtl (available_size, &arrow_allocation); + fixup_allocation_for_rtl (available_size, &arrow_allocation); fixup_allocation_for_rtl (available_size, &item_area); } - + /* translate the items by allocation->(x,y) */ for (i = 0; i < n_items; ++i) { - allocations[i].x += allocation->x; - allocations[i].y += allocation->y; - - if (shadow_type != GTK_SHADOW_NONE) - { - allocations[i].x += style->xthickness; - allocations[i].y += style->ythickness; - } + allocations[i].x += allocation->x + padding.left; + allocations[i].y += allocation->y + padding.top; } - + if (need_arrow) { - arrow_allocation.x += allocation->x; - arrow_allocation.y += allocation->y; - - if (shadow_type != GTK_SHADOW_NONE) - { - arrow_allocation.x += style->xthickness; - arrow_allocation.y += style->ythickness; - } + arrow_allocation.x += allocation->x + padding.left; + arrow_allocation.y += allocation->y + padding.top; } - item_area.x += allocation->x; - item_area.y += allocation->y; - if (shadow_type != GTK_SHADOW_NONE) - { - item_area.x += style->xthickness; - item_area.y += style->ythickness; - } + item_area.x += allocation->x + padding.left; + item_area.y += allocation->y + padding.top; /* did anything change? */ for (list = priv->content, i = 0; list != NULL; list = list->next, i++) { ToolbarContent *content = list->data; - + if (toolbar_content_get_state (content) == NORMAL && - new_states[i] != NORMAL) - { - /* an item disappeared and we didn't change size, so begin sliding */ - if (!size_changed) - gtk_toolbar_begin_sliding (toolbar); - } + new_states[i] != NORMAL) + { + /* an item disappeared and we didn't change size, so begin sliding */ + if (!size_changed) + gtk_toolbar_begin_sliding (toolbar); + } } - + /* finally allocate the items */ if (priv->is_sliding) { for (list = priv->content, i = 0; list != NULL; list = list->next, i++) - { - ToolbarContent *content = list->data; - - toolbar_content_set_goal_allocation (content, &(allocations[i])); - } + { + ToolbarContent *content = list->data; + + toolbar_content_set_goal_allocation (content, &(allocations[i])); + } } - elapsed = g_timer_elapsed (priv->timer, NULL); for (list = priv->content, i = 0; list != NULL; list = list->next, ++i) { ToolbarContent *content = list->data; - if (new_states[i] == OVERFLOWN || - new_states[i] == NORMAL) - { - GtkAllocation alloc; - GtkAllocation start_allocation = { 0, }; - GtkAllocation goal_allocation; - - if (priv->is_sliding) - { - toolbar_content_get_start_allocation (content, &start_allocation); - toolbar_content_get_goal_allocation (content, &goal_allocation); - - compute_intermediate_allocation (toolbar, - &start_allocation, - &goal_allocation, - &alloc); - - priv->need_sync = TRUE; - } - else - { - alloc = allocations[i]; - } - - if (alloc.width <= 0 || alloc.height <= 0) - { - toolbar_content_set_child_visible (content, toolbar, FALSE); - } - else - { - if (!rect_within (&alloc, &item_area)) - { - toolbar_content_set_child_visible (content, toolbar, FALSE); - toolbar_content_size_allocate (content, &alloc); - } - else - { - toolbar_content_set_child_visible (content, toolbar, TRUE); - toolbar_content_size_allocate (content, &alloc); - } - } - } + if (new_states[i] == OVERFLOWN || new_states[i] == NORMAL) + { + GtkAllocation alloc; + GtkAllocation start_allocation = { 0, }; + GtkAllocation goal_allocation; + + if (priv->is_sliding) + { + toolbar_content_get_start_allocation (content, &start_allocation); + toolbar_content_get_goal_allocation (content, &goal_allocation); + + compute_intermediate_allocation (toolbar, + &start_allocation, + &goal_allocation, + &alloc); + + priv->need_sync = TRUE; + } + else + { + alloc = allocations[i]; + } + + if (alloc.width <= 0 || alloc.height <= 0) + { + toolbar_content_set_child_visible (content, toolbar, FALSE); + } + else + { + if (!rect_within (&alloc, &item_area)) + { + toolbar_content_set_child_visible (content, toolbar, FALSE); + toolbar_content_size_allocate (content, &alloc); + } + else + { + toolbar_content_set_child_visible (content, toolbar, TRUE); + toolbar_content_size_allocate (content, &alloc); + } + } + } else - { - toolbar_content_set_child_visible (content, toolbar, FALSE); - } - + { + toolbar_content_set_child_visible (content, toolbar, FALSE); + } + toolbar_content_set_state (content, new_states[i]); } - + if (priv->menu && priv->need_rebuild) rebuild_menu (toolbar); - + if (need_arrow) { gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button), - &arrow_allocation); + &arrow_allocation); gtk_widget_show (GTK_WIDGET (priv->arrow_button)); } else @@ -1776,7 +1827,7 @@ gtk_toolbar_size_allocate (GtkWidget *widget, gtk_widget_hide (GTK_WIDGET (priv->arrow_button)); if (priv->menu && gtk_widget_get_visible (GTK_WIDGET (priv->menu))) - gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu)); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu)); } g_free (allocations); @@ -1800,21 +1851,15 @@ gtk_toolbar_update_button_relief (GtkToolbar *toolbar) } static void -gtk_toolbar_style_set (GtkWidget *widget, - GtkStyle *prev_style) +gtk_toolbar_style_updated (GtkWidget *widget) { GtkToolbar *toolbar = GTK_TOOLBAR (widget); GtkToolbarPrivate *priv = toolbar->priv; - priv->max_homogeneous_pixels = -1; - - if (gtk_widget_get_realized (widget)) - gtk_style_set_background (gtk_widget_get_style (widget), - gtk_widget_get_window (widget), - gtk_widget_get_state (widget)); + GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->style_updated (widget); - if (prev_style) - gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget)); + priv->max_homogeneous_pixels = -1; + gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget)); } static GList * @@ -2047,7 +2092,7 @@ gtk_toolbar_screen_changed (GtkWidget *widget, if (old_settings) { g_signal_handler_disconnect (old_settings, priv->settings_connection); - + priv->settings_connection = 0; g_object_unref (old_settings); } @@ -2323,9 +2368,9 @@ gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar, g_assert (content); g_assert (toolbar_content_is_placeholder (content)); - - gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item), - &requisition); + + gtk_widget_get_preferred_size (GTK_WIDGET (priv->highlight_tool_item), + &requisition, NULL); toolbar_content_set_expand (content, gtk_tool_item_get_expand (tool_item)); @@ -2422,23 +2467,6 @@ gtk_toolbar_show_all (GtkWidget *widget) gtk_widget_show (widget); } -static void -gtk_toolbar_hide_all (GtkWidget *widget) -{ - GtkToolbar *toolbar = GTK_TOOLBAR (widget); - GtkToolbarPrivate *priv = toolbar->priv; - GList *list; - - for (list = priv->content; list != NULL; list = list->next) - { - ToolbarContent *content = list->data; - - toolbar_content_hide_all (content); - } - - gtk_widget_hide (widget); -} - static void gtk_toolbar_add (GtkContainer *container, GtkWidget *widget) @@ -2479,34 +2507,34 @@ gtk_toolbar_remove (GtkContainer *container, static void gtk_toolbar_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) { GtkToolbar *toolbar = GTK_TOOLBAR (container); GtkToolbarPrivate *priv = toolbar->priv; GList *list; - + g_return_if_fail (callback != NULL); - + list = priv->content; while (list) { ToolbarContent *content = list->data; GList *next = list->next; - + if (include_internals || !toolbar_content_is_placeholder (content)) - { - GtkWidget *child = toolbar_content_get_widget (content); - - if (child) - callback (child, callback_data); - } - + { + GtkWidget *child = toolbar_content_get_widget (content); + + if (child) + callback (child, callback_data); + } + list = next; } - - if (include_internals) + + if (include_internals && priv->arrow_button) callback (priv->arrow_button, callback_data); } @@ -2551,6 +2579,7 @@ gtk_toolbar_orientation_changed (GtkToolbar *toolbar, gtk_toolbar_reconfigured (toolbar); + _gtk_orientable_set_style_classes (GTK_ORIENTABLE (toolbar)); gtk_widget_queue_resize (GTK_WIDGET (toolbar)); g_object_notify (G_OBJECT (toolbar), "orientation"); } @@ -2588,20 +2617,22 @@ menu_position_func (GtkMenu *menu, GdkRectangle monitor; gint monitor_num; GdkScreen *screen; - - gtk_widget_size_request (priv->arrow_button, &req); - gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); - + + gtk_widget_get_preferred_size (priv->arrow_button, + &req, NULL); + gtk_widget_get_preferred_size (GTK_WIDGET (menu), + &menu_req, NULL); + screen = gtk_widget_get_screen (GTK_WIDGET (menu)); monitor_num = gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (priv->arrow_button)); if (monitor_num < 0) monitor_num = 0; - gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); + gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor); gtk_widget_get_allocation (priv->arrow_button, &allocation); - gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); + gdk_window_get_origin (gtk_button_get_event_window (GTK_BUTTON (priv->arrow_button)), x, y); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) @@ -2684,7 +2715,7 @@ gtk_toolbar_button_press (GtkWidget *toolbar, { GtkWidget *window; - if (event->button == 3) + if (gdk_event_triggers_context_menu ((GdkEvent *) event)) { gboolean return_value; @@ -2695,6 +2726,9 @@ gtk_toolbar_button_press (GtkWidget *toolbar, return return_value; } + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + window = gtk_widget_get_toplevel (toolbar); if (window) @@ -2921,10 +2955,10 @@ gtk_toolbar_get_n_items (GtkToolbar *toolbar) * * Returns the @n'th item on @toolbar, or %NULL if the * toolbar does not contain an @n'th item. - * - * Return value: The @n'th #GtkToolItem on @toolbar, or %NULL if there - * isn't an @n'th item. - * + * + * Return value: (transfer none): The @n'th #GtkToolItem on @toolbar, + * or %NULL if there isn't an @n'th item. + * * Since: 2.4 **/ GtkToolItem * @@ -3071,30 +3105,46 @@ gtk_toolbar_get_drop_index (GtkToolbar *toolbar, } static void -gtk_toolbar_finalize (GObject *object) +gtk_toolbar_dispose (GObject *object) { - GList *list; GtkToolbar *toolbar = GTK_TOOLBAR (object); GtkToolbarPrivate *priv = toolbar->priv; if (priv->arrow_button) - gtk_widget_unparent (priv->arrow_button); + { + gtk_widget_unparent (priv->arrow_button); + priv->arrow_button = NULL; + } - for (list = priv->content; list != NULL; list = list->next) + if (priv->menu) { - ToolbarContent *content = list->data; + g_signal_handlers_disconnect_by_func (priv->menu, + menu_deactivated, toolbar); + gtk_widget_destroy (GTK_WIDGET (priv->menu)); + priv->menu = NULL; + } - toolbar_content_free (content); + if (priv->settings_connection > 0) + { + g_signal_handler_disconnect (priv->settings, priv->settings_connection); + priv->settings_connection = 0; } - - g_list_free (priv->content); - g_list_free (priv->children); - + + g_clear_object (&priv->settings); + + G_OBJECT_CLASS (gtk_toolbar_parent_class)->dispose (object); +} + +static void +gtk_toolbar_finalize (GObject *object) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (object); + GtkToolbarPrivate *priv = toolbar->priv; + + g_list_free_full (priv->content, (GDestroyNotify)toolbar_content_free); + g_timer_destroy (priv->timer); - - if (priv->menu) - gtk_widget_destroy (GTK_WIDGET (priv->menu)); - + if (priv->idle_id) g_source_remove (priv->idle_id); @@ -3199,6 +3249,7 @@ struct _ToolbarContent ItemState state; GtkToolItem *item; + GtkAllocation allocation; GtkAllocation start_allocation; GtkAllocation goal_allocation; guint is_placeholder : 1; @@ -3206,6 +3257,16 @@ struct _ToolbarContent guint has_menu : 2; }; +static void +toolbar_item_visiblity_notify_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data) +{ + GtkToolbar *toolbar = user_data; + + gtk_toolbar_invalidate_order (toolbar); +} + static ToolbarContent * toolbar_content_new_tool_item (GtkToolbar *toolbar, GtkToolItem *item, @@ -3220,11 +3281,15 @@ toolbar_content_new_tool_item (GtkToolbar *toolbar, content->state = NOT_ALLOCATED; content->item = item; content->is_placeholder = is_placeholder; - - gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar)); priv->content = g_list_insert (priv->content, content, pos); - + + gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar)); + gtk_toolbar_invalidate_order (toolbar); + + g_signal_connect (content->item, "notify::visible", + G_CALLBACK (toolbar_item_visiblity_notify_cb), toolbar); + if (!is_placeholder) { priv->num_children++; @@ -3244,8 +3309,13 @@ toolbar_content_remove (ToolbarContent *content, { GtkToolbarPrivate *priv = toolbar->priv; + gtk_toolbar_invalidate_order (toolbar); gtk_widget_unparent (GTK_WIDGET (content->item)); + g_signal_handlers_disconnect_by_func (content->item, + toolbar_item_visiblity_notify_cb, + toolbar); + priv->content = g_list_remove (priv->content, content); if (!toolbar_content_is_placeholder (content)) @@ -3269,8 +3339,9 @@ calculate_max_homogeneous_pixels (GtkWidget *widget) gint char_width; context = gtk_widget_get_pango_context (widget); + metrics = pango_context_get_metrics (context, - gtk_widget_get_style (widget)->font_desc, + pango_context_get_font_description (context), pango_context_get_language (context)); char_width = pango_font_metrics_get_approximate_char_width (metrics); pango_font_metrics_unref (metrics); @@ -3279,17 +3350,19 @@ calculate_max_homogeneous_pixels (GtkWidget *widget) } static void -toolbar_content_expose (ToolbarContent *content, - GtkContainer *container, - GdkEventExpose *expose) +toolbar_content_draw (ToolbarContent *content, + GtkContainer *container, + cairo_t *cr) { GtkWidget *widget; - if (!content->is_placeholder) - widget = GTK_WIDGET (content->item); + if (content->is_placeholder) + return; + + widget = GTK_WIDGET (content->item); if (widget) - gtk_container_propagate_expose (container, widget, expose); + gtk_container_propagate_draw (container, widget, cr); } static gboolean @@ -3320,8 +3393,8 @@ toolbar_content_size_request (ToolbarContent *content, GtkToolbar *toolbar, GtkRequisition *requisition) { - gtk_widget_size_request (GTK_WIDGET (content->item), - requisition); + gtk_widget_get_preferred_size (GTK_WIDGET (content->item), + requisition, NULL); if (content->is_placeholder && content->disappearing) { @@ -3389,7 +3462,7 @@ toolbar_content_get_state (ToolbarContent *content) static gboolean toolbar_content_child_visible (ToolbarContent *content) { - return GTK_WIDGET_CHILD_VISIBLE (content->item); + return gtk_widget_get_child_visible (GTK_WIDGET (content->item)); } static void @@ -3403,7 +3476,7 @@ static void toolbar_content_get_allocation (ToolbarContent *content, GtkAllocation *allocation) { - gtk_widget_get_allocation (GTK_WIDGET (content->item), allocation); + *allocation = content->allocation; } static void @@ -3450,6 +3523,7 @@ static void toolbar_content_size_allocate (ToolbarContent *content, GtkAllocation *allocation) { + content->allocation = *allocation; gtk_widget_size_allocate (GTK_WIDGET (content->item), allocation); } @@ -3543,16 +3617,6 @@ toolbar_content_show_all (ToolbarContent *content) gtk_widget_show_all (widget); } -static void -toolbar_content_hide_all (ToolbarContent *content) -{ - GtkWidget *widget; - - widget = toolbar_content_get_widget (content); - if (widget) - gtk_widget_hide_all (widget); -} - /* * Getters */ @@ -3560,9 +3624,7 @@ static GtkReliefStyle get_button_relief (GtkToolbar *toolbar) { GtkReliefStyle button_relief = GTK_RELIEF_NORMAL; - - gtk_widget_ensure_style (GTK_WIDGET (toolbar)); - + gtk_widget_style_get (GTK_WIDGET (toolbar), "button-relief", &button_relief, NULL); @@ -3570,18 +3632,6 @@ get_button_relief (GtkToolbar *toolbar) return button_relief; } -static gint -get_internal_padding (GtkToolbar *toolbar) -{ - gint ipadding = 0; - - gtk_widget_style_get (GTK_WIDGET (toolbar), - "internal-padding", &ipadding, - NULL); - - return ipadding; -} - static gint get_max_child_expand (GtkToolbar *toolbar) { @@ -3593,18 +3643,6 @@ get_max_child_expand (GtkToolbar *toolbar) return mexpand; } -static GtkShadowType -get_shadow_type (GtkToolbar *toolbar) -{ - GtkShadowType shadow_type; - - gtk_widget_style_get (GTK_WIDGET (toolbar), - "shadow-type", &shadow_type, - NULL); - - return shadow_type; -} - /* GTK+ internal methods */ gint @@ -3616,24 +3654,25 @@ _gtk_toolbar_get_default_space_size (void) void _gtk_toolbar_paint_space_line (GtkWidget *widget, GtkToolbar *toolbar, - const GdkRectangle *area, - const GtkAllocation *allocation) + cairo_t *cr) { - GtkToolbarPrivate *priv = toolbar->priv; GtkOrientation orientation; - GtkStateType state; - GtkStyle *style; - GdkWindow *window; - const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION); - const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION); + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + gint width, height; + const gdouble start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION); + const gdouble end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION); g_return_if_fail (GTK_IS_WIDGET (widget)); - orientation = toolbar? priv->orientation : GTK_ORIENTATION_HORIZONTAL; + orientation = toolbar ? toolbar->priv->orientation : GTK_ORIENTATION_HORIZONTAL; - style = gtk_widget_get_style (widget); - window = gtk_widget_get_window (widget); - state = gtk_widget_get_state (widget); + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + gtk_style_context_get_padding (context, state, &padding); if (orientation == GTK_ORIENTATION_HORIZONTAL) { @@ -3646,20 +3685,17 @@ _gtk_toolbar_paint_space_line (GtkWidget *widget, NULL); if (wide_separators) - gtk_paint_box (style, window, - state, GTK_SHADOW_ETCHED_OUT, - area, widget, "vseparator", - allocation->x + (allocation->width - separator_width) / 2, - allocation->y + allocation->height * start_fraction, - separator_width, - allocation->height * (end_fraction - start_fraction)); + gtk_render_frame (context, cr, + (width - separator_width) / 2, + height * start_fraction, + separator_width, + height * (end_fraction - start_fraction)); else - gtk_paint_vline (style, window, - state, area, widget, - "toolbar", - allocation->y + allocation->height * start_fraction, - allocation->y + allocation->height * end_fraction, - allocation->x + (allocation->width - style->xthickness) / 2); + gtk_render_line (context, cr, + (width - padding.left) / 2, + height * start_fraction, + (width - padding.left) / 2, + height * end_fraction); } else { @@ -3672,20 +3708,17 @@ _gtk_toolbar_paint_space_line (GtkWidget *widget, NULL); if (wide_separators) - gtk_paint_box (style, window, - state, GTK_SHADOW_ETCHED_OUT, - area, widget, "hseparator", - allocation->x + allocation->width * start_fraction, - allocation->y + (allocation->height - separator_height) / 2, - allocation->width * (end_fraction - start_fraction), - separator_height); + gtk_render_frame (context, cr, + width * start_fraction, + (height - separator_height) / 2, + width * (end_fraction - start_fraction), + separator_height); else - gtk_paint_hline (style, window, - state, area, widget, - "toolbar", - allocation->x + allocation->width * start_fraction, - allocation->x + allocation->width * end_fraction, - allocation->y + (allocation->height - style->ythickness) / 2); + gtk_render_line (context, cr, + width * start_fraction, + (height - padding.top) / 2, + width * end_fraction, + (height - padding.top) / 2); } } @@ -3783,3 +3816,132 @@ toolbar_rebuild_menu (GtkToolShell *shell) gtk_widget_queue_resize (GTK_WIDGET (shell)); } + +typedef struct _CountingData CountingData; +struct _CountingData { + GtkWidget *widget; + gboolean found; + guint before; + guint after; +}; + +static void +count_widget_position (GtkWidget *widget, + gpointer data) +{ + CountingData *count = data; + + if (!gtk_widget_get_visible (widget)) + return; + + if (count->widget == widget) + count->found = TRUE; + else if (count->found) + count->after++; + else + count->before++; +} + +static guint +gtk_toolbar_get_visible_position (GtkToolbar *toolbar, + GtkWidget *child) +{ + CountingData count = { child, FALSE, 0, 0 }; + + if (child == (GtkWidget*)toolbar->priv->highlight_tool_item) + return 0; + + /* foreach iterates in visible order */ + gtk_container_forall (GTK_CONTAINER (toolbar), + count_widget_position, + &count); + + g_assert (count.found); + + if (toolbar->priv->orientation == GTK_ORIENTATION_HORIZONTAL && + gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL) + return count.after; + + return count.before; +} + +static void +add_widget_to_path (gpointer data, + gpointer user_data) +{ + GtkWidget *widget = data; + GtkWidgetPath *path = user_data; + + if (gtk_widget_get_visible (widget)) + gtk_widget_path_append_for_widget (path, widget); +} + +static GtkWidgetPath * +gtk_toolbar_get_path_for_child (GtkContainer *container, + GtkWidget *child) +{ + GtkWidgetPath *path; + GtkToolbar *toolbar; + GtkToolbarPrivate *priv; + GtkWidgetPath *sibling_path; + gint vis_index; + GList *children; + + toolbar = GTK_TOOLBAR (container); + priv = toolbar->priv; + + /* build a path for all the visible children; + * get_children works in visible order + */ + sibling_path = gtk_widget_path_new (); + children = _gtk_container_get_all_children (container); + + if (priv->orientation != GTK_ORIENTATION_HORIZONTAL || + gtk_widget_get_direction (GTK_WIDGET (toolbar)) != GTK_TEXT_DIR_RTL) + children = g_list_reverse (children); + + g_list_foreach (children, add_widget_to_path, sibling_path); + g_list_free (children); + + path = _gtk_widget_create_path (GTK_WIDGET (container)); + if (gtk_widget_get_visible (child)) + { + vis_index = gtk_toolbar_get_visible_position (toolbar, child); + + if (vis_index < gtk_widget_path_length (sibling_path)) + gtk_widget_path_append_with_siblings (path, + sibling_path, + vis_index); + else + gtk_widget_path_append_for_widget (path, child); + } + else + gtk_widget_path_append_for_widget (path, child); + + gtk_widget_path_unref (sibling_path); + return path; +} + +static void +gtk_toolbar_invalidate_order_foreach (GtkWidget *widget) +{ + _gtk_widget_invalidate_style_context (widget, GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_SIBLING_POSITION); +} + +static void +gtk_toolbar_invalidate_order (GtkToolbar *toolbar) +{ + gtk_container_forall (GTK_CONTAINER (toolbar), + (GtkCallback) gtk_toolbar_invalidate_order_foreach, + NULL); +} + +static void +gtk_toolbar_direction_changed (GtkWidget *widget, + GtkTextDirection previous_direction) +{ + GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->direction_changed (widget, previous_direction); + + gtk_toolbar_invalidate_order (GTK_TOOLBAR (widget)); +} +