Code

Fix LPE for groups bounding box calculation by using the SPItem->getBounds method.
[inkscape.git] / src / ui / dialog / livepatheffect-editor.cpp
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     }
109 void
110 LivePathEffectEditor::showParams(LivePathEffect::Effect* effect)
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
129 void
130 LivePathEffectEditor::showText(Glib::ustring const &str)
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 ?
144 void
145 LivePathEffectEditor::set_sensitize_all(bool sensitive)
147     combo_effecttype.set_sensitive(sensitive);
148     button_apply.set_sensitive(sensitive);
149     button_remove.set_sensitive(sensitive);
152 void
153 LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
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     }
188 void 
189 LivePathEffectEditor::setDesktop(SPDesktop *desktop)
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     }
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()
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     }
261 void
262 LivePathEffectEditor::onRemove()
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     }
277 } // namespace Dialog
278 } // namespace UI
279 } // namespace Inkscape