diff options
Diffstat (limited to 'src/ui/interface.cpp')
| -rw-r--r-- | src/ui/interface.cpp | 1019 |
1 files changed, 94 insertions, 925 deletions
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 7e80c1a2f..a0ee5c72b 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -27,14 +27,15 @@ #include <gtkmm/icontheme.h> #include "file.h" #include <glibmm/miscutils.h> -#include <gtkmm/imagemenuitem.h> -#include <gtkmm/separatormenuitem.h> + +#if WITH_GTKMM_3_22 +# include <gdkmm/monitor.h> +#endif #include "inkscape.h" #include "extension/db.h" #include "extension/effect.h" #include "extension/input.h" -#include "widgets/icon.h" #include "preferences.h" #include "shortcuts.h" #include "document.h" @@ -135,8 +136,6 @@ static void sp_ui_menu_item_set_name(GtkWidget *data, Glib::ustring const &name); static void sp_recent_open(GtkRecentChooser *, gpointer); -static void injectRenamedIcons(); - static const int MIN_ONSCREEN_DISTANCE = 50; void @@ -176,13 +175,26 @@ sp_create_window(SPViewWidget *vw, bool editable) gint full = prefs->getBool("/desktop/geometry/fullscreen"); gint maxed = prefs->getBool("/desktop/geometry/maximized"); if (pw>0 && ph>0) { - gint w = MIN(gdk_screen_width(), pw); - gint h = MIN(gdk_screen_height(), ph); - gint x = MIN(gdk_screen_width() - MIN_ONSCREEN_DISTANCE, px); - gint y = MIN(gdk_screen_height() - MIN_ONSCREEN_DISTANCE, py); +#if WITH_GTKMM_3_22 + auto const display = Gdk::Display::get_default(); + auto const monitor = display->get_primary_monitor(); + + // A Gdk::Rectangle in "application pixel" units + Gdk::Rectangle screen_geometry; + monitor->get_geometry(screen_geometry); + auto const screen_width = screen_geometry.get_width(); + auto const screen_height = screen_geometry.get_height(); +#else + auto const screen_width = gdk_screen_width(); + auto const screen_height = gdk_screen_height(); +#endif + gint w = MIN(screen_width, pw); + gint h = MIN(screen_height, ph); + gint x = MIN(screen_width - MIN_ONSCREEN_DISTANCE, px); + gint y = MIN(screen_height - MIN_ONSCREEN_DISTANCE, py); if (w>0 && h>0) { - x = MIN(gdk_screen_width() - w, x); - y = MIN(gdk_screen_height() - h, y); + x = MIN(screen_width - w, x); + y = MIN(screen_height - h, y); desktop->setWindowSize(w, h); } @@ -389,23 +401,6 @@ sp_ui_menu_deselect(gpointer object) view->tipsMessageContext()->clear(); } -/** - * Creates and attaches a scaled icon to the given menu item. - */ -static void -sp_ui_menuitem_add_icon( GtkWidget *item, gchar *icon_name ) -{ - static bool iconsInjected = false; - if ( !iconsInjected ) { - iconsInjected = true; - injectRenamedIcons(); - } - GtkWidget *icon; - - icon = sp_icon_new( Inkscape::ICON_SIZE_MENU, icon_name ); - gtk_widget_show(icon); - gtk_image_menu_item_set_image((GtkImageMenuItem *) item, icon); -} // end of sp_ui_menu_add_icon void sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c) @@ -435,38 +430,82 @@ sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c) } } - /** * Appends a custom menu UI from a verb. * * @see ContextMenu::AppendItemFromVerb for a c++ified alternative. Consider dropping sp_ui_menu_append_item_from_verb when c++ifying interface.cpp. + * + * @param menu The menu to which the item will be appended + * @param verb The verb from which the item's label, action and icon (optionally) will be read + * @param view + * @param show_icon True if an icon should be displayed before the menu item's label + * @param radio True if a radio button should be displayed next to the menu item + * @param group The radio button group that the item should belong to + * + * @details The show_icon flag should be used very sparingly because menu icons are not recommended + * any longer under the GNOME HIG. Also, note that the text appears after the icon, and + * so will be indented relative to "normal" menu items. As such, menus will look best if + * all the items with icons are grouped together between a pair of separators. */ -static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::UI::View::View *view, bool radio = false, GSList *group = NULL) +static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, + Inkscape::Verb *verb, + Inkscape::UI::View::View *view, + bool show_icon = false, + bool radio = false, + GSList *group = NULL) { - SPAction *action; GtkWidget *item; + // Just create a menu separator if this isn't a real action. + // Otherwise, create a real menu item if (verb->get_code() == SP_VERB_NONE) { - item = gtk_separator_menu_item_new(); - } else { + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); - action = verb->get_action(Inkscape::ActionContext(view)); if (!action) return NULL; + // Create the menu item itself, either as a radio menu item, or just + // a regular menu item depending on whether the "radio" flag is set if (radio) { - item = gtk_radio_menu_item_new_with_mnemonic(group, action->name); + item = gtk_radio_menu_item_new(group); } else { - item = gtk_image_menu_item_new_with_mnemonic(action->name); + item = gtk_menu_item_new(); } - gtk_label_set_markup_with_mnemonic( GTK_LABEL(gtk_bin_get_child(GTK_BIN (item))), action->name); + // Create a box to contain all the widgets (icon, label, accelerator) + // that will go inside the menu item + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - GtkAccelGroup *accel_group = sp_shortcut_get_accel_group(); + // Now create the label and add it to the menu item + GtkWidget *label = gtk_accel_label_new(action->name); + gtk_label_set_markup_with_mnemonic( GTK_LABEL(label), action->name); + gtk_label_set_use_underline(GTK_LABEL(label), true); + gtk_label_set_xalign(GTK_LABEL(label), 0.0); + + GtkAccelGroup *accel_group = sp_shortcut_get_accel_group(); gtk_menu_set_accel_group(menu, accel_group); sp_shortcut_add_accelerator(item, sp_shortcut_get_primary(verb)); + gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), item); + + 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(show_icon && action->image) { + icon = gtk_image_new_from_icon_name(action->image, GTK_ICON_SIZE_MENU); + } + else { + icon = gtk_label_new(NULL); // A fake icon just to act as a placeholder + } + + 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 + gtk_container_add(GTK_CONTAINER(item), box); + action->signal_set_sensitive.connect( sigc::bind<0>( @@ -481,9 +520,6 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb gtk_widget_set_sensitive(item, FALSE); } - if (action->image) { - sp_ui_menuitem_add_icon(item, action->image); - } gtk_widget_set_events(item, GDK_KEY_PRESS_MASK); g_object_set_data(G_OBJECT(item), "view", (gpointer) view); g_signal_connect( G_OBJECT(item), "activate", G_CALLBACK(sp_ui_menu_activate), action ); @@ -491,7 +527,7 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb g_signal_connect( G_OBJECT(item), "deselect", G_CALLBACK(sp_ui_menu_deselect_action), action ); } - gtk_widget_show(item); + gtk_widget_show_all(item); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); return item; @@ -806,11 +842,19 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I } if (!strcmp(menu_pntr->name(), "verb")) { gchar const *verb_name = menu_pntr->attribute("verb-id"); + + // Check if the "show-icon" attribute is set, and set the flag here accordingly + bool show_icon = false; + + if(menu_pntr->attribute("show-icon") != NULL) { + show_icon = true; + } + Inkscape::Verb *verb = Inkscape::Verb::getbyid(verb_name); if (verb != NULL) { if (menu_pntr->attribute("radio") != NULL) { - GtkWidget *item = sp_ui_menu_append_item_from_verb (GTK_MENU(menu), verb, view, true, group); + GtkWidget *item = sp_ui_menu_append_item_from_verb (GTK_MENU(menu), verb, view, show_icon, true, group); group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item)); if (menu_pntr->attribute("default") != NULL) { gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); @@ -826,7 +870,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I checkitem_toggled, checkitem_update, verb); } } else { - sp_ui_menu_append_item_from_verb(GTK_MENU(menu), verb, view); + sp_ui_menu_append_item_from_verb(GTK_MENU(menu), verb, view, show_icon); group = NULL; } } else { @@ -1382,894 +1426,19 @@ sp_ui_menu_item_set_name(GtkWidget *data, Glib::ustring const &name) if (GTK_IS_LABEL(child)) { gtk_label_set_markup_with_mnemonic(GTK_LABEL (child), name.c_str()); } else if (GTK_IS_BOX(child)) { + GList *children = gtk_container_get_children(GTK_CONTAINER(child)); + + // Label is second child in list + GtkWidget *label = GTK_WIDGET(children->next->data); + gtk_label_set_markup_with_mnemonic( - GTK_LABEL (gtk_container_get_children(GTK_CONTAINER (child))->data), + GTK_LABEL (label), name.c_str()); }//else sp_ui_menu_append_item_from_verb has been modified and can set //a menu item in yet another way... } } } - -void injectRenamedIcons() -{ - Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default(); - - std::vector< std::pair<Glib::ustring, Glib::ustring> > renamed; - renamed.push_back(std::make_pair("gtk-file", "document-x-generic")); - renamed.push_back(std::make_pair("gtk-directory", "folder")); - - for ( std::vector< std::pair<Glib::ustring, Glib::ustring> >::iterator it = renamed.begin(); it < renamed.end(); ++it ) { - bool hasIcon = iconTheme->has_icon(it->first); - bool hasSecondIcon = iconTheme->has_icon(it->second); - - if ( !hasIcon && hasSecondIcon ) { - Glib::ArrayHandle<int> sizes = iconTheme->get_icon_sizes(it->second); - for ( Glib::ArrayHandle<int>::iterator it2 = sizes.begin(); it2 < sizes.end(); ++it2 ) { - Glib::RefPtr<Gdk::Pixbuf> pb = iconTheme->load_icon( it->second, *it2 ); - if ( pb ) { - // install a private copy of the pixbuf to avoid pinning a theme - Glib::RefPtr<Gdk::Pixbuf> pbCopy = pb->copy(); - Gtk::IconTheme::add_builtin_icon( it->first, *it2, pbCopy ); - } - } - } - } -} - - -ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : - _item(item), - MIGroup(), - MIParent(_("Go to parent")) -{ -// g_message("ContextMenu"); - _object = static_cast<SPObject *>(item); - _desktop = desktop; - - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_UNDO)); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_REDO)); - AddSeparator(); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_CUT)); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_COPY)); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_PASTE)); - AddSeparator(); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_DUPLICATE)); - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_DELETE)); - - positionOfLastDialog = 10; // 9 in front + 1 for the separator in the next if; used to position the dialog menu entries below each other - /* Item menu */ - if (item!=NULL) { - AddSeparator(); - MakeObjectMenu(); - } - AddSeparator(); - /* Lock/Unock Hide/Unhide*/ - Geom::Rect b(_desktop->point(),_desktop->point() + Geom::Point(1,1)); - std::vector< SPItem * > down_items = _desktop->getDocument()->getItemsPartiallyInBox( _desktop->dkey, b, true, true); - bool has_down_hidden = false; - bool has_down_locked = false; - for(std::vector< SPItem * >::iterator down = down_items.begin(); down != down_items.end(); ++down){ - if((*down)->isHidden()) { - has_down_hidden = true; - } - if((*down)->isLocked()) { - has_down_locked = true; - } - } - Gtk::MenuItem* mi; - - mi = Gtk::manage(new Gtk::MenuItem(_("Hide selected objects"),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::HideSelected)); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(false); - } - mi->show(); - append(*mi);//insert(*mi,positionOfLastDialog++); - - mi = Gtk::manage(new Gtk::MenuItem(_("Unhide objects below"),1)); - mi->signal_activate().connect(sigc::bind<std::vector< SPItem * > >(sigc::mem_fun(*this, &ContextMenu::UnHideBelow), down_items)); - if (!has_down_hidden) { - mi->set_sensitive(false); - } - mi->show(); - append(*mi);//insert(*mi,positionOfLastDialog++); - - mi = Gtk::manage(new Gtk::MenuItem(_("Lock selected objects"),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::LockSelected)); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(false); - } - mi->show(); - append(*mi);//insert(*mi,positionOfLastDialog++); - - mi = Gtk::manage(new Gtk::MenuItem(_("Unlock objects below"),1)); - mi->signal_activate().connect(sigc::bind<std::vector< SPItem * > >(sigc::mem_fun(*this, &ContextMenu::UnLockBelow), down_items)); - if (!has_down_locked) { - mi->set_sensitive(false); - } - mi->show(); - append(*mi);//insert(*mi,positionOfLastDialog++); - /* layer menu */ - SPGroup *group=NULL; - if (item) { - if (SP_IS_GROUP(item)) { - group = SP_GROUP(item); - } else if ( item != _desktop->currentRoot() && SP_IS_GROUP(item->parent) ) { - group = SP_GROUP(item->parent); - } - } - - if (( group && group != _desktop->currentLayer() ) || - ( _desktop->currentLayer() != _desktop->currentRoot() && _desktop->currentLayer()->parent != _desktop->currentRoot() ) ) { - AddSeparator(); - } - - if ( group && group != _desktop->currentLayer() ) { - /* TRANSLATORS: #%1 is the id of the group e.g. <g id="#g7">, not a number. */ - MIGroup.set_label (Glib::ustring::compose(_("Enter group #%1"), group->getId())); - MIGroup.set_data("group", group); - MIGroup.signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ContextMenu::EnterGroup),&MIGroup)); - MIGroup.show(); - append(MIGroup); - } - - if ( _desktop->currentLayer() != _desktop->currentRoot() ) { - if ( _desktop->currentLayer()->parent != _desktop->currentRoot() ) { - MIParent.signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::LeaveGroup)); - MIParent.show(); - append(MIParent); - - /* Pop selection out of group */ - Gtk::MenuItem* miu = Gtk::manage(new Gtk::MenuItem(_("_Pop selection out of group"), 1)); - miu->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ActivateUngroupPopSelection)); - miu->show(); - append(*miu); - } - } -} - -ContextMenu::~ContextMenu(void) -{ -} - -Gtk::SeparatorMenuItem* ContextMenu::AddSeparator(void) -{ - Gtk::SeparatorMenuItem* sep = Gtk::manage(new Gtk::SeparatorMenuItem()); - sep->show(); - append(*sep); - return sep; -} - -void ContextMenu::EnterGroup(Gtk::MenuItem* mi) -{ - _desktop->setCurrentLayer(reinterpret_cast<SPObject *>(mi->get_data("group"))); - _desktop->selection->clear(); -} - -void ContextMenu::LeaveGroup(void) -{ - _desktop->setCurrentLayer(_desktop->currentLayer()->parent); -} - -void ContextMenu::LockSelected(void) -{ - auto itemlist = _desktop->selection->items(); - for(auto i=itemlist.begin();i!=itemlist.end(); ++i) { - (*i)->setLocked(true); - } -} - -void ContextMenu::HideSelected(void) -{ - auto itemlist =_desktop->selection->items(); - for(auto i=itemlist.begin();i!=itemlist.end(); ++i) { - (*i)->setHidden(true); - } -} - -void ContextMenu::UnLockBelow(std::vector<SPItem *> items) -{ - _desktop->selection->clear(); - for(auto i=items.begin();i!=items.end(); ++i) { - if ((*i)->isLocked()) { - (*i)->setLocked(false); - _desktop->selection->add(*i); - } - } -} - -void ContextMenu::UnHideBelow(std::vector<SPItem *> items) -{ - _desktop->selection->clear(); - for(auto i=items.begin();i!=items.end(); ++i) { - if ((*i)->isHidden()) { - (*i)->setHidden(false); - _desktop->selection->add(*i); - } - } -} - -void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)//, bool radio, GSList *group) -{ - SPAction *action; - SPDesktop *view = _desktop; - - if (verb->get_code() == SP_VERB_NONE) { - Gtk::MenuItem *item = AddSeparator(); - item->show(); - append(*item); - } else { - action = verb->get_action(Inkscape::ActionContext(view)); - if (!action) { - return; - } - - Gtk::ImageMenuItem *item = Gtk::manage(new Gtk::ImageMenuItem(action->name, true)); - - sp_shortcut_add_accelerator(GTK_WIDGET(item->gobj()), sp_shortcut_get_primary(verb)); - - action->signal_set_sensitive.connect(sigc::mem_fun(*this, &ContextMenu::set_sensitive)); - action->signal_set_name.connect(sigc::mem_fun(*item, &ContextMenu::set_name)); - - if (!action->sensitive) { - item->set_sensitive(FALSE); - } - - if (action->image) { - sp_ui_menuitem_add_icon((GtkWidget*)item->gobj(), action->image); - } - item->set_events(Gdk::KEY_PRESS_MASK); - item->signal_activate().connect(sigc::bind(sigc::ptr_fun(sp_ui_menu_activate),item,action)); - item->signal_select().connect(sigc::bind(sigc::ptr_fun(sp_ui_menu_select_action),item,action)); - item->signal_deselect().connect(sigc::bind(sigc::ptr_fun(sp_ui_menu_deselect_action),item,action)); - item->show(); - append(*item); - } -} - -void ContextMenu::MakeObjectMenu(void) -{ -// GObjectClass *klass = G_OBJECT_GET_CLASS(_object); //to deduce the object's type from its class -// -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_ITEM)) -// { -// MakeItemMenu (); -// } -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_GROUP)) -// { -// MakeGroupMenu(); -// } -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_ANCHOR)) -// { -// MakeAnchorMenu(); -// } -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_IMAGE)) -// { -// MakeImageMenu(); -// } -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_SHAPE)) -// { -// MakeShapeMenu(); -// } -// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_TEXT)) -// { -// MakeTextMenu(); -// } - - if (SP_IS_ITEM(_object)) { - MakeItemMenu(); - } - - if (SP_IS_GROUP(_object)) { - MakeGroupMenu(); - } - - if (SP_IS_ANCHOR(_object)) { - MakeAnchorMenu(); - } - - if (SP_IS_IMAGE(_object)) { - MakeImageMenu(); - } - - if (SP_IS_SHAPE(_object)) { - MakeShapeMenu(); - } - - if (SP_IS_TEXT(_object)) { - MakeTextMenu(); - } -} - -void ContextMenu::MakeItemMenu (void) -{ - Gtk::MenuItem* mi; - - /* Item dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Object Properties..."),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemProperties)); - mi->show(); - append(*mi);//insert(*mi,positionOfLastDialog++); - - AddSeparator(); - - /* Select item */ - if (Inkscape::Verb::getbyid( "org.inkscape.followlink" )) { - mi = Gtk::manage(new Gtk::MenuItem(_("_Select This"), 1)); - if (_desktop->selection->includes(_item)) { - mi->set_sensitive(FALSE); - } else { - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemSelectThis)); - } - mi->show(); - append(*mi); - } - - - mi = Gtk::manage(new Gtk::MenuItem(_("Select Same"))); - mi->show(); - Gtk::Menu *select_same_submenu = Gtk::manage(new Gtk::Menu()); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(FALSE); - } - mi->set_submenu(*select_same_submenu); - append(*mi); - - /* Select same fill and stroke */ - mi = Gtk::manage(new Gtk::MenuItem(_("Fill and Stroke"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SelectSameFillStroke)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - select_same_submenu->append(*mi); - - /* Select same fill color */ - mi = Gtk::manage(new Gtk::MenuItem(_("Fill Color"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SelectSameFillColor)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - select_same_submenu->append(*mi); - - /* Select same stroke color */ - mi = Gtk::manage(new Gtk::MenuItem(_("Stroke Color"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SelectSameStrokeColor)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - select_same_submenu->append(*mi); - - /* Select same stroke style */ - mi = Gtk::manage(new Gtk::MenuItem(_("Stroke Style"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SelectSameStrokeStyle)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - select_same_submenu->append(*mi); - - /* Select same stroke style */ - mi = Gtk::manage(new Gtk::MenuItem(_("Object type"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SelectSameObjectType)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - select_same_submenu->append(*mi); - - /* Move to layer */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Move to layer ..."), 1)); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(FALSE); - } else { - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemMoveTo)); - } - mi->show(); - append(*mi); - - /* Create link */ - mi = Gtk::manage(new Gtk::MenuItem(_("Create _Link"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemCreateLink)); - mi->set_sensitive(!SP_IS_ANCHOR(_item)); - mi->show(); - append(*mi); - - bool ClipRefOK=false; - bool MaskRefOK=false; - if (_item){ - if (_item->clip_ref){ - if (_item->clip_ref->getObject()){ - ClipRefOK=true; - } - } - } - if (_item){ - if (_item->mask_ref){ - if (_item->mask_ref->getObject()){ - MaskRefOK=true; - } - } - } - /* Set mask */ - mi = Gtk::manage(new Gtk::MenuItem(_("Set Mask"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SetMask)); - if (ClipRefOK || MaskRefOK) { - mi->set_sensitive(FALSE); - } else { - mi->set_sensitive(TRUE); - } - mi->show(); - append(*mi); - - /* Release mask */ - mi = Gtk::manage(new Gtk::MenuItem(_("Release Mask"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ReleaseMask)); - if (MaskRefOK) { - mi->set_sensitive(TRUE); - } else { - mi->set_sensitive(FALSE); - } - mi->show(); - append(*mi); - - /*SSet Clip Group */ - mi = Gtk::manage(new Gtk::MenuItem(_("Create Clip G_roup"),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::CreateGroupClip)); - mi->set_sensitive(TRUE); - mi->show(); - append(*mi); - - /* Set Clip */ - mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SetClip)); - if (ClipRefOK || MaskRefOK) { - mi->set_sensitive(FALSE); - } else { - mi->set_sensitive(TRUE); - } - mi->show(); - append(*mi); - - /* Release Clip */ - mi = Gtk::manage(new Gtk::MenuItem(_("Release C_lip"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ReleaseClip)); - if (ClipRefOK) { - mi->set_sensitive(TRUE); - } else { - mi->set_sensitive(FALSE); - } - mi->show(); - append(*mi); - - /* Group */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Group"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ActivateGroup)); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(FALSE); - } else { - mi->set_sensitive(TRUE); - } - mi->show(); - append(*mi); -} - -void ContextMenu::SelectSameFillStroke(void) -{ - sp_select_same_fill_stroke_style(_desktop, true, true, true); -} - -void ContextMenu::SelectSameFillColor(void) -{ - sp_select_same_fill_stroke_style(_desktop, true, false, false); -} - -void ContextMenu::SelectSameStrokeColor(void) -{ - sp_select_same_fill_stroke_style(_desktop, false, true, false); -} - -void ContextMenu::SelectSameStrokeStyle(void) -{ - sp_select_same_fill_stroke_style(_desktop, false, false, true); -} - -void ContextMenu::SelectSameObjectType(void) -{ - sp_select_same_object_type(_desktop); -} - -void ContextMenu::ItemProperties(void) -{ - _desktop->selection->set(_item); - _desktop->_dlg_mgr->showDialog("ObjectProperties"); -} - -void ContextMenu::ItemSelectThis(void) -{ - _desktop->selection->set(_item); -} - -void ContextMenu::ItemMoveTo(void) -{ - Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->currentLayer()); -} - - - -void ContextMenu::ItemCreateLink(void) -{ - Inkscape::XML::Document *xml_doc = _desktop->doc()->getReprDoc(); - Inkscape::XML::Node *repr = xml_doc->createElement("svg:a"); - _item->parent->getRepr()->addChild(repr, _item->getRepr()); - SPObject *object = _item->document->getObjectByRepr(repr); - g_return_if_fail(SP_IS_ANCHOR(object)); - - const char *id = _item->getRepr()->attribute("id"); - Inkscape::XML::Node *child = _item->getRepr()->duplicate(xml_doc); - _item->deleteObject(false); - repr->addChild(child, NULL); - child->setAttribute("id", id); - - Inkscape::GC::release(repr); - Inkscape::GC::release(child); - - DocumentUndo::done(object->document, SP_VERB_NONE, _("Create link")); - - _desktop->selection->set(SP_ITEM(object)); - _desktop->_dlg_mgr->showDialog("ObjectAttributes"); -} - -void ContextMenu::SetMask(void) -{ - _desktop->selection->setMask(false, false); -} - -void ContextMenu::ReleaseMask(void) -{ - _desktop->selection->unsetMask(false); -} - -void ContextMenu::CreateGroupClip(void) -{ - _desktop->selection->setClipGroup(); -} - -void ContextMenu::SetClip(void) -{ - _desktop->selection->setMask(true, false); -} - - -void ContextMenu::ReleaseClip(void) -{ - _desktop->selection->unsetMask(true); -} - -void ContextMenu::MakeGroupMenu(void) -{ - /* Ungroup */ - Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("_Ungroup"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ActivateUngroup)); - mi->show(); - append(*mi); -} - -void ContextMenu::ActivateGroup(void) -{ - _desktop->selection->group(); -} - -void ContextMenu::ActivateUngroup(void) -{ - std::vector<SPItem*> children; - - sp_item_group_ungroup(static_cast<SPGroup*>(_item), children); - _desktop->selection->setList(children); -} - -void ContextMenu::ActivateUngroupPopSelection(void) -{ - _desktop->selection->popFromGroup(); -} - - -void ContextMenu::MakeAnchorMenu(void) -{ - Gtk::MenuItem* mi; - - /* Link dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("Link _Properties..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::AnchorLinkProperties)); - mi->show(); - insert(*mi,positionOfLastDialog++); - - /* Select item */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Follow Link"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::AnchorLinkFollow)); - mi->show(); - append(*mi); - - /* Reset transformations */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Remove Link"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::AnchorLinkRemove)); - mi->show(); - append(*mi); -} - -void ContextMenu::AnchorLinkProperties(void) -{ - _desktop->_dlg_mgr->showDialog("ObjectAttributes"); -} - -void ContextMenu::AnchorLinkFollow(void) -{ - - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - // Opening the selected links with a python extension - Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.inkscape.followlink" ); - if (verb) { - SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); - if (action) { - sp_action_perform(action, NULL); - } - } -} - -void ContextMenu::AnchorLinkRemove(void) -{ - std::vector<SPItem*> children; - sp_item_group_ungroup(static_cast<SPAnchor*>(_item), children, false); - DocumentUndo::done(_desktop->doc(), SP_VERB_NONE, _("Remove link")); -} - -void ContextMenu::MakeImageMenu (void) -{ - Gtk::MenuItem* mi; - Inkscape::XML::Node *ir = _object->getRepr(); - const gchar *href = ir->attribute("xlink:href"); - - /* Image properties */ - mi = Gtk::manage(new Gtk::MenuItem(_("Image _Properties..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageProperties)); - mi->show(); - insert(*mi,positionOfLastDialog++); - - /* Edit externally */ - mi = Gtk::manage(new Gtk::MenuItem(_("Edit Externally..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageEdit)); - mi->show(); - insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { - mi->set_sensitive( FALSE ); - } - - /* Trace Bitmap */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Trace Bitmap..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageTraceBitmap)); - mi->show(); - insert(*mi,positionOfLastDialog++); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(FALSE); - } - - /* Trace Pixel Art */ - mi = Gtk::manage(new Gtk::MenuItem(_("Trace Pixel Art"), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageTracePixelArt)); - mi->show(); - insert(*mi,positionOfLastDialog++); - if (_desktop->selection->isEmpty()) { - mi->set_sensitive(FALSE); - } - - /* Embed image */ - if (Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" )) { - mi = Gtk::manage(new Gtk::MenuItem(C_("Context menu", "Embed Image"))); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageEmbed)); - mi->show(); - insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { - mi->set_sensitive( FALSE ); - } - } - - /* Extract image */ - if (Inkscape::Verb::getbyid( "org.ekips.filter.extractimage" )) { - mi = Gtk::manage(new Gtk::MenuItem(C_("Context menu", "Extract Image..."))); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageExtract)); - mi->show(); - insert(*mi,positionOfLastDialog++); - if ( (!href) || ((strncmp(href, "data:", 5) != 0)) ) { - mi->set_sensitive( FALSE ); - } - } -} - -void ContextMenu::ImageProperties(void) -{ - _desktop->_dlg_mgr->showDialog("ObjectAttributes"); -} - -Glib::ustring ContextMenu::getImageEditorName() { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring value; - Glib::ustring choices = prefs->getString("/options/bitmapeditor/value"); - if (!choices.empty()) { - value = choices; - } - else { - value = "gimp"; - } - return value; -} - -void ContextMenu::ImageEdit(void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - GError* errThing = 0; - Glib::ustring cmdline = getImageEditorName(); - Glib::ustring name; - Glib::ustring fullname; - -#ifdef WIN32 - // g_spawn_command_line_sync parsing is done according to Unix shell rules, - // not Windows command interpreter rules. Thus we need to enclose the - // executable path with single quotes. - int index = cmdline.find(".exe"); - if ( index < 0 ) index = cmdline.find(".bat"); - if ( index < 0 ) index = cmdline.find(".com"); - if ( index >= 0 ) { - Glib::ustring editorBin = cmdline.substr(0, index + 4).c_str(); - Glib::ustring args = cmdline.substr(index + 4, cmdline.length()).c_str(); - editorBin.insert(0, "'"); - editorBin.append("'"); - cmdline = editorBin; - cmdline.append(args); - } else { - // Enclose the whole command line if no executable path can be extracted. - cmdline.insert(0, "'"); - cmdline.append("'"); - } -#endif - - auto itemlist= _desktop->selection->items(); - for(auto i=itemlist.begin();i!=itemlist.end();++i){ - Inkscape::XML::Node *ir = (*i)->getRepr(); - const gchar *href = ir->attribute("xlink:href"); - - if (strncmp (href,"file:",5) == 0) { - // URI to filename conversion - name = g_filename_from_uri(href, NULL, NULL); - } else { - name.append(href); - } - - if (Glib::path_is_absolute(name)) { - fullname = name; - } else if (SP_ACTIVE_DOCUMENT->getBase()) { - fullname = Glib::build_filename(SP_ACTIVE_DOCUMENT->getBase(), name); - } else { - fullname = Glib::build_filename(Glib::get_current_dir(), name); - } - - cmdline.append(" '"); - cmdline.append(fullname.c_str()); - cmdline.append("'"); - } - - //g_warning("##Command line: %s\n", cmdline.c_str()); - - g_spawn_command_line_async(cmdline.c_str(), &errThing); - - if ( errThing ) { - g_warning("Problem launching editor (%d). %s", errThing->code, errThing->message); - (_desktop->messageStack())->flash(Inkscape::ERROR_MESSAGE, errThing->message); - g_error_free(errThing); - errThing = 0; - } -} - -void ContextMenu::ImageTraceBitmap(void) -{ - INKSCAPE.dialogs_unhide(); - _desktop->_dlg_mgr->showDialog("Trace"); -} - -void ContextMenu::ImageTracePixelArt(void) -{ - INKSCAPE.dialogs_unhide(); - _desktop->_dlg_mgr->showDialog("PixelArt"); -} - -void ContextMenu::ImageEmbed(void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" ); - if (verb) { - SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); - if (action) { - sp_action_perform(action, NULL); - } - } -} - -void ContextMenu::ImageExtract(void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.extractimage" ); - if (verb) { - SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); - if (action) { - sp_action_perform(action, NULL); - } - } -} - -void ContextMenu::MakeShapeMenu (void) -{ - Gtk::MenuItem* mi; - - /* Item dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Fill and Stroke..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::FillSettings)); - mi->show(); - insert(*mi,positionOfLastDialog++); -} - -void ContextMenu::FillSettings(void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - _desktop->_dlg_mgr->showDialog("FillAndStroke"); -} - -void ContextMenu::MakeTextMenu (void) -{ - Gtk::MenuItem* mi; - - /* Fill and Stroke dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Fill and Stroke..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::FillSettings)); - mi->show(); - insert(*mi,positionOfLastDialog++); - - /* Edit Text dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("_Text and Font..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::TextSettings)); - mi->show(); - insert(*mi,positionOfLastDialog++); - - /* Spellcheck dialog */ - mi = Gtk::manage(new Gtk::MenuItem(_("Check Spellin_g..."), 1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::SpellcheckSettings)); - mi->show(); - insert(*mi,positionOfLastDialog++); -} - -void ContextMenu::TextSettings (void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - _desktop->_dlg_mgr->showDialog("TextFont"); -} - -void ContextMenu::SpellcheckSettings (void) -{ - if (_desktop->selection->isEmpty()) { - _desktop->selection->set(_item); - } - - _desktop->_dlg_mgr->showDialog("SpellCheck"); -} - /* Local Variables: mode:c++ |
