Code

NR::Maybe => boost::optional
[inkscape.git] / src / interface.cpp
index c913d1122c44e85f68b770f363de208f73a14137..0ec73d81bbcb735a39ae502bd5acfa22ee6d03ed 100644 (file)
 #include "file.h"
 #include "interface.h"
 #include "desktop.h"
-#include "object-ui.h"
+#include "ui/context-menu.h"
 #include "selection.h"
 #include "selection-chemistry.h"
 #include "svg-view-widget.h"
 #include "widgets/desktop-widget.h"
 #include "sp-item-group.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
 #include "sp-namedview.h"
+#include "ui/view/view.h"
 
 #include "helper/action.h"
 #include "helper/gnome-utils.h"
 #include "message-context.h"
 
 // Added for color drag-n-drop
+#if ENABLE_LCMS
+#include "lcms.h"
+#endif // ENABLE_LCMS
 #include "display/sp-canvas.h"
 #include "color.h"
 #include "svg/svg-color.h"
 #include "desktop-style.h"
 #include "style.h"
+#include "event-context.h"
+#include "gradient-drag.h"
 
+// Include Mac OS X menu synchronization on native OSX build
+#ifdef GDK_WINDOWING_QUARTZ
+#include "ige-mac-menu.h"
+#endif
 
 using Inkscape::IO::StringOutputStream;
 using Inkscape::IO::Base64OutputStream;
 
-/* forward declaration */
-static gint sp_ui_delete(GtkWidget *widget, GdkEvent *event, Inkscape::UI::View::View *view);
-
 /* Drag and Drop */
 typedef enum {
     URI_LIST,
@@ -80,13 +89,15 @@ typedef enum {
 } ui_drop_target_info;
 
 static GtkTargetEntry ui_drop_target_entries [] = {
-    {"text/uri-list", 0, URI_LIST},
-    {"image/svg+xml", 0, SVG_XML_DATA},
-    {"image/svg",     0, SVG_DATA},
-    {"image/png",     0, PNG_DATA},
-    {"image/jpeg",    0, JPEG_DATA},
-    {"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
-    {"application/x-color", 0, APP_X_COLOR}
+    {(gchar *)"text/uri-list",                0, URI_LIST        },
+    {(gchar *)"image/svg+xml",                0, SVG_XML_DATA    },
+    {(gchar *)"image/svg",                    0, SVG_DATA        },
+    {(gchar *)"image/png",                    0, PNG_DATA        },
+    {(gchar *)"image/jpeg",                   0, JPEG_DATA       },
+#if ENABLE_MAGIC_COLORS
+    {(gchar *)"application/x-inkscape-color", 0, APP_X_INKY_COLOR},
+#endif // ENABLE_MAGIC_COLORS
+    {(gchar *)"application/x-color",          0, APP_X_COLOR     }
 };
 
 static GtkTargetEntry *completeDropTargets = 0;
@@ -104,54 +115,108 @@ static void sp_ui_drag_data_received(GtkWidget *widget,
                                      guint info,
                                      guint event_time,
                                      gpointer user_data);
+static void sp_ui_drag_motion( GtkWidget *widget,
+                               GdkDragContext *drag_context,
+                               gint x, gint y,
+                               GtkSelectionData *data,
+                               guint info,
+                               guint event_time,
+                               gpointer user_data );
+static void sp_ui_drag_leave( GtkWidget *widget,
+                              GdkDragContext *drag_context,
+                              guint event_time,
+                              gpointer user_data );
 static void sp_ui_menu_item_set_sensitive(SPAction *action,
                                           unsigned int sensitive,
                                           void *data);
+static void sp_ui_menu_item_set_name(SPAction *action, 
+                                     Glib::ustring name,
+                                     void *data);
 
 SPActionEventVector menu_item_event_vector = {
     {NULL},
     NULL,
     NULL, /* set_active */
     sp_ui_menu_item_set_sensitive, /* set_sensitive */
-    NULL  /* set_shortcut */
+    NULL, /* set_shortcut */
+    sp_ui_menu_item_set_name /* set_name */
 };
 
+static const int MIN_ONSCREEN_DISTANCE = 50;
+
 void
 sp_create_window(SPViewWidget *vw, gboolean editable)
 {
-    GtkWidget *w, *hb;
-
     g_return_if_fail(vw != NULL);
     g_return_if_fail(SP_IS_VIEW_WIDGET(vw));
 
-    w = sp_window_new("", TRUE);
+    Gtk::Window *win = Inkscape::UI::window_new("", TRUE);
+
+    gtk_container_add(GTK_CONTAINER(win->gobj()), GTK_WIDGET(vw));
+    gtk_widget_show(GTK_WIDGET(vw));
 
     if (editable) {
-      g_object_set_data(G_OBJECT(vw), "window", w);
-      reinterpret_cast<SPDesktopWidget*>(vw)->window =
-        static_cast<GtkWindow*>((void*)w);
-    }
+               g_object_set_data(G_OBJECT(vw), "window", win);
+               
+               SPDesktopWidget *desktop_widget = reinterpret_cast<SPDesktopWidget*>(vw);
+               SPDesktop* desktop = desktop_widget->desktop;
+               
+               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));
+       
+        gint prefs_geometry = 
+            (2==prefs_get_int_attribute("options.savewindowgeometry", "value", 0));
+        if (prefs_geometry) {
+            gint pw = prefs_get_int_attribute("desktop.geometry", "width", -1);
+            gint ph = prefs_get_int_attribute("desktop.geometry", "height", -1);
+            gint px = prefs_get_int_attribute("desktop.geometry", "x", -1);
+            gint py = prefs_get_int_attribute("desktop.geometry", "y", -1);
+            gint full = prefs_get_int_attribute("desktop.geometry", "fullscreen", 0);
+            gint maxed = prefs_get_int_attribute("desktop.geometry", "maximized", 0);
+            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 (w>0 && h>0 && x>0 && y>0) {
+                    x = MIN(gdk_screen_width() - w, x);
+                    y = MIN(gdk_screen_height() - h, y);
+                }
+                if (w>0 && h>0) {
+                    desktop->setWindowSize(w, h);
+                }
 
-    hb = gtk_hbox_new(FALSE, 0);
-    gtk_widget_show(hb);
-    gtk_container_add(GTK_CONTAINER(w), hb);
-    g_object_set_data(G_OBJECT(w), "hbox", hb);
+                // Only restore xy for the first window so subsequent windows don't overlap exactly
+                // with first.  (Maybe rule should be only restore xy if it's different from xy of
+                // other desktops?)
+
+                // 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(NR::Point(x, y));
+                    }
+                }
+            }
+            if (maxed) {
+                win->maximize();
+            }
+            if (full) {
+                win->fullscreen();
+            }
+        }
 
-    /* fixme: */
-    if (editable) {
-        gtk_window_set_default_size((GtkWindow *) w, 640, 480);
-        g_object_set_data(G_OBJECT(w), "desktop", SP_DESKTOP_WIDGET(vw)->desktop);
-        g_object_set_data(G_OBJECT(w), "desktopwidget", vw);
-        g_signal_connect(G_OBJECT(w), "delete_event", G_CALLBACK(sp_ui_delete), vw->view);
-        g_signal_connect(G_OBJECT(w), "focus_in_event", G_CALLBACK(sp_desktop_widget_set_focus), vw);
     } else {
-        gtk_window_set_policy(GTK_WINDOW(w), TRUE, TRUE, TRUE);
+        gtk_window_set_policy(GTK_WINDOW(win->gobj()), TRUE, TRUE, TRUE);
     }
 
-    gtk_box_pack_end(GTK_BOX(hb), GTK_WIDGET(vw), TRUE, TRUE, 0);
-    gtk_widget_show(GTK_WIDGET(vw));
-
-
     if ( completeDropTargets == 0 || completeDropTargetsCount == 0 )
     {
         std::vector<gchar*> types;
@@ -183,16 +248,26 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
         }
     }
 
-    gtk_drag_dest_set(w,
+    gtk_drag_dest_set((GtkWidget*)win->gobj(),
                       GTK_DEST_DEFAULT_ALL,
                       completeDropTargets,
                       completeDropTargetsCount,
                       GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
-    g_signal_connect(G_OBJECT(w),
+
+
+    g_signal_connect(G_OBJECT(win->gobj()),
                      "drag_data_received",
                      G_CALLBACK(sp_ui_drag_data_received),
                      NULL);
-    gtk_widget_show(w);
+    g_signal_connect(G_OBJECT(win->gobj()),
+                     "drag_motion",
+                     G_CALLBACK(sp_ui_drag_motion),
+                     NULL);
+    g_signal_connect(G_OBJECT(win->gobj()),
+                     "drag_leave",
+                     G_CALLBACK(sp_ui_drag_leave),
+                     NULL);
+    win->show();
 
     // needed because the first ACTIVATE_DESKTOP was sent when there was no window yet
     inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop);
@@ -212,6 +287,7 @@ sp_ui_new_view()
 
     sp_create_window(dtw, TRUE);
     sp_namedview_window_from_document(static_cast<SPDesktop*>(dtw->view));
+    sp_namedview_update_layers_from_document(static_cast<SPDesktop*>(dtw->view));
 }
 
 /* TODO: not yet working */
@@ -236,7 +312,7 @@ sp_ui_new_view_preview()
  * \param widget unused
  */
 void
-sp_ui_close_view(GtkWidget *widget)
+sp_ui_close_view(GtkWidget */*widget*/)
 {
     if (SP_ACTIVE_DESKTOP == NULL) {
         return;
@@ -275,12 +351,6 @@ sp_ui_close_all(void)
     return TRUE;
 }
 
-static gint
-sp_ui_delete(GtkWidget *widget, GdkEvent *event, Inkscape::UI::View::View *view)
-{
-    return view->shutdown();
-}
-
 /*
  * Some day when the right-click menus are ready to start working
  * smarter with the verbs, we'll need to change this NULL being
@@ -289,19 +359,19 @@ sp_ui_delete(GtkWidget *widget, GdkEvent *event, Inkscape::UI::View::View *view)
  * investigate when they're called.
  */
 static void
-sp_ui_menu_activate(void *object, SPAction *action)
+sp_ui_menu_activate(void */*object*/, SPAction *action)
 {
     sp_action_perform(action, NULL);
 }
 
 static void
-sp_ui_menu_select_action(void *object, SPAction *action)
+sp_ui_menu_select_action(void */*object*/, SPAction *action)
 {
     action->view->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, action->tip);
 }
 
 static void
-sp_ui_menu_deselect_action(void *object, SPAction *action)
+sp_ui_menu_deselect_action(void */*object*/, SPAction *action)
 {
     action->view->tipsMessageContext()->clear();
 }
@@ -331,7 +401,7 @@ sp_ui_menuitem_add_icon( GtkWidget *item, gchar *icon_name )
 {
     GtkWidget *icon;
 
-    icon = sp_icon_new( GTK_ICON_SIZE_MENU, icon_name );
+    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
@@ -399,9 +469,10 @@ sp_key_name(guint keyval)
     else if (!strcmp(n, "Page_Down"  ))  return "PgDn";
     else if (!strcmp(n, "grave"      ))  return "`";
     else if (!strcmp(n, "numbersign" ))  return "#";
-    else if (!strcmp(n, "bar" ))  return "|";
-    else if (!strcmp(n, "slash" ))  return "/";
-    else if (!strcmp(n, "exclam" ))  return "!";
+    else if (!strcmp(n, "bar"        ))  return "|";
+    else if (!strcmp(n, "slash"      ))  return "/";
+    else if (!strcmp(n, "exclam"     ))  return "!";
+    else if (!strcmp(n, "percent"    ))  return "%";
     else return n;
 }
 
@@ -563,7 +634,7 @@ checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data)
     Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
 
     gchar const *pref_path;
-    if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen)
+    if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen())
         pref_path = g_strconcat("fullscreen.", pref, NULL);
     else
         pref_path = g_strconcat("window.", pref, NULL);
@@ -575,7 +646,7 @@ checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data)
 }
 
 static gboolean
-checkitem_update(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+checkitem_update(GtkWidget *widget, GdkEventExpose */*event*/, gpointer user_data)
 {
     GtkCheckMenuItem *menuitem=GTK_CHECK_MENU_ITEM(widget);
 
@@ -583,7 +654,7 @@ checkitem_update(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
     Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
 
     gchar const *pref_path;
-    if (static_cast<SPDesktop*>(view)->is_fullscreen)
+    if ((static_cast<SPDesktop*>(view))->is_fullscreen())
         pref_path = g_strconcat("fullscreen.", pref, NULL);
     else
         pref_path = g_strconcat("window.", pref, NULL);
@@ -662,13 +733,13 @@ sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *
 }
 
 static void
-sp_recent_open(GtkWidget *widget, gchar const *uri)
+sp_recent_open(GtkWidget */*widget*/, gchar const *uri)
 {
     sp_file_open(uri, NULL);
 }
 
 static void
-sp_file_new_from_template(GtkWidget *widget, gchar const *uri)
+sp_file_new_from_template(GtkWidget */*widget*/, gchar const *uri)
 {
     sp_file_new(uri);
 }
@@ -690,7 +761,7 @@ sp_menu_append_new_templates(GtkWidget *menu, Inkscape::UI::View::View *view)
 
             if (dir) {
                 for (gchar const *file = g_dir_read_name(dir); file != NULL; file = g_dir_read_name(dir)) {
-                    if (!g_str_has_suffix(file, ".svg"))
+                    if (!g_str_has_suffix(file, ".svg") && !g_str_has_suffix(file, ".svgz"))
                         continue; // skip non-svg files
 
                     gchar *basename = g_path_get_basename(file);
@@ -774,10 +845,10 @@ sp_ui_checkboxes_menus(GtkMenu *m, Inkscape::UI::View::View *view)
                                            checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_RULERS));
     sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "scrollbars",
                                            checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_SCROLLBARS));
-    sp_ui_menu_append_check_item_from_verb(m, view, _("_Statusbar"), _("Show or hide the statusbar (at the bottom of the window)"), "statusbar",
-                                           checkitem_toggled, checkitem_update, 0);
     sp_ui_menu_append_check_item_from_verb(m, view, _("_Palette"), _("Show or hide the color palette"), "panels",
                                            checkitem_toggled, checkitem_update, 0);
+    sp_ui_menu_append_check_item_from_verb(m, view, _("_Statusbar"), _("Show or hide the statusbar (at the bottom of the window)"), "statusbar",
+                                           checkitem_toggled, checkitem_update, 0);
 }
 
 /** \brief  This function turns XML into a menu
@@ -806,9 +877,6 @@ sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, Inkscape::UI:
          menu_pntr != NULL;
          menu_pntr = menu_pntr->next()) {
         if (!strcmp(menu_pntr->name(), "submenu")) {
-            if (!strcmp(menu_pntr->attribute("name"), "Effects") && !prefs_get_int_attribute("extensions", "show-effects-menu", 0)) {
-                continue;
-            }
             GtkWidget *mitem = gtk_menu_item_new_with_mnemonic(_(menu_pntr->attribute("name")));
             GtkWidget *submenu = gtk_menu_new();
             sp_ui_build_dyn_menus(menu_pntr->firstChild(), submenu, view);
@@ -879,9 +947,17 @@ 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));
+#endif
+
     sp_ui_build_dyn_menus(inkscape_get_menus(INKSCAPE), mbar, view);
 
+#ifdef GDK_WINDOWING_QUARTZ
+       return NULL;
+#else
     return mbar;
+#endif
 }
 
 static void leave_group(GtkMenuItem *, SPDesktop *desktop) {
@@ -890,7 +966,7 @@ static void leave_group(GtkMenuItem *, SPDesktop *desktop) {
 
 static void enter_group(GtkMenuItem *mi, SPDesktop *desktop) {
     desktop->setCurrentLayer(reinterpret_cast<SPObject *>(g_object_get_data(G_OBJECT(mi), "group")));
-    SP_DT_SELECTION(desktop)->clear();
+    sp_desktop_selection(desktop)->clear();
 }
 
 GtkWidget *
@@ -937,7 +1013,8 @@ sp_ui_context_menu(Inkscape::UI::View::View *view, SPItem *item)
     }
 
     if (( group && group != dt->currentLayer() ) ||
-        ( dt->currentLayer() != dt->currentRoot() ) ) {
+        ( dt->currentLayer() != dt->currentRoot() && SP_OBJECT_PARENT(dt->currentLayer()) != dt->currentRoot() ) ) {
+        /* Separator */
         sp_ui_menu_append_item(GTK_MENU(m), NULL, NULL, NULL, NULL, NULL, NULL);
     }
 
@@ -972,13 +1049,16 @@ sp_ui_drag_data_received(GtkWidget *widget,
                          gint x, gint y,
                          GtkSelectionData *data,
                          guint info,
-                         guint event_time,
-                         gpointer user_data)
+                         guint /*event_time*/,
+                         gpointer /*user_data*/)
 {
+    SPDocument *doc = SP_ACTIVE_DOCUMENT;
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+
     switch (info) {
+#if ENABLE_MAGIC_COLORS
         case APP_X_INKY_COLOR:
         {
-            SPDesktop *desktop = SP_ACTIVE_DESKTOP;
             int destX = 0;
             int destY = 0;
             gtk_widget_translate_coordinates( widget, &(desktop->canvas->widget), x, y, &destX, &destY );
@@ -987,11 +1067,15 @@ sp_ui_drag_data_received(GtkWidget *widget,
             SPItem *item = desktop->item_at_point( where, true );
             if ( item )
             {
+                bool fillnotstroke = (drag_context->action != GDK_ACTION_MOVE);
+
                 if ( data->length >= 8 ) {
+                    cmsHPROFILE srgbProf = cmsCreate_sRGBProfile();
+
                     gchar c[64] = {0};
                     // Careful about endian issues.
                     guint16* dataVals = (guint16*)data->data;
-                    sp_svg_write_color( c, 64,
+                    sp_svg_write_color( c, sizeof(c),
                                         SP_RGBA32_U_COMPOSE(
                                             0x0ff & (dataVals[0] >> 8),
                                             0x0ff & (dataVals[1] >> 8),
@@ -1000,10 +1084,7 @@ sp_ui_drag_data_received(GtkWidget *widget,
                                             //0x0ff & (data->data[3] >> 8),
                                             ));
                     SPCSSAttr *css = sp_repr_css_attr_new();
-                    sp_repr_css_set_property( css, (drag_context->action != GDK_ACTION_MOVE) ? "fill":"stroke", c );
-
-                    sp_desktop_apply_css_recursive( item, css, true );
-                    item->updateRepr();
+                    bool updatePerformed = false;
 
                     if ( data->length > 14 ) {
                         int flags = dataVals[4];
@@ -1023,51 +1104,110 @@ sp_ui_drag_data_received(GtkWidget *widget,
                             str = 0;
 
                             sp_object_setAttribute( SP_OBJECT(item),
-                                                    (drag_context->action != GDK_ACTION_MOVE) ? "HOTFill":"HOTStroke",
+                                                    fillnotstroke ? "inkscape:x-fill-tag":"inkscape:x-stroke-tag",
                                                     palName.c_str(),
                                                     false );
                             item->updateRepr();
+
+                            sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c );
+                            updatePerformed = true;
                         }
                     }
 
-                    SPDocument *doc = SP_ACTIVE_DOCUMENT;
-                    sp_document_done( doc );
+                    if ( !updatePerformed ) {
+                        sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c );
+                    }
+
+                    sp_desktop_apply_css_recursive( item, css, true );
+                    item->updateRepr();
+
+                    sp_document_done( doc , SP_VERB_NONE, 
+                                      _("Drop color"));
+
+                    if ( srgbProf ) {
+                        cmsCloseProfile( srgbProf );
+                    }
                 }
             }
         }
         break;
+#endif // ENABLE_MAGIC_COLORS
 
         case APP_X_COLOR:
         {
-            SPDesktop *desktop = SP_ACTIVE_DESKTOP;
             int destX = 0;
             int destY = 0;
             gtk_widget_translate_coordinates( widget, &(desktop->canvas->widget), x, y, &destX, &destY );
             NR::Point where( sp_canvas_window_to_world( desktop->canvas, NR::Point( destX, destY ) ) );
+            NR::Point const button_dt(desktop->w2d(where));
+            NR::Point const button_doc(desktop->dt2doc(button_dt));
+
+            if ( data->length == 8 ) {
+                gchar c[64] = {0};
+                // Careful about endian issues.
+                guint16* dataVals = (guint16*)data->data;
+                sp_svg_write_color( c, 64,
+                                    SP_RGBA32_U_COMPOSE(
+                                        0x0ff & (dataVals[0] >> 8),
+                                        0x0ff & (dataVals[1] >> 8),
+                                        0x0ff & (dataVals[2] >> 8),
+                                        0xff // can't have transparency in the color itself
+                                        //0x0ff & (data->data[3] >> 8),
+                                        ));
+
+                SPItem *item = desktop->item_at_point( where, true );
+
+                bool consumed = false;
+                if (desktop->event_context && desktop->event_context->get_drag()) {
+                    consumed = desktop->event_context->get_drag()->dropColor(item, c, button_dt);
+                    if (consumed) {
+                        sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient"));
+                        desktop->event_context->get_drag()->updateDraggers();
+                    }
+                }
+
+                //if (!consumed && tools_active(desktop, TOOLS_TEXT)) {
+                //    consumed = sp_text_context_drop_color(c, button_doc);
+                //    if (consumed) {
+                //        sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient stop"));
+                //    }
+                //}
+
+                if (!consumed && item) {
+                    bool fillnotstroke = (drag_context->action != GDK_ACTION_MOVE);
+                    if (fillnotstroke && 
+                        (SP_IS_SHAPE(item) || SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))) {
+                        Path *livarot_path = Path_for_item(item, true, true);
+                        livarot_path->ConvertWithBackData(0.04);
+
+                        boost::optional<Path::cut_position> position = get_nearest_position_on_Path(livarot_path, button_doc);
+                        if (position) {
+                            NR::Point nearest = get_point_on_Path(livarot_path, position->piece, position->t);
+                            NR::Point delta = nearest - button_doc;
+                            delta = desktop->d2w(delta);
+                            double stroke_tolerance =
+                                ( !SP_OBJECT_STYLE(item)->stroke.isNone() ?
+                                  desktop->current_zoom() *
+                                  SP_OBJECT_STYLE (item)->stroke_width.computed *
+                                  NR::expansion(from_2geom(sp_item_i2d_affine(item))) * 0.5
+                                  : 0.0)
+                                + prefs_get_int_attribute_limited("options.dragtolerance", "value", 0, 0, 100); 
+
+                            if (NR::L2 (delta) < stroke_tolerance) {
+                                fillnotstroke = false;
+                            }
+                        }
+                        delete livarot_path;
+                    }
 
-            SPItem *item = desktop->item_at_point( where, true );
-            if ( item )
-            {
-                if ( data->length == 8 ) {
-                    gchar c[64] = {0};
-                    // Careful about endian issues.
-                    guint16* dataVals = (guint16*)data->data;
-                    sp_svg_write_color( c, 64,
-                                        SP_RGBA32_U_COMPOSE(
-                                            0x0ff & (dataVals[0] >> 8),
-                                            0x0ff & (dataVals[1] >> 8),
-                                            0x0ff & (dataVals[2] >> 8),
-                                            0xff // can't have transparency in the color itself
-                                            //0x0ff & (data->data[3] >> 8),
-                                            ));
                     SPCSSAttr *css = sp_repr_css_attr_new();
-                    sp_repr_css_set_property( css, (drag_context->action != GDK_ACTION_MOVE) ? "fill":"stroke", c );
+                    sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c );
 
                     sp_desktop_apply_css_recursive( item, css, true );
                     item->updateRepr();
 
-                    SPDocument *doc = SP_ACTIVE_DOCUMENT;
-                    sp_document_done( doc );
+                    sp_document_done( doc , SP_VERB_NONE, 
+                                      _("Drop color"));
                 }
             }
         }
@@ -1077,8 +1217,6 @@ sp_ui_drag_data_received(GtkWidget *widget,
         case SVG_XML_DATA: {
             gchar *svgdata = (gchar *)data->data;
 
-            SPDocument *doc = SP_ACTIVE_DOCUMENT;
-
             Inkscape::XML::Document *rnewdoc = sp_repr_read_mem(svgdata, data->length, SP_SVG_NS_URI);
 
             if (rnewdoc == NULL) {
@@ -1086,41 +1224,45 @@ sp_ui_drag_data_received(GtkWidget *widget,
                 return;
             }
 
-            Inkscape::XML::Node *repr = sp_repr_document_root(rnewdoc);
+            Inkscape::XML::Node *repr = rnewdoc->root();
             gchar const *style = repr->attribute("style");
 
-            Inkscape::XML::Node *newgroup = sp_repr_new("svg:g");
+            Inkscape::XML::Node *newgroup = rnewdoc->createElement("svg:g");
             newgroup->setAttribute("style", style);
 
+            Inkscape::XML::Document * xml_doc =  sp_document_repr_doc(doc);
             for (Inkscape::XML::Node *child = repr->firstChild(); child != NULL; child = child->next()) {
-                Inkscape::XML::Node *newchild = child->duplicate();
+                Inkscape::XML::Node *newchild = child->duplicate(xml_doc);
                 newgroup->appendChild(newchild);
             }
 
             Inkscape::GC::release(rnewdoc);
 
-            SPDesktop *desktop = SP_ACTIVE_DESKTOP;
             // Add it to the current layer
 
             // Greg's edits to add intelligent positioning of svg drops
             SPObject *new_obj = NULL;
             new_obj = desktop->currentLayer()->appendChildRepr(newgroup);
 
-            Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+            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.
             {
                 int const saved_pref = prefs_get_int_attribute("options.transform", "pattern", 1);
                 prefs_set_int_attribute("options.transform", "pattern", 1);
-                sp_document_ensure_up_to_date(SP_DT_DOCUMENT(desktop));
-                NR::Point m( desktop->point() - selection->bounds().midpoint() );
-                sp_selection_move_relative(selection, m);
+                sp_document_ensure_up_to_date(sp_desktop_document(desktop));
+                boost::optional<NR::Rect> sel_bbox = selection->bounds();
+                if (sel_bbox) {
+                    NR::Point m( desktop->point() - sel_bbox->midpoint() );
+                    sp_selection_move_relative(selection, m);
+                }
                 prefs_set_int_attribute("options.transform", "pattern", saved_pref);
             }
 
             Inkscape::GC::release(newgroup);
-            sp_document_done(doc);
+            sp_document_done(doc, SP_VERB_NONE, 
+                             _("Drop SVG"));
             break;
         }
 
@@ -1139,9 +1281,9 @@ sp_ui_drag_data_received(GtkWidget *widget,
             Base64OutputStream b64out(outs);
             b64out.setColumnWidth(0);
 
-            SPDocument *doc = SP_ACTIVE_DOCUMENT;
+            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
 
-            Inkscape::XML::Node *newImage = sp_repr_new("svg:image");
+            Inkscape::XML::Node *newImage = xml_doc->createElement("svg:image");
 
             for ( int i = 0; i < data->length; i++ ) {
                 b64out.put( data->data[i] );
@@ -1173,18 +1315,42 @@ sp_ui_drag_data_received(GtkWidget *widget,
                 }
             }
 
-            SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
             // Add it to the current layer
             desktop->currentLayer()->appendChildRepr(newImage);
 
             Inkscape::GC::release(newImage);
-            sp_document_done( doc );
+            sp_document_done( doc , SP_VERB_NONE, 
+                              _("Drop bitmap image"));
             break;
         }
     }
 }
 
+#include "gradient-context.h"
+
+void sp_ui_drag_motion( GtkWidget */*widget*/,
+                        GdkDragContext */*drag_context*/,
+                        gint /*x*/, gint /*y*/,
+                        GtkSelectionData */*data*/,
+                        guint /*info*/,
+                        guint /*event_time*/,
+                        gpointer /*user_data*/)
+{
+//     SPDocument *doc = SP_ACTIVE_DOCUMENT;
+//     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+
+
+//     g_message("drag-n-drop motion (%4d, %4d)  at %d", x, y, event_time);
+}
+
+static void sp_ui_drag_leave( GtkWidget */*widget*/,
+                              GdkDragContext */*drag_context*/,
+                              guint /*event_time*/,
+                              gpointer /*user_data*/ )
+{
+//     g_message("drag-n-drop leave                at %d", event_time);
+}
+
 static void
 sp_ui_import_files(gchar *buffer)
 {
@@ -1197,7 +1363,7 @@ sp_ui_import_files(gchar *buffer)
 }
 
 static void
-sp_ui_import_one_file_with_check(gpointer filename, gpointer unused)
+sp_ui_import_one_file_with_check(gpointer filename, gpointer /*unused*/)
 {
     if (filename) {
         if (strlen((char const *)filename) > 2)
@@ -1225,7 +1391,7 @@ sp_ui_error_dialog(gchar const *message)
     gchar *safeMsg = Inkscape::IO::sanitizeString(message);
 
     dlg = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
-                                 GTK_BUTTONS_CLOSE, safeMsg);
+                                 GTK_BUTTONS_CLOSE, "%s", safeMsg);
     sp_transientize(dlg);
     gtk_window_set_resizable(GTK_WINDOW(dlg), FALSE);
     gtk_dialog_run(GTK_DIALOG(dlg));
@@ -1237,49 +1403,34 @@ bool
 sp_ui_overwrite_file(gchar const *filename)
 {
     bool return_value = FALSE;
-    GtkWidget *dialog;
-    GtkWidget *hbox;
-    GtkWidget *boxdata;
-    gchar *title;
-    gchar *text;
 
     if (Inkscape::IO::file_test(filename, G_FILE_TEST_EXISTS)) {
-
-        title = g_strdup_printf(_("Overwrite %s"), filename);
-        dialog = gtk_dialog_new_with_buttons(title,
-                                             NULL,
-                                             (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
-                                             GTK_STOCK_NO,
-                                             GTK_RESPONSE_NO,
-                                             GTK_STOCK_YES,
-                                             GTK_RESPONSE_YES,
-                                             NULL);
-        gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
-
-        sp_transientize(dialog);
-        gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
-
-        hbox = gtk_hbox_new(FALSE, 5);
-        boxdata = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
-        gtk_widget_show(boxdata);
-        gtk_box_pack_start(GTK_BOX(hbox), boxdata, TRUE, TRUE, 5);
-        text = g_strdup_printf(_("The file %s already exists.  Do you want to overwrite that file with the current document?"), filename);
-        boxdata = gtk_label_new(text);
-        gtk_label_set_line_wrap(GTK_LABEL(boxdata), TRUE);
-        gtk_widget_show(boxdata);
-        gtk_box_pack_start(GTK_BOX(hbox), boxdata, FALSE, FALSE, 5);
-        gtk_widget_show(hbox);
-        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 5);
-
-        if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES) {
+        Gtk::Window *window = SP_ACTIVE_DESKTOP->getToplevel();
+        gchar* baseName = g_path_get_basename( filename );
+        gchar* dirName = g_path_get_dirname( filename );
+        GtkWidget* dialog = gtk_message_dialog_new_with_markup( window->gobj(),
+                                                                (GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
+                                                                GTK_MESSAGE_QUESTION,
+                                                                GTK_BUTTONS_NONE,
+                                                                _( "<span weight=\"bold\" size=\"larger\">A file named \"%s\" already exists. Do you want to replace it?</span>\n\n"
+                                                                   "The file already exists in \"%s\". Replacing it will overwrite its contents." ),
+                                                                baseName,
+                                                                dirName
+            );
+        gtk_dialog_add_buttons( GTK_DIALOG(dialog),
+                                GTK_STOCK_CANCEL, GTK_RESPONSE_NO,
+                                _("Replace"), GTK_RESPONSE_YES,
+                                NULL );
+        gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_YES );
+
+        if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_YES ) {
             return_value = TRUE;
         } else {
             return_value = FALSE;
         }
-
         gtk_widget_destroy(dialog);
-        g_free(title);
-        g_free(text);
+        g_free( baseName );
+        g_free( dirName );
     } else {
         return_value = TRUE;
     }
@@ -1288,11 +1439,30 @@ sp_ui_overwrite_file(gchar const *filename)
 }
 
 static void
-sp_ui_menu_item_set_sensitive(SPAction *action, unsigned int sensitive, void *data)
+sp_ui_menu_item_set_sensitive(SPAction */*action*/, unsigned int sensitive, void *data)
 {
     return gtk_widget_set_sensitive(GTK_WIDGET(data), sensitive);
 }
 
+static void
+sp_ui_menu_item_set_name(SPAction */*action*/, Glib::ustring name, void *data)
+{
+    void *child = GTK_BIN (data)->child;
+    //child is either
+    //- a GtkHBox, whose first child is a label displaying name if the menu
+    //item has an accel key
+    //- a GtkLabel if the menu has no accel key
+    if (GTK_IS_LABEL(child)) {
+        gtk_label_set_markup_with_mnemonic(GTK_LABEL (child), name.c_str());
+    } else if (GTK_IS_HBOX(child)) {
+        gtk_label_set_markup_with_mnemonic(
+        GTK_LABEL (gtk_container_get_children(GTK_CONTAINER (child))->data), 
+        name.c_str());
+    }//else sp_ui_menu_append_item_from_verb has been modified and can set
+    //a menu item in yet another way...
+}
+
+
 /*
   Local Variables:
   mode:c++