diff options
| author | Eduard Braun <eduard.braun2@gmx.de> | 2018-11-02 21:03:39 +0000 |
|---|---|---|
| committer | Patrick Storz <eduard.braun2@gmx.de> | 2018-11-05 22:05:46 +0000 |
| commit | b803a0d60e30f27ddcc67c07931eddb2b68968c9 (patch) | |
| tree | f852fcc33de91e0a7b660d867e8b7e5164576f32 /src/ui | |
| parent | Add filter rendering improvements by caching (diff) | |
| download | inkscape-b803a0d60e30f27ddcc67c07931eddb2b68968c9.tar.gz inkscape-b803a0d60e30f27ddcc67c07931eddb2b68968c9.zip | |
Improve positioning of menu icons
Shift them into the area reserved for toggles (check/radio items).
See also "reserve-toggle-size" property of GtkMenu.
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/interface.cpp | 73 |
1 files changed, 64 insertions, 9 deletions
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 <gtkmm/cssprovider.h> #include <gtkmm/icontheme.h> #include <gtkmm/radiomenuitem.h> #include <gtkmm/separatormenuitem.h> @@ -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<Gtk::Widget*> children = Glib::wrap(GTK_MENU(menu))->get_children(); + for (auto child: children) { + if (child->get_name() == "ImageMenuItem") { + menuitem = static_cast<Gtk::MenuItem *>(child); + content = static_cast<Gtk::Box *>(menuitem->get_child()); + icon = static_cast<Gtk::Image *>(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")) { |
