Code

Make curvature work again by fixing a minor omission
[inkscape.git] / src / interface.cpp
index 8379cd0e23c9e48aa9ea1fe7091f87a902e5355c..415593b7885ba76dbe76fb259af0cd718708bb4e 100644 (file)
@@ -40,6 +40,8 @@
 #include "widgets/desktop-widget.h"
 #include "sp-item-group.h"
 #include "sp-text.h"
+#include "sp-gradient-fns.h"
+#include "sp-gradient.h"
 #include "sp-flowtext.h"
 #include "sp-namedview.h"
 #include "ui/view/view.h"
@@ -61,7 +63,7 @@
 #include "style.h"
 #include "event-context.h"
 #include "gradient-drag.h"
-#include "widgets/eek-color-def.h"
+#include "widgets/ege-paint-def.h"
 
 // Include Mac OS X menu synchronization on native OSX build
 #ifdef GDK_WINDOWING_QUARTZ
@@ -96,6 +98,7 @@ static GtkTargetEntry ui_drop_target_entries [] = {
 
 static GtkTargetEntry *completeDropTargets = 0;
 static int completeDropTargetsCount = 0;
+static bool temporarily_block_actions = false;
 
 #define ENTRIES_SIZE(n) sizeof(n)/sizeof(n[0])
 static guint nui_drop_target_entries = ENTRIES_SIZE(ui_drop_target_entries);
@@ -151,21 +154,21 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
     gtk_widget_show(GTK_WIDGET(vw));
 
     if (editable) {
-               g_object_set_data(G_OBJECT(vw), "window", win);
+        g_object_set_data(G_OBJECT(vw), "window", win);
 
-               SPDesktopWidget *desktop_widget = reinterpret_cast<SPDesktopWidget*>(vw);
-               SPDesktop* desktop = desktop_widget->desktop;
+        SPDesktopWidget *desktop_widget = reinterpret_cast<SPDesktopWidget*>(vw);
+        SPDesktop* desktop = desktop_widget->desktop;
 
-               desktop_widget->window = win;
+        desktop_widget->window = win;
 
         win->set_data("desktop", desktop);
         win->set_data("desktopwidget", desktop_widget);
 
         win->signal_delete_event().connect(sigc::mem_fun(*(SPDesktop*)vw->view, &SPDesktop::onDeleteUI));
-               win->signal_window_state_event().connect(sigc::mem_fun(*desktop, &SPDesktop::onWindowStateEvent));
-               win->signal_focus_in_event().connect(sigc::mem_fun(*desktop_widget, &SPDesktopWidget::onFocusInEvent));
+        win->signal_window_state_event().connect(sigc::mem_fun(*desktop, &SPDesktop::onWindowStateEvent));
+        win->signal_focus_in_event().connect(sigc::mem_fun(*desktop_widget, &SPDesktopWidget::onFocusInEvent));
 
-       Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         gint prefs_geometry =
             (2==prefs->getInt("/options/savewindowgeometry/value", 0));
         if (prefs_geometry) {
@@ -180,11 +183,9 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
                 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 (w>0 && h>0 && x>0 && y>0) {
+                if (w>0 && h>0) {
                     x = MIN(gdk_screen_width() - w, x);
                     y = MIN(gdk_screen_height() - h, y);
-                }
-                if (w>0 && h>0) {
                     desktop->setWindowSize(w, h);
                 }
 
@@ -194,11 +195,9 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
 
                 // Empirically it seems that active_desktop==this desktop only the first time a
                 // desktop is created.
-                if (x>0 && y>0) {
-                    SPDesktop *active_desktop = SP_ACTIVE_DESKTOP;
-                    if (active_desktop == desktop || active_desktop==NULL) {
-                        desktop->setWindowPosition(Geom::Point(x, y));
-                    }
+                SPDesktop *active_desktop = SP_ACTIVE_DESKTOP;
+                if (active_desktop == desktop || active_desktop==NULL) {
+                    desktop->setWindowPosition(Geom::Point(x, y));
                 }
             }
             if (maxed) {
@@ -310,13 +309,19 @@ sp_ui_new_view_preview()
 void
 sp_ui_close_view(GtkWidget */*widget*/)
 {
-    if (SP_ACTIVE_DESKTOP == NULL) {
+       SPDesktop *dt = SP_ACTIVE_DESKTOP;
+
+       if (dt == NULL) {
         return;
     }
-    if ((SP_ACTIVE_DESKTOP)->shutdown()) {
-        return;
+
+    if (dt->shutdown()) {
+        return; // Shutdown operation has been canceled, so do nothing
     }
-    SP_ACTIVE_DESKTOP->destroyWidget();
+
+    // Shutdown can proceed; use the stored reference to the desktop here instead of the current SP_ACTIVE_DESKTOP,
+    // because the user might have changed the focus in the meantime (see bug #381357 on Launchpad)
+    dt->destroyWidget();
 }
 
 
@@ -337,11 +342,14 @@ sp_ui_close_all(void)
     /* Iterate through all the windows, destroying each in the order they
        become active */
     while (SP_ACTIVE_DESKTOP) {
-        if ((SP_ACTIVE_DESKTOP)->shutdown()) {
-            /* The user cancelled the operation, so end doing the close */
+       SPDesktop *dt = SP_ACTIVE_DESKTOP;
+       if (dt->shutdown()) {
+            /* The user canceled the operation, so end doing the close */
             return FALSE;
         }
-        SP_ACTIVE_DESKTOP->destroyWidget();
+       // Shutdown can proceed; use the stored reference to the desktop here instead of the current SP_ACTIVE_DESKTOP,
+       // because the user might have changed the focus in the meantime (see bug #381357 on Launchpad)
+       dt->destroyWidget();
     }
 
     return TRUE;
@@ -357,7 +365,9 @@ sp_ui_close_all(void)
 static void
 sp_ui_menu_activate(void */*object*/, SPAction *action)
 {
-    sp_action_perform(action, NULL);
+    if (!temporarily_block_actions) {
+       sp_action_perform(action, NULL);
+    }
 }
 
 static void
@@ -608,9 +618,8 @@ sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::
             sp_ui_menuitem_add_icon(item, action->image);
         }
         gtk_widget_set_events(item, GDK_KEY_PRESS_MASK);
-        g_signal_connect( G_OBJECT(item), "activate",
-                          G_CALLBACK(sp_ui_menu_activate), action );
-
+        g_object_set_data(G_OBJECT(item), "view", (gpointer) view);
+        g_signal_connect( G_OBJECT(item), "activate", G_CALLBACK(sp_ui_menu_activate), action );
         g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select_action), action );
         g_signal_connect( G_OBJECT(item), "deselect", G_CALLBACK(sp_ui_menu_deselect_action), action );
     }
@@ -673,6 +682,44 @@ checkitem_update(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_dat
     return FALSE;
 }
 
+/**
+ *  \brief Callback function to update the status of the radio buttons in the View -> Display mode menu (Normal, No Filters, Outline)
+ */
+
+static gboolean
+update_view_menu(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_data)
+{
+       SPAction *action = (SPAction *) user_data;
+       g_assert(action->id != NULL);
+
+       Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(widget), "view");
+    SPDesktop *dt = static_cast<SPDesktop*>(view);
+       Inkscape::RenderMode mode = dt->getMode();
+
+       bool new_state = false;
+       if (!strcmp(action->id, "ViewModeNormal")) {
+       new_state = mode == Inkscape::RENDERMODE_NORMAL;
+       } else if (!strcmp(action->id, "ViewModeNoFilters")) {
+       new_state = mode == Inkscape::RENDERMODE_NO_FILTERS;
+    } else if (!strcmp(action->id, "ViewModeOutline")) {
+       new_state = mode == Inkscape::RENDERMODE_OUTLINE;
+    } else {
+       g_warning("update_view_menu does not handle this verb");
+    }
+
+       if (new_state) { //only one of the radio buttons has to be activated; the others will automatically be deactivated
+               if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) {
+                       // When the GtkMenuItem version of the "activate" signal has been emitted by a GtkRadioMenuItem, there is a second
+                       // emission as the most recently active item is toggled to inactive. This is dealt with before the original signal is handled.
+                       // This emission however should not invoke any actions, hence we block it here:
+                       temporarily_block_actions = true;
+                       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (widget), TRUE);
+                       temporarily_block_actions = false;
+               }
+       }
+
+       return FALSE;
+}
 
 void
 sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *view, gchar const *label, gchar const *tip, gchar const *pref,
@@ -820,8 +867,8 @@ sp_ui_checkboxes_menus(GtkMenu *m, Inkscape::UI::View::View *view)
     //                                       checkitem_toggled, checkitem_update, 0);
     sp_ui_menu_append_check_item_from_verb(m, view, _("Commands Bar"), _("Show or hide the Commands bar (under the menu)"), "commands",
                                            checkitem_toggled, checkitem_update, 0);
-    sp_ui_menu_append_check_item_from_verb(m, view, _("Snap controls Bar"), _("Show or hide the snapping controls"), "snaptoolbox",
-                                                                                  checkitem_toggled, checkitem_update, 0);
+    sp_ui_menu_append_check_item_from_verb(m, view, _("Snap Controls Bar"), _("Show or hide the snapping controls"), "snaptoolbox",
+                                           checkitem_toggled, checkitem_update, 0);
     sp_ui_menu_append_check_item_from_verb(m, view, _("Tool Controls Bar"), _("Show or hide the Tool Controls bar"), "toppanel",
                                            checkitem_toggled, checkitem_update, 0);
     sp_ui_menu_append_check_item_from_verb(m, view, _("_Toolbox"), _("Show or hide the main toolbox (on the left)"), "toolbox",
@@ -863,7 +910,7 @@ private:
     a couple of submenus, it is unlikely this will go more than two or
     three times.
 
-    In the case of an unreconginzed verb, a menu item is made to identify
+    In the case of an unrecognized verb, a menu item is made to identify
     the verb that is missing, and display that.  The menu item is also made
     insensitive.
 */
@@ -896,6 +943,10 @@ sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, Inkscape::UI:
                     if (menu_pntr->attribute("default") != NULL) {
                         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
                     }
+                    if (verb->get_code() != SP_VERB_NONE) {
+                       SPAction *action = verb->get_action(view);
+                       g_signal_connect( G_OBJECT(item), "expose_event", (GCallback) update_view_menu, (void *) action);
+                    }
                 } else {
                     sp_ui_menu_append_item_from_verb(GTK_MENU(menu), verb, view);
                     group = NULL;
@@ -941,6 +992,9 @@ sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, Inkscape::UI:
             gtk_recent_filter_add_application(inkscape_only_filter, g_get_prgname());
             gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(recent_menu), inkscape_only_filter);
 
+            gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER(recent_menu), TRUE);
+            gtk_recent_chooser_set_show_not_found (GTK_RECENT_CHOOSER(recent_menu), FALSE);
+
             GtkWidget *recent_item = gtk_menu_item_new_with_mnemonic(_("Open _Recent"));
             gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_item), recent_menu);
 
@@ -970,13 +1024,13 @@ sp_ui_main_menubar(Inkscape::UI::View::View *view)
     GtkWidget *mbar = gtk_menu_bar_new();
 
 #ifdef GDK_WINDOWING_QUARTZ
-       ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(mbar));
+    ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(mbar));
 #endif
 
     sp_ui_build_dyn_menus(inkscape_get_menus(INKSCAPE), mbar, view);
 
 #ifdef GDK_WINDOWING_QUARTZ
-       return NULL;
+    return NULL;
 #else
     return mbar;
 #endif
@@ -1241,20 +1295,41 @@ sp_ui_drag_data_received(GtkWidget *widget,
             bool worked = false;
             Glib::ustring colorspec;
             if ( data->format == 8 ) {
-                eek::ColorDef color;
+                ege::PaintDef color;
                 worked = color.fromMIMEData("application/x-oswb-color",
                                             reinterpret_cast<char*>(data->data),
                                             data->length,
                                             data->format);
                 if ( worked ) {
-                    if ( color.getType() == eek::ColorDef::CLEAR ) {
+                    if ( color.getType() == ege::PaintDef::CLEAR ) {
                         colorspec = ""; // TODO check if this is sufficient
-                    } else if ( color.getType() == eek::ColorDef::NONE ) {
+                    } else if ( color.getType() == ege::PaintDef::NONE ) {
                         colorspec = "none";
-                    } else {                        
-                        gchar* tmp = g_strdup_printf("#%02x%02x%02x", color.getR(), color.getG(), color.getB());
-                        colorspec = tmp;
-                        g_free(tmp);
+                    } else {
+                        unsigned int r = color.getR();
+                        unsigned int g = color.getG();
+                        unsigned int b = color.getB();
+
+                        SPGradient* matches = 0;
+                        const GSList *gradients = sp_document_get_resource_list(doc, "gradient");
+                        for (const GSList *item = gradients; item; item = item->next) {
+                            SPGradient* grad = SP_GRADIENT(item->data);
+                            if ( color.descr == grad->id ) {
+                                if ( grad->has_stops ) {
+                                    matches = grad;
+                                    break;
+                                }
+                            }
+                        }
+                        if (matches) {
+                            colorspec = "url(#";
+                            colorspec += matches->id;
+                            colorspec += ")";
+                        } else {
+                            gchar* tmp = g_strdup_printf("#%02x%02x%02x", r, g, b);
+                            colorspec = tmp;
+                            g_free(tmp);
+                        }
                     }
                 }
             }
@@ -1351,19 +1426,15 @@ sp_ui_drag_data_received(GtkWidget *widget,
 
             Inkscape::Selection *selection = sp_desktop_selection(desktop);
             selection->set(SP_ITEM(new_obj));
-            // To move the imported object, we must temporarily set the "transform pattern with
-            // object" option.
+
+            // move to mouse pointer
             {
-                Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-                bool const saved_pref = prefs->getBool("/options/transform/pattern", true);
-                prefs->setBool("/options/transform/pattern", true);
                 sp_document_ensure_up_to_date(sp_desktop_document(desktop));
                 Geom::OptRect sel_bbox = selection->bounds();
                 if (sel_bbox) {
                     Geom::Point m( desktop->point() - sel_bbox->midpoint() );
-                    sp_selection_move_relative(selection, m);
+                    sp_selection_move_relative(selection, m, false);
                 }
-                prefs->setBool("/options/transform/pattern", saved_pref);
             }
 
             Inkscape::GC::release(newgroup);
@@ -1384,14 +1455,14 @@ sp_ui_drag_data_received(GtkWidget *widget,
             Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
             Inkscape::XML::Node *newImage = xml_doc->createElement("svg:image");
             gchar *atom_name = gdk_atom_name(data->type);
-            
+
             // this formula taken from Glib docs
             guint needed_size = data->length * 4 / 3 + data->length * 4 / (3 * 72) + 7;
             needed_size += 5 + 8 + strlen(atom_name); // 5 bytes for data:, 8 for ;base64,
-            
+
             gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
             buf_work += g_sprintf(buffer, "data:%s;base64,", atom_name);
-            
+
             gint state = 0, save = 0;
             g_base64_encode_step(data->data, data->length, TRUE, buf_work, &state, &save);
             g_base64_encode_close(TRUE, buf_work, &state, &save);