/* * Specialization of GtkTextView for the XML tree view * * Authors: * MenTaLguY * * Copyright (C) 2002 MenTaLguY * Abhishek Sharma * * Released under the GNU GPL; see COPYING for details */ #include #include #include "xml/node-event-vector.h" #include "sp-xmlview-content.h" #include "desktop.h" #include "document-private.h" #include "document-undo.h" #include "inkscape.h" #include "verbs.h" using Inkscape::DocumentUndo; static void sp_xmlview_content_destroy(GtkWidget * object); void sp_xmlview_content_changed (GtkTextBuffer *tb, SPXMLViewContent *text); static void event_content_changed (Inkscape::XML::Node * repr, const gchar * old_content, const gchar * new_content, gpointer data); static Inkscape::XML::NodeEventVector repr_events = { nullptr, /* child_added */ nullptr, /* child_removed */ nullptr, /* attr_changed */ event_content_changed, nullptr /* order_changed */ }; GtkWidget *sp_xmlview_content_new(Inkscape::XML::Node * repr) { GtkTextBuffer *tb = gtk_text_buffer_new(nullptr); SPXMLViewContent *text = SP_XMLVIEW_CONTENT(g_object_new(SP_TYPE_XMLVIEW_CONTENT, nullptr)); gtk_text_view_set_buffer (GTK_TEXT_VIEW (text), tb); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text), GTK_WRAP_CHAR); g_signal_connect (G_OBJECT (tb), "changed", G_CALLBACK (sp_xmlview_content_changed), text); /* should we alter the scrolling adjustments here? */ sp_xmlview_content_set_repr (text, repr); return GTK_WIDGET(text); } void sp_xmlview_content_set_repr (SPXMLViewContent * text, Inkscape::XML::Node * repr) { if ( repr == text->repr ) return; if (text->repr) { sp_repr_remove_listener_by_data (text->repr, text); Inkscape::GC::release(text->repr); } text->repr = repr; if (repr) { Inkscape::GC::anchor(repr); sp_repr_add_listener (repr, &repr_events, text); sp_repr_synthesize_events (repr, &repr_events, text); } else { gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)), "", 0); gtk_text_view_set_editable (GTK_TEXT_VIEW (text), FALSE); } } G_DEFINE_TYPE(SPXMLViewContent, sp_xmlview_content, GTK_TYPE_TEXT_VIEW); void sp_xmlview_content_class_init(SPXMLViewContentClass * klass) { auto widget_class = GTK_WIDGET_CLASS(klass); widget_class->destroy = sp_xmlview_content_destroy; } void sp_xmlview_content_init (SPXMLViewContent *text) { text->repr = nullptr; text->blocked = FALSE; } void sp_xmlview_content_destroy(GtkWidget * object) { SPXMLViewContent * text = SP_XMLVIEW_CONTENT (object); sp_xmlview_content_set_repr (text, nullptr); GTK_WIDGET_CLASS (sp_xmlview_content_parent_class)->destroy (object); } void event_content_changed (Inkscape::XML::Node * /*repr*/, const gchar * /*old_content*/, const gchar * new_content, gpointer data) { SPXMLViewContent * text; text = SP_XMLVIEW_CONTENT (data); if (text->blocked) return; text->blocked = TRUE; if (new_content) { gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)), new_content, strlen (new_content)); } else { gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text)), "", 0); } gtk_text_view_set_editable (GTK_TEXT_VIEW (text), new_content != nullptr); text->blocked = FALSE; } void sp_xmlview_content_changed (GtkTextBuffer *tb, SPXMLViewContent *text) { if (text->blocked) return; if (text->repr) { GtkTextIter start, end; gchar *data; text->blocked = TRUE; gtk_text_buffer_get_bounds (tb, &start, &end); data = gtk_text_buffer_get_text (tb, &start, &end, TRUE); text->repr->setContent(data); g_free (data); text->blocked = FALSE; DocumentUndo::done(SP_ACTIVE_DESKTOP->getDocument(), SP_VERB_DIALOG_XML_EDITOR, _("Type text in a text node")); } }