From: Matthias Clasen Date: Fri, 27 Dec 2019 06:32:27 +0000 (-0500) Subject: toolbar: Simplify overflow implementation X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~486^2~25 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=8ee44d200d6f75a350853d574c4ce9d6c19b566b;p=gtk4.git toolbar: Simplify overflow implementation Do away with the proxy menu items, and instead just have toolitems provide a label for overflow items. We create the overflow widgets ourselves already, as model buttons. Also replace the toggle button used for overflow with a menubutton, simplifying things further. --- diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 698e116302..0c9fa7dc4e 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -3278,9 +3278,8 @@ gtk_tool_item_get_orientation gtk_tool_item_get_toolbar_style gtk_tool_item_get_text_alignment gtk_tool_item_get_text_orientation -gtk_tool_item_retrieve_proxy_menu_item -gtk_tool_item_get_proxy_menu_item -gtk_tool_item_set_proxy_menu_item +gtk_tool_item_set_overflow_text +gtk_tool_item_get_overflow_text gtk_tool_item_rebuild_menu gtk_tool_item_toolbar_reconfigured gtk_tool_item_get_text_size_group diff --git a/gtk/gtkseparatortoolitem.c b/gtk/gtkseparatortoolitem.c index a51e5ef9d7..d85ab09891 100644 --- a/gtk/gtkseparatortoolitem.c +++ b/gtk/gtkseparatortoolitem.c @@ -69,7 +69,6 @@ enum { PROP_DRAW }; -static gboolean gtk_separator_tool_item_create_menu_proxy (GtkToolItem *item); static void gtk_separator_tool_item_set_property (GObject *object, guint prop_id, const GValue *value, @@ -88,19 +87,15 @@ gtk_separator_tool_item_class_init (GtkSeparatorToolItemClass *class) { GObjectClass *object_class; GtkContainerClass *container_class; - GtkToolItemClass *toolitem_class; GtkWidgetClass *widget_class; object_class = (GObjectClass *)class; container_class = (GtkContainerClass *)class; - toolitem_class = (GtkToolItemClass *)class; widget_class = (GtkWidgetClass *)class; object_class->set_property = gtk_separator_tool_item_set_property; object_class->get_property = gtk_separator_tool_item_get_property; - toolitem_class->create_menu_proxy = gtk_separator_tool_item_create_menu_proxy; - container_class->add = gtk_separator_tool_item_add; g_object_class_install_property (object_class, @@ -126,18 +121,6 @@ gtk_separator_tool_item_add (GtkContainer *container, g_warning ("attempt to add a child to a GtkSeparatorToolItem"); } -static gboolean -gtk_separator_tool_item_create_menu_proxy (GtkToolItem *item) -{ - GtkWidget *menu_item = NULL; - - menu_item = gtk_separator_menu_item_new (); - - gtk_tool_item_set_proxy_menu_item (item, MENU_ID, menu_item); - - return TRUE; -} - static void gtk_separator_tool_item_set_property (GObject *object, guint prop_id, diff --git a/gtk/gtktoggletoolbutton.c b/gtk/gtktoggletoolbutton.c index acdb56118a..36241a764f 100644 --- a/gtk/gtktoggletoolbutton.c +++ b/gtk/gtktoggletoolbutton.c @@ -72,12 +72,8 @@ static void gtk_toggle_tool_button_get_property (GObject *object GValue *value, GParamSpec *pspec); -static gboolean gtk_toggle_tool_button_create_menu_proxy (GtkToolItem *button); - static void button_toggled (GtkWidget *widget, GtkToggleToolButton *button); -static void menu_item_activated (GtkWidget *widget, - GtkToggleToolButton *button); static guint toggle_signals[LAST_SIGNAL] = { 0 }; @@ -89,17 +85,14 @@ static void gtk_toggle_tool_button_class_init (GtkToggleToolButtonClass *klass) { GObjectClass *object_class; - GtkToolItemClass *toolitem_class; GtkToolButtonClass *toolbutton_class; object_class = (GObjectClass *)klass; - toolitem_class = (GtkToolItemClass *)klass; toolbutton_class = (GtkToolButtonClass *)klass; object_class->set_property = gtk_toggle_tool_button_set_property; object_class->get_property = gtk_toggle_tool_button_get_property; - toolitem_class->create_menu_proxy = gtk_toggle_tool_button_create_menu_proxy; toolbutton_class->button_type = GTK_TYPE_TOGGLE_BUTTON; /** @@ -189,94 +182,6 @@ gtk_toggle_tool_button_get_property (GObject *object, } } -static gboolean -gtk_toggle_tool_button_create_menu_proxy (GtkToolItem *item) -{ - GtkToolButton *tool_button = GTK_TOOL_BUTTON (item); - GtkToggleToolButton *toggle_tool_button = GTK_TOGGLE_TOOL_BUTTON (item); - GtkWidget *menu_item = NULL; - gboolean use_mnemonic = TRUE; - const char *label; - GtkWidget *label_widget; - const gchar *label_text; - - if (_gtk_tool_item_create_menu_proxy (item)) - return TRUE; - - label_widget = gtk_tool_button_get_label_widget (tool_button); - label_text = gtk_tool_button_get_label (tool_button); - - if (GTK_IS_LABEL (label_widget)) - { - label = gtk_label_get_label (GTK_LABEL (label_widget)); - use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (label_widget)); - } - else if (label_text) - { - label = label_text; - use_mnemonic = gtk_tool_button_get_use_underline (tool_button); - } - else - { - label = ""; - } - - if (use_mnemonic) - menu_item = gtk_check_menu_item_new_with_mnemonic (label); - else - menu_item = gtk_check_menu_item_new_with_label (label); - - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), - toggle_tool_button->priv->active); - - if (GTK_IS_RADIO_TOOL_BUTTON (toggle_tool_button)) - { - gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (menu_item), - TRUE); - } - - g_signal_connect_closure_by_id (menu_item, - g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0, - g_cclosure_new_object (G_CALLBACK (menu_item_activated), - G_OBJECT (toggle_tool_button)), - FALSE); - - gtk_tool_item_set_proxy_menu_item (item, MENU_ID, menu_item); - - return TRUE; -} - -/* There are two activatable widgets, a toggle button and a menu item. - * - * If a widget is activated and the state of the tool button is the same as - * the new state of the activated widget, then the other widget was the one - * that was activated by the user and updated the tool button’s state. - * - * If the state of the tool button is not the same as the new state of the - * activated widget, then the activation was activated by the user, and the - * widget needs to make sure the tool button is updated before the other - * widget is activated. This will make sure the other widget a tool button - * in a state that matches its own new state. - */ -static void -menu_item_activated (GtkWidget *menu_item, - GtkToggleToolButton *toggle_tool_button) -{ - GtkToolButton *tool_button = GTK_TOOL_BUTTON (toggle_tool_button); - gboolean menu_active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item)); - - if (toggle_tool_button->priv->active != menu_active) - { - toggle_tool_button->priv->active = menu_active; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_tool_button_get_button (tool_button)), - toggle_tool_button->priv->active); - - g_object_notify (G_OBJECT (toggle_tool_button), "active"); - g_signal_emit (toggle_tool_button, toggle_signals[TOGGLED], 0); - } -} - static void button_toggled (GtkWidget *widget, GtkToggleToolButton *toggle_tool_button) @@ -287,17 +192,8 @@ button_toggled (GtkWidget *widget, if (toggle_tool_button->priv->active != toggle_active) { - GtkWidget *menu_item; - toggle_tool_button->priv->active = toggle_active; - if ((menu_item = - gtk_tool_item_get_proxy_menu_item (GTK_TOOL_ITEM (toggle_tool_button), MENU_ID))) - { - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), - toggle_tool_button->priv->active); - } - g_object_notify (G_OBJECT (toggle_tool_button), "active"); g_signal_emit (toggle_tool_button, toggle_signals[TOGGLED], 0); } diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c index 102fffd1cb..fc232996f2 100644 --- a/gtk/gtktoolbar.c +++ b/gtk/gtktoolbar.c @@ -64,6 +64,7 @@ #include "gtkwindowprivate.h" #include "gtkgestureclick.h" #include "gtkbuttonprivate.h" +#include "gtkmenubutton.h" /** @@ -143,7 +144,6 @@ struct _GtkToolbarPrivate GtkToolbarStyle style; GtkToolItem *highlight_tool_item; - GtkWidget *arrow; GtkWidget *arrow_button; GtkAllocation prev_allocation; @@ -233,13 +233,6 @@ static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar GtkToolbarStyle style); static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar, gboolean focus_home); -static void gtk_toolbar_arrow_button_press (GtkGesture *gesture, - int n_press, - double x, - double y, - GtkToolbar *toolbar); -static void gtk_toolbar_arrow_button_clicked (GtkWidget *button, - GtkToolbar *toolbar); static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar); static void gtk_toolbar_reconfigured (GtkToolbar *toolbar); @@ -306,7 +299,9 @@ static void toolbar_content_set_size_request (ToolbarContent gint height); static void toolbar_content_toolbar_reconfigured (ToolbarContent *content, GtkToolbar *toolbar); -static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent *content); +static const char * toolbar_content_get_overflow_text (ToolbarContent *content); +static GtkButtonRole toolbar_content_get_button_role (ToolbarContent *content); +static gboolean toolbar_content_get_active (ToolbarContent *content); static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content); static gboolean toolbar_content_is_separator (ToolbarContent *content); static void toolbar_content_set_expand (ToolbarContent *content, @@ -316,6 +311,8 @@ static void toolbar_tool_shell_iface_init (GtkToolShellIface static GtkOrientation toolbar_get_orientation (GtkToolShell *shell); static GtkToolbarStyle toolbar_get_style (GtkToolShell *shell); static void toolbar_rebuild_menu (GtkToolShell *shell); +static void create_popup_func (GtkMenuButton *button, + gpointer data); G_DEFINE_TYPE_WITH_CODE (GtkToolbar, gtk_toolbar, GTK_TYPE_CONTAINER, @@ -558,18 +555,11 @@ gtk_toolbar_init (GtkToolbar *toolbar) _gtk_orientable_set_style_classes (GTK_ORIENTABLE (toolbar)); - priv->arrow_button = gtk_toggle_button_new (); - g_signal_connect (gtk_button_get_gesture (GTK_BUTTON (priv->arrow_button)), "pressed", - G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar); - g_signal_connect (priv->arrow_button, "clicked", - G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar); + priv->arrow_button = gtk_menu_button_new (); + gtk_menu_button_set_create_popup_func (GTK_MENU_BUTTON (priv->arrow_button), create_popup_func, toolbar, NULL); gtk_widget_set_focus_on_click (priv->arrow_button, FALSE); - priv->arrow = gtk_image_new_from_icon_name ("pan-down-symbolic"); - gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow"); - gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow); - gtk_widget_set_parent (priv->arrow_button, widget); /* which child position a drop will occur at */ @@ -656,9 +646,7 @@ gtk_toolbar_snapshot (GtkWidget *widget, toolbar_content_snapshot (content, GTK_CONTAINER (widget), snapshot); } - gtk_widget_snapshot_child (widget, - priv->arrow_button, - snapshot); + gtk_widget_snapshot_child (widget, priv->arrow_button, snapshot); } static void @@ -742,8 +730,7 @@ gtk_toolbar_measure (GtkWidget *widget, arrow_requisition.width = 0; if (priv->show_arrow) - gtk_widget_get_preferred_size (priv->arrow_button, - &arrow_requisition, NULL); + gtk_widget_get_preferred_size (priv->arrow_button, &arrow_requisition, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { @@ -1104,15 +1091,6 @@ remove_item (GtkWidget *menu_item, menu_item); } -static void -menu_deactivated (GtkWidget *menu, - GtkToolbar *toolbar) -{ - GtkToolbarPrivate *priv = toolbar->priv; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE); -} - static void button_clicked (GtkWidget *button, GtkWidget *item) @@ -1123,19 +1101,19 @@ button_clicked (GtkWidget *button, } static void -rebuild_menu (GtkToolbar *toolbar) +create_popup_func (GtkMenuButton *menu_button, + gpointer data) { + GtkToolbar *toolbar = data; GtkToolbarPrivate *priv = toolbar->priv; GList *list; if (!priv->menu) { priv->menu = gtk_popover_menu_new (priv->arrow_button); + gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->arrow_button), priv->menu); priv->menu_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_popover_menu_add_submenu (GTK_POPOVER_MENU (priv->menu), priv->menu_box, "main"); - - g_signal_connect (priv->menu, "closed", - G_CALLBACK (menu_deactivated), toolbar); } gtk_container_foreach (GTK_CONTAINER (priv->menu_box), remove_item, NULL); @@ -1147,49 +1125,15 @@ rebuild_menu (GtkToolbar *toolbar) if (toolbar_content_get_state (content) == OVERFLOWN && !toolbar_content_is_placeholder (content)) { - GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content); - - if (menu_item) + if (toolbar_content_is_separator (content)) + gtk_container_add (GTK_CONTAINER (priv->menu_box), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); + else if (toolbar_content_has_proxy_menu_item (content)) { - GtkWidget *button, *widget; - const char *text; - GtkButtonRole role; - gboolean active; + const char *text = toolbar_content_get_overflow_text (content); + GtkButtonRole role = toolbar_content_get_button_role (content); + gboolean active = toolbar_content_get_active (content); - g_assert (GTK_IS_MENU_ITEM (menu_item)); - text = gtk_menu_item_get_label (GTK_MENU_ITEM (menu_item)); - if (text == NULL) - { - GtkWidget *box, *child; - box = gtk_bin_get_child (GTK_BIN (menu_item)); - for (child = gtk_widget_get_first_child (box); - child; - child = gtk_widget_get_next_sibling (child)) - { - if (GTK_IS_LABEL (child)) - { - text = gtk_label_get_label (GTK_LABEL (child)); - break; - } - } - } - - if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item)) - { - gtk_container_add (GTK_CONTAINER (priv->menu_box), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL)); - continue; - } - else if (GTK_IS_RADIO_MENU_ITEM (menu_item)) - role = GTK_BUTTON_ROLE_RADIO; - else if (GTK_IS_CHECK_MENU_ITEM (menu_item)) - role = GTK_BUTTON_ROLE_CHECK; - else - role = GTK_BUTTON_ROLE_NORMAL; - - if (GTK_IS_CHECK_MENU_ITEM (menu_item)) - active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item)); - else - active = FALSE; + GtkWidget *button, *widget; button = gtk_model_button_new (); g_object_set (button, @@ -1198,8 +1142,7 @@ rebuild_menu (GtkToolbar *toolbar) "active", active, NULL); widget = toolbar_content_get_widget (content); - g_signal_connect (button, "clicked", - G_CALLBACK (button_clicked), widget); + g_signal_connect (button, "clicked", G_CALLBACK (button_clicked), widget); gtk_container_add (GTK_CONTAINER (priv->menu_box), button); } } @@ -1484,7 +1427,7 @@ gtk_toolbar_size_allocate (GtkWidget *widget, } if (priv->menu && priv->need_rebuild) - rebuild_menu (toolbar); + create_popup_func (GTK_MENU_BUTTON (priv->arrow_button), toolbar); if (need_arrow) { @@ -1494,9 +1437,6 @@ gtk_toolbar_size_allocate (GtkWidget *widget, else { 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)); } g_free (allocations); @@ -2116,9 +2056,9 @@ gtk_toolbar_orientation_changed (GtkToolbar *toolbar, priv->orientation = orientation; if (orientation == GTK_ORIENTATION_HORIZONTAL) - gtk_image_set_from_icon_name (GTK_IMAGE (priv->arrow), "pan-down-symbolic"); + gtk_menu_button_set_direction (GTK_MENU_BUTTON (priv->arrow_button), GTK_ARROW_DOWN); else - gtk_image_set_from_icon_name (GTK_IMAGE (priv->arrow), "pan-end-symbolic"); + gtk_menu_button_set_direction (GTK_MENU_BUTTON (priv->arrow_button), GTK_ARROW_RIGHT); gtk_toolbar_reconfigured (toolbar); @@ -2145,50 +2085,6 @@ gtk_toolbar_real_style_changed (GtkToolbar *toolbar, } } -static void -show_menu (GtkToolbar *toolbar, - GdkEventButton *event) -{ - GtkToolbarPrivate *priv = toolbar->priv; - - rebuild_menu (toolbar); - - gtk_popover_popup (GTK_POPOVER (priv->menu)); -} - -static void -gtk_toolbar_arrow_button_clicked (GtkWidget *button, - GtkToolbar *toolbar) -{ - GtkToolbarPrivate *priv = toolbar->priv; - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) && - (!priv->menu || !gtk_widget_get_visible (GTK_WIDGET (priv->menu)))) - { - /* We only get here when the button is clicked with the keyboard, - * because mouse button presses result in the menu being shown so - * that priv->menu would be non-NULL and visible. - */ - show_menu (toolbar, NULL); - gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE); - } -} - -static void -gtk_toolbar_arrow_button_press (GtkGesture *gesture, - int n_press, - double x, - double y, - GtkToolbar *toolbar) -{ - GtkWidget *button; - - button = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)); - show_menu (toolbar, NULL); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); -} - - static void gtk_toolbar_pressed_cb (GtkGestureClick *gesture, int n_press, @@ -2520,14 +2416,6 @@ gtk_toolbar_dispose (GObject *object) g_clear_pointer (&priv->arrow_button, gtk_widget_unparent); - if (priv->menu) - { - g_signal_handlers_disconnect_by_func (priv->menu, - menu_deactivated, toolbar); - gtk_widget_destroy (GTK_WIDGET (priv->menu)); - priv->menu = NULL; - } - if (priv->settings_connection > 0) { g_signal_handler_disconnect (priv->settings, priv->settings_connection); @@ -2867,27 +2755,27 @@ toolbar_content_toolbar_reconfigured (ToolbarContent *content, gtk_tool_item_toolbar_reconfigured (content->item); } -static GtkWidget * -toolbar_content_retrieve_menu_item (ToolbarContent *content) +static const char * +toolbar_content_get_overflow_text (ToolbarContent *content) { - return gtk_tool_item_retrieve_proxy_menu_item (content->item); + return gtk_tool_item_get_overflow_text (content->item); } static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content) { - GtkWidget *menu_item; + const char *text; if (content->has_menu == YES) return TRUE; else if (content->has_menu == NO) return FALSE; - menu_item = toolbar_content_retrieve_menu_item (content); + text = toolbar_content_get_overflow_text (content); - content->has_menu = menu_item? YES : NO; + content->has_menu = text ? YES : NO; - return menu_item != NULL; + return text != NULL; } static void @@ -2896,6 +2784,26 @@ toolbar_content_set_unknown_menu_status (ToolbarContent *content) content->has_menu = UNKNOWN; } +static GtkButtonRole +toolbar_content_get_button_role (ToolbarContent *content) +{ + if (GTK_IS_RADIO_TOOL_BUTTON (content->item)) + return GTK_BUTTON_ROLE_RADIO; + else if (GTK_IS_TOGGLE_TOOL_BUTTON (content->item)) + return GTK_BUTTON_ROLE_CHECK; + else + return GTK_BUTTON_ROLE_NORMAL; +} + +static gboolean +toolbar_content_get_active (ToolbarContent *content) +{ + if (GTK_IS_TOGGLE_TOOL_BUTTON (content->item)) + return gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (content->item)); + else + return FALSE; +} + static gboolean toolbar_content_is_separator (ToolbarContent *content) { diff --git a/gtk/gtktoolbutton.c b/gtk/gtktoolbutton.c index fedbe37faa..8cc681cf8f 100644 --- a/gtk/gtktoolbutton.c +++ b/gtk/gtktoolbutton.c @@ -95,7 +95,6 @@ static void gtk_tool_button_property_notify (GObject *object, static void gtk_tool_button_finalize (GObject *object); static void gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item); -static gboolean gtk_tool_button_create_menu_proxy (GtkToolItem *item); static void button_clicked (GtkWidget *widget, GtkToolButton *button); @@ -168,7 +167,6 @@ gtk_tool_button_class_init (GtkToolButtonClass *klass) object_class->notify = gtk_tool_button_property_notify; object_class->finalize = gtk_tool_button_finalize; - tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy; tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured; klass->button_type = GTK_TYPE_BUTTON; @@ -706,92 +704,6 @@ gtk_tool_button_finalize (GObject *object) parent_class->finalize (object); } -static GtkWidget * -clone_image_menu_size (GtkImage *image) -{ - GtkImageType storage_type = gtk_image_get_storage_type (image); - - if (storage_type == GTK_IMAGE_ICON_NAME) - { - const gchar *icon_name = gtk_image_get_icon_name (image); - - return gtk_image_new_from_icon_name (icon_name); - } - else if (storage_type == GTK_IMAGE_GICON) - { - GIcon *icon = gtk_image_get_gicon (image); - - return gtk_image_new_from_gicon (icon); - } - - return NULL; -} - -static void -click_button (GtkButton *button) -{ - g_signal_emit_by_name (button, "clicked"); -} - -static gboolean -gtk_tool_button_create_menu_proxy (GtkToolItem *item) -{ - GtkToolButton *button = GTK_TOOL_BUTTON (item); - GtkWidget *menu_item; - GtkWidget *menu_image = NULL; - gboolean use_mnemonic = TRUE; - const char *label_text; - GtkWidget *box; - GtkWidget *label; - - if (_gtk_tool_item_create_menu_proxy (item)) - return TRUE; - - if (GTK_IS_LABEL (button->priv->label_widget)) - { - label_text = gtk_label_get_label (GTK_LABEL (button->priv->label_widget)); - use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (button->priv->label_widget)); - } - else if (button->priv->label_text) - { - label_text = button->priv->label_text; - use_mnemonic = button->priv->use_underline; - } - else - { - label_text = ""; - } - - if (GTK_IS_IMAGE (button->priv->icon_widget)) - { - menu_image = clone_image_menu_size (GTK_IMAGE (button->priv->icon_widget)); - } - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - if (use_mnemonic) - label = gtk_label_new_with_mnemonic (label_text); - else - label = gtk_label_new (label_text); - - if (menu_image) - gtk_container_add (GTK_CONTAINER (box), menu_image); - - gtk_container_add (GTK_CONTAINER (box), label); - - menu_item = gtk_menu_item_new (); - gtk_container_add (GTK_CONTAINER (menu_item), box); - - g_signal_connect_closure_by_id (menu_item, - g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0, - g_cclosure_new_object_swap (G_CALLBACK (click_button), - G_OBJECT (GTK_TOOL_BUTTON (button)->priv->button)), - FALSE); - - gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item); - - return TRUE; -} - static void button_clicked (GtkWidget *widget, GtkToolButton *button) @@ -848,6 +760,7 @@ gtk_tool_button_set_label (GtkToolButton *button, gchar *old_label; gchar *elided_label; AtkObject *accessible; + const char *old_overflow_text; g_return_if_fail (GTK_IS_TOOL_BUTTON (button)); @@ -864,6 +777,11 @@ gtk_tool_button_set_label (GtkToolButton *button, g_free (elided_label); } + old_overflow_text = gtk_tool_item_get_overflow_text (GTK_TOOL_ITEM (button)); + if (old_overflow_text == NULL || + (old_label && strcmp (old_overflow_text, old_label) == 0)) + gtk_tool_item_set_overflow_text (GTK_TOOL_ITEM (button), label); + g_free (old_label); g_object_notify (G_OBJECT (button), "label"); diff --git a/gtk/gtktoolitem.c b/gtk/gtktoolitem.c index d21389d138..0de206aaea 100644 --- a/gtk/gtktoolitem.c +++ b/gtk/gtktoolitem.c @@ -70,6 +70,7 @@ enum { PROP_IS_IMPORTANT, PROP_HOMOGENEOUS, PROP_EXPAND_ITEM, + PROP_OVERFLOW_TEXT }; @@ -84,8 +85,7 @@ struct _GtkToolItemPrivate guint expand : 1; guint is_important : 1; - gchar *menu_item_id; - GtkWidget *menu_item; + char *overflow_text; }; static void gtk_tool_item_finalize (GObject *object); @@ -100,8 +100,6 @@ static void gtk_tool_item_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); -static void gtk_tool_item_property_notify (GObject *object, - GParamSpec *pspec); static guint toolitem_signals[LAST_SIGNAL] = { 0 }; @@ -120,10 +118,7 @@ gtk_tool_item_class_init (GtkToolItemClass *klass) object_class->set_property = gtk_tool_item_set_property; object_class->get_property = gtk_tool_item_get_property; object_class->finalize = gtk_tool_item_finalize; - object_class->notify = gtk_tool_item_property_notify; - klass->create_menu_proxy = _gtk_tool_item_create_menu_proxy; - g_object_class_install_property (object_class, PROP_VISIBLE_HORIZONTAL, g_param_spec_boolean ("visible-horizontal", @@ -162,40 +157,21 @@ gtk_tool_item_class_init (GtkToolItemClass *klass) FALSE, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); -/** - * GtkToolItem::create-menu-proxy: - * @tool_item: the object the signal was emitted on - * - * This signal is emitted when the toolbar needs information from @tool_item - * about whether the item should appear in the toolbar overflow menu. In - * response the tool item should either - * - * - call gtk_tool_item_set_proxy_menu_item() with a %NULL - * pointer and return %TRUE to indicate that the item should not appear - * in the overflow menu - * - * - call gtk_tool_item_set_proxy_menu_item() with a new menu - * item and return %TRUE, or - * - * - return %FALSE to indicate that the signal was not handled by the item. - * This means that the item will not appear in the overflow menu unless - * a later handler installs a menu item. - * - * The toolbar may cache the result of this signal. When the tool item changes - * how it will respond to this signal it must call gtk_tool_item_rebuild_menu() - * to invalidate the cache and ensure that the toolbar rebuilds its overflow - * menu. - * - * Returns: %TRUE if the signal was handled, %FALSE if not - **/ - toolitem_signals[CREATE_MENU_PROXY] = - g_signal_new (I_("create-menu-proxy"), - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkToolItemClass, create_menu_proxy), - _gtk_boolean_handled_accumulator, NULL, - _gtk_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); + /** + * GtkToolItem:overflow-text: + * + * The text to use as label in the overflow menu item for this + * toolitem. + * + * If unset, #GtkToolButton:label is used for #GtkToolButtons. + */ + g_object_class_install_property (object_class, + PROP_OVERFLOW_TEXT, + g_param_spec_string ("overflow-text", + P_("Overflow text"), + P_("Label to use in the overflow menu"), + NULL, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY)); /** * GtkToolItem::toolbar-reconfigured: @@ -239,13 +215,6 @@ gtk_tool_item_init (GtkToolItem *toolitem) static void gtk_tool_item_finalize (GObject *object) { - GtkToolItem *item = GTK_TOOL_ITEM (object); - - g_free (item->priv->menu_item_id); - - if (item->priv->menu_item) - g_object_unref (item->priv->menu_item); - G_OBJECT_CLASS (gtk_tool_item_parent_class)->finalize (object); } @@ -285,6 +254,9 @@ gtk_tool_item_set_property (GObject *object, case PROP_HOMOGENEOUS: gtk_tool_item_set_homogeneous (toolitem, g_value_get_boolean (value)); break; + case PROP_OVERFLOW_TEXT: + gtk_tool_item_set_overflow_text (toolitem, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -316,32 +288,15 @@ gtk_tool_item_get_property (GObject *object, case PROP_HOMOGENEOUS: g_value_set_boolean (value, toolitem->priv->homogeneous); break; + case PROP_OVERFLOW_TEXT: + g_value_set_string (value, toolitem->priv->overflow_text); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static void -gtk_tool_item_property_notify (GObject *object, - GParamSpec *pspec) -{ - GtkToolItem *tool_item = GTK_TOOL_ITEM (object); - - if (tool_item->priv->menu_item && strcmp (pspec->name, "sensitive") == 0) - gtk_widget_set_sensitive (tool_item->priv->menu_item, - gtk_widget_get_sensitive (GTK_WIDGET (tool_item))); - - if (G_OBJECT_CLASS (gtk_tool_item_parent_class)->notify) - G_OBJECT_CLASS (gtk_tool_item_parent_class)->notify (object, pspec); -} - -gboolean -_gtk_tool_item_create_menu_proxy (GtkToolItem *item) -{ - return FALSE; -} - /** * gtk_tool_item_new: * @@ -779,60 +734,6 @@ gtk_tool_item_get_visible_vertical (GtkToolItem *toolitem) return toolitem->priv->visible_vertical; } -/** - * gtk_tool_item_retrieve_proxy_menu_item: - * @tool_item: a #GtkToolItem - * - * Returns the #GtkMenuItem that was last set by - * gtk_tool_item_set_proxy_menu_item(), ie. the #GtkMenuItem - * that is going to appear in the overflow menu. - * - * Returns: (transfer none): The #GtkMenuItem that is going to appear in the - * overflow menu for @tool_item. - **/ -GtkWidget * -gtk_tool_item_retrieve_proxy_menu_item (GtkToolItem *tool_item) -{ - gboolean retval; - - g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), NULL); - - g_signal_emit (tool_item, toolitem_signals[CREATE_MENU_PROXY], 0, - &retval); - - return tool_item->priv->menu_item; -} - -/** - * gtk_tool_item_get_proxy_menu_item: - * @tool_item: a #GtkToolItem - * @menu_item_id: a string used to identify the menu item - * - * If @menu_item_id matches the string passed to - * gtk_tool_item_set_proxy_menu_item() return the corresponding #GtkMenuItem. - * - * Custom subclasses of #GtkToolItem should use this function to - * update their menu item when the #GtkToolItem changes. That the - * @menu_item_ids must match ensures that a #GtkToolItem - * will not inadvertently change a menu item that they did not create. - * - * Returns: (transfer none) (nullable): The #GtkMenuItem passed to - * gtk_tool_item_set_proxy_menu_item(), if the @menu_item_ids - * match. - **/ -GtkWidget * -gtk_tool_item_get_proxy_menu_item (GtkToolItem *tool_item, - const gchar *menu_item_id) -{ - g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), NULL); - g_return_val_if_fail (menu_item_id != NULL, NULL); - - if (tool_item->priv->menu_item_id && strcmp (tool_item->priv->menu_item_id, menu_item_id) == 0) - return tool_item->priv->menu_item; - - return NULL; -} - /** * gtk_tool_item_rebuild_menu: * @tool_item: a #GtkToolItem @@ -860,48 +761,6 @@ gtk_tool_item_rebuild_menu (GtkToolItem *tool_item) gtk_tool_shell_rebuild_menu (GTK_TOOL_SHELL (parent)); } -/** - * gtk_tool_item_set_proxy_menu_item: - * @tool_item: a #GtkToolItem - * @menu_item_id: a string used to identify @menu_item - * @menu_item: (nullable): a #GtkMenuItem to use in the overflow menu, or %NULL - * - * Sets the #GtkMenuItem used in the toolbar overflow menu. The - * @menu_item_id is used to identify the caller of this function and - * should also be used with gtk_tool_item_get_proxy_menu_item(). - * - * See also #GtkToolItem::create-menu-proxy. - **/ -void -gtk_tool_item_set_proxy_menu_item (GtkToolItem *tool_item, - const gchar *menu_item_id, - GtkWidget *menu_item) -{ - g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item)); - g_return_if_fail (menu_item == NULL || GTK_IS_MENU_ITEM (menu_item)); - g_return_if_fail (menu_item_id != NULL); - - g_free (tool_item->priv->menu_item_id); - - tool_item->priv->menu_item_id = g_strdup (menu_item_id); - - if (tool_item->priv->menu_item != menu_item) - { - if (tool_item->priv->menu_item) - g_object_unref (tool_item->priv->menu_item); - - if (menu_item) - { - g_object_ref_sink (menu_item); - - gtk_widget_set_sensitive (menu_item, - gtk_widget_get_sensitive (GTK_WIDGET (tool_item))); - } - - tool_item->priv->menu_item = menu_item; - } -} - /** * gtk_tool_item_toolbar_reconfigured: * @tool_item: a #GtkToolItem @@ -926,3 +785,38 @@ gtk_tool_item_toolbar_reconfigured (GtkToolItem *tool_item) gtk_widget_queue_resize (GTK_WIDGET (tool_item)); } + +/** + * gtk_tool_item_set_overflow_text: + * @tool_item: a #GtkToolItem + * @overflow_text: (nullable): Label to use in the overflow menu + * + * Sets the label to use for @tool_item in the overflow menu. + */ +void +gtk_tool_item_set_overflow_text (GtkToolItem *tool_item, + const char *overflow_text) +{ + g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item)); + + g_free (tool_item->priv->overflow_text); + tool_item->priv->overflow_text = g_strdup (overflow_text); + + g_object_notify (G_OBJECT (tool_item), "overflow-text"); +} + +/** + * gtk_tool_item_get_overflow_text: + * @tool_item: a #GtkToolItem + * + * Gets the label that is used for @tool_item in the overflow menu. + * + * Return: the overflow menu label for @tool_item + */ +const char * +gtk_tool_item_get_overflow_text (GtkToolItem *tool_item) +{ + g_return_val_if_fail (GTK_IS_TOOL_ITEM (tool_item), NULL); + + return tool_item->priv->overflow_text; +} diff --git a/gtk/gtktoolitem.h b/gtk/gtktoolitem.h index 6482a09e20..5dcdc80315 100644 --- a/gtk/gtktoolitem.h +++ b/gtk/gtktoolitem.h @@ -53,9 +53,6 @@ struct _GtkToolItem /** * GtkToolItemClass: * @parent_class: The parent class. - * @create_menu_proxy: Signal emitted when the toolbar needs - * information from tool_item about whether the item should appear in - * the toolbar overflow menu. * @toolbar_reconfigured: Signal emitted when some property of the * toolbar that the item is a child of changes. */ @@ -64,7 +61,6 @@ struct _GtkToolItemClass GtkBinClass parent_class; /* signals */ - gboolean (* create_menu_proxy) (GtkToolItem *tool_item); void (* toolbar_reconfigured) (GtkToolItem *tool_item); /*< private >*/ @@ -127,14 +123,10 @@ GDK_AVAILABLE_IN_ALL GtkSizeGroup * gtk_tool_item_get_text_size_group (GtkToolItem *tool_item); GDK_AVAILABLE_IN_ALL -GtkWidget * gtk_tool_item_retrieve_proxy_menu_item (GtkToolItem *tool_item); +const char * gtk_tool_item_get_overflow_text (GtkToolItem *tool_item); GDK_AVAILABLE_IN_ALL -GtkWidget * gtk_tool_item_get_proxy_menu_item (GtkToolItem *tool_item, - const gchar *menu_item_id); -GDK_AVAILABLE_IN_ALL -void gtk_tool_item_set_proxy_menu_item (GtkToolItem *tool_item, - const gchar *menu_item_id, - GtkWidget *menu_item); +void gtk_tool_item_set_overflow_text (GtkToolItem *tool_item, + const char *overflow_text); GDK_AVAILABLE_IN_ALL void gtk_tool_item_rebuild_menu (GtkToolItem *tool_item);