X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktoolbar.c;h=e4dbfa45eb2aa79e5cf54a8f223a9e3161b264ef;hb=a97178af65072e98605b2ce168ee4cc36f684ca2;hp=87b180f99982d7ac4d5bfb3ee7a4ed8d2e76a16b;hpb=d1a9d764a80d7e59d69933bdef38f8c8db32a3f2;p=~andy%2Fgtk diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c index 87b180f99..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 . */ /* @@ -32,31 +30,33 @@ #include "config.h" -#include "gtktoolbar.h" - #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 "gtktoolshell.h" -#include "gtkvbox.h" +#include "gtkbox.h" #include "gtkprivate.h" #include "gtkintl.h" +#include "gtktypebuiltins.h" +#include "gtkwidgetpath.h" +#include "gtkwidgetprivate.h" /** @@ -84,8 +84,6 @@ typedef struct _ToolbarContent ToolbarContent; -#define DEFAULT_IPADDING 0 - #define DEFAULT_SPACE_SIZE 12 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE #define SPACE_LINE_DIVISION 10.0 @@ -106,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; @@ -186,12 +186,16 @@ 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, @@ -211,6 +215,7 @@ 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_add (GtkContainer *container, GtkWidget *widget); @@ -221,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, @@ -239,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, @@ -360,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->draw = gtk_toolbar_draw; - widget_class->size_request = gtk_toolbar_size_request; + 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 */ @@ -382,6 +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->direction_changed = gtk_toolbar_direction_changed; container_class->add = gtk_toolbar_add; container_class->remove = gtk_toolbar_remove; @@ -389,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; @@ -559,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, @@ -592,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"), @@ -640,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, @@ -679,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 @@ -807,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 @@ -822,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; } @@ -836,21 +872,20 @@ gtk_toolbar_draw (GtkWidget *widget, { 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); - gtk_paint_box (gtk_widget_get_style (widget), - cr, - gtk_widget_get_state (widget), - get_shadow_type (toolbar), - widget, "toolbar", - border_width, - border_width, - gtk_widget_get_allocated_width (widget) - 2 * border_width, - gtk_widget_get_allocated_height (widget) - 2 * border_width); - for (list = priv->content; list != NULL; list = list->next) { ToolbarContent *content = list->data; @@ -861,10 +896,30 @@ gtk_toolbar_draw (GtkWidget *widget, 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) @@ -879,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; @@ -973,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, @@ -1192,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; @@ -1214,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; @@ -1258,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; } } @@ -1424,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; @@ -1438,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); @@ -1462,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); + 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); - - shadow_type = get_shadow_type (toolbar); + 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); @@ -1648,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 @@ -1793,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); @@ -1817,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 * @@ -2064,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); } @@ -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"); } @@ -2599,11 +2628,11 @@ menu_position_func (GtkMenu *menu, 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) @@ -2686,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; @@ -2697,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) @@ -3073,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); @@ -3201,6 +3249,7 @@ struct _ToolbarContent ItemState state; GtkToolItem *item; + GtkAllocation allocation; GtkAllocation start_allocation; GtkAllocation goal_allocation; guint is_placeholder : 1; @@ -3208,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, @@ -3222,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++; @@ -3246,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)) @@ -3271,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); @@ -3407,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 @@ -3454,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); } @@ -3554,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); @@ -3564,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) { @@ -3587,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 @@ -3612,24 +3656,23 @@ _gtk_toolbar_paint_space_line (GtkWidget *widget, GtkToolbar *toolbar, cairo_t *cr) { - GtkToolbarPrivate *priv = toolbar->priv; GtkOrientation orientation; - GtkStateType state; - GtkStyle *style; - GdkWindow *window; - int width, height; - 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) { @@ -3642,20 +3685,17 @@ _gtk_toolbar_paint_space_line (GtkWidget *widget, NULL); if (wide_separators) - gtk_paint_box (style, cr, - state, GTK_SHADOW_ETCHED_OUT, - widget, "vseparator", - (width - separator_width) / 2, - height * start_fraction, - separator_width, - 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, cr, - state, widget, - "toolbar", + gtk_render_line (context, cr, + (width - padding.left) / 2, height * start_fraction, - height * end_fraction, - (width - style->xthickness) / 2); + (width - padding.left) / 2, + height * end_fraction); } else { @@ -3668,20 +3708,17 @@ _gtk_toolbar_paint_space_line (GtkWidget *widget, NULL); if (wide_separators) - gtk_paint_box (style, cr, - state, GTK_SHADOW_ETCHED_OUT, - widget, "hseparator", - width * start_fraction, - (height - separator_height) / 2, - 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, cr, - state, widget, - "toolbar", + gtk_render_line (context, cr, width * start_fraction, + (height - padding.top) / 2, width * end_fraction, - (height - style->ythickness) / 2); + (height - padding.top) / 2); } } @@ -3779,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)); +} +