summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ui/interface.cpp73
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")) {