Code

Committing fixed patch for autosave. Fixes bug #171092.
[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 "sp-lpe-item.h"
27 #include "path-chemistry.h"
28 #include "live_effects/effect.h"
29 #include "live_effects/lpeobject.h"
30 #include "gtkmm/widget.h"
31 #include <vector>
32 #include "inkscape.h"
33 #include "desktop-handles.h"
34 #include "desktop.h"
35 #include "document.h"
36 #include "xml/node.h"
37 #include <gtkmm/stock.h>
38 #include <gtkmm/toolbar.h>
40 #include "live_effects/lpeobject-reference.h"
42 namespace Inkscape {
43 class Application;
45 namespace UI {
46 namespace Dialog {
49 /*####################
50  * Callback functions
51  */
52 static void lpeeditor_selection_changed (Inkscape::Selection * selection, gpointer data)
53 {
54     LivePathEffectEditor *lpeeditor = static_cast<LivePathEffectEditor *>(data);
55     lpeeditor->onSelectionChanged(selection);
56 }
58 static void lpeeditor_selection_modified (Inkscape::Selection * selection, guint /*flags*/, gpointer data)
59 {
60     LivePathEffectEditor *lpeeditor = static_cast<LivePathEffectEditor *>(data);
61     lpeeditor->onSelectionChanged(selection);
62 }
65 /*#######################
66  * LivePathEffectEditor
67  */
69 LivePathEffectEditor::LivePathEffectEditor() 
70     : UI::Widget::Panel("", "dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT),
71       combo_effecttype(Inkscape::LivePathEffect::LPETypeConverter),
72       effectwidget(NULL),
73       explain_label("", Gtk::ALIGN_CENTER),
74       effectapplication_frame(_("Apply new effect")),
75       effectcontrol_frame(_("Current effect")),
76       effectlist_frame(_("Effect list")),
77       button_up(Gtk::Stock::GO_UP),
78       button_down(Gtk::Stock::GO_DOWN),
79       button_apply(Gtk::Stock::ADD),
80       button_remove(Gtk::Stock::REMOVE),
81       current_desktop(NULL),
82       current_lpeitem(NULL)
83 {
84     Gtk::Box *contents = _getContents();
85     contents->set_spacing(4);
87     //Add the TreeView, inside a ScrolledWindow, with the button underneath:
88     scrolled_window.add(effectlist_view);
89     //Only show the scrollbars when they are necessary:
90     scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
92     effectapplication_hbox.set_spacing(4);
93     effectcontrol_vbox.set_spacing(4);
94     effectlist_vbox.set_spacing(4);
96     effectapplication_hbox.pack_start(combo_effecttype, true, true);
97     effectapplication_hbox.pack_start(button_apply, true, true);
98     effectapplication_frame.add(effectapplication_hbox);
100     effectlist_vbox.pack_start(scrolled_window, Gtk::PACK_EXPAND_WIDGET);
101     effectlist_vbox.pack_end(toolbar, Gtk::PACK_SHRINK);
102    // effectlist_vbox.pack_end(button_hbox, Gtk::PACK_SHRINK);
103     effectlist_frame.add(effectlist_vbox);
105     effectcontrol_vbox.pack_start(explain_label, true, true);
106     effectcontrol_frame.add(effectcontrol_vbox);
108  //   button_hbox.pack_start(button_up, true, true);
109  //   button_hbox.pack_start(button_down, true, true);
110  //   button_hbox.pack_end(button_remove, true, true);
111         toolbar.set_toolbar_style(Gtk::TOOLBAR_ICONS);  
112  // Add toolbar items to toolbar
113   toolbar.append(button_up);
114   toolbar.append(button_down);
115   toolbar.append(button_remove);
117   
118   // Add toolbar
119   //add_toolbar(toolbar);
120   toolbar.show_all(); //Show the toolbar and all its child widgets.
122       
123     //Create the Tree model:
124     effectlist_store = Gtk::ListStore::create(columns);
125     effectlist_view.set_model(effectlist_store);
127     effectlist_view.set_rules_hint();
128     effectlist_view.set_headers_clickable(true);
129     effectlist_view.set_headers_visible(true);
131     // Handle tree selections
132     effectlist_selection = effectlist_view.get_selection();
133     effectlist_selection->signal_changed().connect( sigc::mem_fun(*this, &LivePathEffectEditor::on_effect_selection_changed) );
135     effectlist_view.set_headers_visible(false);
136     //Add the TreeView's view columns:
137     effectlist_view.append_column("Effect", columns.col_name);
140     contents->pack_start(effectapplication_frame, false, false);
141     contents->pack_start(effectlist_frame, true, true);
142     contents->pack_start(effectcontrol_frame, false, false);
144     // connect callback functions to buttons
145     button_apply.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onApply));
146     button_remove.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onRemove));
148     button_up.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onUp));
149     button_down.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onDown));
151     show_all_children();
153     //button_remove.hide();
156 LivePathEffectEditor::~LivePathEffectEditor() 
158     if (effectwidget) {
159         effectcontrol_vbox.remove(*effectwidget);
160         delete effectwidget;
161         effectwidget = NULL;
162     }
164     if (current_desktop) {
165         selection_changed_connection.disconnect();
166         selection_modified_connection.disconnect();
167     }
170 void
171 LivePathEffectEditor::showParams(LivePathEffect::Effect* effect)
173     if (effectwidget) {
174         effectcontrol_vbox.remove(*effectwidget);
175         delete effectwidget;
176         effectwidget = NULL;
177     }
179     explain_label.set_markup("<b>" + effect->getName() + "</b>");
180     effectwidget = effect->newWidget(&tooltips);
181     if (effectwidget) {
182         effectcontrol_vbox.pack_start(*effectwidget, true, true);
183     }
184     button_remove.show();
186     effectcontrol_vbox.show_all_children();
187     // fixme: add resizing of dialog
190 void
191 LivePathEffectEditor::showText(Glib::ustring const &str)
193     if (effectwidget) {
194         effectcontrol_vbox.remove(*effectwidget);
195         delete effectwidget;
196         effectwidget = NULL;
197     }
199     explain_label.set_label(str);
200     //button_remove.hide();
202     // fixme: do resizing of dialog ?
205 void
206 LivePathEffectEditor::set_sensitize_all(bool sensitive)
208     combo_effecttype.set_sensitive(sensitive);
209     button_apply.set_sensitive(sensitive);
210     button_remove.set_sensitive(sensitive);
211     effectlist_view.set_sensitive(sensitive);
212     button_up.set_sensitive(sensitive);
213     button_down.set_sensitive(sensitive);
217 void
218 LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
220     effectlist_store->clear();
221     current_lpeitem = NULL;
223     if ( sel && !sel->isEmpty() ) {
224         SPItem *item = sel->singleItem();
225         if ( item ) {
226             if ( SP_IS_LPE_ITEM(item) ) {
227                 SPLPEItem *lpeitem = SP_LPE_ITEM(item);
229                 effect_list_update(lpeitem);
231                 current_lpeitem = lpeitem;
232                 
233                 set_sensitize_all(true);
234                 if ( sp_lpe_item_has_path_effect(lpeitem) ) {
235                     Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(lpeitem);
236                     if (lpe) {
237                         showParams(lpe);
238                     } else {
239                         showText(_("Unknown effect is applied"));
240                     }
241                 } else {
242                     showText(_("No effect applied"));
243                     button_remove.set_sensitive(false);
244                 }
245             }
246               else
247             {
248                 showText(_("Item is not a path or shape"));
249                 set_sensitize_all(false);
250             }
251         } else {
252             showText(_("Only one item can be selected"));
253             set_sensitize_all(false);
254         }
255     } else {
256         showText(_("Empty selection"));
257         set_sensitize_all(false);
258     }
261 void
262 LivePathEffectEditor::effect_list_update(SPLPEItem *lpeitem)
264     effectlist_store->clear();
265     
266     PathEffectList effectlist = sp_lpe_item_get_effect_list(lpeitem);
267     PathEffectList::iterator it;
268     for( it = effectlist.begin() ; it!=effectlist.end(); it++ )
269     {
270          Gtk::TreeModel::Row row = *(effectlist_store->append());
271          row[columns.col_name] = (*it)->lpeobject->lpe->getName();
272          row[columns.lperef] = *it;
273     }
277 void 
278 LivePathEffectEditor::setDesktop(SPDesktop *desktop)
280     Panel::setDesktop(desktop);
282     if ( desktop == current_desktop ) {
283         return;
284     }
286     if (current_desktop) {
287         selection_changed_connection.disconnect();
288         selection_modified_connection.disconnect();
289     }
291     current_desktop = desktop;
292     if (desktop) {
293         Inkscape::Selection *selection = sp_desktop_selection(desktop);
294         selection_changed_connection = selection->connectChanged(
295             sigc::bind (sigc::ptr_fun(&lpeeditor_selection_changed), this ) );
296         selection_modified_connection = selection->connectModified(
297             sigc::bind (sigc::ptr_fun(&lpeeditor_selection_modified), this ) );
299         onSelectionChanged(selection);
300     } else {
301         onSelectionChanged(NULL);
302     }
308 /*########################################################################
309 # BUTTON CLICK HANDLERS    (callbacks)
310 ########################################################################*/
312 // TODO:  factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it)
314 void
315 LivePathEffectEditor::onApply()
317     Inkscape::Selection *sel = _getSelection();
318     if ( sel && !sel->isEmpty() ) {
319         SPItem *item = sel->singleItem();
320         if ( item && SP_IS_LPE_ITEM(item) ) {
321             SPDocument *doc = current_desktop->doc();
323             const Util::EnumData<LivePathEffect::EffectType>* data = combo_effecttype.get_active_data();
324             if (!data) return;
326             // If item is a SPRect, convert it to path first:
327             if ( SP_IS_RECT(item) ) {
328                 sp_selected_path_to_curves(false);
329                 item = sel->singleItem(); // get new item
330             }
332             LivePathEffect::Effect::createAndApply(data->key.c_str(), doc, item);
334             onSelectionChanged(sel);
335         }
336     }
339 void
340 LivePathEffectEditor::onRemove()
342     Inkscape::Selection *sel = _getSelection();
343     if ( sel && !sel->isEmpty() ) {
344         SPItem *item = sel->singleItem();
345         if ( item && SP_IS_LPE_ITEM(item) ) {
346             sp_lpe_item_remove_current_path_effect(SP_LPE_ITEM(item), false);
347             
348             sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, 
349                                _("Remove path effect") );
351             effect_list_update(SP_LPE_ITEM(item));
352         }
353     }
356 void LivePathEffectEditor::onUp()
358         Inkscape::Selection *sel = _getSelection();
359     if ( sel && !sel->isEmpty() ) {
360         SPItem *item = sel->singleItem();
361         if ( item && SP_IS_LPE_ITEM(item) ) {
362             
363                               sp_lpe_item_up_current_path_effect(SP_LPE_ITEM(item));
364             
365             sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, 
366                                _("Move path effect up") );
368             effect_list_update(SP_LPE_ITEM(item));
369         }
370     }
371         
374 void LivePathEffectEditor::onDown()
376         Inkscape::Selection *sel = _getSelection();
377     if ( sel && !sel->isEmpty() ) {
378         SPItem *item = sel->singleItem();
379         if ( item && SP_IS_LPE_ITEM(item) ) {
380             
381                         sp_lpe_item_down_current_path_effect(SP_LPE_ITEM(item));
382             
383             sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, 
384                                _("Move path effect down") );
386             effect_list_update(SP_LPE_ITEM(item));
387         }
388     }
391 void LivePathEffectEditor::on_effect_selection_changed()
393     Glib::RefPtr<Gtk::TreeSelection> sel = effectlist_view.get_selection();
394     if (sel->count_selected_rows () == 0)
395         return;
397     Gtk::TreeModel::iterator it = sel->get_selected();
398     LivePathEffect::LPEObjectReference * lperef = (*it)[columns.lperef];
400     if (lperef && current_lpeitem) {
401         sp_lpe_item_set_current_path_effect(current_lpeitem, lperef);
402         showParams(lperef->lpeobject->lpe);
403     }
407 } // namespace Dialog
408 } // namespace UI
409 } // namespace Inkscape
411 /*
412   Local Variables:
413   mode:c++
414   c-file-style:"stroustrup"
415   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
416   indent-tabs-mode:nil
417   fill-column:99
418   End:
419 */
420 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :