1 /**
2 * \brief LivePathEffect dialog
3 *
4 * Authors:
5 * Johan Engelen <j.b.c.engelen@utwente.nl>
6 *
7 * Copyright (C) 2007 Author
8 *
9 * Released under GNU GPL. Read the file 'COPYING' for more information.
10 */
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include <glibmm/i18n.h>
17 #include "livepatheffect-editor.h"
18 #include "verbs.h"
19 #include "selection.h"
20 #include "sp-shape.h"
21 #include "sp-path.h"
22 #include "live_effects/effect.h"
23 #include "live_effects/lpeobject.h"
24 #include "gtkmm/widget.h"
25 #include <vector>
26 #include "inkscape.h"
27 #include "desktop-handles.h"
28 #include "desktop.h"
29 #include "document-private.h"
30 #include "xml/node.h"
31 #include "xml/document.h"
33 namespace Inkscape {
34 class Application;
36 namespace UI {
37 namespace Dialog {
40 /*####################
41 * Callback functions
42 */
43 static void lpeeditor_selection_changed (Inkscape::Selection * selection, gpointer data)
44 {
45 LivePathEffectEditor *lpeeditor = static_cast<LivePathEffectEditor *>(data);
46 lpeeditor->onSelectionChanged(selection);
47 }
49 static void lpeeditor_selection_modified( Inkscape::Selection *selection, guint /*flags*/, gpointer data )
50 {
51 lpeeditor_selection_changed (selection, data);
52 }
55 /*#######################
56 * LivePathEffectEditor
57 */
59 LivePathEffectEditor::LivePathEffectEditor()
60 : UI::Widget::Panel("", "dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT),
61 combo_effecttype(Inkscape::LivePathEffect::LPETypeConverter),
62 button_apply(_("_Apply"), _("Apply chosen effect to selection")),
63 button_remove(_("_Remove"), _("Remove effect from selection")),
64 effectwidget(NULL),
65 explain_label("", Gtk::ALIGN_CENTER),
66 effectapplication_frame(_("Apply new effect")),
67 effectcontrol_frame(_("Current effect")),
68 current_desktop(NULL)
69 {
70 Gtk::Box *contents = _getContents();
71 contents->set_spacing(4);
73 effectapplication_hbox.set_spacing(4);
74 effectcontrol_vbox.set_spacing(4);
76 effectapplication_hbox.pack_start(combo_effecttype, true, true);
77 effectapplication_hbox.pack_start(button_apply, true, true);
78 effectapplication_frame.add(effectapplication_hbox);
80 effectcontrol_vbox.pack_start(explain_label, true, true);
81 effectcontrol_vbox.pack_end(button_remove, true, true);
82 effectcontrol_frame.add(effectcontrol_vbox);
84 contents->pack_start(effectapplication_frame, true, true);
85 contents->pack_start(effectcontrol_frame, true, true);
87 // connect callback functions to buttons
88 button_apply.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onApply));
89 button_remove.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onRemove));
91 show_all_children();
93 button_remove.hide();
94 }
96 LivePathEffectEditor::~LivePathEffectEditor()
97 {
98 if (effectwidget) {
99 effectcontrol_vbox.remove(*effectwidget);
100 effectwidget = NULL;
101 }
103 if (current_desktop) {
104 selection_changed_connection.disconnect();
105 selection_modified_connection.disconnect();
106 }
107 }
109 void
110 LivePathEffectEditor::showParams(LivePathEffect::Effect* effect)
111 {
112 if (effectwidget) {
113 effectcontrol_vbox.remove(*effectwidget);
114 effectwidget = NULL;
115 }
117 explain_label.set_markup("<b>" + effect->getName() + "</b>");
118 effectwidget = effect->getWidget();
119 if (effectwidget) {
120 effectcontrol_vbox.pack_start(*effectwidget, true, true);
121 }
122 button_remove.show();
124 effectcontrol_vbox.show_all_children();
125 // fixme: do resizing of dialog
126 }
128 void
129 LivePathEffectEditor::showText(Glib::ustring const &str)
130 {
131 if (effectwidget) {
132 effectcontrol_vbox.remove(*effectwidget);
133 effectwidget = NULL;
134 }
136 explain_label.set_label(str);
137 button_remove.hide();
139 // fixme: do resizing of dialog ?
140 }
142 void
143 LivePathEffectEditor::set_sensitize_all(bool sensitive)
144 {
145 combo_effecttype.set_sensitive(sensitive);
146 button_apply.set_sensitive(sensitive);
147 button_remove.set_sensitive(sensitive);
148 }
150 void
151 LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
152 {
153 if ( sel && !sel->isEmpty() ) {
154 SPItem *item = sel->singleItem();
155 if ( item ) {
156 if ( SP_IS_SHAPE(item) ) {
157 SPShape *shape = SP_SHAPE(item);
158 LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);
159 set_sensitize_all(true);
160 if (lpeobj) {
161 if (lpeobj->lpe) {
162 showParams(lpeobj->lpe);
163 } else {
164 showText(_("Unknown effect is applied"));
165 }
166 } else {
167 showText(_("No effect applied"));
168 button_remove.set_sensitive(false);
169 }
170 } else {
171 showText(_("Item is not a shape or path"));
172 set_sensitize_all(false);
173 }
174 } else {
175 showText(_("Only one item can be selected"));
176 set_sensitize_all(false);
177 }
178 } else {
179 showText(_("Empty selection"));
180 set_sensitize_all(false);
181 }
182 }
184 void
185 LivePathEffectEditor::setDesktop(SPDesktop *desktop)
186 {
187 Panel::setDesktop(desktop);
189 if ( desktop == current_desktop ) {
190 return;
191 }
193 if (current_desktop) {
194 selection_changed_connection.disconnect();
195 selection_modified_connection.disconnect();
196 }
198 current_desktop = desktop;
199 if (desktop) {
200 Inkscape::Selection *selection = sp_desktop_selection(desktop);
201 selection_changed_connection = selection->connectChanged(
202 sigc::bind (sigc::ptr_fun(&lpeeditor_selection_changed), this ) );
203 selection_modified_connection = selection->connectModified(
204 sigc::bind (sigc::ptr_fun(&lpeeditor_selection_modified), this ) );
206 onSelectionChanged(selection);
207 } else {
208 onSelectionChanged(NULL);
209 }
210 }
215 /*########################################################################
216 # BUTTON CLICK HANDLERS (callbacks)
217 ########################################################################*/
219 // TODO: factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it)
221 void
222 LivePathEffectEditor::onApply()
223 {
224 Inkscape::Selection *sel = _getSelection();
225 if ( sel && !sel->isEmpty() ) {
226 SPItem *item = sel->singleItem();
227 if ( item && SP_IS_SHAPE(item) ) {
228 SPDocument *doc = current_desktop->doc();
230 const Util::EnumData<LivePathEffect::EffectType>* data = combo_effecttype.get_active_data();
231 if (!data) return;
233 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
234 Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");
235 repr->setAttribute("effect", data->key.c_str() );
237 SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute
238 const gchar * repr_id = repr->attribute("id");
239 Inkscape::GC::release(repr);
241 gchar *href = g_strdup_printf("#%s", repr_id);
242 sp_shape_set_path_effect(SP_SHAPE(item), href);
243 g_free(href);
245 // make sure there is an original-d for paths!!!
246 if ( SP_IS_PATH(item) ) {
247 Inkscape::XML::Node *pathrepr = SP_OBJECT_REPR(item);
248 if ( ! pathrepr->attribute("inkscape:original-d") ) {
249 pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));
250 }
251 }
253 LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(SP_SHAPE(item));
254 if (lpeobj && lpeobj->lpe) {
255 lpeobj->lpe->resetDefaults(item);
256 }
258 sp_document_done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT,
259 _("Create and apply path effect"));
260 }
261 }
262 }
264 void
265 LivePathEffectEditor::onRemove()
266 {
267 Inkscape::Selection *sel = _getSelection();
268 if ( sel && !sel->isEmpty() ) {
269 SPItem *item = sel->singleItem();
270 if ( item && SP_IS_SHAPE(item) ) {
271 sp_shape_remove_path_effect(SP_SHAPE(item));
272 sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
273 _("Remove path effect") );
274 }
275 }
276 }
280 } // namespace Dialog
281 } // namespace UI
282 } // namespace Inkscape