Code

place apply horizonally
[inkscape.git] / src / ui / dialog / livepatheffect-editor.cpp
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