/** * \brief LivePathEffect dialog * * Authors: * Johan Engelen * * Copyright (C) 2007 Author * * Released under GNU GPL. Read the file 'COPYING' for more information. */ #ifdef HAVE_CONFIG_H # include #endif #include #include "livepatheffect-editor.h" #include "verbs.h" #include "selection.h" #include "sp-shape.h" #include "sp-path.h" #include "live_effects/effect.h" #include "live_effects/lpeobject.h" #include "gtkmm/widget.h" #include #include "inkscape.h" #include "desktop-handles.h" #include "desktop.h" #include "document-private.h" #include "xml/node.h" #include "xml/document.h" namespace Inkscape { class Application; namespace UI { namespace Dialog { /*#################### * Callback functions */ static void lpeeditor_selection_changed (Inkscape::Selection * selection, gpointer data) { LivePathEffectEditor *lpeeditor = static_cast(data); lpeeditor->onSelectionChanged(selection); } static void lpeeditor_selection_modified (Inkscape::Selection *selection, guint flags, gpointer data) { lpeeditor_selection_changed (selection, data); } static void lpeeditor_desktop_change(Inkscape::Application*, SPDesktop* desktop, void *data) { if (!desktop) { return; } LivePathEffectEditor* editor = reinterpret_cast(data); editor->setDesktop(desktop); } /*####################### * LivePathEffectEditor */ LivePathEffectEditor::LivePathEffectEditor(Behavior::BehaviorFactory behavior_factory) : Dialog (behavior_factory, "dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT), combo_effecttype(Inkscape::LivePathEffect::LPETypeConverter), button_apply(_("_Apply"), _("Apply chosen effect to selection")), button_remove(_("_Remove"), _("Remove effect from selection")), effectwidget(NULL), explain_label("", Gtk::ALIGN_CENTER), effectapplication_frame(_("Apply new effect")), effectcontrol_frame(_("Current effect")), current_desktop(NULL) { // Top level vbox Gtk::VBox *vbox = get_vbox(); vbox->set_spacing(4); effectapplication_hbox.set_spacing(4); effectcontrol_vbox.set_spacing(4); effectapplication_hbox.pack_start(combo_effecttype, true, true); effectapplication_hbox.pack_start(button_apply, true, true); effectapplication_frame.add(effectapplication_hbox); effectcontrol_vbox.pack_start(explain_label, true, true); effectcontrol_vbox.pack_end(button_remove, true, true); effectcontrol_frame.add(effectcontrol_vbox); vbox->pack_start(effectapplication_frame, true, true); vbox->pack_start(effectcontrol_frame, true, true); // connect callback functions to buttons button_apply.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onApply)); button_remove.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onRemove)); // connect callback functions to changes in selected desktop. g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(lpeeditor_desktop_change), this); g_signal_connect( G_OBJECT(INKSCAPE), "deactivate_desktop", G_CALLBACK(lpeeditor_desktop_change), this); setDesktop(SP_ACTIVE_DESKTOP); show_all_children(); button_remove.hide(); } LivePathEffectEditor::~LivePathEffectEditor() { if (effectwidget) { effectcontrol_vbox.remove(*effectwidget); effectwidget = NULL; } if (current_desktop) { selection_changed_connection.disconnect(); selection_modified_connection.disconnect(); } } void LivePathEffectEditor::showParams(LivePathEffect::Effect* effect) { if (effectwidget) { effectcontrol_vbox.remove(*effectwidget); effectwidget = NULL; } explain_label.set_markup("" + effect->getName() + ""); effectwidget = effect->getWidget(); if (effectwidget) { effectcontrol_vbox.pack_start(*effectwidget, true, true); } button_remove.show(); effectcontrol_vbox.show_all_children(); // fixme: do resizing of dialog } void LivePathEffectEditor::showText(Glib::ustring const &str) { if (effectwidget) { effectcontrol_vbox.remove(*effectwidget); effectwidget = NULL; } explain_label.set_label(str); button_remove.hide(); // fixme: do resizing of dialog ? } void LivePathEffectEditor::set_sensitize_all(bool sensitive) { combo_effecttype.set_sensitive(sensitive); button_apply.set_sensitive(sensitive); button_remove.set_sensitive(sensitive); } void LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) { if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if ( item ) { if ( SP_IS_SHAPE(item) ) { SPShape *shape = SP_SHAPE(item); LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape); set_sensitize_all(true); if (lpeobj) { if (lpeobj->lpe) { showParams(lpeobj->lpe); } else { showText(_("Unknown effect is applied")); } } else { showText(_("No effect applied")); button_remove.set_sensitive(false); } } else { showText(_("Item is not a shape or path")); set_sensitize_all(false); } } else { showText(_("Only one item can be selected")); set_sensitize_all(false); } } else { showText(_("Empty selection")); set_sensitize_all(false); } } void LivePathEffectEditor::setDesktop(SPDesktop *desktop) { if ( desktop == current_desktop ) { return; } if (current_desktop) { selection_changed_connection.disconnect(); selection_modified_connection.disconnect(); } current_desktop = desktop; if (desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); selection_changed_connection = selection->connectChanged( sigc::bind (sigc::ptr_fun(&lpeeditor_selection_changed), this ) ); selection_modified_connection = selection->connectModified( sigc::bind (sigc::ptr_fun(&lpeeditor_selection_modified), this ) ); onSelectionChanged(selection); } else { onSelectionChanged(NULL); } } /*######################################################################## # BUTTON CLICK HANDLERS (callbacks) ########################################################################*/ // TODO: factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it) void LivePathEffectEditor::onApply() { Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if ( item && SP_IS_SHAPE(item) ) { SPDocument *doc = current_desktop->doc(); const Util::EnumData* data = combo_effecttype.get_active_data(); if (!data) return; Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect"); repr->setAttribute("effect", data->key.c_str() ); SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to and assigns the 'id' attribute const gchar * repr_id = repr->attribute("id"); Inkscape::GC::release(repr); gchar *href = g_strdup_printf("#%s", repr_id); sp_shape_set_path_effect(SP_SHAPE(item), href); g_free(href); // make sure there is an original-d for paths!!! if ( SP_IS_PATH(item) ) { Inkscape::XML::Node *pathrepr = SP_OBJECT_REPR(item); if ( ! pathrepr->attribute("inkscape:original-d") ) { pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d")); } } sp_document_done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Create and apply path effect")); } } } void LivePathEffectEditor::onRemove() { Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if ( item && SP_IS_SHAPE(item) ) { sp_shape_remove_path_effect(SP_SHAPE(item)); sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Remove path effect") ); } } } } // namespace Dialog } // namespace UI } // namespace Inkscape