Code

Simple tracking of time to display dialogs and main window.
[inkscape.git] / src / dialogs / xml-tree.cpp
index e515a3f37440f3eb3d5cef0beaaff6e0873b57bd..d25bdad723550b097117e8b346b2014b93241f8d 100644 (file)
@@ -1,67 +1,52 @@
-#define __SP_XMLVIEW_TREE_C__
-
-/**
- * \brief  XML View
- *
- * Authors:
+/** @file
+ * @brief XML editor
+ */
+/* Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   MenTaLguY <mental@rydia.net>
  *   bulia byak <buliabyak@users.sf.net>
+ *   Johan Engelen <goejendaagh@zonnet.nl>
+ *   David Turner
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
- * Copyright (C) 1999-2005 Authors
- * Copyright (C) 2004 David Turner
- *
+ * Copyright (C) 1999-2006 Authors
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gtk/gtkmain.h>
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkhpaned.h>
-#include <gtk/gtkvpaned.h>
-#include <gtk/gtkhseparator.h>
-#include <gtk/gtkhbbox.h>
-#include <gtk/gtktoolbar.h>
-#include <gtk/gtkscrolledwindow.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkarrow.h>
-
+#include <gdk/gdkkeysyms.h>
 #include <glibmm/i18n.h>
+#include <gtk/gtk.h>
+
+#include "desktop.h"
+#include "../desktop-handles.h"
+#include "dialog-events.h"
+#include "../document.h"
+#include "../event-context.h"
 #include "helper/window.h"
-#include "macros.h"
 #include "../inkscape.h"
-#include "../document.h"
-#include "../desktop-handles.h"
-#include "desktop.h"
+#include "../interface.h"
+#include "macros.h"
+#include "message-context.h"
+#include "message-stack.h"
+#include "../preferences.h"
 #include "../selection.h"
+#include "shortcuts.h"
+#include "../sp-root.h"
 #include "../sp-string.h"
 #include "../sp-tspan.h"
-#include "../sp-root.h"
-#include "../event-context.h"
-#include "in-dt-coordsys.h"
-
-
-#include "../widgets/sp-xmlview-tree.h"
-#include "../widgets/sp-xmlview-content.h"
-#include "../widgets/sp-xmlview-attr-list.h"
-
-#include "../inkscape-stock.h"
+#include "ui/icon-names.h"
+#include "../verbs.h"
 #include "widgets/icon.h"
+#include "../widgets/sp-xmlview-attr-list.h"
+#include "../widgets/sp-xmlview-content.h"
+#include "../widgets/sp-xmlview-tree.h"
+#include "util/ege-appear-time-tracker.h"
 
-#include "dialog-events.h"
-#include "../prefs-utils.h"
-#include "../verbs.h"
-#include "../interface.h"
+using Inkscape::DocumentUndo;
+using ege::AppearTimeTracker;
 
-#include "shortcuts.h"
-#include <gdk/gdkkeysyms.h>
-
-#include "message-stack.h"
-#include "message-context.h"
+#define MIN_ONSCREEN_DISTANCE 50
 
 struct EditableDest {
     GtkEditable *editable;
@@ -75,7 +60,7 @@ static sigc::connection document_replaced_connection;
 static win_data wd;
 // impossible original values to make sure they are read from prefs
 static gint x = -1000, y = -1000, w = 0, h = 0;
-static gchar *prefs_path = "dialogs.xml";
+static Glib::ustring const prefs_path = "/dialogs/xml/";
 static GtkWidget *status = NULL;
 static Inkscape::MessageStack *_message_stack = NULL;
 static Inkscape::MessageContext *_message_context = NULL;
@@ -94,7 +79,8 @@ static SPDocument *current_document = NULL;
 static gint selected_attr = 0;
 static Inkscape::XML::Node *selected_repr = NULL;
 
-static void sp_xmltree_desktop_change( Inkscape::Application *inkscape,  SPDesktop *desktop, GtkWidget *dialog );
+static void sp_xmltree_desktop_activate( Inkscape::Application *inkscape,  SPDesktop *desktop, GtkWidget *dialog );
+static void sp_xmltree_desktop_deactivate( Inkscape::Application *inkscape,  SPDesktop *desktop, GtkWidget *dialog );
 
 static void set_tree_desktop(SPDesktop *desktop);
 static void set_tree_document(SPDocument *document);
@@ -161,6 +147,7 @@ static void cmd_set_attr(GtkObject *object, gpointer data);
 
 static gboolean sp_xml_tree_key_press(GtkWidget *widget, GdkEventKey *event);
 
+static bool in_dt_coordsys(SPObject const &item);
 
 /*
  * \brief Sets the XML status bar when the tree is selected.
@@ -193,11 +180,13 @@ void attr_reset_context(gint attr)
 void sp_xml_tree_dialog()
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
-
     if (!desktop) {
         return;
     }
 
+    bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
+    GTimer *timer = wantTiming ? g_timer_new() : 0;
+
     if (dlg == NULL)
     { // very long block
 
@@ -209,27 +198,28 @@ void sp_xml_tree_dialog()
         gtk_tooltips_enable(tooltips);
 
         dlg = sp_window_new("", TRUE);
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         if (x == -1000 || y == -1000) {
-            x = prefs_get_int_attribute(prefs_path, "x", 0);
-            y = prefs_get_int_attribute(prefs_path, "y", 0);
+            x = prefs->getInt(prefs_path + "x", -1000);
+            y = prefs->getInt(prefs_path + "y", -1000);
         }
         if (w ==0 || h == 0) {
-            w = prefs_get_int_attribute(prefs_path, "w", 0);
-            h = prefs_get_int_attribute(prefs_path, "h", 0);
+            w = prefs->getInt(prefs_path + "w", 0);
+            h = prefs->getInt(prefs_path + "h", 0);
         }
-        
-        if (x<0) x=0;
-        if (y<0) y=0;
 
-        if (x != 0 || y != 0) {
+//        if (x<0) x=0;
+//        if (y<0) y=0;
+
+        if (w && h) {
+            gtk_window_resize((GtkWindow *) dlg, w, h);
+        }
+        if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) {
             gtk_window_move((GtkWindow *) dlg, x, y);
         } else {
             gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
         }
 
-        if (w && h) {
-            gtk_window_resize((GtkWindow *) dlg, w, h);
-        }
         sp_transientize(dlg);
         wd.win = dlg;
         wd.stop = 0;
@@ -301,7 +291,7 @@ void sp_xml_tree_dialog()
                 _("New element node"),
                 NULL,
                 sp_icon_new( Inkscape::ICON_SIZE_LARGE_TOOLBAR,
-                                    INKSCAPE_STOCK_ADD_XML_ELEMENT_NODE ),
+                                    INKSCAPE_ICON_XML_ELEMENT_NEW ),
                 G_CALLBACK(cmd_new_element_node),
                 NULL);
 
@@ -322,7 +312,7 @@ void sp_xml_tree_dialog()
         button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
                 NULL, _("New text node"), NULL,
                 sp_icon_new( Inkscape::ICON_SIZE_LARGE_TOOLBAR,
-                             INKSCAPE_STOCK_ADD_XML_TEXT_NODE ),
+                             INKSCAPE_ICON_XML_TEXT_NEW ),
                 G_CALLBACK(cmd_new_text_node),
                 NULL);
 
@@ -343,7 +333,7 @@ void sp_xml_tree_dialog()
         button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
                 NULL, _("Duplicate node"), NULL,
                 sp_icon_new( Inkscape::ICON_SIZE_LARGE_TOOLBAR,
-                             INKSCAPE_STOCK_DUPLICATE_XML_NODE ),
+                             INKSCAPE_ICON_XML_NODE_DUPLICATE ),
                 G_CALLBACK(cmd_duplicate_node),
                 NULL);
 
@@ -362,9 +352,9 @@ void sp_xml_tree_dialog()
         gtk_toolbar_append_space(GTK_TOOLBAR(toolbar));
 
         button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
-                NULL, _("Delete node"), NULL,
+                NULL, Q_("nodeAsInXMLdialogTooltip|Delete node"), NULL,
                 sp_icon_new( Inkscape::ICON_SIZE_LARGE_TOOLBAR,
-                             INKSCAPE_STOCK_DELETE_XML_NODE ),
+                             INKSCAPE_ICON_XML_NODE_DELETE ),
                                            G_CALLBACK(cmd_delete_node), NULL );
 
         gtk_signal_connect_while_alive(GTK_OBJECT(tree), "tree_select_row",
@@ -464,7 +454,7 @@ void sp_xml_tree_dialog()
         button = gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),
                 NULL, _("Delete attribute"), NULL,
                 sp_icon_new( Inkscape::ICON_SIZE_LARGE_TOOLBAR,
-                             INKSCAPE_STOCK_DELETE_XML_ATTRIBUTE ),
+                             INKSCAPE_ICON_XML_ATTRIBUTE_DELETE ),
                (GCallback) cmd_delete_attr, NULL);
 
         gtk_signal_connect_while_alive(GTK_OBJECT(attributes), "select_row",
@@ -608,16 +598,23 @@ void sp_xml_tree_dialog()
         gtk_widget_hide(text_container);
 
         g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop",
-                           G_CALLBACK(sp_xmltree_desktop_change), dlg);
+                           G_CALLBACK(sp_xmltree_desktop_activate), dlg);
 
         g_signal_connect( G_OBJECT(INKSCAPE), "deactivate_desktop",
-                           G_CALLBACK(sp_xmltree_desktop_change), dlg);
+                           G_CALLBACK(sp_xmltree_desktop_deactivate), dlg);
 
         g_signal_connect((GObject *) dlg, "key_press_event", (GCallback) sp_xml_tree_key_press, NULL);
 
         tree_reset_context();
     } // end of if (dlg == NULL)
 
+    if ( wantTiming ) {
+        // Time tracker takes ownership of the timer.
+        AppearTimeTracker *tracker = new AppearTimeTracker(timer, GTK_WIDGET(dlg), "DialogXMLEditor");
+        tracker->setAutodelete(true);
+        timer = 0;
+    }
+
     gtk_window_present((GtkWindow *) dlg);
 
     g_assert(desktop != NULL);
@@ -625,7 +622,7 @@ void sp_xml_tree_dialog()
 
 } // end of sp_xml_tree_dialog()
 
-static gboolean sp_xml_tree_key_press(GtkWidget *widget, GdkEventKey *event)
+static gboolean sp_xml_tree_key_press(GtkWidget */*widget*/, GdkEventKey *event)
 {
 
     unsigned int shortcut = get_group0_keyval(event) |
@@ -646,16 +643,20 @@ static gboolean sp_xml_tree_key_press(GtkWidget *widget, GdkEventKey *event)
 }
 
 
-static void sp_xmltree_desktop_change(Inkscape::Application *inkscape,
+static void sp_xmltree_desktop_activate(Inkscape::Application */*inkscape*/,
                                       SPDesktop *desktop,
-                                      GtkWidget *dialog )
+                                      GtkWidget */*dialog*/ )
 {
-    if (!desktop) {
-        return;
-    }
     set_tree_desktop(desktop);
 }
 
+static void sp_xmltree_desktop_deactivate(Inkscape::Application */*inkscape*/,
+                                      SPDesktop */*desktop*/,
+                                      GtkWidget */*dialog*/ )
+{
+    set_tree_desktop(NULL);
+}
+
 
 void set_tree_desktop(SPDesktop *desktop)
 {
@@ -693,9 +694,8 @@ void set_tree_document(SPDocument *document)
     if (current_document) {
 
         document_uri_set_connection = current_document->connectURISet(sigc::bind(sigc::ptr_fun(&on_document_uri_set), current_document));
-        on_document_uri_set(SP_DOCUMENT_URI(current_document), current_document);
-        set_tree_repr(sp_document_repr_root(current_document));
-
+        on_document_uri_set( current_document->getURI(), current_document );
+        set_tree_repr(current_document->getReprRoot());
     } else {
         set_tree_repr(NULL);
     }
@@ -769,7 +769,7 @@ void propagate_tree_select(Inkscape::XML::Node *repr)
         sp_xmlview_attr_list_set_repr(attributes, NULL);
     }
 
-    if (repr && ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE ) ) {
+    if (repr && ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE || repr->type() == Inkscape::XML::PI_NODE ) ) {
         sp_xmlview_content_set_repr(content, repr);
     } else {
         sp_xmlview_content_set_repr(content, NULL);
@@ -825,8 +825,8 @@ void set_dt_select(Inkscape::XML::Node *repr)
 
 void on_tree_select_row(GtkCTree *tree,
                         GtkCTreeNode *node,
-                        gint column,
-                        gpointer data)
+                        gint /*column*/,
+                        gpointer /*data*/)
 {
     if (blocked) {
         return;
@@ -855,8 +855,8 @@ void on_tree_select_row(GtkCTree *tree,
 
 void on_tree_unselect_row(GtkCTree *tree,
                           GtkCTreeNode *node,
-                          gint column,
-                          gpointer data)
+                          gint /*column*/,
+                          gpointer /*data*/)
 {
     if (blocked) {
         return;
@@ -875,24 +875,24 @@ void on_tree_unselect_row(GtkCTree *tree,
 
 
 
-void after_tree_move(GtkCTree *tree,
+void after_tree_move(GtkCTree */*tree*/,
                      GtkCTreeNode *node,
                      GtkCTreeNode *new_parent,
                      GtkCTreeNode *new_sibling,
-                     gpointer data)
+                     gpointer /*data*/)
 {
     if (GTK_CTREE_ROW(node)->parent  == new_parent &&
         GTK_CTREE_ROW(node)->sibling == new_sibling)
     {
-        sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                         /* TODO: annotate */ "xml-tree.cpp:888");
+        DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                           _("Drag XML subtree"));
     } else {
-        sp_document_cancel(current_document);
+        DocumentUndo::cancel(current_document);
     }
 }
 
 
-static void on_destroy(GtkObject *object, gpointer data)
+static void on_destroy(GtkObject */*object*/, gpointer /*data*/)
 {
     set_tree_desktop(NULL);
     gtk_object_destroy(GTK_OBJECT(tooltips));
@@ -913,7 +913,7 @@ static void on_destroy(GtkObject *object, gpointer data)
 
 
 
-static gboolean on_delete(GtkObject *object, GdkEvent *event, gpointer data)
+static gboolean on_delete(GtkObject */*object*/, GdkEvent */*event*/, gpointer /*data*/)
 {
     gtk_window_get_position((GtkWindow *) dlg, &x, &y);
     gtk_window_get_size((GtkWindow *) dlg, &w, &h);
@@ -921,16 +921,17 @@ static gboolean on_delete(GtkObject *object, GdkEvent *event, gpointer data)
     if (x<0) x=0;
     if (y<0) y=0;
 
-    prefs_set_int_attribute(prefs_path, "x", x);
-    prefs_set_int_attribute(prefs_path, "y", y);
-    prefs_set_int_attribute(prefs_path, "w", w);
-    prefs_set_int_attribute(prefs_path, "h", h);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->setInt(prefs_path + "x", x);
+    prefs->setInt(prefs_path + "y", y);
+    prefs->setInt(prefs_path + "w", w);
+    prefs->setInt(prefs_path + "h", h);
 
     return FALSE; // which means, go ahead and destroy it
 }
 
 
-static void _set_status_message(Inkscape::MessageType type, const gchar *message, GtkWidget *dialog)
+static void _set_status_message(Inkscape::MessageType /*type*/, const gchar *message, GtkWidget */*dialog*/)
 {
     if (status) {
         gtk_label_set_markup(GTK_LABEL(status), message ? message : "");
@@ -938,9 +939,9 @@ static void _set_status_message(Inkscape::MessageType type, const gchar *message
 }
 
 
-void on_tree_select_row_enable(GtkCTree *tree,
-                               GtkCTreeNode *node,
-                               gint column,
+void on_tree_select_row_enable(GtkCTree */*tree*/,
+                               GtkCTreeNode */*node*/,
+                               gint /*column*/,
                                gpointer data)
 {
     gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
@@ -950,7 +951,7 @@ void on_tree_select_row_enable(GtkCTree *tree,
 
 void on_tree_select_row_enable_if_element(GtkCTree *tree,
                                           GtkCTreeNode *node,
-                                          gint column,
+                                          gint /*column*/,
                                           gpointer data )
 {
     Inkscape::XML::Node *repr = sp_xmlview_tree_node_get_repr(SP_XMLVIEW_TREE(tree), node);
@@ -965,7 +966,7 @@ void on_tree_select_row_enable_if_element(GtkCTree *tree,
 
 
 void on_tree_select_row_show_if_element(GtkCTree *tree, GtkCTreeNode *node,
-                                        gint column, gpointer data)
+                                        gint /*column*/, gpointer data)
 {
     Inkscape::XML::Node *repr = sp_xmlview_tree_node_get_repr(SP_XMLVIEW_TREE(tree), node);
 
@@ -979,11 +980,11 @@ void on_tree_select_row_show_if_element(GtkCTree *tree, GtkCTreeNode *node,
 
 
 void on_tree_select_row_show_if_text(GtkCTree *tree, GtkCTreeNode *node,
-                                     gint column, gpointer data)
+                                     gint /*column*/, gpointer data)
 {
     Inkscape::XML::Node *repr = sp_xmlview_tree_node_get_repr(SP_XMLVIEW_TREE(tree), node);
 
-    if ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE ) {
+    if ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE || repr->type() == Inkscape::XML::PI_NODE ) {
         gtk_widget_show(GTK_WIDGET(data));
     } else {
         gtk_widget_hide(GTK_WIDGET(data));
@@ -1018,32 +1019,32 @@ gboolean xml_tree_node_mutable(GtkCTreeNode *node)
 }
 
 
-void on_tree_select_row_enable_if_mutable(GtkCTree *tree, GtkCTreeNode *node,
-                                          gint column, gpointer data)
+void on_tree_select_row_enable_if_mutable(GtkCTree */*tree*/, GtkCTreeNode *node,
+                                          gint /*column*/, gpointer data)
 {
     gtk_widget_set_sensitive(GTK_WIDGET(data), xml_tree_node_mutable(node));
 }
 
 
 
-void on_tree_unselect_row_disable(GtkCTree *tree, GtkCTreeNode *node,
-                                  gint column, gpointer data)
+void on_tree_unselect_row_disable(GtkCTree */*tree*/, GtkCTreeNode */*node*/,
+                                  gint /*column*/, gpointer data)
 {
     gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
 }
 
 
 
-void on_tree_unselect_row_hide(GtkCTree *tree, GtkCTreeNode *node,
-                               gint column, gpointer data)
+void on_tree_unselect_row_hide(GtkCTree */*tree*/, GtkCTreeNode */*node*/,
+                               gint /*column*/, gpointer data)
 {
     gtk_widget_hide(GTK_WIDGET(data));
 }
 
 
 
-void on_tree_unselect_row_clear_text(GtkCTree *tree, GtkCTreeNode *node,
-                                     gint column, gpointer data)
+void on_tree_unselect_row_clear_text(GtkCTree */*tree*/, GtkCTreeNode */*node*/,
+                                     gint /*column*/, gpointer data)
 {
     if (GTK_IS_EDITABLE(data)) {
         gtk_editable_delete_text(GTK_EDITABLE(data), 0, -1);
@@ -1055,8 +1056,8 @@ void on_tree_unselect_row_clear_text(GtkCTree *tree, GtkCTreeNode *node,
 }
 
 
-void on_attr_select_row(GtkCList *list, gint row, gint column,
-                        GdkEventButton *event, gpointer data)
+void on_attr_select_row(GtkCList *list, gint row, gint /*column*/,
+                        GdkEventButton */*event*/, gpointer /*data*/)
 {
     selected_attr = sp_xmlview_attr_list_get_row_key(list, row);
     gtk_window_set_focus(GTK_WINDOW(dlg), GTK_WIDGET(attr_value));
@@ -1065,15 +1066,15 @@ void on_attr_select_row(GtkCList *list, gint row, gint column,
 }
 
 
-void on_attr_unselect_row(GtkCList *list, gint row, gint column,
-                          GdkEventButton *event, gpointer data)
+void on_attr_unselect_row(GtkCList */*list*/, gint /*row*/, gint /*column*/,
+                          GdkEventButton */*event*/, gpointer /*data*/)
 {
     selected_attr = 0;
     attr_reset_context(selected_attr);
 }
 
 
-void on_attr_row_changed(GtkCList *list, gint row, gpointer data)
+void on_attr_row_changed(GtkCList *list, gint row, gpointer /*data*/)
 {
     gint attr = sp_xmlview_attr_list_get_row_key(list, row);
 
@@ -1112,7 +1113,7 @@ void on_attr_row_changed(GtkCList *list, gint row, gpointer data)
 
 
 void on_attr_select_row_set_name_content(GtkCList *list, gint row,
-                                         gint column, GdkEventButton *event,
+                                         gint /*column*/, GdkEventButton */*event*/,
                                          gpointer data)
 {
     GtkEditable *editable = GTK_EDITABLE(data);
@@ -1124,8 +1125,8 @@ void on_attr_select_row_set_name_content(GtkCList *list, gint row,
 
 
 
-void on_attr_select_row_set_value_content(GtkCList *list, gint row, gint column,
-                                          GdkEventButton *event,
+void on_attr_select_row_set_value_content(GtkCList *list, gint row, gint /*column*/,
+                                          GdkEventButton */*event*/,
                                           gpointer data)
 {
     GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(data));
@@ -1139,7 +1140,7 @@ void on_attr_select_row_set_value_content(GtkCList *list, gint row, gint column,
 
 
 void on_tree_select_row_enable_if_indentable(GtkCTree *tree, GtkCTreeNode *node,
-                                             gint column, gpointer data)
+                                             gint /*column*/, gpointer data)
 {
     gboolean indentable = FALSE;
 
@@ -1154,7 +1155,7 @@ void on_tree_select_row_enable_if_indentable(GtkCTree *tree, GtkCTreeNode *node,
             // skip to the child just before the current repr
             for ( prev = parent->firstChild() ;
                   prev && prev->next() != repr ;
-                  prev = prev->next() );
+                  prev = prev->next() ){};
 
             if (prev && prev->type() == Inkscape::XML::ELEMENT_NODE) {
                 indentable = TRUE;
@@ -1169,7 +1170,7 @@ void on_tree_select_row_enable_if_indentable(GtkCTree *tree, GtkCTreeNode *node,
 
 void on_tree_select_row_enable_if_not_first_child(GtkCTree *tree,
                                                   GtkCTreeNode *node,
-                                                  gint column,
+                                                  gint /*column*/,
                                                   gpointer data)
 {
     Inkscape::XML::Node *repr = sp_xmlview_tree_node_get_repr(SP_XMLVIEW_TREE(tree), node);
@@ -1186,7 +1187,7 @@ void on_tree_select_row_enable_if_not_first_child(GtkCTree *tree,
 
 void on_tree_select_row_enable_if_not_last_child(GtkCTree *tree,
                                                  GtkCTreeNode *node,
-                                                 gint column, gpointer data)
+                                                 gint /*column*/, gpointer data)
 {
     Inkscape::XML::Node *repr = sp_xmlview_tree_node_get_repr(SP_XMLVIEW_TREE(tree), node);
 
@@ -1200,9 +1201,9 @@ void on_tree_select_row_enable_if_not_last_child(GtkCTree *tree,
 
 
 
-void on_tree_select_row_enable_if_has_grandparent(GtkCTree *tree,
+void on_tree_select_row_enable_if_has_grandparent(GtkCTree */*tree*/,
                                                   GtkCTreeNode *node,
-                                                  gint column, gpointer data)
+                                                  gint /*column*/, gpointer data)
 {
     GtkCTreeNode *parent = GTK_CTREE_ROW(node)->parent;
 
@@ -1220,24 +1221,24 @@ void on_tree_select_row_enable_if_has_grandparent(GtkCTree *tree,
 
 
 
-void on_attr_select_row_enable(GtkCList *list, gint row, gint column,
-                               GdkEventButton *event, gpointer data)
+void on_attr_select_row_enable(GtkCList */*list*/, gint /*row*/, gint /*column*/,
+                               GdkEventButton */*event*/, gpointer data)
 {
     gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
 }
 
 
 
-void on_attr_unselect_row_disable(GtkCList *list, gint row, gint column,
-                                  GdkEventButton *event, gpointer data)
+void on_attr_unselect_row_disable(GtkCList */*list*/, gint /*row*/, gint /*column*/,
+                                  GdkEventButton */*event*/, gpointer data)
 {
     gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
 }
 
 
 
-void on_attr_unselect_row_clear_text(GtkCList *list, gint row, gint column,
-                                     GdkEventButton *event, gpointer data)
+void on_attr_unselect_row_clear_text(GtkCList */*list*/, gint /*row*/, gint /*column*/,
+                                     GdkEventButton */*event*/, gpointer data)
 {
     if (GTK_IS_EDITABLE(data)) {
         gtk_editable_delete_text(GTK_EDITABLE(data), 0, -1);
@@ -1267,7 +1268,7 @@ void on_editable_changed_enable_if_valid_xml_name(GtkEditable *editable,
 
 
 
-void on_desktop_selection_changed(Inkscape::Selection *selection)
+void on_desktop_selection_changed(Inkscape::Selection */*selection*/)
 {
     if (!blocked++) {
         set_tree_select(get_dt_select());
@@ -1284,26 +1285,35 @@ static void on_document_replaced(SPDesktop *dt, SPDocument *doc)
     set_tree_document(doc);
 }
 
-void on_document_uri_set(gchar const *uri, SPDocument *document)
+void on_document_uri_set(gchar const */*uri*/, SPDocument *document)
 {
     gchar title[500];
     sp_ui_dialog_title_string(Inkscape::Verb::get(SP_VERB_DIALOG_XML_EDITOR), title);
-    gchar *t = g_strdup_printf("%s: %s", SP_DOCUMENT_NAME(document), title);
+    gchar *t = g_strdup_printf("%s: %s", document->getName(), title);
     gtk_window_set_title(GTK_WINDOW(dlg), t);
     g_free(t);
 }
 
 
 
-void on_clicked_get_editable_text(GtkWidget *widget, gpointer data)
+void on_clicked_get_editable_text(GtkWidget */*widget*/, gpointer data)
 {
     EditableDest *dest = (EditableDest *) data;
     dest->text = gtk_editable_get_chars(dest->editable, 0, -1);
 }
 
+gboolean
+quit_on_esc (GtkWidget *w, GdkEventKey *event, GObject */*tbl*/)
+{
+    switch (get_group0_keyval (event)) {
+        case GDK_Escape: // defocus
+            gtk_widget_destroy(w);
+            return TRUE;
+    }
+    return FALSE;
+}
 
-
-void cmd_new_element_node(GtkObject *object, gpointer data)
+void cmd_new_element_node(GtkObject */*object*/, gpointer /*data*/)
 {
     EditableDest name;
     GtkWidget *window, *create, *cancel, *vbox, *entry, *bbox, *sep;
@@ -1318,6 +1328,7 @@ void cmd_new_element_node(GtkObject *object, gpointer data)
     gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(dlg));
     gtk_window_set_modal(GTK_WINDOW(window), TRUE);
     gtk_signal_connect(GTK_OBJECT(window), "destroy", gtk_main_quit, NULL);
+    gtk_signal_connect(GTK_OBJECT(window), "key-press-event", G_CALLBACK(quit_on_esc), window);
 
     vbox = gtk_vbox_new(FALSE, 4);
     gtk_container_add(GTK_CONTAINER(window), vbox);
@@ -1334,6 +1345,8 @@ void cmd_new_element_node(GtkObject *object, gpointer data)
     gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
 
     cancel = gtk_button_new_with_label(_("Cancel"));
+    GTK_WIDGET_SET_FLAGS( GTK_WIDGET(cancel),
+                           GTK_CAN_DEFAULT );
     gtk_signal_connect_object( GTK_OBJECT(cancel), "clicked",
                                 G_CALLBACK(gtk_widget_destroy),
                                 GTK_OBJECT(window) );
@@ -1362,30 +1375,34 @@ void cmd_new_element_node(GtkObject *object, gpointer data)
 
     gtk_main();
 
-    g_assert(selected_repr != NULL);
-
-    if (name.text) {
+    if (selected_repr != NULL && name.text) {
+        Inkscape::XML::Document *xml_doc = current_document->getReprDoc();
         Inkscape::XML::Node *new_repr;
-        new_repr = sp_repr_new(name.text);
+        new_repr = xml_doc->createElement(name.text);
+        Inkscape::GC::release(new_repr);
         g_free(name.text);
         selected_repr->appendChild(new_repr);
         set_tree_select(new_repr);
         set_dt_select(new_repr);
+
+        DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                           _("Create new element node"));
     }
 
 } // end of cmd_new_element_node()
 
 
 
-void cmd_new_text_node(GtkObject *object, gpointer data)
+void cmd_new_text_node(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
 
-    Inkscape::XML::Node *text = sp_repr_new_text("");
+    Inkscape::XML::Document *xml_doc = current_document->getReprDoc();
+    Inkscape::XML::Node *text = xml_doc->createTextNode("");
     selected_repr->appendChild(text);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                     /* TODO: annotate */ "xml-tree.cpp:1388");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Create new text node"));
 
     set_tree_select(text);
     set_dt_select(text);
@@ -1394,16 +1411,16 @@ void cmd_new_text_node(GtkObject *object, gpointer data)
 
 }
 
-void cmd_duplicate_node(GtkObject *object, gpointer data)
+void cmd_duplicate_node(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
 
     Inkscape::XML::Node *parent = sp_repr_parent(selected_repr);
-    Inkscape::XML::Node *dup = selected_repr->duplicate();
+    Inkscape::XML::Node *dup = selected_repr->duplicate(parent->document());
     parent->addChild(dup, selected_repr);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                     /* TODO: annotate */ "xml-tree.cpp:1406");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Duplicate node"));
 
     GtkCTreeNode *node = sp_xmlview_tree_get_repr_node(SP_XMLVIEW_TREE(tree), dup);
 
@@ -1414,18 +1431,18 @@ void cmd_duplicate_node(GtkObject *object, gpointer data)
 
 
 
-void cmd_delete_node(GtkObject *object, gpointer data)
+void cmd_delete_node(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
     sp_repr_unparent(selected_repr);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                     /* TODO: annotate */ "xml-tree.cpp:1423");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       Q_("nodeAsInXMLinHistoryDialog|Delete node"));
 }
 
 
 
-void cmd_delete_attr(GtkObject *object, gpointer data)
+void cmd_delete_attr(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
     g_assert(selected_attr != 0);
@@ -1437,13 +1454,13 @@ void cmd_delete_attr(GtkObject *object, gpointer data)
         updated->updateRepr();
     }
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR, 
-                     /* TODO: annotate */ "xml-tree.cpp:1441");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Delete attribute"));
 }
 
 
 
-void cmd_set_attr(GtkObject *object, gpointer data)
+void cmd_set_attr(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
 
@@ -1455,11 +1472,7 @@ void cmd_set_attr(GtkObject *object, gpointer data)
     gchar *value = gtk_text_buffer_get_text( gtk_text_view_get_buffer(attr_value),
                                        &start, &end, TRUE );
 
-    if (!sp_repr_set_attr(selected_repr, name, value)) {
-        gchar *message = g_strdup_printf(_("Cannot set <b>%s</b>: Another element with value <b>%s</b> already exists!"), name, value);
-        _message_stack->flash(Inkscape::WARNING_MESSAGE, message);
-        g_free(message);
-    }
+    selected_repr->setAttribute(name, value, false);
 
     g_free(name);
     g_free(value);
@@ -1470,8 +1483,8 @@ void cmd_set_attr(GtkObject *object, gpointer data)
         updated->updateRepr();
     }
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                     /* TODO: annotate */ "xml-tree.cpp:1474");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Change attribute"));
 
     /* TODO: actually, the row won't have been created yet.  why? */
     gint row = sp_xmlview_attr_list_find_row_from_key(GTK_CLIST(attributes),
@@ -1483,7 +1496,7 @@ void cmd_set_attr(GtkObject *object, gpointer data)
 
 
 
-void cmd_raise_node(GtkObject *object, gpointer data)
+void cmd_raise_node(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
 
@@ -1500,8 +1513,8 @@ void cmd_raise_node(GtkObject *object, gpointer data)
 
     parent->changeOrder(selected_repr, ref);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR, 
-                     /* TODO: annotate */ "xml-tree.cpp:1504");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Raise node"));
 
     set_tree_select(selected_repr);
     set_dt_select(selected_repr);
@@ -1509,7 +1522,7 @@ void cmd_raise_node(GtkObject *object, gpointer data)
 
 
 
-void cmd_lower_node(GtkObject *object, gpointer data)
+void cmd_lower_node(GtkObject */*object*/, gpointer /*data*/)
 {
     g_assert(selected_repr != NULL);
     g_return_if_fail(selected_repr->next() != NULL);
@@ -1517,14 +1530,14 @@ void cmd_lower_node(GtkObject *object, gpointer data)
 
     parent->changeOrder(selected_repr, selected_repr->next());
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR,
-                     /* TODO: annotate */ "xml-tree.cpp:1521");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Lower node"));
 
     set_tree_select(selected_repr);
     set_dt_select(selected_repr);
 }
 
-void cmd_indent_node(GtkObject *object, gpointer data)
+void cmd_indent_node(GtkObject */*object*/, gpointer /*data*/)
 {
     Inkscape::XML::Node *repr = selected_repr;
     g_assert(repr != NULL);
@@ -1541,14 +1554,14 @@ void cmd_indent_node(GtkObject *object, gpointer data)
 
     Inkscape::XML::Node* ref = NULL;
     if (prev->firstChild()) {
-        for( ref = prev->firstChild() ; ref->next() ; ref = ref->next() );
+        for( ref = prev->firstChild() ; ref->next() ; ref = ref->next() ){};
     }
 
     parent->removeChild(repr);
     prev->addChild(repr, ref);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR, 
-                     /* TODO: annotate */ "xml-tree.cpp:1551");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Indent node"));
     set_tree_select(repr);
     set_dt_select(repr);
 
@@ -1556,7 +1569,7 @@ void cmd_indent_node(GtkObject *object, gpointer data)
 
 
 
-void cmd_unindent_node(GtkObject *object, gpointer data)
+void cmd_unindent_node(GtkObject */*object*/, gpointer /*data*/)
 {
     Inkscape::XML::Node *repr = selected_repr;
     g_assert(repr != NULL);
@@ -1568,13 +1581,38 @@ void cmd_unindent_node(GtkObject *object, gpointer data)
     parent->removeChild(repr);
     grandparent->addChild(repr, parent);
 
-    sp_document_done(current_document, SP_VERB_DIALOG_XML_EDITOR, 
-                     /* TODO: annotate */ "xml-tree.cpp:1572");
+    DocumentUndo::done(current_document, SP_VERB_DIALOG_XML_EDITOR,
+                       _("Unindent node"));
     set_tree_select(repr);
     set_dt_select(repr);
 
 } // end of cmd_unindent_node()
 
+/** Returns true iff \a item is suitable to be included in the selection, in particular
+    whether it has a bounding box in the desktop coordinate system for rendering resize handles.
+
+    Descendents of <defs> nodes (markers etc.) return false, for example.
+*/
+bool in_dt_coordsys(SPObject const &item)
+{
+    /* Definition based on sp_item_i2doc_affine. */
+    SPObject const *child = &item;
+    g_return_val_if_fail(child != NULL, false);
+    for(;;) {
+        if (!SP_IS_ITEM(child)) {
+            return false;
+        }
+        SPObject const * const parent = SP_OBJECT_PARENT(child);
+        if (parent == NULL) {
+            break;
+        }
+        child = parent;
+    }
+    g_assert(SP_IS_ROOT(child));
+    /* Relevance: Otherwise, I'm not sure whether to return true or false. */
+    return true;
+}
+
 
 /*
   Local Variables:
@@ -1585,4 +1623,4 @@ void cmd_unindent_node(GtkObject *object, gpointer data)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :