From: JucaBlues Date: Thu, 15 Jan 2009 18:01:02 +0000 (+0000) Subject: adding a "scripting" tab to document properties dialog that allow the user to manage... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=79c85082c597f5473d1bec6000cef677e87dae6e;p=inkscape.git adding a "scripting" tab to document properties dialog that allow the user to manage external javascript references. (also only working for "Inkscape SVG") --- diff --git a/src/sp-script.cpp b/src/sp-script.cpp index 2b855e455..a40132450 100644 --- a/src/sp-script.cpp +++ b/src/sp-script.cpp @@ -12,6 +12,9 @@ */ #include "sp-script.h" +#include "attributes.h" +#include +#include "document.h" static void sp_script_class_init(SPScriptClass *sc); static void sp_script_init(SPScript *script); @@ -19,6 +22,8 @@ static void sp_script_init(SPScript *script); static void sp_script_release(SPObject *object); static void sp_script_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_script_modified(SPObject *object, guint flags); +static void sp_script_set(SPObject *object, unsigned int key, gchar const *value); +static void sp_script_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static Inkscape::XML::Node *sp_script_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static SPObjectClass *parent_class; @@ -51,10 +56,12 @@ static void sp_script_class_init(SPScriptClass *sc) parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT); SPObjectClass *sp_object_class = (SPObjectClass *) sc; + sp_object_class->build = sp_script_build; sp_object_class->release = sp_script_release; sp_object_class->update = sp_script_update; sp_object_class->modified = sp_script_modified; sp_object_class->write = sp_script_write; + sp_object_class->set = sp_script_set; } static void sp_script_init(SPScript */*script*/) @@ -62,11 +69,34 @@ static void sp_script_init(SPScript */*script*/) } + +/** + * Reads the Inkscape::XML::Node, and initializes SPScript variables. For this to get called, + * our name must be associated with a repr via "sp_object_type_register". Best done through + * sp-object-repr.cpp's repr_name_entries array. + */ +static void +sp_script_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) +{ + if (((SPObjectClass *) parent_class)->build) { + ((SPObjectClass *) parent_class)->build(object, document, repr); + } + + //Read values of key attributes from XML nodes into object. + sp_object_read_attr(object, "xlink:href"); + + sp_document_add_resource(document, "script", object); +} + static void sp_script_release(SPObject *object) { - if (((SPObjectClass *) (parent_class))->release) { - ((SPObjectClass *) (parent_class))->release(object); + if (SP_OBJECT_DOCUMENT(object)) { + /* Unregister ourselves */ + sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "script", SP_OBJECT(object)); } + + if (((SPObjectClass *) parent_class)->release) + ((SPObjectClass *) parent_class)->release(object); } static void sp_script_update(SPObject */*object*/, SPCtx */*ctx*/, guint /*flags*/) @@ -77,6 +107,24 @@ static void sp_script_modified(SPObject */*object*/, guint /*flags*/) { } +static void +sp_script_set(SPObject *object, unsigned int key, gchar const *value) +{ + SPScript *scr = SP_SCRIPT(object); + + switch (key) { + case SP_ATTR_XLINK_HREF: + if (scr->xlinkhref) g_free(scr->xlinkhref); + scr->xlinkhref = g_strdup(value); + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + default: + if (((SPObjectClass *) parent_class)->set) + ((SPObjectClass *) parent_class)->set(object, key, value); + break; + } +} + static Inkscape::XML::Node *sp_script_write(SPObject */*object*/, Inkscape::XML::Document */*xml_doc*/, Inkscape::XML::Node *repr, guint /*flags*/) { /* diff --git a/src/sp-script.h b/src/sp-script.h index 8a48f9b92..fa1906052 100644 --- a/src/sp-script.h +++ b/src/sp-script.h @@ -23,6 +23,7 @@ /* SPScript */ struct SPScript : public SPObject { + gchar *xlinkhref; }; struct SPScriptClass { diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 277652596..b2b3d1e81 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -32,6 +32,7 @@ #include "sp-namedview.h" #include "sp-object-repr.h" #include "sp-root.h" +#include "sp-script.h" #include "ui/widget/color-picker.h" #include "ui/widget/scalar-unit.h" #include "verbs.h" @@ -87,7 +88,7 @@ DocumentProperties::getInstance() DocumentProperties::DocumentProperties() : UI::Widget::Panel ("", "/dialogs/documentoptions", SP_VERB_DIALOG_NAMEDVIEW), _page_page(1, 1, true, true), _page_guides(1, 1), - _page_snap(1, 1), _page_snap_dtls(1, 1), _page_cms(1, 1), + _page_snap(1, 1), _page_snap_dtls(1, 1), _page_cms(1, 1), _page_scripting(1, 1), //--------------------------------------------------------------- _rcb_canb(_("Show page _border"), _("If set, rectangular page border is shown"), "showborder", _wr, false), _rcb_bord(_("Border on _top of drawing"), _("If set, border is always on top of the drawing"), "borderlayer", _wr, false), @@ -141,6 +142,7 @@ DocumentProperties::DocumentProperties() _notebook.append_page(_page_snap, _("Snap")); _notebook.append_page(_page_snap_dtls, _("Snap points")); _notebook.append_page(_page_cms, _("Color Management")); + _notebook.append_page(_page_scripting, _("Scripting")); build_page(); build_guides(); @@ -150,6 +152,7 @@ DocumentProperties::DocumentProperties() #if ENABLE_LCMS build_cms(); #endif // ENABLE_LCMS + build_scripting(); _grids_button_new.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onNewGrid)); _grids_button_remove.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onRemoveGrid)); @@ -511,6 +514,13 @@ DocumentProperties::populate_linked_profiles_box() } } +void DocumentProperties::external_scripts_list_button_release(GdkEventButton* event) +{ + if((event->type == GDK_BUTTON_RELEASE) && (event->button == 3)) { + _ExternalScriptsContextMenu.popup(event->button, event->time); + } +} + void DocumentProperties::linked_profiles_list_button_release(GdkEventButton* event) { if((event->type == GDK_BUTTON_RELEASE) && (event->button == 3)) { @@ -518,7 +528,7 @@ void DocumentProperties::linked_profiles_list_button_release(GdkEventButton* eve } } -void DocumentProperties::create_popup_menu(Gtk::Widget& parent, sigc::slot rem) +void DocumentProperties::cms_create_popup_menu(Gtk::Widget& parent, sigc::slot rem) { Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE)); _EmbProfContextMenu.append(*mi); @@ -527,6 +537,16 @@ void DocumentProperties::create_popup_menu(Gtk::Widget& parent, sigc::slot _EmbProfContextMenu.accelerate(parent); } + +void DocumentProperties::scripting_create_popup_menu(Gtk::Widget& parent, sigc::slot rem) +{ + Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE)); + _ExternalScriptsContextMenu.append(*mi); + mi->signal_activate().connect(rem); + mi->show(); + _ExternalScriptsContextMenu.accelerate(parent); +} + void DocumentProperties::removeSelectedProfile(){ Glib::ustring name; if(_LinkedProfilesList.get_selection()) { @@ -609,7 +629,7 @@ DocumentProperties::build_cms() _link_btn.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::linkSelectedProfile)); _LinkedProfilesList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::linked_profiles_list_button_release)); - create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile)); + cms_create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile)); const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "defs" ); if (current) { @@ -619,6 +639,121 @@ DocumentProperties::build_cms() } #endif // ENABLE_LCMS +void +DocumentProperties::build_scripting() +{ + _page_scripting.show(); + + Gtk::Label *label_script= manage (new Gtk::Label("", Gtk::ALIGN_LEFT)); + label_script->set_markup (_("External script files:")); + + _add_btn.set_label(_("Add")); + + _page_scripting.set_spacing(4); + gint row = 0; + + label_script->set_alignment(0.0); + _page_scripting.table().attach(*label_script, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + row++; + _page_scripting.table().attach(_ExternalScriptsListScroller, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + row++; + + Gtk::HBox* spacer = Gtk::manage(new Gtk::HBox()); + spacer->set_size_request(SPACE_SIZE_X, SPACE_SIZE_Y); + _page_scripting.table().attach(*spacer, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + row++; + + _page_scripting.table().attach(_script_entry, 0, 2, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + _page_scripting.table().attach(_add_btn, 2, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0); + row++; + + //# Set up the External Scripts box + _ExternalScriptsListStore = Gtk::ListStore::create(_ExternalScriptsListColumns); + _ExternalScriptsList.set_model(_ExternalScriptsListStore); + _ExternalScriptsList.append_column(_("Filename"), _ExternalScriptsListColumns.filenameColumn); + _ExternalScriptsList.set_headers_visible(true); +// TODO restore? _ExternalScriptsList.set_fixed_height_mode(true); + + populate_external_scripts_box(); + + _ExternalScriptsListScroller.add(_ExternalScriptsList); + _ExternalScriptsListScroller.set_shadow_type(Gtk::SHADOW_IN); + _ExternalScriptsListScroller.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS); + _ExternalScriptsListScroller.set_size_request(-1, 90); + + _add_btn.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::addExternalScript)); + + _ExternalScriptsList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::external_scripts_list_button_release)); + scripting_create_popup_menu(_ExternalScriptsList, sigc::mem_fun(*this, &DocumentProperties::removeExternalScript)); + +//TODO: review this observers code: + const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" ); + if (current) { + _ext_scripts_observer.set(SP_OBJECT(current->data)->parent); + } + _ext_scripts_observer.signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::populate_external_scripts_box)); +} + + +void DocumentProperties::addExternalScript(){ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop){ + g_warning("No active desktop"); + } else { + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc()); + Inkscape::XML::Node *scriptRepr = xml_doc->createElement("svg:script"); + scriptRepr->setAttribute("xlink:href", (gchar*) _script_entry.get_text().c_str()); + _script_entry.set_text(""); + + xml_doc->root()->addChild(scriptRepr, NULL); + + // inform the document, so we can undo + sp_document_done(desktop->doc(), SP_VERB_EDIT_ADD_EXTERNAL_SCRIPT, _("Add external script...")); + + populate_external_scripts_box(); + } +} + +void DocumentProperties::removeExternalScript(){ + Glib::ustring name; + if(_ExternalScriptsList.get_selection()) { + Gtk::TreeModel::iterator i = _ExternalScriptsList.get_selection()->get_selected(); + + if(i){ + name = (*i)[_ExternalScriptsListColumns.filenameColumn]; + } else { + return; + } + } + + const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" ); + while ( current ) { + SPObject* obj = SP_OBJECT(current->data); + SPScript* script = (SPScript*) obj; + if (!name.compare(script->xlinkhref)){ + sp_repr_unparent(obj->repr); + sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EXTERNAL_SCRIPT, _("Remove external script")); + } + current = g_slist_next(current); + } + + populate_external_scripts_box(); + +} + +void DocumentProperties::populate_external_scripts_box(){ + _ExternalScriptsListStore->clear(); + const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" ); + if (current) _ext_scripts_observer.set(SP_OBJECT(current->data)->parent); + while ( current ) { + SPObject* obj = SP_OBJECT(current->data); + SPScript* script = (SPScript*) obj; + Gtk::TreeModel::Row row = *(_ExternalScriptsListStore->append()); + row[_ExternalScriptsListColumns.filenameColumn] = script->xlinkhref; + current = g_slist_next(current); + } +} + /** * Called for _updating_ the dialog (e.g. when a new grid was manually added in XML) */ diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index f4d5724be..df16edca7 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -52,6 +52,7 @@ protected: #if ENABLE_LCMS void build_cms(); #endif // ENABLE_LCMS + void build_scripting(); void init(); virtual void on_response (int); @@ -61,19 +62,25 @@ protected: void linkSelectedProfile(); void removeSelectedProfile(); void linked_profiles_list_button_release(GdkEventButton* event); - void create_popup_menu(Gtk::Widget& parent, sigc::slot rem); + void cms_create_popup_menu(Gtk::Widget& parent, sigc::slot rem); #endif // ENABLE_LCMS + void external_scripts_list_button_release(GdkEventButton* event); + void populate_external_scripts_box(); + void addExternalScript(); + void removeExternalScript(); + void scripting_create_popup_menu(Gtk::Widget& parent, sigc::slot rem); + void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document); void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop); void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop); - Inkscape::XML::SignalObserver _emb_profiles_observer; + Inkscape::XML::SignalObserver _emb_profiles_observer, _ext_scripts_observer; Gtk::Tooltips _tt; Gtk::Notebook _notebook; NotebookPage _page_page, _page_guides; - NotebookPage _page_snap, _page_snap_dtls, _page_cms; + NotebookPage _page_snap, _page_snap_dtls, _page_cms, _page_scripting; Gtk::VBox _grids_vbox; Registry _wr; @@ -109,7 +116,24 @@ protected: Gtk::TreeView _LinkedProfilesList; Gtk::ScrolledWindow _LinkedProfilesListScroller; Gtk::Menu _EmbProfContextMenu; + //--------------------------------------------------------------- + Gtk::Button _add_btn; + class ExternalScriptsColumns : public Gtk::TreeModel::ColumnRecord + { + public: + ExternalScriptsColumns() + { add(filenameColumn); } + Gtk::TreeModelColumn filenameColumn; + }; + ExternalScriptsColumns _ExternalScriptsListColumns; + Glib::RefPtr _ExternalScriptsListStore; + Gtk::TreeView _ExternalScriptsList; + Gtk::ScrolledWindow _ExternalScriptsListScroller; + Gtk::Menu _ExternalScriptsContextMenu; + Gtk::Entry _script_entry; + //--------------------------------------------------------------- + Gtk::Notebook _grids_notebook; Gtk::HBox _grids_hbox_crea; Gtk::Label _grids_label_crea; diff --git a/src/verbs.h b/src/verbs.h index 28812dde6..7798f6364 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -274,6 +274,9 @@ enum { /* Color management */ SP_VERB_EDIT_LINK_COLOR_PROFILE, SP_VERB_EDIT_REMOVE_COLOR_PROFILE, + /*Scripting*/ + SP_VERB_EDIT_ADD_EXTERNAL_SCRIPT, + SP_VERB_EDIT_REMOVE_EXTERNAL_SCRIPT, /* Footer */ SP_VERB_LAST };