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() \r
70 : Dialog ("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_vbox.set_spacing(4);\r
85 effectcontrol_vbox.set_spacing(4);\r
86 \r
87 effectapplication_vbox.pack_start(combo_effecttype, true, true);\r
88 effectapplication_vbox.pack_start(button_apply, true, true);\r
89 effectapplication_vbox.pack_start(button_remove, true, true);\r
90 effectapplication_frame.add(effectapplication_vbox);\r
91 \r
92 effectcontrol_vbox.pack_start(explain_label, 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 }\r
112 \r
113 LivePathEffectEditor::~LivePathEffectEditor() \r
114 {\r
115 if (effectwidget) {\r
116 effectcontrol_vbox.remove(*effectwidget);\r
117 effectwidget = NULL;\r
118 }\r
119 \r
120 if (current_desktop) {\r
121 selection_changed_connection.disconnect();\r
122 selection_modified_connection.disconnect();\r
123 }\r
124 }\r
125 \r
126 void\r
127 LivePathEffectEditor::showParams(LivePathEffect::Effect* effect)\r
128 {\r
129 if (effectwidget) {\r
130 effectcontrol_vbox.remove(*effectwidget);\r
131 effectwidget = NULL;\r
132 }\r
133 \r
134 explain_label.set_markup("<b>" + effect->getName() + "</b>");\r
135 effectwidget = effect->getWidget();\r
136 if (effectwidget) {\r
137 effectcontrol_vbox.pack_start(*effectwidget, true, true);\r
138 }\r
139 \r
140 effectcontrol_vbox.show_all_children();\r
141 // fixme: do resizing of dialog \r
142 }\r
143 \r
144 void\r
145 LivePathEffectEditor::showText(Glib::ustring const &str)\r
146 {\r
147 if (effectwidget) {\r
148 effectcontrol_vbox.remove(*effectwidget);\r
149 effectwidget = NULL;\r
150 }\r
151 \r
152 explain_label.set_label(str);\r
153 \r
154 // fixme: do resizing of dialog ?\r
155 }\r
156 \r
157 void\r
158 LivePathEffectEditor::set_sensitize_all(bool sensitive)\r
159 {\r
160 combo_effecttype.set_sensitive(sensitive);\r
161 button_apply.set_sensitive(sensitive);\r
162 button_remove.set_sensitive(sensitive);\r
163 }\r
164 \r
165 void\r
166 LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)\r
167 {\r
168 if ( sel && !sel->isEmpty() ) {\r
169 SPItem *item = sel->singleItem();\r
170 if ( item ) {\r
171 if ( SP_IS_SHAPE(item) ) {\r
172 SPShape *shape = SP_SHAPE(item);\r
173 LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);\r
174 set_sensitize_all(true);\r
175 if (lpeobj) {\r
176 if (lpeobj->lpe) {\r
177 showParams(lpeobj->lpe);\r
178 } else {\r
179 showText(_("Unknown effect is applied"));\r
180 }\r
181 } else {\r
182 showText(_("No effect applied"));\r
183 button_remove.set_sensitive(false);\r
184 }\r
185 } else {\r
186 showText(_("Item is not a shape"));\r
187 set_sensitize_all(false);\r
188 }\r
189 } else {\r
190 showText(_("Only one item can be selected"));\r
191 set_sensitize_all(false);\r
192 }\r
193 } else {\r
194 showText(_("Empty selection"));\r
195 set_sensitize_all(false);\r
196 }\r
197 }\r
198 \r
199 void \r
200 LivePathEffectEditor::setDesktop(SPDesktop *desktop)\r
201 {\r
202 \r
203 if ( desktop == current_desktop ) {\r
204 return;\r
205 }\r
206 \r
207 if (current_desktop) {\r
208 selection_changed_connection.disconnect();\r
209 selection_modified_connection.disconnect();\r
210 }\r
211 \r
212 current_desktop = desktop;\r
213 if (desktop) {\r
214 Inkscape::Selection *selection = sp_desktop_selection(desktop);\r
215 selection_changed_connection = selection->connectChanged(\r
216 sigc::bind (sigc::ptr_fun(&lpeeditor_selection_changed), this ) );\r
217 selection_modified_connection = selection->connectModified(\r
218 sigc::bind (sigc::ptr_fun(&lpeeditor_selection_modified), this ) );\r
219 \r
220 onSelectionChanged(selection);\r
221 } else {\r
222 onSelectionChanged(NULL);\r
223 }\r
224 }\r
225 \r
226 \r
227 \r
228 \r
229 /*########################################################################\r
230 # BUTTON CLICK HANDLERS (callbacks)\r
231 ########################################################################*/\r
232 \r
233 void\r
234 LivePathEffectEditor::onApply()\r
235 {\r
236 Inkscape::Selection *sel = _getSelection();\r
237 if ( sel && !sel->isEmpty() ) {\r
238 SPItem *item = sel->singleItem();\r
239 if ( item && SP_IS_SHAPE(item) ) {\r
240 SPDocument *doc = current_desktop->doc();\r
241 \r
242 const Util::EnumData<LivePathEffect::EffectType>* data = combo_effecttype.get_active_data();\r
243 if (!data) return;\r
244 \r
245 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);\r
246 Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");\r
247 repr->setAttribute("effect", data->key.c_str() );\r
248 \r
249 SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute\r
250 const gchar * repr_id = repr->attribute("id");\r
251 Inkscape::GC::release(repr);\r
252 \r
253 gchar *href = g_strdup_printf("#%s", repr_id);\r
254 sp_shape_set_path_effect(SP_SHAPE(item), href);\r
255 g_free(href);\r
256 \r
257 // make sure there is an original-d for paths!!!\r
258 if ( SP_IS_PATH(item) ) {\r
259 Inkscape::XML::Node *pathrepr = SP_OBJECT_REPR(item);\r
260 if ( ! pathrepr->attribute("inkscape:original-d") ) {\r
261 pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));\r
262 }\r
263 }\r
264 \r
265 sp_document_done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT, \r
266 _("Create and apply live effect"));\r
267 }\r
268 }\r
269 }\r
270 \r
271 void\r
272 LivePathEffectEditor::onRemove()\r
273 {\r
274 Inkscape::Selection *sel = _getSelection();\r
275 if ( sel && !sel->isEmpty() ) {\r
276 SPItem *item = sel->singleItem();\r
277 if ( item && SP_IS_SHAPE(item) ) {\r
278 sp_shape_remove_path_effect(SP_SHAPE(item));\r
279 sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, \r
280 _("Remove live path effect") );\r
281 }\r
282 }\r
283 }\r
284 \r
285 \r
286 \r
287 } // namespace Dialog\r
288 } // namespace UI\r
289 } // namespace Inkscape\r
290 \r