1 /**
2 * \brief LivePathEffect dialog
3 *
4 * Authors:
5 * Johan Engelen <j.b.c.engelen@utwente.nl>
6 * Steren Giannini <steren.giannini@gmail.com>
7 * Bastien Bouclet <bgkweb@gmail.com>
8 *
9 * Copyright (C) 2007 Author
10 *
11 * Released under GNU GPL. Read the file 'COPYING' for more information.
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include <glibmm/i18n.h>
19 #include "livepatheffect-editor.h"
20 #include "verbs.h"
21 #include "selection.h"
22 #include "sp-shape.h"
23 #include "sp-item-group.h"
24 #include "sp-path.h"
25 #include "sp-rect.h"
26 #include "path-chemistry.h"
27 #include "live_effects/effect.h"
28 #include "live_effects/lpeobject.h"
29 #include "gtkmm/widget.h"
30 #include <vector>
31 #include "inkscape.h"
32 #include "desktop-handles.h"
33 #include "desktop.h"
34 #include "document-private.h"
35 #include "xml/node.h"
36 #include "xml/document.h"
38 namespace Inkscape {
39 class Application;
41 namespace UI {
42 namespace Dialog {
45 /*####################
46 * Callback functions
47 */
48 static void lpeeditor_selection_changed (Inkscape::Selection * selection, gpointer data)
49 {
50 LivePathEffectEditor *lpeeditor = static_cast<LivePathEffectEditor *>(data);
51 lpeeditor->onSelectionChanged(selection);
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, false, false);
85 contents->pack_start(effectcontrol_frame, false, false);
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 delete effectwidget;
101 effectwidget = NULL;
102 }
104 if (current_desktop) {
105 selection_changed_connection.disconnect();
106 }
107 }
109 void
110 LivePathEffectEditor::showParams(LivePathEffect::Effect* effect)
111 {
112 if (effectwidget) {
113 effectcontrol_vbox.remove(*effectwidget);
114 delete effectwidget;
115 effectwidget = NULL;
116 }
118 explain_label.set_markup("<b>" + effect->getName() + "</b>");
119 effectwidget = effect->newWidget(&tooltips);
120 if (effectwidget) {
121 effectcontrol_vbox.pack_start(*effectwidget, true, true);
122 }
123 button_remove.show();
125 effectcontrol_vbox.show_all_children();
126 // fixme: add resizing of dialog
127 }
129 void
130 LivePathEffectEditor::showText(Glib::ustring const &str)
131 {
132 if (effectwidget) {
133 effectcontrol_vbox.remove(*effectwidget);
134 delete effectwidget;
135 effectwidget = NULL;
136 }
138 explain_label.set_label(str);
139 button_remove.hide();
141 // fixme: do resizing of dialog ?
142 }
144 void
145 LivePathEffectEditor::set_sensitize_all(bool sensitive)
146 {
147 combo_effecttype.set_sensitive(sensitive);
148 button_apply.set_sensitive(sensitive);
149 button_remove.set_sensitive(sensitive);
150 }
152 void
153 LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
154 {
155 if ( sel && !sel->isEmpty() ) {
156 SPItem *item = sel->singleItem();
157 if ( item ) {
158 if ( SP_IS_LPE_ITEM(item) ) {
159 SPLPEItem *lpeitem = SP_LPE_ITEM(item);
160 LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
161 set_sensitize_all(true);
162 if (lpeobj) {
163 if (lpeobj->lpe) {
164 showParams(lpeobj->lpe);
165 } else {
166 showText(_("Unknown effect is applied"));
167 }
168 } else {
169 showText(_("No effect applied"));
170 button_remove.set_sensitive(false);
171 }
172 }
173 else
174 {
175 showText(_("Item is not compound by paths"));
176 set_sensitize_all(false);
177 }
178 } else {
179 showText(_("Only one item can be selected"));
180 set_sensitize_all(false);
181 }
182 } else {
183 showText(_("Empty selection"));
184 set_sensitize_all(false);
185 }
186 }
188 void
189 LivePathEffectEditor::setDesktop(SPDesktop *desktop)
190 {
191 Panel::setDesktop(desktop);
193 if ( desktop == current_desktop ) {
194 return;
195 }
197 if (current_desktop) {
198 selection_changed_connection.disconnect();
199 }
201 current_desktop = desktop;
202 if (desktop) {
203 Inkscape::Selection *selection = sp_desktop_selection(desktop);
204 selection_changed_connection = selection->connectChanged(
205 sigc::bind (sigc::ptr_fun(&lpeeditor_selection_changed), this ) );
207 onSelectionChanged(selection);
208 } else {
209 onSelectionChanged(NULL);
210 }
211 }
216 /*########################################################################
217 # BUTTON CLICK HANDLERS (callbacks)
218 ########################################################################*/
220 // TODO: factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it)
222 void
223 LivePathEffectEditor::onApply()
224 {
225 Inkscape::Selection *sel = _getSelection();
226 if ( sel && !sel->isEmpty() ) {
227 SPItem *item = sel->singleItem();
228 if ( item && SP_IS_LPE_ITEM(item) ) {
229 SPDocument *doc = current_desktop->doc();
231 const Util::EnumData<LivePathEffect::EffectType>* data = combo_effecttype.get_active_data();
232 if (!data) return;
234 // If item is a SPRect, convert it to path first:
235 if ( SP_IS_RECT(item) ) {
236 sp_selected_path_to_curves(false);
237 item = sel->singleItem(); // get new item
238 }
240 // Path effect definition
241 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
242 Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");
243 repr->setAttribute("effect", data->key.c_str() );
245 SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute
246 const gchar * repr_id = repr->attribute("id");
247 Inkscape::GC::release(repr);
249 gchar *href = g_strdup_printf("#%s", repr_id);
250 sp_lpe_item_set_path_effect(SP_LPE_ITEM(item), href, true);
251 g_free(href);
253 sp_document_done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT,
254 _("Create and apply path effect"));
256 onSelectionChanged(sel);
257 }
258 }
259 }
261 void
262 LivePathEffectEditor::onRemove()
263 {
264 Inkscape::Selection *sel = _getSelection();
265 if ( sel && !sel->isEmpty() ) {
266 SPItem *item = sel->singleItem();
267 if ( item && SP_IS_LPE_ITEM(item) ) {
268 sp_lpe_item_remove_path_effect(SP_LPE_ITEM(item), false);
269 showText(_("No effect applied"));
270 button_remove.set_sensitive(false);
271 sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
272 _("Remove path effect") );
273 }
274 }
275 }
277 } // namespace Dialog
278 } // namespace UI
279 } // namespace Inkscape