diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/egg/egg-editable-toolbar.c | 36 | ||||
-rw-r--r-- | lib/egg/eggtoolbar.c | 586 | ||||
-rw-r--r-- | lib/egg/eggtoolitem.h | 1 |
3 files changed, 325 insertions, 298 deletions
diff --git a/lib/egg/egg-editable-toolbar.c b/lib/egg/egg-editable-toolbar.c index 31122be46..8e875842e 100755 --- a/lib/egg/egg-editable-toolbar.c +++ b/lib/egg/egg-editable-toolbar.c @@ -989,7 +989,7 @@ setup_editor (EggEditableToolbar *etoolbar, gtk_box_pack_start (GTK_BOX (label_hbox), label, FALSE, TRUE, 0); gtk_dialog_add_button (GTK_DIALOG (editor), - _("Add Toolbar"), RESPONSE_ADD_TOOLBAR); + _("_Add a New Toolbar"), RESPONSE_ADD_TOOLBAR); gtk_dialog_add_button (GTK_DIALOG (editor), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE); @@ -1008,6 +1008,32 @@ add_to_list (EggToolbarsItem *item, *l = g_list_append (*l, item); } +static gchar * +elide_underscores (const gchar *original) +{ + gchar *q, *result; + const gchar *p; + gboolean last_underscore; + + q = result = g_malloc (strlen (original) + 1); + last_underscore = FALSE; + + for (p = original; *p; p++) + { + if (!last_underscore && *p == '_') + last_underscore = TRUE; + else + { + last_underscore = FALSE; + *q++ = *p; + } + } + + *q = '\0'; + + return result; +} + static GtkWidget * editor_create_item (EggEditableToolbar *etoolbar, const char *stock_id, @@ -1018,6 +1044,7 @@ editor_create_item (EggEditableToolbar *etoolbar, GtkWidget *vbox; GtkWidget *icon; GtkWidget *label; + gchar *label_no_mnemonic = NULL; event_box = gtk_event_box_new (); gtk_widget_show (event_box); @@ -1038,8 +1065,9 @@ editor_create_item (EggEditableToolbar *etoolbar, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_widget_show (icon); gtk_box_pack_start (GTK_BOX (vbox), icon, FALSE, TRUE, 0); - - label = gtk_label_new_with_mnemonic (label_text); + label_no_mnemonic = elide_underscores (label_text); + label = gtk_label_new (label_no_mnemonic); + g_free (label_no_mnemonic); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); @@ -1093,7 +1121,7 @@ update_editor_sheet (EggEditableToolbar *etoolbar) g_return_if_fail (action != NULL); item = editor_create_item (etoolbar, action->stock_id, - action->label, GDK_ACTION_MOVE); + action->short_label, GDK_ACTION_MOVE); g_object_set_data (G_OBJECT (item), "egg-action", action); gtk_table_attach_defaults (GTK_TABLE (etoolbar->priv->table), item, x, x + 1, y, y + 1); diff --git a/lib/egg/eggtoolbar.c b/lib/egg/eggtoolbar.c index d88e7b429..7dabc6ddf 100644 --- a/lib/egg/eggtoolbar.c +++ b/lib/egg/eggtoolbar.c @@ -172,7 +172,6 @@ static GtkWidget *egg_toolbar_internal_insert_element (EggToolbar *tool typedef struct { GList *items; - GList *first_non_fitting_item; gint max_child_width; gint max_child_height; @@ -803,9 +802,9 @@ egg_toolbar_size_request (GtkWidget *widget, /* Extra spacing */ gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); - - requisition->width += 2 * ipadding; - requisition->height += 2 * ipadding; + + requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width); + requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width); priv->max_child_width = max_child_width; priv->max_child_height = max_child_height; @@ -815,45 +814,63 @@ egg_toolbar_size_request (GtkWidget *widget, } static void -egg_toolbar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +fixup_allocation_for_rtl (gint total_size, GtkAllocation *allocation) { - EggToolbar *toolbar = EGG_TOOLBAR (widget); - EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); - GList *items; - GtkAllocation child_allocation; - gint ipadding, space_size; - gint border_width, edge_position; - gint available_width, available_height; - gint available_size, total_size; - GtkRequisition child_requisition; - gint remaining_size; - gint number_expandable, expandable_size; - gboolean first_expandable; - gint child_x; + allocation->x += (total_size - (2 * allocation->x + allocation->width)); +} - widget->allocation = *allocation; - border_width = GTK_CONTAINER (widget)->border_width; - total_size = 0; - number_expandable = 0; - space_size = get_space_size (toolbar); +static void +fixup_allocation_for_vertical (GtkAllocation *allocation) +{ + gint tmp; - gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); - border_width += ipadding; + tmp = allocation->x; + allocation->x = allocation->y; + allocation->y = tmp; + + tmp = allocation->width; + allocation->width = allocation->height; + allocation->height = tmp; +} + +static gint +get_child_size (EggToolbar *toolbar, GtkWidget *child) +{ + GtkRequisition requisition; + + gtk_widget_get_child_requisition (child, &requisition); - available_width = allocation->width - 2 * border_width; - available_height = allocation->height - 2 * border_width; if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - edge_position = allocation->x + allocation->width - border_width; - available_size = available_width; - } + return requisition.width; else - { - edge_position = allocation->height - border_width; - available_size = available_height; - } + return requisition.height; +} +static void +egg_toolbar_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + gint ipadding; + gint space_size; + GtkAllocation *pack_end_allocations; + GtkAllocation *pack_front_allocations; + GtkAllocation arrow_allocation; + GList *pack_end_items = NULL; + GList *pack_front_items = NULL; + gint arrow_size; + gint size, pos, short_size; + GList *list; + gint i; + gboolean need_arrow; + gint n_pack_end_items; + gint n_pack_front_items; + gint n_expand_items; + gint homogeneous_size; + gint border_width = GTK_CONTAINER (toolbar)->border_width; + gint total_size; + + widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)) { gdk_window_move_resize (widget->window, @@ -862,304 +879,288 @@ egg_toolbar_size_allocate (GtkWidget *widget, allocation->width - border_width * 2, allocation->height - border_width * 2); } - - items = g_list_last (priv->items); + space_size = get_space_size (toolbar); + gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); - while (items) + arrow_size = get_child_size (toolbar, priv->button); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) { - EggToolItem *item = EGG_TOOL_ITEM (items->data); + total_size = size = allocation->width - 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + homogeneous_size = toolbar->button_maxw; + short_size = allocation->height - 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + } + else + { + total_size = size = allocation->height - 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + homogeneous_size = toolbar->button_maxh; + short_size = allocation->width - 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + } + + for (list = priv->items; list != NULL; list = list->next) + { + EggToolItem *item = list->data; - if (!item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) - { - items = items->prev; - continue; - } - - if (!GTK_BIN (item)->child) + if (item->pack_end) + pack_end_items = g_list_prepend (pack_end_items, item); + else + pack_front_items = g_list_prepend (pack_front_items, item); + } + + pack_end_items = g_list_reverse (pack_end_items); + pack_front_items = g_list_reverse (pack_front_items); + + n_pack_end_items = g_list_length (pack_end_items); + n_pack_front_items = g_list_length (pack_front_items); + + pack_end_allocations = g_new (GtkAllocation, n_pack_end_items); + pack_front_allocations = g_new (GtkAllocation, n_pack_front_items); + + need_arrow = FALSE; + + /* calculate widths for pack end items */ + for (list = pack_end_items, i = 0; list != NULL; list = list->next, i++) + { + EggToolItem *item = list->data; + gint item_size; + + if (!TOOLBAR_ITEM_VISIBLE (item)) + continue; + + if (item->homogeneous) + item_size = homogeneous_size; + else if (!GTK_BIN (item)->child) + item_size = space_size; + else + item_size = get_child_size (toolbar, GTK_WIDGET (item)); + + if (item_size <= size - arrow_size || + (item_size <= size && list->next == NULL)) { - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - child_allocation.width = space_size; - child_allocation.height = available_height; - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - child_allocation.x = edge_position - child_allocation.width; - else - child_allocation.x = allocation->x + allocation->width - edge_position; - - child_allocation.y = (allocation->height - child_allocation.height) / 2; - - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); - - edge_position -= child_allocation.width; - available_size -= child_allocation.width; - } - else - { - child_allocation.width = available_width; - child_allocation.height = space_size; - child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; - child_allocation.y = edge_position - child_allocation.height; - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); - - edge_position -= child_allocation.height; - available_size -= child_allocation.height; - } + pack_end_allocations[i].width = item_size; + + size -= item_size; + + item->overflow_item = FALSE; } else { - gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + need_arrow = TRUE; - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (item->homogeneous) - child_allocation.width = toolbar->button_maxw; - else - child_allocation.width = child_requisition.width; - child_allocation.height = available_height; - child_allocation.y = (allocation->height - child_allocation.height) / 2; - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - child_allocation.x = edge_position - child_allocation.width; - else - child_allocation.x = allocation->x + allocation->width - edge_position; - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); - - edge_position -= child_allocation.width; - available_size -= child_allocation.width; - } - else + while (list) { - if (item->homogeneous) - child_allocation.height = toolbar->button_maxh; - else - child_allocation.height = child_requisition.height; - - child_allocation.width = available_width; - child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; - child_allocation.y = edge_position - child_allocation.height; - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + item = list->data; - edge_position -= child_allocation.height; - available_size -= child_allocation.height; + item->overflow_item = TRUE; + list = list->next; } + + break; } - - items = items->prev; } - - /* Now go through the items and see if they fit */ - items = priv->items; - - while (items) + + /* calculate widths for pack front items */ + for (list = pack_front_items, i = 0; list != NULL; list = list->next, i++) { - EggToolItem *item = EGG_TOOL_ITEM (items->data); - - if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) - { - items = items->next; - continue; - } - - if (item->expandable) - number_expandable += 1; - - if (!GTK_BIN (item)->child) + EggToolItem *item = list->data; + gint item_size; + + if (!TOOLBAR_ITEM_VISIBLE (item)) + continue; + + if (item->homogeneous) + item_size = homogeneous_size; + else if (!GTK_BIN (item)->child) + item_size = space_size; + else + item_size = get_child_size (toolbar, GTK_WIDGET (item)); + + if (item_size <= size - arrow_size || + (item_size <= size && list->next == NULL)) { - total_size += space_size; + pack_front_allocations[i].width = item_size; + + size -= item_size; + + item->overflow_item = FALSE; } else { - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + need_arrow = TRUE; + while (list) { - gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + item = list->data; - if (item->homogeneous) - total_size += toolbar->button_maxw; - else - total_size += child_requisition.width; - } - else - { - gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); + item->overflow_item = TRUE; - if (item->homogeneous) - total_size += toolbar->button_maxh; - else - total_size += child_requisition.height; + list = list->next; } + + break; } - items = items->next; } - - /* Check if we need to allocate and show the arrow */ - if (available_size < total_size) + + /* arrow width */ + if (need_arrow) { - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - gtk_widget_get_child_requisition (priv->button, &child_requisition); - available_size -= child_requisition.width; - - child_allocation.width = child_requisition.width; - child_allocation.height = priv->max_child_height; - child_allocation.y = (allocation->height - child_allocation.height) / 2; - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - child_allocation.x = edge_position - child_allocation.width; - else - child_allocation.x = allocation->x + allocation->width - edge_position; - } - else - { - gtk_widget_get_child_requisition (priv->button, &child_requisition); - available_size -= child_requisition.width; - - child_allocation.height = child_requisition.height; - child_allocation.width = priv->max_child_width; - child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; - child_allocation.y = edge_position - child_allocation.height; - } - - gtk_widget_size_allocate (priv->button, &child_allocation); - gtk_widget_show (priv->button); + g_assert (size >= arrow_size); + arrow_allocation.width = arrow_size; + arrow_allocation.height = short_size; + size -= arrow_size; } - else - gtk_widget_hide (priv->button); - /* Finally allocate the remaining items */ - items = priv->items; - child_x = allocation->x + border_width; - child_allocation.y = border_width; - remaining_size = MAX (0, available_size - total_size); - total_size = 0; - first_expandable = TRUE; + /* expand expandable items */ + n_expand_items = 0; + for (list = priv->items; list != NULL; list = list->next) + { + EggToolItem *item = list->data; + + if (TOOLBAR_ITEM_VISIBLE (item) && item->expandable && !item->overflow_item) + n_expand_items++; + } - while (items) + for (list = pack_end_items, i = 0; list != NULL; list = list->next, ++i) { - EggToolItem *item = EGG_TOOL_ITEM (items->data); - - if (item->pack_end || !TOOLBAR_ITEM_VISIBLE (item)) + EggToolItem *item = list->data; + + if (item->expandable && !item->overflow_item && TOOLBAR_ITEM_VISIBLE (item)) { - items = items->next; - continue; + gint extra = size / n_expand_items; + if (size % n_expand_items != 0) + extra++; + + pack_end_allocations[i].width += extra; + size -= extra; + n_expand_items--; } + } + + for (list = pack_front_items, i = 0; list != NULL; list = list->next, ++i) + { + EggToolItem *item = list->data; - if (!GTK_BIN (item)->child) + if (item->expandable && !item->overflow_item && TOOLBAR_ITEM_VISIBLE (item)) { - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - child_allocation.width = space_size; - child_allocation.height = available_height; - child_allocation.y = (allocation->height - child_allocation.height) / 2; - total_size += child_allocation.width; - - if (total_size > available_size) - break; - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - child_allocation.x = child_x; - else - child_allocation.x = allocation->x + allocation->width - - child_x - child_allocation.width; - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); - gtk_widget_map (GTK_WIDGET (item)); - - child_x += child_allocation.width; - } - else - { - child_allocation.width = available_width; - child_allocation.height = space_size; - child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; - total_size += child_allocation.height; - - if (total_size > available_size) - break; - - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); - gtk_widget_map (GTK_WIDGET (item)); + gint extra = size / n_expand_items; + if (size % n_expand_items != 0) + extra++; - child_allocation.y += child_allocation.height; - } + pack_front_allocations[i].width += extra; + size -= extra; + n_expand_items--; } - else + } + g_assert (n_expand_items == 0); + + /* position items */ + pos = 0; + for (list = pack_front_items, i = 0; list != NULL; list = list->next, ++i) + { + EggToolItem *item = list->data; + + if (TOOLBAR_ITEM_VISIBLE (item) && !item->overflow_item) { - gtk_widget_get_child_requisition (GTK_WIDGET (item), &child_requisition); - - if (item->expandable) - { - expandable_size = remaining_size / number_expandable; - - if (first_expandable) - { - expandable_size += remaining_size % number_expandable; - first_expandable = FALSE; - } - } - else - expandable_size = 0; + pack_front_allocations[i].x = pos; + pos += pack_front_allocations[i].width; - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (item->homogeneous) - child_allocation.width = toolbar->button_maxw; - else - child_allocation.width = child_requisition.width; - - child_allocation.height = available_height; - child_allocation.width += expandable_size; - child_allocation.y = (allocation->height - child_allocation.height) / 2; - total_size += child_allocation.width; - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - child_allocation.x = child_x; - else - child_allocation.x = allocation->x + allocation->width - - child_x - child_allocation.width; - - } - else - { - if (item->homogeneous) - child_allocation.height = toolbar->button_maxh; - else - child_allocation.height = child_requisition.height; - - child_allocation.width = available_width; - child_allocation.height += expandable_size; - child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2; - total_size += child_allocation.height; - - } + pack_front_allocations[i].y = 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + pack_front_allocations[i].height = short_size; + } + } + + pos = total_size; + for (list = pack_end_items, i = 0; list != NULL; list = list->next, ++i) + { + EggToolItem *item = list->data; + + if (TOOLBAR_ITEM_VISIBLE (item) && !item->overflow_item) + { + gint width = pack_end_allocations[i].width; - if (total_size > available_size) - break; + pack_end_allocations[i].x = pos - width; + pos -= width; - gtk_widget_size_allocate (GTK_WIDGET (item), &child_allocation); + pack_end_allocations[i].y = 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + pack_end_allocations[i].height = short_size; + } + } + + if (need_arrow) + { + arrow_allocation.x = pos - arrow_allocation.width; + arrow_allocation.y = 2 * (GTK_CONTAINER (widget)->border_width + ipadding); + } + + /* fix up allocations in the vertical or RTL cases */ + if (toolbar->orientation == GTK_ORIENTATION_VERTICAL) + { + for (i = 0; i < n_pack_end_items; ++i) + fixup_allocation_for_vertical (&(pack_end_allocations[i])); + + for (i = 0; i < n_pack_front_items; ++i) + fixup_allocation_for_vertical (&(pack_front_allocations[i])); + + fixup_allocation_for_vertical (&arrow_allocation); + } + else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL) + { + for (i = 0; i < n_pack_end_items; ++i) + fixup_allocation_for_rtl (total_size, &(pack_end_allocations[i])); + + for (i = 0; i < n_pack_front_items; ++i) + fixup_allocation_for_rtl (total_size, &(pack_front_allocations[i])); + + fixup_allocation_for_rtl (total_size, &arrow_allocation); + } + + /* finally allocate the items */ + for (list = pack_end_items, i = 0; list != NULL; list = list->next, i++) + { + EggToolItem *item = list->data; + + if (item->overflow_item) + { + gtk_widget_unmap (GTK_WIDGET (item)); + continue; + } + + if (TOOLBAR_ITEM_VISIBLE (item) && !item->overflow_item) + { + gtk_widget_size_allocate (GTK_WIDGET (item), &(pack_end_allocations[i])); gtk_widget_map (GTK_WIDGET (item)); - - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - child_x += child_allocation.width; - else - child_allocation.y += child_allocation.height; - + } + } + + for (list = pack_front_items, i = 0; i < n_pack_front_items; list = list->next, ++i) + { + EggToolItem *item = list->data; + + if (item->overflow_item) + { + gtk_widget_unmap (GTK_WIDGET (item)); + continue; } - items = items->next; + if (TOOLBAR_ITEM_VISIBLE (item) && !item->overflow_item) + { + gtk_widget_size_allocate (GTK_WIDGET (item), &(pack_front_allocations[i])); + gtk_widget_map (GTK_WIDGET (item)); + } } - /* Unmap the remaining items */ - priv->first_non_fitting_item = items; - while (items) + if (need_arrow) { - EggToolItem *item = EGG_TOOL_ITEM (items->data); - - gtk_widget_unmap (GTK_WIDGET (item)); - items = items->next; + gtk_widget_size_allocate (GTK_WIDGET (priv->button), &arrow_allocation); + gtk_widget_show (GTK_WIDGET (priv->button)); } + else + gtk_widget_hide (GTK_WIDGET (priv->button)); + + g_list_free (pack_end_items); + g_list_free (pack_front_items); + g_free (pack_end_allocations); + g_free (pack_front_allocations); } static void @@ -1761,7 +1762,7 @@ static void show_menu (EggToolbar *toolbar, GdkEventButton *event) { EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); - GList *items; + GList *list; GtkWidget *menu_item; if (priv->menu) @@ -1770,12 +1771,11 @@ show_menu (EggToolbar *toolbar, GdkEventButton *event) priv->menu = GTK_MENU (gtk_menu_new ()); g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar); - items = priv->first_non_fitting_item; - while (items) + for (list = priv->items; list != NULL; list = list->next) { - EggToolItem *item = EGG_TOOL_ITEM (items->data); + EggToolItem *item = list->data; - if (TOOLBAR_ITEM_VISIBLE (item) && !item->pack_end) + if (TOOLBAR_ITEM_VISIBLE (item) && item->overflow_item) { menu_item = NULL; g_signal_emit_by_name (item, "create_menu_proxy", &menu_item); @@ -1783,7 +1783,6 @@ show_menu (EggToolbar *toolbar, GdkEventButton *event) if (menu_item) gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item); } - items = items->next; } gtk_widget_show_all (GTK_WIDGET (priv->menu)); @@ -2150,7 +2149,6 @@ egg_toolbar_unset_icon_size (EggToolbar *toolbar) } } - void egg_toolbar_set_show_arrow (EggToolbar *toolbar, gboolean show_arrow) diff --git a/lib/egg/eggtoolitem.h b/lib/egg/eggtoolitem.h index 4c4fea46a..ad6f8b251 100644 --- a/lib/egg/eggtoolitem.h +++ b/lib/egg/eggtoolitem.h @@ -54,6 +54,7 @@ struct _EggToolItem guint expandable : 1; guint pack_end : 1; guint use_drag_window : 1; + guint overflow_item : 1; }; struct _EggToolItemClass |