X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkmenubar.c;h=d337d712ae4f7ed2a1b09c0874f801c1fec035c4;hb=cf216d780cb2c889a3bcb5faa825fc1b21af8896;hp=fb823d3680b18d6a4aa7a7ef407693a03feb391a;hpb=22a1bd6d6baefc2b7935cafde41046a39ffe88b2;p=~andy%2Fgtk diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index fb823d368..d337d712a 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -12,9 +12,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 . */ /* @@ -48,13 +46,11 @@ #include "gtksettings.h" #include "gtksizerequest.h" #include "gtkwindow.h" +#include "gtkcontainerprivate.h" #include "gtkintl.h" #include "gtkprivate.h" #include "gtktypebuiltins.h" -#define BORDER_SPACING 0 -#define DEFAULT_IPADDING 1 - /* Properties */ enum { PROP_0, @@ -129,6 +125,8 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) widget_class->draw = gtk_menu_bar_draw; widget_class->hierarchy_changed = gtk_menu_bar_hierarchy_changed; + gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_MENU_BAR); + menu_shell_class->submenu_placement = GTK_TOP_BOTTOM; menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay; menu_shell_class->move_current = gtk_menu_bar_move_current; @@ -218,14 +216,24 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class) GTK_SHADOW_OUT, GTK_PARAM_READABLE)); + /** + * GtkMenuBar:internal-padding: + * + * Amount of border space between the menubar shadow and the menu items + * + * Deprecated: 3.8: 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 menubar shadow and the menu items"), 0, G_MAXINT, - DEFAULT_IPADDING, - GTK_PARAM_READABLE)); + 0, + GTK_PARAM_READABLE | + G_PARAM_DEPRECATED)); g_type_class_add_private (gobject_class, sizeof (GtkMenuBarPrivate)); } @@ -331,10 +339,12 @@ gtk_menu_bar_size_request (GtkWidget *widget, GtkMenuShell *menu_shell; GtkWidget *child; GList *children; - gint ipadding; guint border_width; gboolean use_toggle_size, use_maximize; gint child_minimum, child_natural; + GtkStyleContext *context; + GtkBorder border; + GtkStateFlags flags; *minimum = 0; *natural = 0; @@ -390,33 +400,39 @@ gtk_menu_bar_size_request (GtkWidget *widget, } } - gtk_widget_style_get (widget, "internal-padding", &ipadding, NULL); - border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_bar)); - *minimum += (border_width + ipadding + BORDER_SPACING) * 2; - *natural += (border_width + ipadding + BORDER_SPACING) * 2; + context = gtk_widget_get_style_context (widget); + flags = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, flags, &border); - if (get_shadow_type (menu_bar) != GTK_SHADOW_NONE) + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - GtkStyleContext *context; - GtkBorder *border; + *minimum += border.left + border.right; + *natural += border.left + border.right; + } + else + { + *minimum += border.top + border.bottom; + *natural += border.top + border.bottom; + } - context = gtk_widget_get_style_context (widget); + border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_bar)); + *minimum += border_width * 2; + *natural += border_width * 2; - gtk_style_context_get (context, 0, - "border-width", &border, - NULL); + if (get_shadow_type (menu_bar) != GTK_SHADOW_NONE) + { + gtk_style_context_get_border (context, flags, &border); if (orientation == GTK_ORIENTATION_HORIZONTAL) { - *minimum += border->left + border->right; - *natural += border->left + border->right; + *minimum += border.left + border.right; + *natural += border.left + border.right; } else { - *minimum += border->top + border->bottom; - *natural += border->top + border->bottom; + *minimum += border.top + border.bottom; + *natural += border.top + border.bottom; } - gtk_border_free (border); } } @@ -463,13 +479,11 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, GtkMenuBarPrivate *priv; GtkWidget *child; GList *children; - GtkAllocation child_allocation; - GtkRequisition child_requisition; - guint offset; - GtkTextDirection direction; - gint ltr_x, ltr_y; - gint ipadding; + GtkAllocation remaining_space; guint border_width; + GArray *requested_sizes; + gint toggle_size; + guint i; g_return_if_fail (GTK_IS_MENU_BAR (widget)); g_return_if_fail (allocation != NULL); @@ -478,8 +492,6 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, menu_shell = GTK_MENU_SHELL (widget); priv = menu_bar->priv; - direction = gtk_widget_get_direction (widget); - gtk_widget_set_allocation (widget, allocation); if (gtk_widget_get_realized (widget)) @@ -487,136 +499,148 @@ gtk_menu_bar_size_allocate (GtkWidget *widget, allocation->x, allocation->y, allocation->width, allocation->height); - gtk_widget_style_get (widget, "internal-padding", &ipadding, NULL); - if (menu_shell->priv->children) { + GtkStyleContext *context; + GtkStateFlags flags; + GtkBorder border; + + context = gtk_widget_get_style_context (widget); + flags = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, flags, &border); + border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_bar)); - child_allocation.x = (border_width + - ipadding + - BORDER_SPACING); - child_allocation.y = (border_width + - BORDER_SPACING); - - if (get_shadow_type (menu_bar) != GTK_SHADOW_NONE) - { - GtkStyleContext *context; - GtkBorder *border; - context = gtk_widget_get_style_context (widget); - gtk_style_context_get (context, 0, - "border-width", &border, - NULL); + remaining_space.x = (border_width + border.left); + remaining_space.y = (border_width + border.top); + remaining_space.width = allocation->width - + 2 * (border_width) - border.left - border.right; + remaining_space.height = allocation->height - + 2 * (border_width) - border.top - border.bottom; - child_allocation.x += border->left; - child_allocation.y += border->top; + if (get_shadow_type (menu_bar) != GTK_SHADOW_NONE) + { + gtk_style_context_get_border (context, flags, &border); - gtk_border_free (border); + remaining_space.x += border.left; + remaining_space.y += border.top; + remaining_space.width -= border.left + border.right; + remaining_space.height -= border.top + border.bottom; } + requested_sizes = g_array_new (FALSE, FALSE, sizeof (GtkRequestedSize)); + if (priv->pack_direction == GTK_PACK_DIRECTION_LTR || priv->pack_direction == GTK_PACK_DIRECTION_RTL) { - child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2); + int size = remaining_space.width; + gboolean ltr = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) == (priv->pack_direction == GTK_PACK_DIRECTION_LTR); - offset = child_allocation.x; /* Window edge to menubar start */ - ltr_x = child_allocation.x; - - children = menu_shell->priv->children; - while (children) + for (children = menu_shell->priv->children; children; children = children->next) { - gint toggle_size; - + GtkRequestedSize request; child = children->data; - children = children->next; - + + if (!gtk_widget_get_visible (child)) + continue; + + request.data = child; + gtk_widget_get_preferred_width_for_height (child, + remaining_space.height, + &request.minimum_size, + &request.natural_size); gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size); - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - - if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || - priv->child_pack_direction == GTK_PACK_DIRECTION_RTL) - child_requisition.width += toggle_size; - else - child_requisition.height += toggle_size; - - /* Support for the right justified help menu */ - if (children == NULL && - GTK_IS_MENU_ITEM (child) && - GTK_MENU_ITEM (child)->priv->right_justify) - { - ltr_x = allocation->width - - child_requisition.width - offset; - } - if (gtk_widget_get_visible (child)) - { - if ((direction == GTK_TEXT_DIR_LTR) == (priv->pack_direction == GTK_PACK_DIRECTION_LTR)) - child_allocation.x = ltr_x; - else - child_allocation.x = allocation->width - - child_requisition.width - ltr_x; - - child_allocation.width = child_requisition.width; - - gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), - toggle_size); - gtk_widget_size_allocate (child, &child_allocation); - - ltr_x += child_allocation.width; - } - } + request.minimum_size += toggle_size; + request.natural_size += toggle_size; + + gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), toggle_size); + + g_array_append_val (requested_sizes, request); + + size -= request.minimum_size; + } + + size = gtk_distribute_natural_allocation (size, + requested_sizes->len, + (GtkRequestedSize *) requested_sizes->data); + + for (i = 0; i < requested_sizes->len; i++) + { + GtkAllocation child_allocation = remaining_space; + GtkRequestedSize *request = &g_array_index (requested_sizes, GtkRequestedSize, i); + + child_allocation.width = request->minimum_size; + remaining_space.width -= request->minimum_size; + + if (i + 1 == requested_sizes->len && GTK_IS_MENU_ITEM (request->data) && + GTK_MENU_ITEM (request->data)->priv->right_justify) + ltr = !ltr; + + if (ltr) + remaining_space.x += request->minimum_size; + else + child_allocation.x += remaining_space.width; + + gtk_widget_size_allocate (request->data, &child_allocation); + } } else { - child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2); + int size = remaining_space.height; + gboolean ttb = (priv->pack_direction == GTK_PACK_DIRECTION_TTB); - offset = child_allocation.y; /* Window edge to menubar start */ - ltr_y = child_allocation.y; - - children = menu_shell->priv->children; - while (children) + for (children = menu_shell->priv->children; children; children = children->next) { - gint toggle_size; - + GtkRequestedSize request; child = children->data; - children = children->next; - + + if (!gtk_widget_get_visible (child)) + continue; + + request.data = child; + gtk_widget_get_preferred_height_for_width (child, + remaining_space.width, + &request.minimum_size, + &request.natural_size); gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size); - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - - if (priv->child_pack_direction == GTK_PACK_DIRECTION_LTR || - priv->child_pack_direction == GTK_PACK_DIRECTION_RTL) - child_requisition.width += toggle_size; - else - child_requisition.height += toggle_size; - - /* Support for the right justified help menu */ - if (children == NULL && - GTK_IS_MENU_ITEM (child) && - GTK_MENU_ITEM (child)->priv->right_justify) - { - ltr_y = allocation->height - - child_requisition.height - offset; - } - if (gtk_widget_get_visible (child)) - { - if ((direction == GTK_TEXT_DIR_LTR) == - (priv->pack_direction == GTK_PACK_DIRECTION_TTB)) - child_allocation.y = ltr_y; - else - child_allocation.y = allocation->height - - child_requisition.height - ltr_y; - child_allocation.height = child_requisition.height; - - gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), - toggle_size); - gtk_widget_size_allocate (child, &child_allocation); - - ltr_y += child_allocation.height; - } - } + request.minimum_size += toggle_size; + request.natural_size += toggle_size; + + gtk_menu_item_toggle_size_allocate (GTK_MENU_ITEM (child), toggle_size); + + g_array_append_val (requested_sizes, request); + + size -= request.minimum_size; + } + + size = gtk_distribute_natural_allocation (size, + requested_sizes->len, + (GtkRequestedSize *) requested_sizes->data); + + for (i = 0; i < requested_sizes->len; i++) + { + GtkAllocation child_allocation = remaining_space; + GtkRequestedSize *request = &g_array_index (requested_sizes, GtkRequestedSize, i); + + child_allocation.height = request->minimum_size; + remaining_space.height -= request->minimum_size; + + if (i + 1 == requested_sizes->len && GTK_IS_MENU_ITEM (request->data) && + GTK_MENU_ITEM (request->data)->priv->right_justify) + ttb = !ttb; + + if (ttb) + remaining_space.y += request->minimum_size; + else + child_allocation.y += remaining_space.height; + + gtk_widget_size_allocate (request->data, &child_allocation); + } } + + g_array_free (requested_sizes, TRUE); } } @@ -625,25 +649,21 @@ gtk_menu_bar_draw (GtkWidget *widget, cairo_t *cr) { GtkStyleContext *context; - GtkStateFlags state; int border; border = gtk_container_get_border_width (GTK_CONTAINER (widget)); context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); - gtk_style_context_set_state (context, state); + gtk_render_background (context, cr, + border, border, + gtk_widget_get_allocated_width (widget) - border * 2, + gtk_widget_get_allocated_height (widget) - border * 2); if (get_shadow_type (GTK_MENU_BAR (widget)) != GTK_SHADOW_NONE) - gtk_render_background (context, cr, - border, border, - gtk_widget_get_allocated_width (widget) - border * 2, - gtk_widget_get_allocated_height (widget) - border * 2); - - gtk_render_frame (context, cr, - border, border, - gtk_widget_get_allocated_width (widget) - border * 2, - gtk_widget_get_allocated_height (widget) - border * 2); + gtk_render_frame (context, cr, + border, border, + gtk_widget_get_allocated_width (widget) - border * 2, + gtk_widget_get_allocated_height (widget) - border * 2); GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->draw (widget, cr); @@ -1036,3 +1056,32 @@ gtk_menu_bar_set_child_pack_direction (GtkMenuBar *menubar, g_object_notify (G_OBJECT (menubar), "child-pack-direction"); } } + +/** + * gtk_menu_bar_new_from_model: + * @model: a #GMenuModel + * + * Creates a new #GtkMenuBar and populates it with menu items + * and submenus according to @model. + * + * The created menu items are connected to actions found in the + * #GtkApplicationWindow to which the menu bar belongs - typically + * by means of being contained within the #GtkApplicationWindows + * widget hierarchy. + * + * Returns: a new #GtkMenuBar + * + * Since: 3.4 + */ +GtkWidget * +gtk_menu_bar_new_from_model (GMenuModel *model) +{ + GtkWidget *menubar; + + g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL); + + menubar = gtk_menu_bar_new (); + gtk_menu_shell_bind_model (GTK_MENU_SHELL (menubar), model, NULL, FALSE); + + return menubar; +}