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