From b803a0d60e30f27ddcc67c07931eddb2b68968c9 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Fri, 2 Nov 2018 22:03:39 +0100 Subject: Improve positioning of menu icons Shift them into the area reserved for toggles (check/radio items). See also "reserve-toggle-size" property of GtkMenu. --- src/ui/interface.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-) (limited to 'src/ui/interface.cpp') diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index f644aa174..fc8b4032e 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -19,6 +19,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include #include #include #include @@ -446,6 +447,64 @@ sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c) g_free(key); } } + +/* install CSS to shift icons into the space reserved for toggles (i.e. check and radio items) */ +void shift_icons(GtkWidget *menu, gpointer /* user_data */) +{ + static auto provider = Gtk::CssProvider::create(); + static bool provider_added = false; + + Gtk::MenuItem *menuitem = nullptr; + Gtk::Box *content = nullptr; + Gtk::Image *icon = nullptr; + + static int current_shift = 0; + int calculated_shift = 0; + + // install CssProvider for our custom styles + if (!provider_added) { + auto const screen = Gdk::Screen::get_default(); + Gtk::StyleContext::add_provider_for_screen(screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + provider_added = true; + } + + // get the first MenuItem with an image (i.e. "ImageMenuItem" as named below) + std::vector children = Glib::wrap(GTK_MENU(menu))->get_children(); + for (auto child: children) { + if (child->get_name() == "ImageMenuItem") { + menuitem = static_cast(child); + content = static_cast(menuitem->get_child()); + icon = static_cast(content->get_children()[0]); + break; + } + } + + // calculate how far we have to shift the icon to fit it into the empty space between menuitem and its content + if (icon) { + auto allocation_menuitem = menuitem->get_allocation(); + auto allocation_icon = icon->get_allocation(); + + if (menuitem->get_direction() == Gtk::TEXT_DIR_RTL) { + calculated_shift = allocation_menuitem.get_width() - allocation_icon.get_x() - allocation_icon.get_width(); + } else { + calculated_shift = -allocation_icon.get_x(); + } + } + + // install CSS to shift icon, use a threshold to avoid overly frequent updates + // (gtk's own calculations for the reserved space are off by a few pixels if there is no check/radio item in a menu) + if (calculated_shift && std::abs(current_shift - calculated_shift) > 2) { + current_shift = calculated_shift; + + std::string css_str; + if (menuitem->get_direction() == Gtk::TEXT_DIR_RTL) { + css_str = "#ImageMenuItem image {margin-right:" + std::to_string(-calculated_shift) + "px;}"; + } else { + css_str = "#ImageMenuItem image {margin-left:" + std::to_string(calculated_shift) + "px;}"; + } + provider->load_from_data(css_str); + } +} /** * Appends a custom menu UI from a verb. @@ -511,18 +570,13 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *men sp_shortcut_add_accelerator(item->gobj(), sp_shortcut_get_primary(verb)); gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), item->gobj()); - GtkWidget *icon; - - // If there is an image associated with the action, then we can add it as an - // icon for the menu item. If not, give the label a bit more space + // If there is an image associated with the action, then we can add it as an icon for the menu item. if(show_icon && action->image) { - icon = GTK_WIDGET(sp_get_icon_image(action->image, GTK_ICON_SIZE_MENU)->gobj()); - } - else { - icon = gtk_label_new(nullptr); // A fake icon just to act as a placeholder + GtkWidget *icon = GTK_WIDGET(sp_get_icon_image(action->image, GTK_ICON_SIZE_MENU)->gobj()); + gtk_box_pack_start(GTK_BOX(box), icon, FALSE, FALSE, 0); + item->set_name("ImageMenuItem"); } - gtk_box_pack_start(GTK_BOX(box), icon, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0); // Finally, pack all the widgets into the menu item @@ -867,6 +921,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I sp_ui_build_dyn_menus(menu_pntr->firstChild(), submenu, view); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), GTK_WIDGET(submenu)); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mitem); + g_signal_connect(submenu, "map", G_CALLBACK(shift_icons), NULL); continue; } if (!strcmp(menu_pntr->name(), "verb")) { -- cgit v1.2.3